@openclaw/line 2026.8.1-beta.3 → 2026.9.1-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/dist/api.js +1 -1
  2. package/dist/{card-command-CyDSm-OU.js → card-command-CmU47gD9.js} +16 -10
  3. package/dist/{channel-DmoKZXmG.js → channel-CsQLcrsA.js} +32 -15
  4. package/dist/channel-plugin-api.js +1 -1
  5. package/dist/channel.runtime-B83x7k_i.js +4 -0
  6. package/dist/index.js +1 -1
  7. package/dist/{markdown-to-line-rEaras_0.js → markdown-to-line-BmZ4hhfC.js} +17 -22
  8. package/dist/media-control-cards-CksNB8Wk.js +474 -0
  9. package/dist/{monitor-BYXS_B6r.js → monitor-Bd9XDV1i.js} +20 -11
  10. package/dist/monitor.runtime-BCCa6qTX.js +2 -0
  11. package/dist/{outbound.runtime-DDTeqaBW.js → outbound.runtime-D4w0-Gkc.js} +2 -2
  12. package/dist/runtime-api.js +6 -7
  13. package/dist/{send-BJCeiiOB.js → send-Dce0m539.js} +13 -9
  14. package/dist/{send-receipt-DKZzgHMO.js → send-receipt-CCPTalf9.js} +1 -371
  15. package/node_modules/typebox/build/format/date.d.mts +1 -1
  16. package/node_modules/typebox/build/format/date.mjs +1 -1
  17. package/node_modules/typebox/build/format/date_time.d.mts +2 -2
  18. package/node_modules/typebox/build/format/date_time.mjs +3 -3
  19. package/node_modules/typebox/build/format/email.d.mts +1 -1
  20. package/node_modules/typebox/build/format/email.mjs +2 -2
  21. package/node_modules/typebox/build/format/hostname.mjs +2 -10
  22. package/node_modules/typebox/build/format/idn_email.d.mts +1 -1
  23. package/node_modules/typebox/build/format/idn_email.mjs +3 -3
  24. package/node_modules/typebox/build/format/idn_hostname.d.mts +1 -0
  25. package/node_modules/typebox/build/format/idn_hostname.mjs +3 -11
  26. package/node_modules/typebox/build/format/idna/format/bidi.d.mts +3 -0
  27. package/node_modules/typebox/build/format/idna/format/bidi.mjs +98 -0
  28. package/node_modules/typebox/build/format/idna/format/puny.d.mts +3 -0
  29. package/node_modules/typebox/build/format/idna/format/puny.mjs +144 -0
  30. package/node_modules/typebox/build/format/idna/hostname.d.mts +1 -0
  31. package/node_modules/typebox/build/format/idna/hostname.mjs +16 -0
  32. package/node_modules/typebox/build/format/idna/idn-hostname.d.mts +1 -0
  33. package/node_modules/typebox/build/format/idna/idn-hostname.mjs +23 -0
  34. package/node_modules/typebox/build/format/idna/index.d.mts +2 -0
  35. package/node_modules/typebox/build/format/idna/index.mjs +2 -0
  36. package/node_modules/typebox/build/format/idna/label/ascii.d.mts +1 -0
  37. package/node_modules/typebox/build/format/idna/label/ascii.mjs +9 -0
  38. package/node_modules/typebox/build/format/idna/label/puny.d.mts +1 -0
  39. package/node_modules/typebox/build/format/idna/label/puny.mjs +28 -0
  40. package/node_modules/typebox/build/format/idna/label/unicode.d.mts +1 -0
  41. package/node_modules/typebox/build/format/idna/label/unicode.mjs +106 -0
  42. package/node_modules/typebox/build/format/idna/pattern/pattern.d.mts +30 -0
  43. package/node_modules/typebox/build/format/idna/pattern/pattern.mjs +70 -0
  44. package/node_modules/typebox/build/format/ipv4.d.mts +0 -1
  45. package/node_modules/typebox/build/format/ipv4.mjs +2 -32
  46. package/node_modules/typebox/build/format/ipv6.mjs +2 -61
  47. package/node_modules/typebox/build/format/iri.d.mts +2 -2
  48. package/node_modules/typebox/build/format/iri.mjs +26 -8
  49. package/node_modules/typebox/build/format/iri_reference.d.mts +2 -2
  50. package/node_modules/typebox/build/format/iri_reference.mjs +9 -55
  51. package/node_modules/typebox/build/format/regex.d.mts +1 -2
  52. package/node_modules/typebox/build/format/regex.mjs +2 -6
  53. package/node_modules/typebox/build/format/time.d.mts +2 -2
  54. package/node_modules/typebox/build/format/time.mjs +19 -14
  55. package/node_modules/typebox/build/format/uri.d.mts +1 -1
  56. package/node_modules/typebox/build/format/uri.mjs +3 -130
  57. package/node_modules/typebox/build/format/uri_reference.d.mts +1 -1
  58. package/node_modules/typebox/build/format/uri_reference.mjs +2 -3
  59. package/node_modules/typebox/build/format/uri_template.d.mts +2 -3
  60. package/node_modules/typebox/build/format/uri_template.mjs +4 -5
  61. package/node_modules/typebox/build/format/url.d.mts +3 -3
  62. package/node_modules/typebox/build/format/url.mjs +4 -5
  63. package/node_modules/typebox/build/guard/emit.d.mts +3 -1
  64. package/node_modules/typebox/build/guard/emit.mjs +12 -5
  65. package/node_modules/typebox/build/guard/guard.d.mts +8 -2
  66. package/node_modules/typebox/build/guard/guard.mjs +25 -4
  67. package/node_modules/typebox/build/guard/string.d.mts +2 -2
  68. package/node_modules/typebox/build/guard/string.mjs +7 -7
  69. package/node_modules/typebox/build/schema/engine/_context.mjs +3 -3
  70. package/node_modules/typebox/build/schema/engine/_functions.mjs +1 -2
  71. package/node_modules/typebox/build/schema/engine/_regexp.d.mts +2 -0
  72. package/node_modules/typebox/build/schema/engine/_regexp.mjs +4 -0
  73. package/node_modules/typebox/build/schema/engine/_stack.mjs +12 -13
  74. package/node_modules/typebox/build/schema/engine/additionalItems.mjs +17 -7
  75. package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +4 -3
  76. package/node_modules/typebox/build/schema/engine/contains.mjs +18 -6
  77. package/node_modules/typebox/build/schema/engine/enum.mjs +1 -1
  78. package/node_modules/typebox/build/schema/engine/items.mjs +26 -6
  79. package/node_modules/typebox/build/schema/engine/maxContains.mjs +3 -3
  80. package/node_modules/typebox/build/schema/engine/minContains.mjs +14 -4
  81. package/node_modules/typebox/build/schema/engine/not.mjs +4 -2
  82. package/node_modules/typebox/build/schema/engine/oneOf.mjs +7 -6
  83. package/node_modules/typebox/build/schema/engine/pattern.mjs +3 -2
  84. package/node_modules/typebox/build/schema/engine/patternProperties.mjs +4 -3
  85. package/node_modules/typebox/build/schema/engine/ref.mjs +1 -7
  86. package/node_modules/typebox/build/schema/engine/schema.mjs +13 -4
  87. package/node_modules/typebox/build/schema/engine/type.mjs +1 -1
  88. package/node_modules/typebox/build/schema/resolve/resolve.d.mts +4 -1
  89. package/node_modules/typebox/build/schema/resolve/resolve.mjs +202 -1
  90. package/node_modules/typebox/build/schema/static/propertyNames.d.mts +5 -0
  91. package/node_modules/typebox/build/schema/static/propertyNames.mjs +3 -0
  92. package/node_modules/typebox/build/schema/static/schema.d.mts +3 -0
  93. package/node_modules/typebox/build/schema/types/index.d.mts +0 -2
  94. package/node_modules/typebox/build/schema/types/index.mjs +0 -2
  95. package/node_modules/typebox/build/system/memory/clone.mjs +14 -11
  96. package/node_modules/typebox/build/system/memory/discard.mjs +6 -5
  97. package/node_modules/typebox/build/system/settings/settings.d.mts +9 -0
  98. package/node_modules/typebox/build/system/settings/settings.mjs +2 -0
  99. package/node_modules/typebox/build/type/engine/call/distribute_arguments.d.mts +6 -1
  100. package/node_modules/typebox/build/type/engine/call/distribute_arguments.mjs +16 -3
  101. package/node_modules/typebox/build/type/engine/call/instantiate.mjs +34 -4
  102. package/node_modules/typebox/build/type/engine/evaluate/broaden.d.mts +5 -5
  103. package/node_modules/typebox/build/type/engine/evaluate/broaden.mjs +20 -26
  104. package/node_modules/typebox/build/type/engine/evaluate/compare.d.mts +6 -10
  105. package/node_modules/typebox/build/type/engine/evaluate/compare.mjs +9 -13
  106. package/node_modules/typebox/build/type/engine/evaluate/composite.d.mts +7 -4
  107. package/node_modules/typebox/build/type/engine/evaluate/composite.mjs +12 -19
  108. package/node_modules/typebox/build/type/engine/evaluate/distribute.d.mts +4 -20
  109. package/node_modules/typebox/build/type/engine/evaluate/distribute.mjs +8 -20
  110. package/node_modules/typebox/build/type/engine/evaluate/evaluate.d.mts +4 -4
  111. package/node_modules/typebox/build/type/engine/evaluate/evaluate.mjs +11 -8
  112. package/node_modules/typebox/build/type/engine/evaluate/flatten.d.mts +1 -1
  113. package/node_modules/typebox/build/type/engine/evaluate/flatten.mjs +3 -4
  114. package/node_modules/typebox/build/type/engine/evaluate/narrow.d.mts +17 -2
  115. package/node_modules/typebox/build/type/engine/evaluate/narrow.mjs +26 -6
  116. package/node_modules/typebox/build/type/engine/exclude/operation.mjs +3 -4
  117. package/node_modules/typebox/build/type/engine/extract/operation.d.mts +1 -1
  118. package/node_modules/typebox/build/type/engine/extract/operation.mjs +3 -4
  119. package/node_modules/typebox/build/type/engine/priority/priority.d.mts +2 -2
  120. package/node_modules/typebox/build/type/engine/priority/priority.mjs +3 -4
  121. package/node_modules/typebox/build/type/script/mapping.d.mts +32 -29
  122. package/node_modules/typebox/build/type/script/mapping.mjs +18 -25
  123. package/node_modules/typebox/build/type/script/parser.d.mts +19 -25
  124. package/node_modules/typebox/build/type/script/parser.mjs +27 -23
  125. package/node_modules/typebox/build/value/errors/errors.d.mts +2 -2
  126. package/node_modules/typebox/build/value/errors/errors.mjs +1 -1
  127. package/node_modules/typebox/package.json +27 -27
  128. package/node_modules/typebox/readme.md +79 -82
  129. package/openclaw.plugin.json +10 -0
  130. package/package.json +6 -6
  131. package/dist/channel.runtime-qrUV6wPE.js +0 -4
  132. package/dist/config-schema-Be3azjB_.js +0 -47
  133. package/dist/monitor.runtime-B2z_5ugU.js +0 -2
  134. package/dist/quick-reply-fallback-D86FwAfr.js +0 -56
  135. package/node_modules/typebox/build/format/_idna.d.mts +0 -2
  136. package/node_modules/typebox/build/format/_idna.mjs +0 -246
  137. package/node_modules/typebox/build/format/_puny.d.mts +0 -1
  138. package/node_modules/typebox/build/format/_puny.mjs +0 -77
  139. package/node_modules/typebox/build/schema/resolve/ref.d.mts +0 -3
  140. package/node_modules/typebox/build/schema/resolve/ref.mjs +0 -146
  141. package/node_modules/typebox/build/schema/types/contentEncoding.d.mts +0 -9
  142. package/node_modules/typebox/build/schema/types/contentEncoding.mjs +0 -13
  143. package/node_modules/typebox/build/schema/types/contentMediaType.d.mts +0 -9
  144. package/node_modules/typebox/build/schema/types/contentMediaType.mjs +0 -13
