@openclaw/line 2026.6.11 → 2026.7.1-beta.2

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.
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { defineBundledChannelEntry } from "openclaw/plugin-sdk/channel-entry-contract";
2
+ import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
2
3
  //#region extensions/line/index.ts
3
- let lineCardCommandPromise = null;
4
- async function loadLineCardCommand(api) {
5
- lineCardCommandPromise ??= (async () => {
4
+ function createLineCardCommandLoader(api) {
5
+ return createLazyRuntimeModule(async () => {
6
6
  let registered = null;
7
- const { registerLineCardCommand } = await import("./card-command-ML0lh9al.js");
7
+ const { registerLineCardCommand } = await import("./card-command-DZVv78B6.js");
8
8
  registerLineCardCommand({
9
9
  ...api,
10
10
  registerCommand(command) {
@@ -13,8 +13,7 @@ async function loadLineCardCommand(api) {
13
13
  });
14
14
  if (!registered) throw new Error("LINE card command registration unavailable");
15
15
  return registered;
16
- })();
17
- return await lineCardCommandPromise;
16
+ });
18
17
  }
19
18
  var line_default = defineBundledChannelEntry({
20
19
  id: "line",
@@ -30,13 +29,14 @@ var line_default = defineBundledChannelEntry({
30
29
  exportName: "setLineRuntime"
31
30
  },
32
31
  registerFull(api) {
32
+ const loadLineCardCommand = createLineCardCommandLoader(api);
33
33
  api.registerCommand({
34
34
  name: "card",
35
35
  description: "Send a rich card message (LINE).",
36
36
  acceptsArgs: true,
37
37
  requireAuth: false,
38
38
  async handler(ctx) {
39
- return await (await loadLineCardCommand(api)).handler(ctx);
39
+ return await (await loadLineCardCommand()).handler(ctx);
40
40
  }
41
41
  });
42
42
  }
@@ -1,70 +1,12 @@
1
- import { i as resolveLineAccount } from "./accounts-B-K3yrdP.js";
2
- import { l as validateLineMediaUrl, o as createLineSendReceipt } from "./reply-payload-transform-DZ8-37Ot.js";
3
- import { r as createReceiptCard } from "./schedule-cards-Bq74H30B.js";
1
+ import { i as resolveLineAccount } from "./accounts-DJVOv1JI.js";
2
+ import { o as validateLineMediaUrl, r as createLineSendReceipt } from "./reply-payload-transform-BwF-zq0G.js";
3
+ import { c as uriAction, d as createReceiptCard, o as messageAction, s as postbackAction, t as toFlexMessage } from "./flex-templates-DPBtqQ8R.js";
4
+ import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
4
5
  import { messagingApi } from "@line/bot-sdk";
5
6
  import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
6
7
  import { recordChannelActivity } from "openclaw/plugin-sdk/channel-activity-runtime";
7
8
  import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
8
9
  import { stripMarkdown, stripMarkdown as stripMarkdown$1 } from "openclaw/plugin-sdk/text-chunking";
9
- //#region extensions/line/src/flex-templates/message.ts
10
- /**
11
- * Wrap a FlexContainer in a FlexMessage
12
- */
13
- function toFlexMessage(altText, contents) {
14
- return {
15
- type: "flex",
16
- altText,
17
- contents
18
- };
19
- }
20
- //#endregion
21
- //#region extensions/line/src/actions.ts
22
- /**
23
- * Create a message action (sends text when tapped)
24
- */
25
- function messageAction(label, text) {
26
- return {
27
- type: "message",
28
- label: label.slice(0, 20),
29
- text: text ?? label
30
- };
31
- }
32
- /**
33
- * Create a URI action (opens a URL when tapped)
34
- */
35
- function uriAction(label, uri) {
36
- return {
37
- type: "uri",
38
- label: label.slice(0, 20),
39
- uri
40
- };
41
- }
42
- /**
43
- * Create a postback action (sends data to webhook when tapped)
44
- */
45
- function postbackAction(label, data, displayText) {
46
- return {
47
- type: "postback",
48
- label: label.slice(0, 20),
49
- data: data.slice(0, 300),
50
- displayText: displayText?.slice(0, 300)
51
- };
52
- }
53
- /**
54
- * Create a datetime picker action
55
- */
56
- function datetimePickerAction(label, data, mode, options) {
57
- return {
58
- type: "datetimepicker",
59
- label: label.slice(0, 20),
60
- data: data.slice(0, 300),
61
- mode,
62
- initial: options?.initial,
63
- max: options?.max,
64
- min: options?.min
65
- };
66
- }
67
- //#endregion
68
10
  //#region extensions/line/src/template-messages.ts
69
11
  const COMPACT_TEMPLATE_TEXT_LIMIT = 60;
70
12
  const graphemeSegmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
@@ -90,6 +32,9 @@ function truncateTemplateText(text, limit) {
90
32
  }
91
33
  return result;
92
34
  }
35
+ function truncateOptionalTemplateText(value, limit) {
36
+ return value === void 0 ? void 0 : truncateTemplateText(value, limit);
37
+ }
93
38
  function formatProductCarouselText(description, price) {
94
39
  if (!price) return description;
95
40
  const priceText = truncateTemplateText(price, COMPACT_TEMPLATE_TEXT_LIMIT);
@@ -102,12 +47,12 @@ function formatProductCarouselText(description, price) {
102
47
  function createConfirmTemplate(text, confirmAction, cancelAction, altText) {
103
48
  const template = {
104
49
  type: "confirm",
105
- text: text.slice(0, 240),
50
+ text: truncateTemplateText(text, 240),
106
51
  actions: [confirmAction, cancelAction]
107
52
  };
108
53
  return {
109
54
  type: "template",
110
- altText: altText?.slice(0, 400) ?? text.slice(0, 400),
55
+ altText: truncateOptionalTemplateText(altText, 400) ?? truncateTemplateText(text, 400),
111
56
  template
112
57
  };
113
58
  }
@@ -122,7 +67,7 @@ function createButtonTemplate(title, text, actions, options) {
122
67
  });
123
68
  const template = {
124
69
  type: "buttons",
125
- title: title.slice(0, 40),
70
+ title: truncateTemplateText(title, 40),
126
71
  text: truncateTemplateText(text, textLimit),
127
72
  actions: actions.slice(0, 4),
128
73
  thumbnailImageUrl: options?.thumbnailImageUrl,
@@ -133,7 +78,7 @@ function createButtonTemplate(title, text, actions, options) {
133
78
  };
134
79
  return {
135
80
  type: "template",
136
- altText: options?.altText?.slice(0, 400) ?? `${title}: ${text}`.slice(0, 400),
81
+ altText: truncateOptionalTemplateText(options?.altText, 400) ?? truncateTemplateText(`${title}: ${text}`, 400),
137
82
  template
138
83
  };
139
84
  }
@@ -149,7 +94,7 @@ function createTemplateCarousel(columns, options) {
149
94
  };
150
95
  return {
151
96
  type: "template",
152
- altText: options?.altText?.slice(0, 400) ?? "View carousel",
97
+ altText: truncateOptionalTemplateText(options?.altText, 400) ?? "View carousel",
153
98
  template
154
99
  };
155
100
  }
@@ -162,7 +107,7 @@ function createCarouselColumn(params) {
162
107
  textOnlyLimit: 120
163
108
  });
164
109
  return {
165
- title: params.title?.slice(0, 40),
110
+ title: truncateOptionalTemplateText(params.title, 40),
166
111
  text: truncateTemplateText(params.text, textLimit),
167
112
  actions: params.actions.slice(0, 3),
168
113
  thumbnailImageUrl: params.thumbnailImageUrl,
@@ -180,7 +125,7 @@ function createImageCarousel(columns, altText) {
180
125
  };
181
126
  return {
182
127
  type: "template",
183
- altText: altText?.slice(0, 400) ?? "View images",
128
+ altText: truncateOptionalTemplateText(altText, 400) ?? "View images",
184
129
  template
185
130
  };
186
131
  }
@@ -335,8 +280,8 @@ function createAudioMessage(originalContentUrl, durationMs) {
335
280
  function createLocationMessage(location) {
336
281
  return {
337
282
  type: "location",
338
- title: location.title.slice(0, 100),
339
- address: location.address.slice(0, 100),
283
+ title: truncateUtf16Safe(location.title, 100),
284
+ address: truncateUtf16Safe(location.address, 100),
340
285
  latitude: location.latitude,
341
286
  longitude: location.longitude
342
287
  };
@@ -469,7 +414,7 @@ async function pushLocationMessage(to, location, opts) {
469
414
  async function pushFlexMessage(to, altText, contents, opts) {
470
415
  return pushLineMessages(to, [{
471
416
  type: "flex",
472
- altText: altText.slice(0, 400),
417
+ altText: truncateUtf16Safe(altText, 400),
473
418
  contents
474
419
  }], opts, {
475
420
  errorContext: "push flex message",
@@ -485,11 +430,7 @@ async function pushTextMessageWithQuickReplies(to, text, quickReplyLabels, opts)
485
430
  function createQuickReplyItems(labels) {
486
431
  return { items: labels.slice(0, 13).map((label) => ({
487
432
  type: "action",
488
- action: {
489
- type: "message",
490
- label: label.slice(0, 20),
491
- text: label
492
- }
433
+ action: messageAction(label, label)
493
434
  })) };
494
435
  }
495
436
  function createTextMessageWithQuickReplies(text, quickReplyLabels) {
@@ -712,7 +653,7 @@ function extractCodeBlocks(text) {
712
653
  */
713
654
  function convertCodeBlockToFlexBubble(block) {
714
655
  const titleText = block.language ? `Code (${block.language})` : "Code";
715
- const displayCode = block.code.length > 2e3 ? block.code.slice(0, 2e3) + "\n..." : block.code;
656
+ const displayCode = block.code.length > 2e3 ? truncateUtf16Safe(block.code, 2e3) + "\n..." : block.code;
716
657
  return {
717
658
  type: "bubble",
718
659
  body: {
@@ -783,11 +724,7 @@ function convertLinksToFlexBubble(links) {
783
724
  layout: "vertical",
784
725
  contents: links.slice(0, 4).map((link, index) => ({
785
726
  type: "button",
786
- action: {
787
- type: "uri",
788
- label: link.text.slice(0, 20),
789
- uri: link.url
790
- },
727
+ action: uriAction(link.text, link.url),
791
728
  style: index === 0 ? "primary" : "secondary",
792
729
  margin: index > 0 ? "sm" : void 0
793
730
  })),
@@ -840,4 +777,4 @@ function hasMarkdownToConvert(text) {
840
777
  return false;
841
778
  }
842
779
  //#endregion
843
- export { buildTemplateMessageFromPayload as A, createYesNoConfirm as B, pushMessagesLine as C, sendMessageLine as D, replyMessageLine as E, createImageCarousel as F, toFlexMessage as G, messageAction as H, createImageCarouselColumn as I, createLinkMenu as L, createButtonTemplate as M, createCarouselColumn as N, showLoadingAnimation as O, createConfirmTemplate as P, createProductCarousel as R, pushMessageLine as S, pushTextMessageWithQuickReplies as T, postbackAction as U, datetimePickerAction as V, uriAction as W, getUserDisplayName as _, extractLinks as a, pushImageMessage as b, processLineMessage as c, createFlexMessage as d, createImageMessage as f, createVideoMessage as g, createTextMessageWithQuickReplies as h, extractCodeBlocks as i, createButtonMenu as j, resolveLineChannelAccessToken as k, stripMarkdown$1 as l, createQuickReplyItems as m, convertLinksToFlexBubble as n, extractMarkdownTables as o, createLocationMessage as p, convertTableToFlexBubble as r, hasMarkdownToConvert as s, convertCodeBlockToFlexBubble as t, createAudioMessage as u, getUserProfile as v, pushTemplateMessage as w, pushLocationMessage as x, pushFlexMessage as y, createTemplateCarousel as z };
780
+ export { buildTemplateMessageFromPayload as A, createYesNoConfirm as B, pushMessagesLine as C, sendMessageLine as D, replyMessageLine as E, createImageCarousel as F, createImageCarouselColumn as I, createLinkMenu as L, createButtonTemplate as M, createCarouselColumn as N, showLoadingAnimation as O, createConfirmTemplate as P, createProductCarousel as R, pushMessageLine as S, pushTextMessageWithQuickReplies as T, getUserDisplayName as _, extractLinks as a, pushImageMessage as b, processLineMessage as c, createFlexMessage as d, createImageMessage as f, createVideoMessage as g, createTextMessageWithQuickReplies as h, extractCodeBlocks as i, createButtonMenu as j, resolveLineChannelAccessToken as k, stripMarkdown$1 as l, createQuickReplyItems as m, convertLinksToFlexBubble as n, extractMarkdownTables as o, createLocationMessage as p, convertTableToFlexBubble as r, hasMarkdownToConvert as s, convertCodeBlockToFlexBubble as t, createAudioMessage as u, getUserProfile as v, pushTemplateMessage as w, pushLocationMessage as x, pushFlexMessage as y, createTemplateCarousel as z };
@@ -1,10 +1,11 @@
1
- import { i as resolveLineAccount, r as resolveDefaultLineAccountId } from "./accounts-B-K3yrdP.js";
2
- import { h as resolveLineGroupConfigEntry, s as buildLineQuickReplyFallbackText, u as getLineRuntime } from "./reply-payload-transform-DZ8-37Ot.js";
3
- import { A as buildTemplateMessageFromPayload, C as pushMessagesLine, E as replyMessageLine, O as showLoadingAnimation, S as pushMessageLine, T as pushTextMessageWithQuickReplies, _ as getUserDisplayName, c as processLineMessage, d as createFlexMessage, f as createImageMessage, h as createTextMessageWithQuickReplies, m as createQuickReplyItems, p as createLocationMessage } from "./markdown-to-line-juqp-iiY.js";
1
+ import { i as resolveLineAccount, r as resolveDefaultLineAccountId } from "./accounts-DJVOv1JI.js";
2
+ import { f as resolveLineGroupConfigEntry, i as buildLineQuickReplyFallbackText, s as getLineRuntime } from "./reply-payload-transform-BwF-zq0G.js";
3
+ import { A as buildTemplateMessageFromPayload, C as pushMessagesLine, E as replyMessageLine, O as showLoadingAnimation, S as pushMessageLine, T as pushTextMessageWithQuickReplies, _ as getUserDisplayName, c as processLineMessage, d as createFlexMessage, f as createImageMessage, h as createTextMessageWithQuickReplies, m as createQuickReplyItems, p as createLocationMessage } from "./markdown-to-line-CFx7ME4o.js";
4
4
  import { createChannelPairingChallengeIssuer } from "openclaw/plugin-sdk/channel-pairing";
5
5
  import { normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
6
6
  import { createMessageReceiveContext } from "openclaw/plugin-sdk/channel-outbound";
7
7
  import { resolveSendableOutboundReplyParts } from "openclaw/plugin-sdk/reply-payload";
8
+ import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
8
9
  import { firstDefined } from "openclaw/plugin-sdk/allow-from";
9
10
  import { messagingApi } from "@line/bot-sdk";
10
11
  import { saveMediaStream } from "openclaw/plugin-sdk/media-store";
@@ -41,8 +42,8 @@ const normalizeAllowFrom = (list) => {
41
42
  };
42
43
  //#endregion
43
44
  //#region extensions/line/src/download.ts
44
- async function downloadLineMedia(messageId, channelAccessToken, maxBytes = 10 * 1024 * 1024) {
45
- const saved = await saveMediaStream(await new messagingApi.MessagingApiBlobClient({ channelAccessToken }).getMessageContent(messageId), void 0, "inbound", maxBytes);
45
+ async function downloadLineMedia(messageId, channelAccessToken, maxBytes = 10 * 1024 * 1024, options) {
46
+ const saved = await saveMediaStream(await new messagingApi.MessagingApiBlobClient({ channelAccessToken }).getMessageContent(messageId), void 0, "inbound", maxBytes, options?.originalFilename);
46
47
  logVerbose(`line: persisted media ${messageId} to ${saved.path} (${saved.size} bytes)`);
47
48
  return {
48
49
  path: saved.path,
@@ -83,7 +84,7 @@ async function deliverLineAutoReply(params) {
83
84
  };
84
85
  const richMessages = [];
85
86
  const hasQuickReplies = Boolean(lineData.quickReplies?.length);
86
- if (lineData.flexMessage) richMessages.push(deps.createFlexMessage(lineData.flexMessage.altText.slice(0, 400), lineData.flexMessage.contents));
87
+ if (lineData.flexMessage) richMessages.push(deps.createFlexMessage(truncateUtf16Safe(lineData.flexMessage.altText, 400), lineData.flexMessage.contents));
87
88
  if (lineData.templateMessage) {
88
89
  const templateMsg = deps.buildTemplateMessageFromPayload(lineData.templateMessage);
89
90
  if (templateMsg) richMessages.push(templateMsg);
@@ -93,7 +94,7 @@ async function deliverLineAutoReply(params) {
93
94
  text: "",
94
95
  flexMessages: []
95
96
  };
96
- for (const flexMsg of processed.flexMessages) richMessages.push(deps.createFlexMessage(flexMsg.altText.slice(0, 400), flexMsg.contents));
97
+ for (const flexMsg of processed.flexMessages) richMessages.push(deps.createFlexMessage(truncateUtf16Safe(flexMsg.altText, 400), flexMsg.contents));
97
98
  const chunks = processed.text ? deps.chunkMarkdownText(processed.text, textLimit) : [];
98
99
  const mediaMessages = resolveSendableOutboundReplyParts(payload).mediaUrls.map((url) => url?.trim()).filter((url) => Boolean(url)).map((url) => deps.createImageMessage(url));
99
100
  if (chunks.length > 0) {
@@ -839,7 +840,8 @@ async function handleMessageEvent(event, context) {
839
840
  }
840
841
  const allMedia = [];
841
842
  if (isDownloadableLineMessageType(message.type)) try {
842
- const media = await downloadLineMedia(message.id, account.channelAccessToken, mediaMaxBytes);
843
+ const originalFilename = message.type === "file" ? normalizeOptionalString(message.fileName) : void 0;
844
+ const media = await downloadLineMedia(message.id, account.channelAccessToken, mediaMaxBytes, { originalFilename });
843
845
  allMedia.push({
844
846
  path: media.path,
845
847
  contentType: media.contentType
@@ -0,0 +1,2 @@
1
+ import { t as monitorLineProvider } from "./monitor-DzkYuWhv.js";
2
+ export { monitorLineProvider };
@@ -1,2 +1,2 @@
1
- import { A as buildTemplateMessageFromPayload, C as pushMessagesLine, D as sendMessageLine, S as pushMessageLine, T as pushTextMessageWithQuickReplies, c as processLineMessage, m as createQuickReplyItems, w as pushTemplateMessage, x as pushLocationMessage, y as pushFlexMessage } from "./markdown-to-line-juqp-iiY.js";
1
+ import { A as buildTemplateMessageFromPayload, C as pushMessagesLine, D as sendMessageLine, S as pushMessageLine, T as pushTextMessageWithQuickReplies, c as processLineMessage, m as createQuickReplyItems, w as pushTemplateMessage, x as pushLocationMessage, y as pushFlexMessage } from "./markdown-to-line-CFx7ME4o.js";
2
2
  export { buildTemplateMessageFromPayload, createQuickReplyItems, processLineMessage, pushFlexMessage, pushLocationMessage, pushMessageLine, pushMessagesLine, pushTemplateMessage, pushTextMessageWithQuickReplies, sendMessageLine };
@@ -0,0 +1,2 @@
1
+ import { t as probeLineBot } from "./probe-BslD77tJ.js";
2
+ export { probeLineBot };