@openclaw/line 2026.8.2 → 2026.9.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.
@@ -1,6 +1,6 @@
1
1
  import { i as resolveLineAccount } from "./accounts-BBEFMYbY.js";
2
2
  import { t as hasLineCredentials } from "./account-helpers-BSUyZwLm.js";
3
- import { _ as truncateLineActionLabel, a as createAgendaCard, c as createActionCard, g as postbackAction, o as createEventCard, p as messageAction } from "./send-retry-CUvrarfE.js";
3
+ import { S as fitsLineFlexBubble, b as truncateLineActionLabel, c as createAgendaCard, d as createActionCard, g as messageAction, l as createEventCard, y as postbackAction } from "./send-retry-ChpfJ-LM.js";
4
4
  import { normalizeAccountId } from "openclaw/plugin-sdk/account-id";
5
5
  import { resolveAccountEntry } from "openclaw/plugin-sdk/account-resolution";
6
6
  import { isRecord, normalizeLowercaseStringOrEmpty, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
@@ -111,6 +111,14 @@ function buildLineQuickReplyFallbackText(labels) {
111
111
  }
112
112
  //#endregion
113
113
  //#region extensions/line/src/flex-templates/media-control-cards.ts
114
+ function horizontalRow(contents, options = {}) {
115
+ return {
116
+ type: "box",
117
+ layout: "horizontal",
118
+ contents,
119
+ ...options
120
+ };
121
+ }
114
122
  /**
115
123
  * Create a media player card for Sonos, Spotify, Apple Music, etc.
116
124
  *
@@ -136,27 +144,22 @@ function createMediaPlayerCard(params) {
136
144
  margin: "sm"
137
145
  });
138
146
  const statusItems = [];
139
- if (isPlaying !== void 0) statusItems.push({
147
+ if (isPlaying !== void 0) statusItems.push(horizontalRow([{
140
148
  type: "box",
141
- layout: "horizontal",
142
- contents: [{
143
- type: "box",
144
- layout: "vertical",
145
- contents: [],
146
- width: "8px",
147
- height: "8px",
148
- backgroundColor: isPlaying ? "#06C755" : "#CCCCCC",
149
- cornerRadius: "4px"
150
- }, {
151
- type: "text",
152
- text: isPlaying ? "Now Playing" : "Paused",
153
- size: "xs",
154
- color: isPlaying ? "#06C755" : "#888888",
155
- weight: "bold",
156
- margin: "sm"
157
- }],
158
- alignItems: "center"
159
- });
149
+ layout: "vertical",
150
+ contents: [],
151
+ width: "8px",
152
+ height: "8px",
153
+ backgroundColor: isPlaying ? "#06C755" : "#CCCCCC",
154
+ cornerRadius: "4px"
155
+ }, {
156
+ type: "text",
157
+ text: isPlaying ? "Now Playing" : "Paused",
158
+ size: "xs",
159
+ color: isPlaying ? "#06C755" : "#888888",
160
+ weight: "bold",
161
+ margin: "sm"
162
+ }], { alignItems: "center" }));
160
163
  if (source) statusItems.push({
161
164
  type: "text",
162
165
  text: source,
@@ -177,13 +180,10 @@ function createMediaPlayerCard(params) {
177
180
  layout: "vertical",
178
181
  contents: trackInfo
179
182
  }];
180
- if (statusItems.length > 0) bodyContents.push({
181
- type: "box",
182
- layout: "horizontal",
183
- contents: statusItems,
183
+ if (statusItems.length > 0) bodyContents.push(horizontalRow(statusItems, {
184
184
  margin: "lg",
185
185
  alignItems: "center"
186
- });
186
+ }));
187
187
  const bubble = {
188
188
  type: "bubble",
189
189
  size: "mega",
@@ -206,56 +206,50 @@ function createMediaPlayerCard(params) {
206
206
  const footerContents = [];
207
207
  if (controls) {
208
208
  const controlButtons = [];
209
- if (controls.previous) controlButtons.push({
210
- type: "button",
211
- action: postbackAction("⏮", controls.previous.data),
212
- style: "secondary",
213
- flex: 1,
214
- height: "sm"
215
- });
216
- if (controls.play) controlButtons.push({
217
- type: "button",
218
- action: postbackAction("▶", controls.play.data),
219
- style: isPlaying ? "secondary" : "primary",
220
- flex: 1,
221
- height: "sm",
222
- margin: controls.previous ? "md" : void 0
223
- });
224
- if (controls.pause) controlButtons.push({
225
- type: "button",
226
- action: postbackAction("⏸", controls.pause.data),
227
- style: isPlaying ? "primary" : "secondary",
228
- flex: 1,
229
- height: "sm",
230
- margin: controlButtons.length > 0 ? "md" : void 0
231
- });
232
- if (controls.next) controlButtons.push({
233
- type: "button",
234
- action: postbackAction("⏭", controls.next.data),
235
- style: "secondary",
236
- flex: 1,
237
- height: "sm",
238
- margin: controlButtons.length > 0 ? "md" : void 0
239
- });
240
- if (controlButtons.length > 0) footerContents.push({
241
- type: "box",
242
- layout: "horizontal",
243
- contents: controlButtons
244
- });
209
+ for (const [key, label, style] of [
210
+ [
211
+ "previous",
212
+ "⏮",
213
+ "secondary"
214
+ ],
215
+ [
216
+ "play",
217
+ "▶",
218
+ isPlaying ? "secondary" : "primary"
219
+ ],
220
+ [
221
+ "pause",
222
+ "⏸",
223
+ isPlaying ? "primary" : "secondary"
224
+ ],
225
+ [
226
+ "next",
227
+ "⏭",
228
+ "secondary"
229
+ ]
230
+ ]) {
231
+ const control = controls[key];
232
+ if (!control) continue;
233
+ const button = {
234
+ type: "button",
235
+ action: postbackAction(label, control.data),
236
+ style,
237
+ flex: 1,
238
+ height: "sm"
239
+ };
240
+ if (key !== "previous") button.margin = controlButtons.length > 0 ? "md" : void 0;
241
+ controlButtons.push(button);
242
+ }
243
+ if (controlButtons.length > 0) footerContents.push(horizontalRow(controlButtons));
245
244
  }
246
- if (extraActions?.length) footerContents.push({
247
- type: "box",
248
- layout: "horizontal",
249
- contents: extraActions.slice(0, 2).map((action, index) => ({
250
- type: "button",
251
- action: postbackAction(truncateLineActionLabel(action.label, 15), action.data),
252
- style: "secondary",
253
- flex: 1,
254
- height: "sm",
255
- margin: index > 0 ? "md" : void 0
256
- })),
257
- margin: "md"
258
- });
245
+ if (extraActions?.length) footerContents.push(horizontalRow(extraActions.slice(0, 2).map((action, index) => ({
246
+ type: "button",
247
+ action: postbackAction(truncateLineActionLabel(action.label, 15), action.data),
248
+ style: "secondary",
249
+ flex: 1,
250
+ height: "sm",
251
+ margin: index > 0 ? "md" : void 0
252
+ })), { margin: "md" }));
259
253
  if (footerContents.length > 0) bubble.footer = {
260
254
  type: "box",
261
255
  layout: "vertical",
@@ -294,59 +288,30 @@ function createAppleTvRemoteCard(params) {
294
288
  height: "sm",
295
289
  flex: 1
296
290
  });
297
- const dpadRows = [
298
- {
299
- type: "box",
300
- layout: "horizontal",
301
- contents: [
302
- { type: "filler" },
303
- makeButton("↑", actionData.up),
304
- { type: "filler" }
305
- ]
306
- },
307
- {
308
- type: "box",
309
- layout: "horizontal",
310
- contents: [
311
- makeButton("←", actionData.left),
312
- makeButton("OK", actionData.select, "primary"),
313
- makeButton("→", actionData.right)
314
- ],
315
- margin: "md"
316
- },
317
- {
318
- type: "box",
319
- layout: "horizontal",
320
- contents: [
321
- { type: "filler" },
322
- makeButton("↓", actionData.down),
323
- { type: "filler" }
324
- ],
325
- margin: "md"
326
- }
327
- ];
328
- const menuRow = {
329
- type: "box",
330
- layout: "horizontal",
331
- contents: [makeButton("Menu", actionData.menu), makeButton("Home", actionData.home)],
332
- margin: "lg"
333
- };
334
- const playbackRow = {
335
- type: "box",
336
- layout: "horizontal",
337
- contents: [makeButton("Play", actionData.play), makeButton("Pause", actionData.pause)],
338
- margin: "md"
339
- };
340
- const volumeRow = {
341
- type: "box",
342
- layout: "horizontal",
343
- contents: [
291
+ const controlRows = [
292
+ horizontalRow([
293
+ { type: "filler" },
294
+ makeButton("↑", actionData.up),
295
+ { type: "filler" }
296
+ ]),
297
+ horizontalRow([
298
+ makeButton("←", actionData.left),
299
+ makeButton("OK", actionData.select, "primary"),
300
+ makeButton("→", actionData.right)
301
+ ], { margin: "md" }),
302
+ horizontalRow([
303
+ { type: "filler" },
304
+ makeButton("↓", actionData.down),
305
+ { type: "filler" }
306
+ ], { margin: "md" }),
307
+ horizontalRow([makeButton("Menu", actionData.menu), makeButton("Home", actionData.home)], { margin: "lg" }),
308
+ horizontalRow([makeButton("Play", actionData.play), makeButton("Pause", actionData.pause)], { margin: "md" }),
309
+ horizontalRow([
344
310
  makeButton("Vol +", actionData.volumeUp),
345
311
  makeButton("Mute", actionData.mute),
346
312
  makeButton("Vol -", actionData.volumeDown)
347
- ],
348
- margin: "md"
349
- };
313
+ ], { margin: "md" })
314
+ ];
350
315
  return {
351
316
  type: "bubble",
352
317
  size: "mega",
@@ -364,10 +329,7 @@ function createAppleTvRemoteCard(params) {
364
329
  margin: "lg",
365
330
  color: "#EEEEEE"
366
331
  },
367
- ...dpadRows,
368
- menuRow,
369
- playbackRow,
370
- volumeRow
332
+ ...controlRows
371
333
  ],
372
334
  paddingAll: "xl",
373
335
  backgroundColor: "#FFFFFF"
@@ -382,29 +344,24 @@ function createAppleTvRemoteCard(params) {
382
344
  */
383
345
  function createDeviceControlCard(params) {
384
346
  const { deviceName, deviceType, status, isOnline, imageUrl, controls } = params;
385
- const headerContents = [{
347
+ const headerContents = [horizontalRow([{
386
348
  type: "box",
387
- layout: "horizontal",
388
- contents: [{
389
- type: "box",
390
- layout: "vertical",
391
- contents: [],
392
- width: "10px",
393
- height: "10px",
394
- backgroundColor: isOnline !== false ? "#06C755" : "#FF5555",
395
- cornerRadius: "5px"
396
- }, {
397
- type: "text",
398
- text: deviceName,
399
- weight: "bold",
400
- size: "xl",
401
- color: "#111111",
402
- wrap: true,
403
- flex: 1,
404
- margin: "md"
405
- }],
406
- alignItems: "center"
407
- }];
349
+ layout: "vertical",
350
+ contents: [],
351
+ width: "10px",
352
+ height: "10px",
353
+ backgroundColor: isOnline !== false ? "#06C755" : "#FF5555",
354
+ cornerRadius: "5px"
355
+ }, {
356
+ type: "text",
357
+ text: deviceName,
358
+ weight: "bold",
359
+ size: "xl",
360
+ color: "#111111",
361
+ wrap: true,
362
+ flex: 1,
363
+ margin: "md"
364
+ }], { alignItems: "center" })];
408
365
  if (deviceType) headerContents.push({
409
366
  type: "text",
410
367
  text: deviceType,
@@ -462,12 +419,7 @@ function createDeviceControlCard(params) {
462
419
  });
463
420
  }
464
421
  if (rowButtons.length === 1) rowButtons.push({ type: "filler" });
465
- rows.push({
466
- type: "box",
467
- layout: "horizontal",
468
- contents: rowButtons,
469
- margin: i > 0 ? "md" : void 0
470
- });
422
+ rows.push(horizontalRow(rowButtons, { margin: i > 0 ? "md" : void 0 }));
471
423
  }
472
424
  bubble.footer = {
473
425
  type: "box",
@@ -572,6 +524,7 @@ const lineMessageActions = {
572
524
  },
573
525
  prepareSendPayload: ({ payload }) => payload
574
526
  };
527
+ const LINE_QUICK_REPLY_LIMIT = 13;
575
528
  const LINE_PRESENTATION_CAPABILITIES = {
576
529
  supported: true,
577
530
  buttons: true,
@@ -585,8 +538,7 @@ const LINE_PRESENTATION_CAPABILITIES = {
585
538
  maxLabelLength: 40
586
539
  },
587
540
  selects: {
588
- maxOptions: 13,
589
- maxLabelLength: 20,
541
+ maxOptions: LINE_QUICK_REPLY_LIMIT,
590
542
  maxValueBytes: 300
591
543
  },
592
544
  text: { markdownDialect: "plain" }
@@ -618,29 +570,58 @@ function toLineAction(button) {
618
570
  };
619
571
  }
620
572
  function renderLinePresentation(payload, presentation) {
621
- const buttons = presentation.blocks.flatMap((block) => block.type === "buttons" ? block.buttons : []);
622
- const buttonActions = buttons.map(toLineAction);
623
- const options = presentation.blocks.flatMap((block) => block.type === "select" ? block.options : []);
624
- const quickReplyItems = options.flatMap((option) => {
625
- const action = resolveMessagePresentationOptionAction(option);
626
- return action?.type === "command" || action?.type === "callback" ? [{
627
- label: option.label,
573
+ const hasCard = presentation.blocks.some((block) => block.type === "buttons" && block.buttons.length > 0);
574
+ const buttons = [];
575
+ const quickReplyItems = [];
576
+ const carriedBlocks = [];
577
+ const cardBody = [];
578
+ for (const block of presentation.blocks) if (block.type === "buttons") for (const button of block.buttons) {
579
+ const action = toLineAction(button);
580
+ if (!action) return null;
581
+ buttons.push({
582
+ label: button.label,
628
583
  action
629
- }] : [];
630
- });
631
- if (buttons.length > 0 && buttonActions.some((action) => !action) || quickReplyItems.length !== options.length || buttons.length === 0 && options.length === 0) return null;
584
+ });
585
+ }
586
+ else if (block.type === "select") {
587
+ const overflow = [];
588
+ for (const option of block.options) {
589
+ const action = resolveMessagePresentationOptionAction(option);
590
+ if (!action) return null;
591
+ if (quickReplyItems.length < LINE_QUICK_REPLY_LIMIT) quickReplyItems.push({
592
+ label: option.label,
593
+ action
594
+ });
595
+ else overflow.push(option);
596
+ }
597
+ if (overflow.length > 0) carriedBlocks.push({
598
+ ...block,
599
+ options: overflow
600
+ });
601
+ else if (block.placeholder) carriedBlocks.push({
602
+ type: "context",
603
+ text: block.placeholder
604
+ });
605
+ } else if (!hasCard) carriedBlocks.push(block);
606
+ else if (block.type === "text" || block.type === "context") cardBody.push(block.text);
607
+ if (buttons.length === 0 && quickReplyItems.length === 0) return null;
632
608
  const lineData = isRecord(payload.channelData?.line) ? payload.channelData.line : {};
633
- const text = presentation.blocks.flatMap((block) => block.type === "text" || block.type === "context" ? [block.text] : []).join("\n");
634
609
  const title = presentation.title || "Choose an option";
635
- const flexMessage = buttonActions.length > 0 ? {
610
+ const flexMessage = hasCard ? {
636
611
  altText: title,
637
- contents: createActionCard(title, text || "Choose an option.", buttons.map((button, index) => ({
638
- label: button.label,
639
- action: buttonActions[index]
640
- })))
612
+ contents: createActionCard(title, cardBody.join("\n") || "Choose an option.", buttons)
641
613
  } : void 0;
614
+ if (flexMessage && !fitsLineFlexBubble(flexMessage.contents)) return null;
615
+ const text = renderMessagePresentationFallbackText({
616
+ text: payload.text,
617
+ presentation: {
618
+ title: hasCard ? void 0 : presentation.title,
619
+ blocks: carriedBlocks
620
+ }
621
+ });
642
622
  return {
643
623
  ...payload,
624
+ ...text ? { text } : {},
644
625
  channelData: {
645
626
  ...payload.channelData,
646
627
  line: {
@@ -662,7 +643,7 @@ function prepareLineReplyPayload(payload) {
662
643
  const presentation = normalizeMessagePresentation(payload.presentation);
663
644
  if (!presentation) return payload;
664
645
  const { presentation: _presentation, presentationTextMode, ...rest } = payload;
665
- const usesFallbackText = presentationTextMode === "fallback";
646
+ const usesFallbackText = presentationTextMode === "fallback" && Boolean(rest.text?.trim());
666
647
  const rendered = renderLinePresentation(usesFallbackText ? {
667
648
  ...rest,
668
649
  text: void 0
@@ -752,7 +733,7 @@ function renderLineCard(card) {
752
733
  };
753
734
  }
754
735
  function createLineQuickReply(items) {
755
- return { items: items.slice(0, 13).map((item) => ({
736
+ return { items: items.slice(0, LINE_QUICK_REPLY_LIMIT).map((item) => ({
756
737
  type: "action",
757
738
  action: item.action.type === "command" ? messageAction(item.label, item.action.command) : postbackAction(item.label, item.action.value, item.label)
758
739
  })) };
@@ -1,10 +1,9 @@
1
1
  import { i as resolveLineAccount, n as normalizeAccountId, r as resolveDefaultLineAccountId, t as listLineAccountIds } from "./accounts-BBEFMYbY.js";
2
- import { _ as LineChannelConfigSchema, c as createDeviceControlCard, d as resolveExactLineGroupConfigKey, f as resolveLineGroupConfigEntry, g as setLineRuntime, l as createMediaPlayerCard, m as resolveLineGroupsConfig, p as resolveLineGroupLookupIds, s as createAppleTvRemoteCard, v as LineConfigSchema } from "./rich-messages-CIP7xn5E.js";
3
- import { S as createVideoMessage, a as createAgendaCard, b as createAudioMessage, c as createActionCard, d as createListCard, f as datetimePickerAction, g as postbackAction, l as createImageCard, o as createEventCard, p as messageAction, s as createReceiptCard, u as createInfoCard, v as uriAction, x as createImageMessage } from "./send-retry-CUvrarfE.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-CSpwQCBI.js";
5
- import { t as probeLineBot } from "./probe-4gc_YQ2L.js";
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--jytmFan.js";
7
- import { _ as showLoadingAnimation, c as pushFlexMessage, d as pushMessageLine, f as pushMessagesLine, g as sendMessageLine, h as replyMessageLine, i as createTextMessageWithQuickReplies, l as pushImageMessage, m as pushTextMessageWithQuickReplies, n as createLocationMessage, o as getUserDisplayName, p as pushTemplateMessage, r as createQuickReplyItems, s as getUserProfile, t as createFlexMessage, u as pushLocationMessage, y as resolveLineChannelAccessToken } from "./send-wVUV00WS.js";
2
+ import { _ as LineChannelConfigSchema, c as createDeviceControlCard, d as resolveExactLineGroupConfigKey, f as resolveLineGroupConfigEntry, g as setLineRuntime, l as createMediaPlayerCard, m as resolveLineGroupsConfig, p as resolveLineGroupLookupIds, s as createAppleTvRemoteCard, v as LineConfigSchema } from "./rich-messages-DY1AGKAJ.js";
3
+ import { C as toFlexMessage, D as createVideoMessage, E as createImageMessage, T as createAudioMessage, a as probeLineBot, c as createAgendaCard, d as createActionCard, f as createImageCard, g as messageAction, h as datetimePickerAction, l as createEventCard, m as createListCard, o as resolveLineChannelAccessToken, p as createInfoCard, u as createReceiptCard, x as uriAction, y as postbackAction } from "./send-retry-ChpfJ-LM.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-D0fHFXCi.js";
5
+ import { a as stripMarkdown, c as createCarouselColumn, 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-B-sj-7II.js";
6
+ import { _ as showLoadingAnimation, c as pushFlexMessage, d as pushMessageLine, f as pushMessagesLine, g as sendMessageLine, h as replyMessageLine, i as createTextMessageWithQuickReplies, l as pushImageMessage, m as pushTextMessageWithQuickReplies, n as createLocationMessage, o as getUserDisplayName, p as pushTemplateMessage, r as createQuickReplyItems, s as getUserProfile, t as createFlexMessage, u as pushLocationMessage } from "./send-CQQxpxPp.js";
8
7
  import { buildChannelConfigSchema } from "openclaw/plugin-sdk/channel-config-schema";
9
8
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
10
9
  import { mimeTypeFromFilePath } from "openclaw/plugin-sdk/media-mime";
@@ -13,6 +12,7 @@ import { DEFAULT_ACCOUNT_ID, formatDocsLink, setSetupChannelEnabled, splitSetupE
13
12
  import { buildComputedAccountStatusSnapshot, buildTokenChannelStatusSummary } from "openclaw/plugin-sdk/status-helpers";
14
13
  import { clearAccountEntryFields } from "openclaw/plugin-sdk/core";
15
14
  import { danger, logVerbose } from "openclaw/plugin-sdk/runtime-env";
15
+ import { bufferToBlobPart } from "openclaw/plugin-sdk/blob-runtime";
16
16
  import { getAgentScopedMediaLocalRoots } from "openclaw/plugin-sdk/media-local-roots";
17
17
  import { loadWebMediaRaw } from "openclaw/plugin-sdk/web-media";
18
18
  //#region extensions/line/src/webhook.ts
@@ -123,9 +123,8 @@ async function uploadRichMenuImage(richMenuId, imagePath, opts) {
123
123
  const blobClient = getBlobClient(opts);
124
124
  const media = await loadWebMediaRaw(imagePath, { localRoots: opts.mediaLocalRoots ?? getAgentScopedMediaLocalRoots(opts.cfg) });
125
125
  const contentType = media.contentType === "image/png" || media.contentType === "image/jpeg" ? media.contentType : mimeTypeFromFilePath(imagePath) === "image/png" ? "image/png" : "image/jpeg";
126
- const imageBytes = new ArrayBuffer(media.buffer.byteLength);
127
- new Uint8Array(imageBytes).set(media.buffer);
128
- await blobClient.setRichMenuImage(richMenuId, new Blob([imageBytes], { type: contentType }));
126
+ const blob = new Blob([bufferToBlobPart(media.buffer)], { type: contentType });
127
+ await blobClient.setRichMenuImage(richMenuId, blob);
129
128
  if (opts.verbose) logVerbose(`line: uploaded image to rich menu ${richMenuId}`);
130
129
  }
131
130
  async function setDefaultRichMenu(richMenuId, opts) {
@@ -1,24 +1,17 @@
1
1
  import { i as resolveLineAccount } from "./accounts-BBEFMYbY.js";
2
- import { h as normalizeLineMessageActions, i as createLineSendReceipt, p as messageAction, r as runLinePushWithRetries, y as buildLineMediaMessage } from "./send-retry-CUvrarfE.js";
2
+ import { g as messageAction, i as runLinePushWithRetries, o as resolveLineChannelAccessToken, s as createLineSendReceipt, v as normalizeLineMessage, w as buildLineMediaMessage } from "./send-retry-ChpfJ-LM.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 { HTTPFetchError, messagingApi } from "@line/bot-sdk";
6
- import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
6
+ import { readProviderJsonResponse, readResponseTextLimited } from "openclaw/plugin-sdk/provider-http";
7
7
  import { fetchWithRuntimeDispatcherOrMockedGlobal } from "openclaw/plugin-sdk/runtime-fetch";
8
+ import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
8
9
  import { randomUUID } from "node:crypto";
9
10
  import lineBotSdkPackage from "@line/bot-sdk/package.json" with { type: "json" };
10
11
  import { recordChannelActivity } from "openclaw/plugin-sdk/channel-activity-runtime";
11
12
  import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
12
13
  import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
13
- import { readProviderJsonResponse, readResponseTextLimited } from "openclaw/plugin-sdk/provider-http";
14
14
  import { createDedupeCache } from "openclaw/plugin-sdk/dedupe-runtime";
15
- //#region extensions/line/src/channel-access-token.ts
16
- function resolveLineChannelAccessToken(explicit, params) {
17
- if (explicit?.trim()) return explicit.trim();
18
- if (!params.channelAccessToken) throw new Error(`LINE channel access token missing for account "${params.accountId}" (set channels.line.channelAccessToken or LINE_CHANNEL_ACCESS_TOKEN).`);
19
- return params.channelAccessToken.trim();
20
- }
21
- //#endregion
22
15
  //#region extensions/line/src/outbound-message-log.ts
23
16
  const RECENT_SENT_LIMIT = 500;
24
17
  const recentSentByAccount = /* @__PURE__ */ new Map();
@@ -224,7 +217,7 @@ function resolveLineReceiptKind(messages) {
224
217
  async function pushLineMessages(to, messages, opts, behavior = {}) {
225
218
  if (messages.length === 0) throw new Error("Message must be non-empty for LINE sends");
226
219
  const { account, token, chatId } = createLinePushContext(to, opts);
227
- const normalizedMessages = messages.map(normalizeLineMessageActions);
220
+ const normalizedMessages = messages.map(normalizeLineMessage);
228
221
  const retryKey = randomUUID();
229
222
  const { messageId, messageIds } = resolveLineProviderMessageIds(await runLinePushWithRetries(async () => {
230
223
  try {
@@ -263,7 +256,7 @@ async function replyLineMessages(replyToken, messages, opts) {
263
256
  return {
264
257
  ...resolveLineProviderMessageIds(await sendLineProviderMessages("reply", token, {
265
258
  replyToken,
266
- messages: messages.map(normalizeLineMessageActions)
259
+ messages: messages.map(normalizeLineMessage)
267
260
  }), "reply"),
268
261
  accountId: account.accountId
269
262
  };
@@ -436,4 +429,4 @@ async function getLineGroupName(groupId, opts) {
436
429
  }
437
430
  }
438
431
  //#endregion
439
- export { showLoadingAnimation as _, getLineGroupName as a, pushFlexMessage as c, pushMessageLine as d, pushMessagesLine as f, sendMessageLine as g, replyMessageLine as h, createTextMessageWithQuickReplies as i, pushImageMessage as l, pushTextMessageWithQuickReplies as m, createLocationMessage as n, getUserDisplayName as o, pushTemplateMessage as p, createQuickReplyItems as r, getUserProfile as s, createFlexMessage as t, pushLocationMessage as u, quotesLineBotMessage as v, resolveLineChannelAccessToken as y };
432
+ export { showLoadingAnimation as _, getLineGroupName as a, pushFlexMessage as c, pushMessageLine as d, pushMessagesLine as f, sendMessageLine as g, replyMessageLine as h, createTextMessageWithQuickReplies as i, pushImageMessage as l, pushTextMessageWithQuickReplies as m, createLocationMessage as n, getUserDisplayName as o, pushTemplateMessage as p, createQuickReplyItems as r, getUserProfile as s, createFlexMessage as t, pushLocationMessage as u, quotesLineBotMessage as v };