@@ -0,0 +1,474 @@
1
+ import { m as truncateLineActionLabel, p as postbackAction } from "./send-receipt-CCPTalf9.js";
2
+ import { normalizeAccountId } from "openclaw/plugin-sdk/account-id";
3
+ import { resolveAccountEntry } from "openclaw/plugin-sdk/account-resolution";
4
+ import { normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
5
+ import { DmPolicySchema, GroupPolicySchema, buildChannelConfigSchema, buildGroupEntrySchema, buildMultiAccountChannelSchema, requireOpenAllowFrom } from "openclaw/plugin-sdk/channel-config-schema";
6
+ import { requireChannelOpenAllowFrom } from "openclaw/plugin-sdk/extension-shared";
7
+ import { z } from "zod";
8
+ import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";
9
+ //#region extensions/line/src/config-schema.ts
10
+ const ThreadBindingsSchema = z.object({
11
+ enabled: z.boolean().optional(),
12
+ idleHours: z.number().optional(),
13
+ maxAgeHours: z.number().optional(),
14
+ spawnSessions: z.boolean().optional(),
15
+ defaultSpawnContext: z.enum(["isolated", "fork"]).optional()
16
+ }).strict();
17
+ const LineCommonConfigSchemaBase = z.object({
18
+ enabled: z.boolean().optional(),
19
+ configWrites: z.boolean().optional(),
20
+ historyLimit: z.number().int().min(0).optional(),
21
+ channelAccessToken: z.string().optional(),
22
+ channelSecret: z.string().optional(),
23
+ tokenFile: z.string().optional(),
24
+ secretFile: z.string().optional(),
25
+ name: z.string().optional(),
26
+ allowFrom: z.array(z.union([z.string(), z.number()])).optional(),
27
+ groupAllowFrom: z.array(z.union([z.string(), z.number()])).optional(),
28
+ dmPolicy: DmPolicySchema.optional().default("pairing"),
29
+ groupPolicy: GroupPolicySchema.optional().default("allowlist"),
30
+ responsePrefix: z.string().optional(),
31
+ mediaMaxMb: z.number().optional(),
32
+ webhookPath: z.string().optional(),
33
+ threadBindings: ThreadBindingsSchema.optional()
34
+ });
35
+ const LineGroupConfigSchema = buildGroupEntrySchema().omit({
36
+ tools: true,
37
+ toolsBySender: true
38
+ });
39
+ const LineConfigSchema = buildMultiAccountChannelSchema(LineCommonConfigSchemaBase.extend({ groups: z.record(z.string(), LineGroupConfigSchema.optional()).optional() }).strict(), {
40
+ optionalAccount: true,
41
+ refine: (value, ctx) => {
42
+ requireChannelOpenAllowFrom({
43
+ channel: "line",
44
+ policy: value.dmPolicy,
45
+ allowFrom: value.allowFrom,
46
+ ctx,
47
+ requireOpenAllowFrom
48
+ });
49
+ }
50
+ });
51
+ const LineChannelConfigSchema = buildChannelConfigSchema(LineConfigSchema);
52
+ //#endregion
53
+ //#region extensions/line/src/runtime.ts
54
+ const { setRuntime: setLineRuntime, getRuntime: getLineRuntime } = createPluginRuntimeStore({
55
+ pluginId: "line",
56
+ errorMessage: "LINE runtime not initialized - plugin not registered"
57
+ });
58
+ //#endregion
59
+ //#region extensions/line/src/group-keys.ts
60
+ function resolveLineGroupLookupIds(groupId) {
61
+ const normalized = groupId?.trim();
62
+ if (!normalized) return [];
63
+ if (normalized.startsWith("group:") || normalized.startsWith("room:")) {
64
+ const rawId = normalized.split(":").slice(1).join(":");
65
+ return rawId ? [rawId, normalized] : [normalized];
66
+ }
67
+ return [
68
+ normalized,
69
+ `group:${normalized}`,
70
+ `room:${normalized}`
71
+ ];
72
+ }
73
+ function resolveLineGroupConfigEntry(groups, params) {
74
+ if (!groups) return;
75
+ for (const candidate of resolveLineGroupLookupIds(params.groupId)) {
76
+ const hit = groups[candidate];
77
+ if (hit) return hit;
78
+ }
79
+ for (const candidate of resolveLineGroupLookupIds(params.roomId)) {
80
+ const hit = groups[candidate];
81
+ if (hit) return hit;
82
+ }
83
+ return groups["*"];
84
+ }
85
+ function resolveLineGroupsConfig(cfg, accountId) {
86
+ const lineConfig = cfg.channels?.line;
87
+ if (!lineConfig) return;
88
+ const normalizedAccountId = normalizeAccountId(accountId);
89
+ return resolveAccountEntry(lineConfig.accounts, normalizedAccountId)?.groups ?? lineConfig.groups;
90
+ }
91
+ function resolveExactLineGroupConfigKey(params) {
92
+ const { groups } = params;
93
+ if (!groups) return;
94
+ return resolveLineGroupLookupIds(params.groupId).find((candidate) => Object.hasOwn(groups, candidate));
95
+ }
96
+ //#endregion
97
+ //#region extensions/line/src/quick-reply-fallback.ts
98
+ function buildLineQuickReplyFallbackText(labels) {
99
+ const normalized = normalizeStringEntries(labels ?? []).slice(0, 13);
100
+ if (normalized.length === 0) return "Choose an option.";
101
+ return `Options:\n${normalized.map((label) => `- ${label}`).join("\n")}`;
102
+ }
103
+ //#endregion
104
+ //#region extensions/line/src/flex-templates/media-control-cards.ts
105
+ /**
106
+ * Create a media player card for Sonos, Spotify, Apple Music, etc.
107
+ *
108
+ * Editorial design: Album art hero with gradient overlay for text,
109
+ * prominent now-playing indicator, refined playback controls.
110
+ */
111
+ function createMediaPlayerCard(params) {
112
+ const { title, subtitle, source, imageUrl, isPlaying, progress, controls, extraActions } = params;
113
+ const trackInfo = [{
114
+ type: "text",
115
+ text: title,
116
+ weight: "bold",
117
+ size: "xl",
118
+ color: "#111111",
119
+ wrap: true
120
+ }];
121
+ if (subtitle) trackInfo.push({
122
+ type: "text",
123
+ text: subtitle,
124
+ size: "md",
125
+ color: "#666666",
126
+ wrap: true,
127
+ margin: "sm"
128
+ });
129
+ const statusItems = [];
130
+ if (isPlaying !== void 0) statusItems.push({
131
+ type: "box",
132
+ layout: "horizontal",
133
+ contents: [{
134
+ type: "box",
135
+ layout: "vertical",
136
+ contents: [],
137
+ width: "8px",
138
+ height: "8px",
139
+ backgroundColor: isPlaying ? "#06C755" : "#CCCCCC",
140
+ cornerRadius: "4px"
141
+ }, {
142
+ type: "text",
143
+ text: isPlaying ? "Now Playing" : "Paused",
144
+ size: "xs",
145
+ color: isPlaying ? "#06C755" : "#888888",
146
+ weight: "bold",
147
+ margin: "sm"
148
+ }],
149
+ alignItems: "center"
150
+ });
151
+ if (source) statusItems.push({
152
+ type: "text",
153
+ text: source,
154
+ size: "xs",
155
+ color: "#AAAAAA",
156
+ margin: statusItems.length > 0 ? "lg" : void 0
157
+ });
158
+ if (progress) statusItems.push({
159
+ type: "text",
160
+ text: progress,
161
+ size: "xs",
162
+ color: "#888888",
163
+ align: "end",
164
+ flex: 1
165
+ });
166
+ const bodyContents = [{
167
+ type: "box",
168
+ layout: "vertical",
169
+ contents: trackInfo
170
+ }];
171
+ if (statusItems.length > 0) bodyContents.push({
172
+ type: "box",
173
+ layout: "horizontal",
174
+ contents: statusItems,
175
+ margin: "lg",
176
+ alignItems: "center"
177
+ });
178
+ const bubble = {
179
+ type: "bubble",
180
+ size: "mega",
181
+ body: {
182
+ type: "box",
183
+ layout: "vertical",
184
+ contents: bodyContents,
185
+ paddingAll: "xl",
186
+ backgroundColor: "#FFFFFF"
187
+ }
188
+ };
189
+ if (imageUrl) bubble.hero = {
190
+ type: "image",
191
+ url: imageUrl,
192
+ size: "full",
193
+ aspectRatio: "1:1",
194
+ aspectMode: "cover"
195
+ };
196
+ if (controls || extraActions?.length) {
197
+ const footerContents = [];
198
+ if (controls) {
199
+ const controlButtons = [];
200
+ if (controls.previous) controlButtons.push({
201
+ type: "button",
202
+ action: postbackAction("⏮", controls.previous.data),
203
+ style: "secondary",
204
+ flex: 1,
205
+ height: "sm"
206
+ });
207
+ if (controls.play) controlButtons.push({
208
+ type: "button",
209
+ action: postbackAction("▶", controls.play.data),
210
+ style: isPlaying ? "secondary" : "primary",
211
+ flex: 1,
212
+ height: "sm",
213
+ margin: controls.previous ? "md" : void 0
214
+ });
215
+ if (controls.pause) controlButtons.push({
216
+ type: "button",
217
+ action: postbackAction("⏸", controls.pause.data),
218
+ style: isPlaying ? "primary" : "secondary",
219
+ flex: 1,
220
+ height: "sm",
221
+ margin: controlButtons.length > 0 ? "md" : void 0
222
+ });
223
+ if (controls.next) controlButtons.push({
224
+ type: "button",
225
+ action: postbackAction("⏭", controls.next.data),
226
+ style: "secondary",
227
+ flex: 1,
228
+ height: "sm",
229
+ margin: controlButtons.length > 0 ? "md" : void 0
230
+ });
231
+ if (controlButtons.length > 0) footerContents.push({
232
+ type: "box",
233
+ layout: "horizontal",
234
+ contents: controlButtons
235
+ });
236
+ }
237
+ if (extraActions?.length) footerContents.push({
238
+ type: "box",
239
+ layout: "horizontal",
240
+ contents: extraActions.slice(0, 2).map((action, index) => ({
241
+ type: "button",
242
+ action: postbackAction(truncateLineActionLabel(action.label, 15), action.data),
243
+ style: "secondary",
244
+ flex: 1,
245
+ height: "sm",
246
+ margin: index > 0 ? "md" : void 0
247
+ })),
248
+ margin: "md"
249
+ });
250
+ if (footerContents.length > 0) bubble.footer = {
251
+ type: "box",
252
+ layout: "vertical",
253
+ contents: footerContents,
254
+ paddingAll: "lg",
255
+ backgroundColor: "#FAFAFA"
256
+ };
257
+ }
258
+ return bubble;
259
+ }
260
+ /**
261
+ * Create an Apple TV remote card with a D-pad and control rows.
262
+ */
263
+ function createAppleTvRemoteCard(params) {
264
+ const { deviceName, status, actionData } = params;
265
+ const headerContents = [{
266
+ type: "text",
267
+ text: deviceName,
268
+ weight: "bold",
269
+ size: "xl",
270
+ color: "#111111",
271
+ wrap: true
272
+ }];
273
+ if (status) headerContents.push({
274
+ type: "text",
275
+ text: status,
276
+ size: "sm",
277
+ color: "#666666",
278
+ wrap: true,
279
+ margin: "sm"
280
+ });
281
+ const makeButton = (label, data, style = "secondary") => ({
282
+ type: "button",
283
+ action: postbackAction(label, data),
284
+ style,
285
+ height: "sm",
286
+ flex: 1
287
+ });
288
+ const dpadRows = [
289
+ {
290
+ type: "box",
291
+ layout: "horizontal",
292
+ contents: [
293
+ { type: "filler" },
294
+ makeButton("↑", actionData.up),
295
+ { type: "filler" }
296
+ ]
297
+ },
298
+ {
299
+ type: "box",
300
+ layout: "horizontal",
301
+ contents: [
302
+ makeButton("←", actionData.left),
303
+ makeButton("OK", actionData.select, "primary"),
304
+ makeButton("→", actionData.right)
305
+ ],
306
+ margin: "md"
307
+ },
308
+ {
309
+ type: "box",
310
+ layout: "horizontal",
311
+ contents: [
312
+ { type: "filler" },
313
+ makeButton("↓", actionData.down),
314
+ { type: "filler" }
315
+ ],
316
+ margin: "md"
317
+ }
318
+ ];
319
+ const menuRow = {
320
+ type: "box",
321
+ layout: "horizontal",
322
+ contents: [makeButton("Menu", actionData.menu), makeButton("Home", actionData.home)],
323
+ margin: "lg"
324
+ };
325
+ const playbackRow = {
326
+ type: "box",
327
+ layout: "horizontal",
328
+ contents: [makeButton("Play", actionData.play), makeButton("Pause", actionData.pause)],
329
+ margin: "md"
330
+ };
331
+ const volumeRow = {
332
+ type: "box",
333
+ layout: "horizontal",
334
+ contents: [
335
+ makeButton("Vol +", actionData.volumeUp),
336
+ makeButton("Mute", actionData.mute),
337
+ makeButton("Vol -", actionData.volumeDown)
338
+ ],
339
+ margin: "md"
340
+ };
341
+ return {
342
+ type: "bubble",
343
+ size: "mega",
344
+ body: {
345
+ type: "box",
346
+ layout: "vertical",
347
+ contents: [
348
+ {
349
+ type: "box",
350
+ layout: "vertical",
351
+ contents: headerContents
352
+ },
353
+ {
354
+ type: "separator",
355
+ margin: "lg",
356
+ color: "#EEEEEE"
357
+ },
358
+ ...dpadRows,
359
+ menuRow,
360
+ playbackRow,
361
+ volumeRow
362
+ ],
363
+ paddingAll: "xl",
364
+ backgroundColor: "#FFFFFF"
365
+ }
366
+ };
367
+ }
368
+ /**
369
+ * Create a device control card for Apple TV, smart home devices, etc.
370
+ *
371
+ * Editorial design: Device-focused header with status indicator,
372
+ * clean control grid with clear visual hierarchy.
373
+ */
374
+ function createDeviceControlCard(params) {
375
+ const { deviceName, deviceType, status, isOnline, imageUrl, controls } = params;
376
+ const headerContents = [{
377
+ type: "box",
378
+ layout: "horizontal",
379
+ contents: [{
380
+ type: "box",
381
+ layout: "vertical",
382
+ contents: [],
383
+ width: "10px",
384
+ height: "10px",
385
+ backgroundColor: isOnline !== false ? "#06C755" : "#FF5555",
386
+ cornerRadius: "5px"
387
+ }, {
388
+ type: "text",
389
+ text: deviceName,
390
+ weight: "bold",
391
+ size: "xl",
392
+ color: "#111111",
393
+ wrap: true,
394
+ flex: 1,
395
+ margin: "md"
396
+ }],
397
+ alignItems: "center"
398
+ }];
399
+ if (deviceType) headerContents.push({
400
+ type: "text",
401
+ text: deviceType,
402
+ size: "sm",
403
+ color: "#888888",
404
+ margin: "sm"
405
+ });
406
+ if (status) headerContents.push({
407
+ type: "box",
408
+ layout: "vertical",
409
+ contents: [{
410
+ type: "text",
411
+ text: status,
412
+ size: "sm",
413
+ color: "#444444",
414
+ wrap: true
415
+ }],
416
+ margin: "lg",
417
+ paddingAll: "md",
418
+ backgroundColor: "#F8F9FA",
419
+ cornerRadius: "md"
420
+ });
421
+ const bubble = {
422
+ type: "bubble",
423
+ size: "mega",
424
+ body: {
425
+ type: "box",
426
+ layout: "vertical",
427
+ contents: headerContents,
428
+ paddingAll: "xl",
429
+ backgroundColor: "#FFFFFF"
430
+ }
431
+ };
432
+ if (imageUrl) bubble.hero = {
433
+ type: "image",
434
+ url: imageUrl,
435
+ size: "full",
436
+ aspectRatio: "16:9",
437
+ aspectMode: "cover"
438
+ };
439
+ if (controls.length > 0) {
440
+ const rows = [];
441
+ const limitedControls = controls.slice(0, 6);
442
+ for (let i = 0; i < limitedControls.length; i += 2) {
443
+ const rowButtons = [];
444
+ for (const [offset, ctrl] of limitedControls.slice(i, i + 2).entries()) {
445
+ const buttonLabel = ctrl.icon ? `${ctrl.icon} ${ctrl.label}` : ctrl.label;
446
+ rowButtons.push({
447
+ type: "button",
448
+ action: postbackAction(truncateLineActionLabel(buttonLabel, 18), ctrl.data),
449
+ style: ctrl.style ?? "secondary",
450
+ flex: 1,
451
+ height: "sm",
452
+ margin: offset > 0 ? "md" : void 0
453
+ });
454
+ }
455
+ if (rowButtons.length === 1) rowButtons.push({ type: "filler" });
456
+ rows.push({
457
+ type: "box",
458
+ layout: "horizontal",
459
+ contents: rowButtons,
460
+ margin: i > 0 ? "md" : void 0
461
+ });
462
+ }
463
+ bubble.footer = {
464
+ type: "box",
465
+ layout: "vertical",
466
+ contents: rows,
467
+ paddingAll: "lg",
468
+ backgroundColor: "#FAFAFA"
469
+ };
470
+ }
471
+ return bubble;
472
+ }
473
+ //#endregion
474
+ export { resolveExactLineGroupConfigKey as a, resolveLineGroupsConfig as c, LineChannelConfigSchema as d, LineConfigSchema as f, buildLineQuickReplyFallbackText as i, getLineRuntime as l, createDeviceControlCard as n, resolveLineGroupConfigEntry as o, createMediaPlayerCard as r, resolveLineGroupLookupIds as s, createAppleTvRemoteCard as t, setLineRuntime as u };
@@ -1,8 +1,8 @@
1
1
  import { i as resolveLineAccount, r as resolveDefaultLineAccountId } from "./accounts-BqEVsDoB.js";
2
- import { a as resolveLineGroupConfigEntry, n as getLineRuntime, t as buildLineQuickReplyFallbackText } from "./quick-reply-fallback-D86FwAfr.js";
3
- import { v as buildLineMediaMessage, y as hasLineSpecificMediaOptions } from "./send-receipt-DKZzgHMO.js";
4
- import { i as processLineMessage, o as buildTemplateMessageFromPayload } from "./markdown-to-line-rEaras_0.js";
5
- import { _ as replyMessageLine, a as createQuickReplyItems, c as getUserDisplayName, i as createLocationMessage, m as pushMessagesLine, n as createFlexMessage, p as pushMessageLine, y as showLoadingAnimation } from "./send-BJCeiiOB.js";
2
+ import { i as buildLineQuickReplyFallbackText, l as getLineRuntime, o as resolveLineGroupConfigEntry } from "./media-control-cards-CksNB8Wk.js";
3
+ import { _ as hasLineSpecificMediaOptions, g as buildLineMediaMessage } from "./send-receipt-CCPTalf9.js";
4
+ import { i as processLineMessage, s as buildTemplateMessageFromPayload } from "./markdown-to-line-BmZ4hhfC.js";
5
+ import { _ as replyMessageLine, a as createQuickReplyItems, c as getUserDisplayName, i as createLocationMessage, m as pushMessagesLine, n as createFlexMessage, p as pushMessageLine, y as showLoadingAnimation } from "./send-Dce0m539.js";
6
6
  import { createChannelPairingChallengeIssuer } from "openclaw/plugin-sdk/channel-pairing";
7
7
  import { normalizeNullableString, normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
8
8
  import { DEFAULT_INGRESS_ADOPTION_STALL_MS, DEFAULT_INGRESS_RETRY_MAX_ATTEMPTS, bindIngressLifecycleToReplyOptions, createChannelIngressError, createChannelIngressMonitor } from "openclaw/plugin-sdk/channel-outbound";
@@ -284,20 +284,25 @@ async function deliverLineAutoReply(params) {
284
284
  type: "text",
285
285
  text
286
286
  }));
