@openclaw/line 2026.7.1 → 2026.7.2-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/api.js +2 -2
- package/dist/{card-command--jtkAqp8.js → card-command-DQ-epsgt.js} +7 -3
- package/dist/{channel-C_8hLniz.js → channel-BHR-GoJ0.js} +63 -84
- package/dist/channel-plugin-api.js +1 -1
- package/dist/channel.runtime-DFgZ_Xwn.js +4 -0
- package/dist/{flex-templates-DEIXn69v.js → flex-templates-K1lS9i8L.js} +2 -3
- package/dist/index.js +1 -1
- package/dist/{markdown-to-line-DmpZY78n.js → markdown-to-line-XceqeKRP.js} +20 -20
- package/dist/{monitor-0eXlx_Pe.js → monitor-Db2rZsSX.js} +283 -228
- package/dist/monitor.runtime-CZuQgsEE.js +2 -0
- package/dist/{outbound.runtime-BwC7Y2U9.js → outbound.runtime-DnpU0Cms.js} +1 -1
- package/dist/{reply-payload-transform-C7r5npxP.js → reply-payload-transform-r9sa-TYT.js} +121 -84
- package/dist/runtime-api.js +8 -34
- package/dist/setup-api.js +1 -1
- package/dist/{setup-surface-Bc36YSS3.js → setup-surface-B7W6pwn3.js} +36 -44
- package/npm-shrinkwrap.json +3 -3
- package/openclaw.plugin.json +57 -57
- package/package.json +4 -4
- package/dist/channel.runtime-Bh_AQM0k.js +0 -4
- package/dist/monitor.runtime-BGIpxzfB.js +0 -2
package/dist/api.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as lineChannelPluginCommon, t as linePlugin } from "./channel-
|
|
2
|
-
import { n as lineSetupAdapter, t as lineSetupWizard } from "./setup-surface-
|
|
1
|
+
import { n as lineChannelPluginCommon, t as linePlugin } from "./channel-BHR-GoJ0.js";
|
|
2
|
+
import { n as lineSetupAdapter, t as lineSetupWizard } from "./setup-surface-B7W6pwn3.js";
|
|
3
3
|
//#region extensions/line/src/channel.setup.ts
|
|
4
4
|
const lineSetupPlugin = {
|
|
5
5
|
id: "line",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { c as uriAction, d as createReceiptCard, f as createActionCard, g as createListCard, h as createInfoCard, m as createImageCard, o as messageAction, s as postbackAction } from "./flex-templates-
|
|
1
|
+
import { c as uriAction, d as createReceiptCard, f as createActionCard, g as createListCard, h as createInfoCard, m as createImageCard, o as messageAction, s as postbackAction } from "./flex-templates-K1lS9i8L.js";
|
|
2
2
|
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
3
3
|
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
4
|
+
import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
|
|
4
5
|
//#region extensions/line/src/card-command.ts
|
|
5
6
|
const CARD_USAGE = `Usage: /card <type> "title" "body" [options]
|
|
6
7
|
|
|
@@ -92,9 +93,12 @@ function parseCardArgs(argsStrInput) {
|
|
|
92
93
|
}
|
|
93
94
|
const quotedRegex = /"([^"]*?)"/g;
|
|
94
95
|
let match;
|
|
95
|
-
while ((match = quotedRegex.exec(argsStr)) !== null) result.args.push(match[1]);
|
|
96
|
+
while ((match = quotedRegex.exec(argsStr)) !== null) result.args.push(expectDefined(match[1], "quoted card argument capture"));
|
|
96
97
|
const flagRegex = /--(\w+)\s+(?:"([^"]*?)"|(\S+))/g;
|
|
97
|
-
while ((match = flagRegex.exec(argsStr)) !== null)
|
|
98
|
+
while ((match = flagRegex.exec(argsStr)) !== null) {
|
|
99
|
+
const key = expectDefined(match[1], "card flag name capture");
|
|
100
|
+
result.flags[key] = expectDefined(match[2] ?? match[3], "card flag value capture");
|
|
101
|
+
}
|
|
98
102
|
return result;
|
|
99
103
|
}
|
|
100
104
|
function registerLineCardCommand(api) {
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { i as resolveLineAccount, r as resolveDefaultLineAccountId, t as listLineAccountIds } from "./accounts-DJVOv1JI.js";
|
|
2
|
-
import { n as lineSetupAdapter, r as hasLineCredentials, t as lineSetupWizard } from "./setup-surface-
|
|
3
|
-
import { a as
|
|
2
|
+
import { n as lineSetupAdapter, r as hasLineCredentials, t as lineSetupWizard } from "./setup-surface-B7W6pwn3.js";
|
|
3
|
+
import { a as buildLineMediaMessage, d as LineChannelConfigSchema, i as buildLineQuickReplyFallbackText, l as getLineRuntime, n as parseLineDirectives, o as hasLineSpecificMediaOptions, p as resolveExactLineGroupConfigKey, r as createLineSendReceipt, s as resolveLineOutboundMedia, t as hasLineDirectives } from "./reply-payload-transform-r9sa-TYT.js";
|
|
4
4
|
import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
|
|
5
|
+
import { buildDmGroupAccountAllowlistAdapter, createFlatAllowlistOverrideResolver } from "openclaw/plugin-sdk/allowlist-config-edit";
|
|
5
6
|
import { buildChannelOutboundSessionRoute, createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core";
|
|
6
7
|
import { createPairingPrefixStripper } from "openclaw/plugin-sdk/channel-pairing";
|
|
7
|
-
import { createRestrictSendersChannelSecurity,
|
|
8
|
+
import { buildChannelGroupsScopeTree, createRestrictSendersChannelSecurity, resolveScopeRequireMention } from "openclaw/plugin-sdk/channel-policy";
|
|
8
9
|
import { createEmptyChannelDirectoryAdapter } from "openclaw/plugin-sdk/directory-runtime";
|
|
9
10
|
import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1 } from "openclaw/plugin-sdk/account-id";
|
|
10
11
|
import { clearAccountEntryFields } from "openclaw/plugin-sdk/core";
|
|
@@ -14,6 +15,7 @@ import { normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtim
|
|
|
14
15
|
import { defineChannelMessageAdapter } from "openclaw/plugin-sdk/channel-outbound";
|
|
15
16
|
import { createAttachedChannelResultAdapter, createEmptyChannelResult } from "openclaw/plugin-sdk/channel-send-result";
|
|
16
17
|
import { resolveOutboundMediaUrls } from "openclaw/plugin-sdk/reply-payload";
|
|
18
|
+
import { sanitizeAssistantVisibleText } from "openclaw/plugin-sdk/text-chunking";
|
|
17
19
|
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
18
20
|
import { buildTokenChannelStatusSummary, createComputedAccountStatusAdapter, createDefaultChannelRuntimeState, createDependentCredentialStatusIssueCollector } from "openclaw/plugin-sdk/status-helpers";
|
|
19
21
|
//#region extensions/line/src/bindings.ts
|
|
@@ -58,6 +60,22 @@ const lineBindingsAdapter = {
|
|
|
58
60
|
function normalizeLineAllowFrom(entry) {
|
|
59
61
|
return entry.replace(/^line:(?:user:)?/i, "");
|
|
60
62
|
}
|
|
63
|
+
const lineConfigAdapter = createScopedChannelConfigAdapter({
|
|
64
|
+
sectionKey: "line",
|
|
65
|
+
listAccountIds: listLineAccountIds,
|
|
66
|
+
resolveAccount: (cfg, accountId) => resolveLineAccount({
|
|
67
|
+
cfg,
|
|
68
|
+
accountId: accountId ?? void 0
|
|
69
|
+
}),
|
|
70
|
+
defaultAccountId: resolveDefaultLineAccountId,
|
|
71
|
+
clearBaseFields: [
|
|
72
|
+
"channelSecret",
|
|
73
|
+
"tokenFile",
|
|
74
|
+
"secretFile"
|
|
75
|
+
],
|
|
76
|
+
resolveAllowFrom: (account) => account.config.allowFrom,
|
|
77
|
+
formatAllowFrom: (allowFrom) => normalizeStringEntries(allowFrom).map(normalizeLineAllowFrom)
|
|
78
|
+
});
|
|
61
79
|
const lineChannelPluginCommon = {
|
|
62
80
|
meta: {
|
|
63
81
|
id: "line",
|
|
@@ -81,22 +99,7 @@ const lineChannelPluginCommon = {
|
|
|
81
99
|
reload: { configPrefixes: ["channels.line"] },
|
|
82
100
|
configSchema: LineChannelConfigSchema,
|
|
83
101
|
config: {
|
|
84
|
-
...
|
|
85
|
-
sectionKey: "line",
|
|
86
|
-
listAccountIds: listLineAccountIds,
|
|
87
|
-
resolveAccount: (cfg, accountId) => resolveLineAccount({
|
|
88
|
-
cfg,
|
|
89
|
-
accountId: accountId ?? void 0
|
|
90
|
-
}),
|
|
91
|
-
defaultAccountId: resolveDefaultLineAccountId,
|
|
92
|
-
clearBaseFields: [
|
|
93
|
-
"channelSecret",
|
|
94
|
-
"tokenFile",
|
|
95
|
-
"secretFile"
|
|
96
|
-
],
|
|
97
|
-
resolveAllowFrom: (account) => account.config.allowFrom,
|
|
98
|
-
formatAllowFrom: (allowFrom) => normalizeStringEntries(allowFrom).map(normalizeLineAllowFrom)
|
|
99
|
-
}),
|
|
102
|
+
...lineConfigAdapter,
|
|
100
103
|
isConfigured: (account) => hasLineCredentials(account),
|
|
101
104
|
describeAccount: (account) => describeWebhookAccountSnapshot({
|
|
102
105
|
account,
|
|
@@ -108,7 +111,7 @@ const lineChannelPluginCommon = {
|
|
|
108
111
|
//#endregion
|
|
109
112
|
//#region extensions/line/src/gateway.ts
|
|
110
113
|
const loadLineProbeRuntime$1 = createLazyRuntimeModule(() => import("./probe.runtime-CRhVGqwl.js"));
|
|
111
|
-
const loadLineMonitorRuntime = createLazyRuntimeModule(() => import("./monitor.runtime-
|
|
114
|
+
const loadLineMonitorRuntime = createLazyRuntimeModule(() => import("./monitor.runtime-CZuQgsEE.js"));
|
|
112
115
|
const lineGatewayAdapter = {
|
|
113
116
|
startAccount: async (ctx) => {
|
|
114
117
|
const account = ctx.account;
|
|
@@ -198,16 +201,14 @@ const lineGatewayAdapter = {
|
|
|
198
201
|
//#endregion
|
|
199
202
|
//#region extensions/line/src/group-policy.ts
|
|
200
203
|
function resolveLineGroupRequireMention(params) {
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
204
|
+
const tree = buildChannelGroupsScopeTree(params.cfg, "line", params.accountId);
|
|
205
|
+
const matchedKey = resolveExactLineGroupConfigKey({
|
|
206
|
+
groups: tree.scopes,
|
|
204
207
|
groupId: params.groupId
|
|
205
208
|
});
|
|
206
|
-
return
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
groupId: exactGroupId ?? params.groupId,
|
|
210
|
-
accountId: params.accountId
|
|
209
|
+
return resolveScopeRequireMention({
|
|
210
|
+
tree,
|
|
211
|
+
path: matchedKey ? [matchedKey] : []
|
|
211
212
|
});
|
|
212
213
|
}
|
|
213
214
|
//#endregion
|
|
@@ -225,42 +226,12 @@ function inferLineTargetChatType(target) {
|
|
|
225
226
|
}
|
|
226
227
|
//#endregion
|
|
227
228
|
//#region extensions/line/src/outbound.ts
|
|
228
|
-
const loadLineOutboundRuntime = createLazyRuntimeModule(() => import("./outbound.runtime-
|
|
229
|
-
function isLineUserTarget(target) {
|
|
230
|
-
const normalized = target.trim().replace(/^line:(group|room|user):/i, "").replace(/^line:/i, "");
|
|
231
|
-
return /^U/i.test(normalized);
|
|
232
|
-
}
|
|
233
|
-
function hasLineSpecificMediaOptions(lineData) {
|
|
234
|
-
return Boolean(lineData.mediaKind ?? lineData.previewImageUrl?.trim() ?? (typeof lineData.durationMs === "number" ? lineData.durationMs : void 0) ?? lineData.trackingId?.trim());
|
|
235
|
-
}
|
|
236
|
-
function buildLineMediaMessageObject(resolved, opts) {
|
|
237
|
-
switch (resolved.mediaKind) {
|
|
238
|
-
case "video": {
|
|
239
|
-
const previewImageUrl = resolved.previewImageUrl?.trim();
|
|
240
|
-
if (!previewImageUrl) throw new Error("LINE video messages require previewImageUrl to reference an image URL");
|
|
241
|
-
return {
|
|
242
|
-
type: "video",
|
|
243
|
-
originalContentUrl: resolved.mediaUrl,
|
|
244
|
-
previewImageUrl,
|
|
245
|
-
...opts?.allowTrackingId && resolved.trackingId ? { trackingId: resolved.trackingId } : {}
|
|
246
|
-
};
|
|
247
|
-
}
|
|
248
|
-
case "audio": return {
|
|
249
|
-
type: "audio",
|
|
250
|
-
originalContentUrl: resolved.mediaUrl,
|
|
251
|
-
duration: resolved.durationMs ?? 6e4
|
|
252
|
-
};
|
|
253
|
-
default: return {
|
|
254
|
-
type: "image",
|
|
255
|
-
originalContentUrl: resolved.mediaUrl,
|
|
256
|
-
previewImageUrl: resolved.previewImageUrl ?? resolved.mediaUrl
|
|
257
|
-
};
|
|
258
|
-
}
|
|
259
|
-
}
|
|
229
|
+
const loadLineOutboundRuntime = createLazyRuntimeModule(() => import("./outbound.runtime-DnpU0Cms.js"));
|
|
260
230
|
const lineOutboundAdapter = {
|
|
261
231
|
deliveryMode: "direct",
|
|
262
232
|
chunker: (text, limit) => getLineRuntime().channel.text.chunkMarkdownText(text, limit),
|
|
263
233
|
textChunkLimit: 5e3,
|
|
234
|
+
sanitizeText: ({ text }) => sanitizeAssistantVisibleText(text),
|
|
264
235
|
sendPayload: async ({ to, payload, accountId, cfg, onDeliveryResult }) => {
|
|
265
236
|
const runtime = getLineRuntime();
|
|
266
237
|
const outboundRuntime = await loadLineOutboundRuntime();
|
|
@@ -302,6 +273,12 @@ const lineOutboundAdapter = {
|
|
|
302
273
|
const chunks = processed.text ? runtime.channel.text.chunkMarkdownText(processed.text, chunkLimit) : [];
|
|
303
274
|
const mediaUrls = resolveOutboundMediaUrls(payload);
|
|
304
275
|
const useLineSpecificMedia = hasLineSpecificMediaOptions(lineData);
|
|
276
|
+
const mediaOptions = {
|
|
277
|
+
mediaKind: useLineSpecificMedia ? lineData.mediaKind : "image",
|
|
278
|
+
previewImageUrl: lineData.previewImageUrl,
|
|
279
|
+
durationMs: lineData.durationMs,
|
|
280
|
+
trackingId: lineData.trackingId
|
|
281
|
+
};
|
|
305
282
|
const shouldSendQuickRepliesInline = chunks.length === 0 && hasQuickReplies;
|
|
306
283
|
const sendMediaMessages = async () => {
|
|
307
284
|
for (const url of mediaUrls) {
|
|
@@ -316,12 +293,7 @@ const lineOutboundAdapter = {
|
|
|
316
293
|
}));
|
|
317
294
|
continue;
|
|
318
295
|
}
|
|
319
|
-
const resolved = await resolveLineOutboundMedia(trimmed,
|
|
320
|
-
mediaKind: lineData.mediaKind,
|
|
321
|
-
previewImageUrl: lineData.previewImageUrl,
|
|
322
|
-
durationMs: lineData.durationMs,
|
|
323
|
-
trackingId: lineData.trackingId
|
|
324
|
-
});
|
|
296
|
+
const resolved = await resolveLineOutboundMedia(trimmed, mediaOptions);
|
|
325
297
|
await recordResult((lineRuntime?.sendMessageLine ?? outboundRuntime.sendMessageLine)(to, "", {
|
|
326
298
|
verbose: false,
|
|
327
299
|
mediaUrl: resolved.mediaUrl,
|
|
@@ -367,12 +339,12 @@ const lineOutboundAdapter = {
|
|
|
367
339
|
}
|
|
368
340
|
const sendMediaAfterText = !(hasQuickReplies && chunks.length > 0);
|
|
369
341
|
if (mediaUrls.length > 0 && !shouldSendQuickRepliesInline && !sendMediaAfterText) await sendMediaMessages();
|
|
370
|
-
if (chunks.length > 0) for (
|
|
342
|
+
if (chunks.length > 0) for (const [i, chunk] of chunks.entries()) if (i === chunks.length - 1 && hasQuickReplies) await recordResult(sendQuickReplies(to, chunk, quickReplies, {
|
|
371
343
|
verbose: false,
|
|
372
344
|
cfg,
|
|
373
345
|
accountId: accountId ?? void 0
|
|
374
346
|
}));
|
|
375
|
-
else await recordResult(sendText(to,
|
|
347
|
+
else await recordResult(sendText(to, chunk, {
|
|
376
348
|
verbose: false,
|
|
377
349
|
cfg,
|
|
378
350
|
accountId: accountId ?? void 0
|
|
@@ -403,21 +375,7 @@ const lineOutboundAdapter = {
|
|
|
403
375
|
for (const url of mediaUrls) {
|
|
404
376
|
const trimmed = url?.trim();
|
|
405
377
|
if (!trimmed) continue;
|
|
406
|
-
|
|
407
|
-
quickReplyMessages.push({
|
|
408
|
-
type: "image",
|
|
409
|
-
originalContentUrl: trimmed,
|
|
410
|
-
previewImageUrl: trimmed
|
|
411
|
-
});
|
|
412
|
-
continue;
|
|
413
|
-
}
|
|
414
|
-
const resolved = await resolveLineOutboundMedia(trimmed, {
|
|
415
|
-
mediaKind: lineData.mediaKind,
|
|
416
|
-
previewImageUrl: lineData.previewImageUrl,
|
|
417
|
-
durationMs: lineData.durationMs,
|
|
418
|
-
trackingId: lineData.trackingId
|
|
419
|
-
});
|
|
420
|
-
quickReplyMessages.push(buildLineMediaMessageObject(resolved, { allowTrackingId: isLineUserTarget(to) }));
|
|
378
|
+
quickReplyMessages.push(await buildLineMediaMessage(trimmed, mediaOptions, to));
|
|
421
379
|
}
|
|
422
380
|
if (quickReplyMessages.length > 0 && quickReply) {
|
|
423
381
|
const lastIndex = quickReplyMessages.length - 1;
|
|
@@ -562,7 +520,7 @@ const lineStatusAdapter = createComputedAccountStatusAdapter({
|
|
|
562
520
|
});
|
|
563
521
|
//#endregion
|
|
564
522
|
//#region extensions/line/src/channel.ts
|
|
565
|
-
const loadLineChannelRuntime = createLazyRuntimeModule(() => import("./channel.runtime-
|
|
523
|
+
const loadLineChannelRuntime = createLazyRuntimeModule(() => import("./channel.runtime-DFgZ_Xwn.js"));
|
|
566
524
|
const lineSecurityAdapter = createRestrictSendersChannelSecurity({
|
|
567
525
|
channelKey: "line",
|
|
568
526
|
resolveDmPolicy: (account) => account.config.dmPolicy,
|
|
@@ -583,6 +541,27 @@ const linePlugin = createChatChannelPlugin({
|
|
|
583
541
|
...lineChannelPluginCommon,
|
|
584
542
|
setupWizard: lineSetupWizard,
|
|
585
543
|
groups: { resolveRequireMention: resolveLineGroupRequireMention },
|
|
544
|
+
allowlist: buildDmGroupAccountAllowlistAdapter({
|
|
545
|
+
channelId: "line",
|
|
546
|
+
resolveAccount: ({ cfg, accountId }) => resolveLineAccount({
|
|
547
|
+
cfg,
|
|
548
|
+
accountId: accountId ?? void 0
|
|
549
|
+
}),
|
|
550
|
+
normalize: ({ cfg, accountId, values }) => lineConfigAdapter.formatAllowFrom({
|
|
551
|
+
cfg,
|
|
552
|
+
accountId,
|
|
553
|
+
allowFrom: values
|
|
554
|
+
}),
|
|
555
|
+
resolveDmAllowFrom: (account) => account.config.allowFrom,
|
|
556
|
+
resolveGroupAllowFrom: (account) => account.config.groupAllowFrom,
|
|
557
|
+
resolveDmPolicy: (account) => account.config.dmPolicy,
|
|
558
|
+
resolveGroupPolicy: (account) => account.config.groupPolicy,
|
|
559
|
+
resolveGroupOverrides: createFlatAllowlistOverrideResolver({
|
|
560
|
+
resolveRecord: (account) => account.config.groups,
|
|
561
|
+
label: (groupId) => groupId,
|
|
562
|
+
resolveEntries: (groupCfg) => groupCfg?.allowFrom
|
|
563
|
+
})
|
|
564
|
+
}),
|
|
586
565
|
messaging: {
|
|
587
566
|
targetPrefixes: ["line"],
|
|
588
567
|
normalizeTarget: normalizeLineMessagingTarget,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as linePlugin } from "./channel-
|
|
1
|
+
import { t as linePlugin } from "./channel-BHR-GoJ0.js";
|
|
2
2
|
export { linePlugin };
|
|
@@ -1081,8 +1081,7 @@ function createDeviceControlCard(params) {
|
|
|
1081
1081
|
const limitedControls = controls.slice(0, 6);
|
|
1082
1082
|
for (let i = 0; i < limitedControls.length; i += 2) {
|
|
1083
1083
|
const rowButtons = [];
|
|
1084
|
-
for (
|
|
1085
|
-
const ctrl = limitedControls[j];
|
|
1084
|
+
for (const [offset, ctrl] of limitedControls.slice(i, i + 2).entries()) {
|
|
1086
1085
|
const buttonLabel = ctrl.icon ? `${ctrl.icon} ${ctrl.label}` : ctrl.label;
|
|
1087
1086
|
rowButtons.push({
|
|
1088
1087
|
type: "button",
|
|
@@ -1094,7 +1093,7 @@ function createDeviceControlCard(params) {
|
|
|
1094
1093
|
style: ctrl.style ?? "secondary",
|
|
1095
1094
|
flex: 1,
|
|
1096
1095
|
height: "sm",
|
|
1097
|
-
margin:
|
|
1096
|
+
margin: offset > 0 ? "md" : void 0
|
|
1098
1097
|
});
|
|
1099
1098
|
}
|
|
1100
1099
|
if (rowButtons.length === 1) rowButtons.push({ type: "filler" });
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
|
|
|
4
4
|
function createLineCardCommandLoader(api) {
|
|
5
5
|
return createLazyRuntimeModule(async () => {
|
|
6
6
|
let registered = null;
|
|
7
|
-
const { registerLineCardCommand } = await import("./card-command
|
|
7
|
+
const { registerLineCardCommand } = await import("./card-command-DQ-epsgt.js");
|
|
8
8
|
registerLineCardCommand({
|
|
9
9
|
...api,
|
|
10
10
|
registerCommand(command) {
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { i as resolveLineAccount } from "./accounts-DJVOv1JI.js";
|
|
2
|
-
import {
|
|
3
|
-
import { c as uriAction, d as createReceiptCard, o as messageAction, s as postbackAction, t as toFlexMessage } from "./flex-templates-
|
|
2
|
+
import { c as validateLineMediaUrl, r as createLineSendReceipt } from "./reply-payload-transform-r9sa-TYT.js";
|
|
3
|
+
import { c as uriAction, d as createReceiptCard, o as messageAction, s as postbackAction, t as toFlexMessage } from "./flex-templates-K1lS9i8L.js";
|
|
4
|
+
import { stripMarkdown, stripMarkdown as stripMarkdown$1 } from "openclaw/plugin-sdk/text-chunking";
|
|
4
5
|
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
5
|
-
import {
|
|
6
|
+
import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
|
|
6
7
|
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
|
|
8
|
+
import { messagingApi } from "@line/bot-sdk";
|
|
7
9
|
import { recordChannelActivity } from "openclaw/plugin-sdk/channel-activity-runtime";
|
|
8
10
|
import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
|
|
9
|
-
import { stripMarkdown, stripMarkdown as stripMarkdown$1 } from "openclaw/plugin-sdk/text-chunking";
|
|
10
11
|
//#region extensions/line/src/template-messages.ts
|
|
11
12
|
const COMPACT_TEMPLATE_TEXT_LIMIT = 60;
|
|
12
13
|
const graphemeSegmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
|
|
@@ -60,14 +61,15 @@ function createConfirmTemplate(text, confirmAction, cancelAction, altText) {
|
|
|
60
61
|
* Create a button template with title, text, and action buttons
|
|
61
62
|
*/
|
|
62
63
|
function createButtonTemplate(title, text, actions, options) {
|
|
64
|
+
const normalizedTitle = title || void 0;
|
|
63
65
|
const textLimit = resolveTemplateTextLimit({
|
|
64
|
-
title,
|
|
66
|
+
title: normalizedTitle,
|
|
65
67
|
thumbnailImageUrl: options?.thumbnailImageUrl,
|
|
66
68
|
textOnlyLimit: 160
|
|
67
69
|
});
|
|
68
70
|
const template = {
|
|
69
71
|
type: "buttons",
|
|
70
|
-
title: truncateTemplateText(
|
|
72
|
+
...normalizedTitle ? { title: truncateTemplateText(normalizedTitle, 40) } : {},
|
|
71
73
|
text: truncateTemplateText(text, textLimit),
|
|
72
74
|
actions: actions.slice(0, 4),
|
|
73
75
|
thumbnailImageUrl: options?.thumbnailImageUrl,
|
|
@@ -78,7 +80,7 @@ function createButtonTemplate(title, text, actions, options) {
|
|
|
78
80
|
};
|
|
79
81
|
return {
|
|
80
82
|
type: "template",
|
|
81
|
-
altText: truncateOptionalTemplateText(options?.altText, 400) ?? truncateTemplateText(`${
|
|
83
|
+
altText: truncateOptionalTemplateText(options?.altText, 400) ?? truncateTemplateText(normalizedTitle ? `${normalizedTitle}: ${text}` : text, 400),
|
|
82
84
|
template
|
|
83
85
|
};
|
|
84
86
|
}
|
|
@@ -224,7 +226,7 @@ function normalizeTarget(to) {
|
|
|
224
226
|
if (!trimmed) throw new Error("Recipient is required for LINE sends");
|
|
225
227
|
const normalized = trimmed.replace(/^line:group:/i, "").replace(/^line:room:/i, "").replace(/^line:user:/i, "").replace(/^line:/i, "");
|
|
226
228
|
if (!normalized) throw new Error("Recipient is required for LINE sends");
|
|
227
|
-
if (normalized.length >= 33 && !/^[CUR]/.test(normalized)) throw new Error(`Recipient is not a valid LINE id (case-sensitive; expected leading capital C/U/R): ${normalized
|
|
229
|
+
if (normalized.length >= 33 && !/^[CUR]/.test(normalized)) throw new Error(`Recipient is not a valid LINE id (case-sensitive; expected leading capital C/U/R): ${truncateUtf16Safe(normalized, 4)}…`);
|
|
228
230
|
return normalized;
|
|
229
231
|
}
|
|
230
232
|
function isLineUserChatId(chatId) {
|
|
@@ -498,9 +500,9 @@ function extractMarkdownTables(text) {
|
|
|
498
500
|
let match;
|
|
499
501
|
const matches = [];
|
|
500
502
|
while ((match = MARKDOWN_TABLE_REGEX.exec(text)) !== null) {
|
|
501
|
-
const fullMatch = match[0];
|
|
502
|
-
const headerLine = match[1];
|
|
503
|
-
const bodyLines = match[2];
|
|
503
|
+
const fullMatch = expectDefined(match[0], "Markdown table match");
|
|
504
|
+
const headerLine = expectDefined(match[1], "Markdown table header capture");
|
|
505
|
+
const bodyLines = expectDefined(match[2], "Markdown table body capture");
|
|
504
506
|
const headers = parseTableRow(headerLine);
|
|
505
507
|
const rows = bodyLines.trim().split(/[\r\n]+/).filter((line) => line.trim()).map(parseTableRow);
|
|
506
508
|
if (headers.length > 0 && rows.length > 0) matches.push({
|
|
@@ -511,8 +513,7 @@ function extractMarkdownTables(text) {
|
|
|
511
513
|
}
|
|
512
514
|
});
|
|
513
515
|
}
|
|
514
|
-
for (
|
|
515
|
-
const { fullMatch, table } = matches[i];
|
|
516
|
+
for (const { fullMatch, table } of matches.toReversed()) {
|
|
516
517
|
tables.unshift(table);
|
|
517
518
|
textWithoutTables = textWithoutTables.replace(fullMatch, "");
|
|
518
519
|
}
|
|
@@ -627,9 +628,9 @@ function extractCodeBlocks(text) {
|
|
|
627
628
|
let match;
|
|
628
629
|
const matches = [];
|
|
629
630
|
while ((match = MARKDOWN_CODE_BLOCK_REGEX.exec(text)) !== null) {
|
|
630
|
-
const fullMatch = match[0];
|
|
631
|
+
const fullMatch = expectDefined(match[0], "Markdown code block match");
|
|
631
632
|
const language = match[1] || void 0;
|
|
632
|
-
const code = match[2];
|
|
633
|
+
const code = expectDefined(match[2], "Markdown code body capture");
|
|
633
634
|
matches.push({
|
|
634
635
|
fullMatch,
|
|
635
636
|
block: {
|
|
@@ -638,8 +639,7 @@ function extractCodeBlocks(text) {
|
|
|
638
639
|
}
|
|
639
640
|
});
|
|
640
641
|
}
|
|
641
|
-
for (
|
|
642
|
-
const { fullMatch, block } = matches[i];
|
|
642
|
+
for (const { fullMatch, block } of matches.toReversed()) {
|
|
643
643
|
codeBlocks.unshift(block);
|
|
644
644
|
textWithoutCode = textWithoutCode.replace(fullMatch, "");
|
|
645
645
|
}
|
|
@@ -692,8 +692,8 @@ function extractLinks(text) {
|
|
|
692
692
|
MARKDOWN_LINK_REGEX.lastIndex = 0;
|
|
693
693
|
let match;
|
|
694
694
|
while ((match = MARKDOWN_LINK_REGEX.exec(text)) !== null) links.push({
|
|
695
|
-
text: match[1],
|
|
696
|
-
url: match[2]
|
|
695
|
+
text: expectDefined(match[1], "Markdown link text capture"),
|
|
696
|
+
url: expectDefined(match[2], "Markdown link URL capture")
|
|
697
697
|
});
|
|
698
698
|
return {
|
|
699
699
|
links,
|
|
@@ -756,7 +756,7 @@ function processLineMessage(text) {
|
|
|
756
756
|
}
|
|
757
757
|
const { textWithLinks } = extractLinks(processedText);
|
|
758
758
|
processedText = textWithLinks;
|
|
759
|
-
processedText = stripMarkdown(processedText);
|
|
759
|
+
processedText = stripMarkdown(processedText, { assistantTranscriptRoleHeaders: true });
|
|
760
760
|
return {
|
|
761
761
|
text: processedText,
|
|
762
762
|
flexMessages
|