287
- const richMediaMessages = [...richMessages, ...mediaMessages];
287
+ const orderedDeliveryMessages = hasQuickReplies && chunks.length === 0 ? void 0 : orderedMessages;
288
+ const richMediaMessages = [
289
+ ...richMessages,
290
+ ...orderedDeliveryMessages ? [] : orderedMessages ?? [],
291
+ ...mediaMessages
292
+ ];
288
293
  if (hasQuickReplies && textMessages.length === 0 && richMediaMessages.length === 0) textMessages.push({
289
294
  type: "text",
290
295
  text: buildLineQuickReplyFallbackText(lineData.quickReplies)
291
296
  });
292
297
  if (hasQuickReplies) {
293
- const targetMessages = orderedMessages?.length ? orderedMessages : textMessages.length > 0 ? textMessages : richMediaMessages;
298
+ const targetMessages = orderedDeliveryMessages?.length ? orderedDeliveryMessages : textMessages.length > 0 ? textMessages : richMediaMessages;
294
299
  const lastIndex = targetMessages.length - 1;
295
300
  targetMessages[lastIndex] = {
296
301
  ...expectDefined(targetMessages[lastIndex], "last LINE auto-reply message"),
297
302
  quickReply: deps.createQuickReplyItems(lineData.quickReplies)
298
303
  };
299
304
  }
300
- const messages = hasQuickReplies ? [...richMediaMessages, ...orderedMessages ?? textMessages] : [...orderedMessages ?? textMessages, ...richMediaMessages];
305
+ const messages = hasQuickReplies ? [...richMediaMessages, ...orderedDeliveryMessages ?? textMessages] : [...orderedDeliveryMessages ?? textMessages, ...richMediaMessages];
301
306
  try {
302
307
  await sendLineMessages(messages, true);
303
308
  } catch (err) {
@@ -312,9 +317,13 @@ async function deliverLineAutoReply(params) {
312
317
  text: buildLineQuickReplyFallbackText(lineData.quickReplies),
313
318
  quickReply: deps.createQuickReplyItems(lineData.quickReplies)
314
319
  }] : [];
315
- if (retryMessages.length > 0 && failedSegment?.failedBatch.some((message) => message.type !== "text") && httpError?.status === 400) try {
316
- await sendLineMessages(retryMessages, false);
317
- } catch {}
320
+ if (retryMessages.length > 0 && failedSegment?.failedBatch.some((message) => message.type !== "text") && httpError?.status === 400) {
321
+ const lastRetryMessage = retryMessages.at(-1);
322
+ if (quickRepliesNeedCarrier && lastRetryMessage && !lastRetryMessage.quickReply) lastRetryMessage.quickReply = deps.createQuickReplyItems(lineData.quickReplies);
323
+ try {
324
+ await sendLineMessages(retryMessages, false);
325
+ } catch {}
326
+ }
318
327
  }
319
328
  if (deliveryError !== void 0) {
320
329
  if (!visibleReplySent) throw toLineDeliveryError(deliveryError);
@@ -1353,7 +1362,7 @@ function createLineBot(opts) {
1353
1362
  processMessage,
1354
1363
  ...control.turnAdoptionLifecycle ? { turnAdoptionLifecycle: control.turnAdoptionLifecycle } : {},
1355
1364
  groupHistories,
1356
- historyLimit: cfg.messages?.groupChat?.historyLimit ?? DEFAULT_GROUP_HISTORY_LIMIT
1365
+ historyLimit: account.config.historyLimit ?? cfg.messages?.groupChat?.historyLimit ?? DEFAULT_GROUP_HISTORY_LIMIT
1357
1366
  })
1358
1367
  });
1359
1368
  spool.start();
@@ -0,0 +1,2 @@
1
+ import { t as monitorLineProvider } from "./monitor-Bd9XDV1i.js";
2
+ export { monitorLineProvider };
@@ -1,3 +1,3 @@
1
- import { i as processLineMessage, o as buildTemplateMessageFromPayload } from "./markdown-to-line-rEaras_0.js";
2
- import { a as createQuickReplyItems, f as pushLocationMessage, g as pushTextMessageWithQuickReplies, h as pushTemplateMessage, i as createLocationMessage, m as pushMessagesLine, n as createFlexMessage, p as pushMessageLine, u as pushFlexMessage, v as sendMessageLine } from "./send-BJCeiiOB.js";
1
+ import { i as processLineMessage, s as buildTemplateMessageFromPayload } from "./markdown-to-line-BmZ4hhfC.js";
2
+ import { a as createQuickReplyItems, f as pushLocationMessage, g as pushTextMessageWithQuickReplies, h as pushTemplateMessage, i as createLocationMessage, m as pushMessagesLine, n as createFlexMessage, p as pushMessageLine, u as pushFlexMessage, v as sendMessageLine } from "./send-Dce0m539.js";
3
3
  export { buildTemplateMessageFromPayload, createFlexMessage, createLocationMessage, createQuickReplyItems, processLineMessage, pushFlexMessage, pushLocationMessage, pushMessageLine, pushMessagesLine, pushTemplateMessage, pushTextMessageWithQuickReplies, sendMessageLine };
@@ -1,13 +1,12 @@
1
1
  import { i as resolveLineAccount, n as normalizeAccountId, r as resolveDefaultLineAccountId, t as listLineAccountIds } from "./accounts-BqEVsDoB.js";
2
- import { a as resolveLineGroupConfigEntry, i as resolveExactLineGroupConfigKey, o as resolveLineGroupLookupIds, r as setLineRuntime, s as resolveLineGroupsConfig } from "./quick-reply-fallback-D86FwAfr.js";
3
- import { n as LineConfigSchema, t as LineChannelConfigSchema } from "./config-schema-Be3azjB_.js";
4
- import { _ as uriAction, a as createAgendaCard, c as createActionCard, d as createListCard, f as datetimePickerAction, g as postbackAction, i as createMediaPlayerCard, l as createImageCard, n as createAppleTvRemoteCard, o as createEventCard, p as messageAction, r as createDeviceControlCard, s as createReceiptCard, u as createInfoCard } from "./send-receipt-DKZzgHMO.js";
5
- import { a as stripMarkdown, c as createCarouselColumn, d as toFlexMessage, i as processLineMessage, l as createConfirmTemplate, n as convertTableToFlexBubble, o as buildTemplateMessageFromPayload, r as hasMarkdownToConvert, s as createButtonTemplate, t as convertCodeBlockToFlexBubble, u as createTemplateCarousel } from "./markdown-to-line-rEaras_0.js";
6
- import { a as validateLineSignature, c as normalizeAllowFrom, i as parseLineWebhookBody, n as createLineNodeWebhookHandler, o as downloadLineMedia, r as readLineWebhookRequestBody, s as firstDefined, t as monitorLineProvider } from "./monitor-BYXS_B6r.js";
2
+ import { a as resolveExactLineGroupConfigKey, c as resolveLineGroupsConfig, d as LineChannelConfigSchema, f as LineConfigSchema, n as createDeviceControlCard, o as resolveLineGroupConfigEntry, r as createMediaPlayerCard, s as resolveLineGroupLookupIds, t as createAppleTvRemoteCard, u as setLineRuntime } from "./media-control-cards-CksNB8Wk.js";
3
+ import { a as createActionCard, c as createListCard, h as uriAction, i as createReceiptCard, l as datetimePickerAction, n as createAgendaCard, o as createImageCard, p as postbackAction, r as createEventCard, s as createInfoCard, u as messageAction } from "./send-receipt-CCPTalf9.js";
4
+ import { a as validateLineSignature, c as normalizeAllowFrom, i as parseLineWebhookBody, n as createLineNodeWebhookHandler, o as downloadLineMedia, r as readLineWebhookRequestBody, s as firstDefined, t as monitorLineProvider } from "./monitor-Bd9XDV1i.js";
7
5
  import { t as probeLineBot } from "./probe-CM03wo6r.js";
8
- import { _ as replyMessageLine, a as createQuickReplyItems, b as resolveLineChannelAccessToken, c as getUserDisplayName, d as pushImageMessage, f as pushLocationMessage, g as pushTextMessageWithQuickReplies, h as pushTemplateMessage, i as createLocationMessage, l as getUserProfile, m as pushMessagesLine, n as createFlexMessage, o as createTextMessageWithQuickReplies, p as pushMessageLine, r as createImageMessage, s as createVideoMessage, t as createAudioMessage, u as pushFlexMessage, v as sendMessageLine, y as showLoadingAnimation } from "./send-BJCeiiOB.js";
9
- import { clearAccountEntryFields } from "openclaw/plugin-sdk/core";
6
+ import { a as stripMarkdown, c as createButtonTemplate, d as createTemplateCarousel, i as processLineMessage, l as createCarouselColumn, n as convertTableToFlexBubble, o as toFlexMessage, r as hasMarkdownToConvert, s as buildTemplateMessageFromPayload, t as convertCodeBlockToFlexBubble, u as createConfirmTemplate } from "./markdown-to-line-BmZ4hhfC.js";
7
+ import { _ as replyMessageLine, a as createQuickReplyItems, b as resolveLineChannelAccessToken, c as getUserDisplayName, d as pushImageMessage, f as pushLocationMessage, g as pushTextMessageWithQuickReplies, h as pushTemplateMessage, i as createLocationMessage, l as getUserProfile, m as pushMessagesLine, n as createFlexMessage, o as createTextMessageWithQuickReplies, p as pushMessageLine, r as createImageMessage, s as createVideoMessage, t as createAudioMessage, u as pushFlexMessage, v as sendMessageLine, y as showLoadingAnimation } from "./send-Dce0m539.js";
10
8
  import { buildChannelConfigSchema } from "openclaw/plugin-sdk/channel-config-schema";
9
+ import { clearAccountEntryFields } from "openclaw/plugin-sdk/core";
11
10
  import { DEFAULT_ACCOUNT_ID, formatDocsLink, setSetupChannelEnabled, splitSetupEntries } from "openclaw/plugin-sdk/setup";
12
11
  import { buildComputedAccountStatusSnapshot, buildTokenChannelStatusSummary } from "openclaw/plugin-sdk/status-helpers";
13
12
  import { danger, logVerbose } from "openclaw/plugin-sdk/runtime-env";
@@ -1,5 +1,5 @@
1
1
  import { i as resolveLineAccount } from "./accounts-BqEVsDoB.js";
2
- import { h as normalizeLineMessageActions, p as messageAction, t as createLineSendReceipt, x as validateLineMediaUrl } from "./send-receipt-DKZzgHMO.js";
2
+ import { f as normalizeLineMessageActions, t as createLineSendReceipt, u as messageAction, y as validateLineMediaUrl } from "./send-receipt-CCPTalf9.js";
3
3
  import { createChannelPartialDeliveryError } from "openclaw/plugin-sdk/channel-inbound";
4
4
  import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
5
5
  import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
@@ -11,6 +11,7 @@ import lineBotSdkPackage from "@line/bot-sdk/package.json" with { type: "json" }
11
11
  import { recordChannelActivity } from "openclaw/plugin-sdk/channel-activity-runtime";
12
12
  import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
13
13
  import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
14
+ import { readProviderJsonResponse, readResponseTextLimited } from "openclaw/plugin-sdk/provider-http";
14
15
  import { classifyTransientNetworkErrorCode, createChannelApiRetryRunner } from "openclaw/plugin-sdk/retry-runtime";
15
16
  //#region extensions/line/src/channel-access-token.ts
16
17
  function resolveLineChannelAccessToken(explicit, params) {
@@ -42,6 +43,7 @@ const PROFILE_CACHE_TTL_MS = 300 * 1e3;
42
43
  const PROFILE_CACHE_MAX_ENTRIES = 1e3;
43
44
  const LINE_FLEX_ALT_TEXT_LIMIT = 1500;
44
45
  const LINE_LOCATION_LABEL_LIMIT = 100;
46
+ const LINE_PROVIDER_RESPONSE_MAX_BYTES = 16 * 1024;
45
47
  function cacheUserProfile(userId, profile) {
46
48
  userProfileCache.delete(userId);
47
49
  userProfileCache.set(userId, profile);
@@ -114,15 +116,17 @@ async function sendLineProviderMessages(operation, token, request, retryKey) {
114
116
  body: JSON.stringify(request)
115
117
  });
116
118
  const acceptedRetryConflict = retryKey !== void 0 && response.status === 409;
117
- if (!response.ok && !acceptedRetryConflict) throw new HTTPFetchError(`${response.status} - ${response.statusText}`, {
118
- status: response.status,
119
- statusText: response.statusText,
120
- headers: response.headers,
121
- body: await response.text()
122
- });
119
+ if (!response.ok && !acceptedRetryConflict) {
120
+ const body = await readResponseTextLimited(response, LINE_PROVIDER_RESPONSE_MAX_BYTES).catch(() => "");
121
+ throw new HTTPFetchError(`${response.status} - ${response.statusText}`, {
122
+ status: response.status,
123
+ statusText: response.statusText,
124
+ headers: response.headers,
125
+ body
126
+ });
127
+ }
123
128
  try {
124
- const text = await response.text();
125
- return text ? JSON.parse(text) : null;
129
+ return await readProviderJsonResponse(response, `LINE ${operation} response`, { maxBytes: LINE_PROVIDER_RESPONSE_MAX_BYTES });
126
130
  } catch (error) {
127
131
  throw createChannelPartialDeliveryError(error, {
128
132
  messageIds: [],