@openclaw/line 2026.5.2-beta.2 → 2026.5.3-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 (109) hide show
  1. package/dist/accounts-UXAvdBo_.js +105 -0
  2. package/dist/api.js +11 -0
  3. package/dist/basic-cards-7DTG6E-A.js +307 -0
  4. package/dist/card-command-UlPc6Vuc.js +240 -0
  5. package/dist/channel-Rls9s60K.js +601 -0
  6. package/dist/channel-plugin-api.js +2 -0
  7. package/dist/channel.runtime-bXoj8_Sl.js +4 -0
  8. package/dist/contract-api.js +2 -0
  9. package/dist/index.js +45 -0
  10. package/dist/markdown-to-line-CCWK6PJh.js +789 -0
  11. package/dist/monitor-B4_RxHc0.js +1523 -0
  12. package/dist/monitor.runtime-DyxYlrM9.js +2 -0
  13. package/dist/outbound-media-BfhBmWq5.js +55 -0
  14. package/dist/outbound.runtime-B-luYwEB.js +2 -0
  15. package/dist/probe-D9BPzb2n.js +30 -0
  16. package/dist/probe.runtime-N91OWW1J.js +2 -0
  17. package/dist/quick-reply-fallback-HskUUWsn.js +55 -0
  18. package/dist/reply-payload-transform-CFGTs9ln.js +713 -0
  19. package/dist/runtime-api.js +277 -0
  20. package/dist/schedule-cards-BwQChTdM.js +359 -0
  21. package/dist/secret-contract-api.js +5 -0
  22. package/dist/setup-api.js +2 -0
  23. package/dist/setup-entry.js +11 -0
  24. package/dist/setup-surface-DCH7CE-y.js +281 -0
  25. package/package.json +14 -6
  26. package/api.ts +0 -11
  27. package/channel-plugin-api.ts +0 -1
  28. package/contract-api.ts +0 -5
  29. package/index.ts +0 -54
  30. package/runtime-api.ts +0 -187
  31. package/secret-contract-api.ts +0 -4
  32. package/setup-api.ts +0 -2
  33. package/setup-entry.ts +0 -9
  34. package/src/account-helpers.ts +0 -16
  35. package/src/accounts.test.ts +0 -290
  36. package/src/accounts.ts +0 -187
  37. package/src/actions.ts +0 -61
  38. package/src/auto-reply-delivery.test.ts +0 -248
  39. package/src/auto-reply-delivery.ts +0 -200
  40. package/src/bindings.ts +0 -65
  41. package/src/bot-access.ts +0 -48
  42. package/src/bot-handlers.test.ts +0 -1089
  43. package/src/bot-handlers.ts +0 -642
  44. package/src/bot-message-context.test.ts +0 -405
  45. package/src/bot-message-context.ts +0 -581
  46. package/src/bot.ts +0 -70
  47. package/src/card-command.ts +0 -347
  48. package/src/channel-access-token.ts +0 -14
  49. package/src/channel-api.ts +0 -17
  50. package/src/channel-setup-status.contract.test.ts +0 -70
  51. package/src/channel-shared.ts +0 -48
  52. package/src/channel.logout.test.ts +0 -145
  53. package/src/channel.runtime.ts +0 -3
  54. package/src/channel.sendPayload.test.ts +0 -514
  55. package/src/channel.setup.ts +0 -11
  56. package/src/channel.status.test.ts +0 -63
  57. package/src/channel.ts +0 -154
  58. package/src/config-adapter.ts +0 -29
  59. package/src/config-schema.ts +0 -57
  60. package/src/download.test.ts +0 -133
  61. package/src/download.ts +0 -87
  62. package/src/flex-templates/basic-cards.ts +0 -395
  63. package/src/flex-templates/common.ts +0 -20
  64. package/src/flex-templates/media-control-cards.ts +0 -555
  65. package/src/flex-templates/message.ts +0 -13
  66. package/src/flex-templates/schedule-cards.ts +0 -467
  67. package/src/flex-templates/types.ts +0 -22
  68. package/src/flex-templates.ts +0 -32
  69. package/src/gateway.ts +0 -129
  70. package/src/group-keys.test.ts +0 -123
  71. package/src/group-keys.ts +0 -65
  72. package/src/group-policy.ts +0 -22
  73. package/src/markdown-to-line.test.ts +0 -348
  74. package/src/markdown-to-line.ts +0 -416
  75. package/src/message-cards.test.ts +0 -204
  76. package/src/monitor.lifecycle.test.ts +0 -421
  77. package/src/monitor.runtime.ts +0 -1
  78. package/src/monitor.ts +0 -506
  79. package/src/outbound-media.test.ts +0 -189
  80. package/src/outbound-media.ts +0 -120
  81. package/src/outbound.runtime.ts +0 -12
  82. package/src/outbound.ts +0 -356
  83. package/src/probe.contract.test.ts +0 -9
  84. package/src/probe.runtime.ts +0 -1
  85. package/src/probe.ts +0 -34
  86. package/src/quick-reply-fallback.ts +0 -10
  87. package/src/reply-chunks.test.ts +0 -179
  88. package/src/reply-chunks.ts +0 -110
  89. package/src/reply-payload-transform.test.ts +0 -387
  90. package/src/reply-payload-transform.ts +0 -317
  91. package/src/rich-menu.test.ts +0 -310
  92. package/src/rich-menu.ts +0 -326
  93. package/src/runtime.ts +0 -32
  94. package/src/send.test.ts +0 -346
  95. package/src/send.ts +0 -489
  96. package/src/setup-core.ts +0 -149
  97. package/src/setup-runtime-api.ts +0 -9
  98. package/src/setup-surface.test.ts +0 -474
  99. package/src/setup-surface.ts +0 -227
  100. package/src/signature.test.ts +0 -34
  101. package/src/signature.ts +0 -24
  102. package/src/status.ts +0 -37
  103. package/src/template-messages.ts +0 -333
  104. package/src/types.ts +0 -128
  105. package/src/webhook-node.test.ts +0 -513
  106. package/src/webhook-node.ts +0 -131
  107. package/src/webhook-utils.ts +0 -10
  108. package/src/webhook.ts +0 -111
  109. package/tsconfig.json +0 -16
package/src/send.ts DELETED
@@ -1,489 +0,0 @@
1
- import { messagingApi } from "@line/bot-sdk";
2
- import { recordChannelActivity } from "openclaw/plugin-sdk/channel-activity-runtime";
3
- import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types";
4
- import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
5
- import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
6
- import { resolveLineAccount } from "./accounts.js";
7
- import { resolveLineChannelAccessToken } from "./channel-access-token.js";
8
- import { validateLineMediaUrl } from "./outbound-media.js";
9
- import type { LineSendResult } from "./types.js";
10
-
11
- type Message = messagingApi.Message;
12
- type TextMessage = messagingApi.TextMessage;
13
- type ImageMessage = messagingApi.ImageMessage;
14
- type VideoMessage = messagingApi.VideoMessage & { trackingId?: string };
15
- type AudioMessage = messagingApi.AudioMessage;
16
- type LocationMessage = messagingApi.LocationMessage;
17
- type FlexMessage = messagingApi.FlexMessage;
18
- type FlexContainer = messagingApi.FlexContainer;
19
- type TemplateMessage = messagingApi.TemplateMessage;
20
- type QuickReply = messagingApi.QuickReply;
21
- type QuickReplyItem = messagingApi.QuickReplyItem;
22
-
23
- const userProfileCache = new Map<
24
- string,
25
- { displayName: string; pictureUrl?: string; fetchedAt: number }
26
- >();
27
- const PROFILE_CACHE_TTL_MS = 5 * 60 * 1000;
28
-
29
- interface LineSendOpts {
30
- cfg: OpenClawConfig;
31
- channelAccessToken?: string;
32
- accountId?: string;
33
- verbose?: boolean;
34
- mediaUrl?: string;
35
- mediaKind?: "image" | "video" | "audio";
36
- previewImageUrl?: string;
37
- durationMs?: number;
38
- trackingId?: string;
39
- replyToken?: string;
40
- }
41
-
42
- type LineClientOpts = Pick<LineSendOpts, "cfg" | "channelAccessToken" | "accountId">;
43
- type LinePushOpts = Pick<LineSendOpts, "cfg" | "channelAccessToken" | "accountId" | "verbose">;
44
-
45
- interface LinePushBehavior {
46
- errorContext?: string;
47
- verboseMessage?: (chatId: string, messageCount: number) => string;
48
- }
49
-
50
- interface LineReplyBehavior {
51
- verboseMessage?: (messageCount: number) => string;
52
- }
53
-
54
- function normalizeTarget(to: string): string {
55
- const trimmed = to.trim();
56
- if (!trimmed) {
57
- throw new Error("Recipient is required for LINE sends");
58
- }
59
-
60
- const normalized = trimmed
61
- .replace(/^line:group:/i, "")
62
- .replace(/^line:room:/i, "")
63
- .replace(/^line:user:/i, "")
64
- .replace(/^line:/i, "");
65
-
66
- if (!normalized) {
67
- throw new Error("Recipient is required for LINE sends");
68
- }
69
-
70
- return normalized;
71
- }
72
-
73
- function isLineUserChatId(chatId: string): boolean {
74
- return /^U/i.test(chatId);
75
- }
76
-
77
- function createLineMessagingClient(opts: LineClientOpts): {
78
- account: ReturnType<typeof resolveLineAccount>;
79
- client: messagingApi.MessagingApiClient;
80
- } {
81
- const cfg = requireRuntimeConfig(opts.cfg, "LINE send");
82
- const account = resolveLineAccount({
83
- cfg,
84
- accountId: opts.accountId,
85
- });
86
- const token = resolveLineChannelAccessToken(opts.channelAccessToken, account);
87
- const client = new messagingApi.MessagingApiClient({
88
- channelAccessToken: token,
89
- });
90
- return { account, client };
91
- }
92
-
93
- function createLinePushContext(
94
- to: string,
95
- opts: LineClientOpts,
96
- ): {
97
- account: ReturnType<typeof resolveLineAccount>;
98
- client: messagingApi.MessagingApiClient;
99
- chatId: string;
100
- } {
101
- const { account, client } = createLineMessagingClient(opts);
102
- const chatId = normalizeTarget(to);
103
- return { account, client, chatId };
104
- }
105
-
106
- function createTextMessage(text: string): TextMessage {
107
- return { type: "text", text };
108
- }
109
-
110
- export function createImageMessage(
111
- originalContentUrl: string,
112
- previewImageUrl?: string,
113
- ): ImageMessage {
114
- return {
115
- type: "image",
116
- originalContentUrl,
117
- previewImageUrl: previewImageUrl ?? originalContentUrl,
118
- };
119
- }
120
-
121
- export function createVideoMessage(
122
- originalContentUrl: string,
123
- previewImageUrl: string,
124
- trackingId?: string,
125
- ): VideoMessage {
126
- return {
127
- type: "video",
128
- originalContentUrl,
129
- previewImageUrl,
130
- ...(trackingId ? { trackingId } : {}),
131
- };
132
- }
133
-
134
- export function createAudioMessage(originalContentUrl: string, durationMs: number): AudioMessage {
135
- return {
136
- type: "audio",
137
- originalContentUrl,
138
- duration: durationMs,
139
- };
140
- }
141
-
142
- export function createLocationMessage(location: {
143
- title: string;
144
- address: string;
145
- latitude: number;
146
- longitude: number;
147
- }): LocationMessage {
148
- return {
149
- type: "location",
150
- title: location.title.slice(0, 100),
151
- address: location.address.slice(0, 100),
152
- latitude: location.latitude,
153
- longitude: location.longitude,
154
- };
155
- }
156
-
157
- function logLineHttpError(err: unknown, context: string): void {
158
- if (!err || typeof err !== "object") {
159
- return;
160
- }
161
- const { status, statusText, body } = err as {
162
- status?: number;
163
- statusText?: string;
164
- body?: string;
165
- };
166
- if (typeof body === "string") {
167
- const summary = status ? `${status} ${statusText ?? ""}`.trim() : "unknown status";
168
- logVerbose(`line: ${context} failed (${summary}): ${body}`);
169
- }
170
- }
171
-
172
- function recordLineOutboundActivity(accountId: string): void {
173
- recordChannelActivity({
174
- channel: "line",
175
- accountId,
176
- direction: "outbound",
177
- });
178
- }
179
-
180
- async function pushLineMessages(
181
- to: string,
182
- messages: Message[],
183
- opts: LinePushOpts,
184
- behavior: LinePushBehavior = {},
185
- ): Promise<LineSendResult> {
186
- if (messages.length === 0) {
187
- throw new Error("Message must be non-empty for LINE sends");
188
- }
189
-
190
- const { account, client, chatId } = createLinePushContext(to, opts);
191
- const pushRequest = client.pushMessage({
192
- to: chatId,
193
- messages,
194
- });
195
-
196
- if (behavior.errorContext) {
197
- await pushRequest.catch((err) => {
198
- logLineHttpError(err, behavior.errorContext!);
199
- throw err;
200
- });
201
- } else {
202
- await pushRequest;
203
- }
204
-
205
- recordLineOutboundActivity(account.accountId);
206
-
207
- if (opts.verbose) {
208
- const logMessage =
209
- behavior.verboseMessage?.(chatId, messages.length) ??
210
- `line: pushed ${messages.length} messages to ${chatId}`;
211
- logVerbose(logMessage);
212
- }
213
-
214
- return {
215
- messageId: "push",
216
- chatId,
217
- };
218
- }
219
-
220
- async function replyLineMessages(
221
- replyToken: string,
222
- messages: Message[],
223
- opts: LinePushOpts,
224
- behavior: LineReplyBehavior = {},
225
- ): Promise<void> {
226
- const { account, client } = createLineMessagingClient(opts);
227
-
228
- await client.replyMessage({
229
- replyToken,
230
- messages,
231
- });
232
-
233
- recordLineOutboundActivity(account.accountId);
234
-
235
- if (opts.verbose) {
236
- logVerbose(
237
- behavior.verboseMessage?.(messages.length) ??
238
- `line: replied with ${messages.length} messages`,
239
- );
240
- }
241
- }
242
-
243
- export async function sendMessageLine(
244
- to: string,
245
- text: string,
246
- opts: LineSendOpts,
247
- ): Promise<LineSendResult> {
248
- const chatId = normalizeTarget(to);
249
- const messages: Message[] = [];
250
-
251
- const mediaUrl = opts.mediaUrl?.trim();
252
- if (mediaUrl) {
253
- await validateLineMediaUrl(mediaUrl);
254
- switch (opts.mediaKind) {
255
- case "video": {
256
- const previewImageUrl = opts.previewImageUrl?.trim();
257
- if (!previewImageUrl) {
258
- throw new Error("LINE video messages require previewImageUrl to reference an image URL");
259
- }
260
- await validateLineMediaUrl(previewImageUrl);
261
- const trackingId = isLineUserChatId(chatId) ? opts.trackingId : undefined;
262
- messages.push(createVideoMessage(mediaUrl, previewImageUrl, trackingId));
263
- break;
264
- }
265
- case "audio":
266
- messages.push(createAudioMessage(mediaUrl, opts.durationMs ?? 60000));
267
- break;
268
- case "image":
269
- default:
270
- // Backward compatibility: keep image as default when media kind is unspecified.
271
- {
272
- const previewImageUrl = opts.previewImageUrl?.trim() || mediaUrl;
273
- await validateLineMediaUrl(previewImageUrl);
274
- messages.push(createImageMessage(mediaUrl, previewImageUrl));
275
- }
276
- break;
277
- }
278
- }
279
-
280
- if (text?.trim()) {
281
- messages.push(createTextMessage(text.trim()));
282
- }
283
-
284
- if (messages.length === 0) {
285
- throw new Error("Message must be non-empty for LINE sends");
286
- }
287
-
288
- if (opts.replyToken) {
289
- await replyLineMessages(opts.replyToken, messages, opts, {
290
- verboseMessage: () => `line: replied to ${chatId}`,
291
- });
292
-
293
- return {
294
- messageId: "reply",
295
- chatId,
296
- };
297
- }
298
-
299
- return pushLineMessages(chatId, messages, opts, {
300
- verboseMessage: (resolvedChatId) => `line: pushed message to ${resolvedChatId}`,
301
- });
302
- }
303
-
304
- export async function pushMessageLine(
305
- to: string,
306
- text: string,
307
- opts: LineSendOpts,
308
- ): Promise<LineSendResult> {
309
- return sendMessageLine(to, text, { ...opts, replyToken: undefined });
310
- }
311
-
312
- export async function replyMessageLine(
313
- replyToken: string,
314
- messages: Message[],
315
- opts: LinePushOpts,
316
- ): Promise<void> {
317
- await replyLineMessages(replyToken, messages, opts);
318
- }
319
-
320
- export async function pushMessagesLine(
321
- to: string,
322
- messages: Message[],
323
- opts: LinePushOpts,
324
- ): Promise<LineSendResult> {
325
- return pushLineMessages(to, messages, opts, {
326
- errorContext: "push message",
327
- });
328
- }
329
-
330
- export function createFlexMessage(
331
- altText: string,
332
- contents: messagingApi.FlexContainer,
333
- ): messagingApi.FlexMessage {
334
- return {
335
- type: "flex",
336
- altText,
337
- contents,
338
- };
339
- }
340
-
341
- export async function pushImageMessage(
342
- to: string,
343
- originalContentUrl: string,
344
- previewImageUrl: string | undefined,
345
- opts: LinePushOpts,
346
- ): Promise<LineSendResult> {
347
- await validateLineMediaUrl(originalContentUrl);
348
- if (previewImageUrl) {
349
- await validateLineMediaUrl(previewImageUrl);
350
- }
351
- return pushLineMessages(to, [createImageMessage(originalContentUrl, previewImageUrl)], opts, {
352
- verboseMessage: (chatId) => `line: pushed image to ${chatId}`,
353
- });
354
- }
355
-
356
- export async function pushLocationMessage(
357
- to: string,
358
- location: {
359
- title: string;
360
- address: string;
361
- latitude: number;
362
- longitude: number;
363
- },
364
- opts: LinePushOpts,
365
- ): Promise<LineSendResult> {
366
- return pushLineMessages(to, [createLocationMessage(location)], opts, {
367
- verboseMessage: (chatId) => `line: pushed location to ${chatId}`,
368
- });
369
- }
370
-
371
- export async function pushFlexMessage(
372
- to: string,
373
- altText: string,
374
- contents: FlexContainer,
375
- opts: LinePushOpts,
376
- ): Promise<LineSendResult> {
377
- const flexMessage: FlexMessage = {
378
- type: "flex",
379
- altText: altText.slice(0, 400),
380
- contents,
381
- };
382
-
383
- return pushLineMessages(to, [flexMessage], opts, {
384
- errorContext: "push flex message",
385
- verboseMessage: (chatId) => `line: pushed flex message to ${chatId}`,
386
- });
387
- }
388
-
389
- export async function pushTemplateMessage(
390
- to: string,
391
- template: TemplateMessage,
392
- opts: LinePushOpts,
393
- ): Promise<LineSendResult> {
394
- return pushLineMessages(to, [template], opts, {
395
- verboseMessage: (chatId) => `line: pushed template message to ${chatId}`,
396
- });
397
- }
398
-
399
- export async function pushTextMessageWithQuickReplies(
400
- to: string,
401
- text: string,
402
- quickReplyLabels: string[],
403
- opts: LinePushOpts,
404
- ): Promise<LineSendResult> {
405
- const message = createTextMessageWithQuickReplies(text, quickReplyLabels);
406
-
407
- return pushLineMessages(to, [message], opts, {
408
- verboseMessage: (chatId) => `line: pushed message with quick replies to ${chatId}`,
409
- });
410
- }
411
-
412
- export function createQuickReplyItems(labels: string[]): QuickReply {
413
- const items: QuickReplyItem[] = labels.slice(0, 13).map((label) => ({
414
- type: "action",
415
- action: {
416
- type: "message",
417
- label: label.slice(0, 20),
418
- text: label,
419
- },
420
- }));
421
- return { items };
422
- }
423
-
424
- export function createTextMessageWithQuickReplies(
425
- text: string,
426
- quickReplyLabels: string[],
427
- ): TextMessage & { quickReply: QuickReply } {
428
- return {
429
- type: "text",
430
- text,
431
- quickReply: createQuickReplyItems(quickReplyLabels),
432
- };
433
- }
434
-
435
- export async function showLoadingAnimation(
436
- chatId: string,
437
- opts: LineClientOpts & { loadingSeconds?: number },
438
- ): Promise<void> {
439
- const { client } = createLineMessagingClient(opts);
440
-
441
- try {
442
- await client.showLoadingAnimation({
443
- chatId: normalizeTarget(chatId),
444
- loadingSeconds: opts.loadingSeconds ?? 20,
445
- });
446
- logVerbose(`line: showing loading animation to ${chatId}`);
447
- } catch (err) {
448
- logVerbose(`line: loading animation failed (non-fatal): ${String(err)}`);
449
- }
450
- }
451
-
452
- export async function getUserProfile(
453
- userId: string,
454
- opts: LineClientOpts & { useCache?: boolean },
455
- ): Promise<{ displayName: string; pictureUrl?: string } | null> {
456
- const useCache = opts.useCache ?? true;
457
-
458
- if (useCache) {
459
- const cached = userProfileCache.get(userId);
460
- if (cached && Date.now() - cached.fetchedAt < PROFILE_CACHE_TTL_MS) {
461
- return { displayName: cached.displayName, pictureUrl: cached.pictureUrl };
462
- }
463
- }
464
-
465
- const { client } = createLineMessagingClient(opts);
466
-
467
- try {
468
- const profile = await client.getProfile(userId);
469
- const result = {
470
- displayName: profile.displayName,
471
- pictureUrl: profile.pictureUrl,
472
- };
473
-
474
- userProfileCache.set(userId, {
475
- ...result,
476
- fetchedAt: Date.now(),
477
- });
478
-
479
- return result;
480
- } catch (err) {
481
- logVerbose(`line: failed to fetch profile for ${userId}: ${String(err)}`);
482
- return null;
483
- }
484
- }
485
-
486
- export async function getUserDisplayName(userId: string, opts: LineClientOpts): Promise<string> {
487
- const profile = await getUserProfile(userId, opts);
488
- return profile?.displayName ?? userId;
489
- }
package/src/setup-core.ts DELETED
@@ -1,149 +0,0 @@
1
- import type { ChannelSetupAdapter, OpenClawConfig } from "openclaw/plugin-sdk/setup";
2
- import { createSetupInputPresenceValidator } from "openclaw/plugin-sdk/setup";
3
- import { hasLineCredentials, parseLineAllowFromId } from "./account-helpers.js";
4
- import {
5
- DEFAULT_ACCOUNT_ID,
6
- listLineAccountIds,
7
- normalizeAccountId,
8
- resolveLineAccount,
9
- type LineConfig,
10
- } from "./setup-runtime-api.js";
11
-
12
- export function patchLineAccountConfig(params: {
13
- cfg: OpenClawConfig;
14
- accountId: string;
15
- patch: Record<string, unknown>;
16
- clearFields?: string[];
17
- enabled?: boolean;
18
- }): OpenClawConfig {
19
- const accountId = normalizeAccountId(params.accountId);
20
- const lineConfig = (params.cfg.channels?.line ?? {}) as LineConfig;
21
- const clearFields = params.clearFields ?? [];
22
-
23
- if (accountId === DEFAULT_ACCOUNT_ID) {
24
- const nextLine = { ...lineConfig } as Record<string, unknown>;
25
- for (const field of clearFields) {
26
- delete nextLine[field];
27
- }
28
- return {
29
- ...params.cfg,
30
- channels: {
31
- ...params.cfg.channels,
32
- line: {
33
- ...nextLine,
34
- ...(params.enabled ? { enabled: true } : {}),
35
- ...params.patch,
36
- },
37
- },
38
- };
39
- }
40
-
41
- const nextAccount = {
42
- ...lineConfig.accounts?.[accountId],
43
- } as Record<string, unknown>;
44
- for (const field of clearFields) {
45
- delete nextAccount[field];
46
- }
47
-
48
- return {
49
- ...params.cfg,
50
- channels: {
51
- ...params.cfg.channels,
52
- line: {
53
- ...lineConfig,
54
- ...(params.enabled ? { enabled: true } : {}),
55
- accounts: {
56
- ...lineConfig.accounts,
57
- [accountId]: {
58
- ...nextAccount,
59
- ...(params.enabled ? { enabled: true } : {}),
60
- ...params.patch,
61
- },
62
- },
63
- },
64
- },
65
- };
66
- }
67
-
68
- export function isLineConfigured(cfg: OpenClawConfig, accountId: string): boolean {
69
- return hasLineCredentials(resolveLineAccount({ cfg, accountId }));
70
- }
71
-
72
- export { parseLineAllowFromId };
73
-
74
- export const lineSetupAdapter: ChannelSetupAdapter = {
75
- resolveAccountId: ({ accountId }) => normalizeAccountId(accountId),
76
- applyAccountName: ({ cfg, accountId, name }) =>
77
- patchLineAccountConfig({
78
- cfg,
79
- accountId,
80
- patch: name?.trim() ? { name: name.trim() } : {},
81
- }),
82
- validateInput: createSetupInputPresenceValidator({
83
- defaultAccountOnlyEnvError:
84
- "LINE_CHANNEL_ACCESS_TOKEN can only be used for the default account.",
85
- whenNotUseEnv: [
86
- {
87
- someOf: ["channelAccessToken", "tokenFile"],
88
- message: "LINE requires channelAccessToken or --token-file (or --use-env).",
89
- },
90
- {
91
- someOf: ["channelSecret", "secretFile"],
92
- message: "LINE requires channelSecret or --secret-file (or --use-env).",
93
- },
94
- ],
95
- }),
96
- applyAccountConfig: ({ cfg, accountId, input }) => {
97
- const typedInput = input as {
98
- useEnv?: boolean;
99
- channelAccessToken?: string;
100
- channelSecret?: string;
101
- tokenFile?: string;
102
- secretFile?: string;
103
- };
104
- const normalizedAccountId = normalizeAccountId(accountId);
105
- if (normalizedAccountId === DEFAULT_ACCOUNT_ID) {
106
- return patchLineAccountConfig({
107
- cfg,
108
- accountId: normalizedAccountId,
109
- enabled: true,
110
- clearFields: typedInput.useEnv
111
- ? ["channelAccessToken", "channelSecret", "tokenFile", "secretFile"]
112
- : undefined,
113
- patch: typedInput.useEnv
114
- ? {}
115
- : {
116
- ...(typedInput.tokenFile
117
- ? { tokenFile: typedInput.tokenFile }
118
- : typedInput.channelAccessToken
119
- ? { channelAccessToken: typedInput.channelAccessToken }
120
- : {}),
121
- ...(typedInput.secretFile
122
- ? { secretFile: typedInput.secretFile }
123
- : typedInput.channelSecret
124
- ? { channelSecret: typedInput.channelSecret }
125
- : {}),
126
- },
127
- });
128
- }
129
- return patchLineAccountConfig({
130
- cfg,
131
- accountId: normalizedAccountId,
132
- enabled: true,
133
- patch: {
134
- ...(typedInput.tokenFile
135
- ? { tokenFile: typedInput.tokenFile }
136
- : typedInput.channelAccessToken
137
- ? { channelAccessToken: typedInput.channelAccessToken }
138
- : {}),
139
- ...(typedInput.secretFile
140
- ? { secretFile: typedInput.secretFile }
141
- : typedInput.channelSecret
142
- ? { channelSecret: typedInput.channelSecret }
143
- : {}),
144
- },
145
- });
146
- },
147
- };
148
-
149
- export { listLineAccountIds };
@@ -1,9 +0,0 @@
1
- export {
2
- DEFAULT_ACCOUNT_ID,
3
- formatDocsLink,
4
- setSetupChannelEnabled,
5
- splitSetupEntries,
6
- } from "openclaw/plugin-sdk/setup";
7
- export type { ChannelSetupDmPolicy, ChannelSetupWizard } from "openclaw/plugin-sdk/setup";
8
- export { listLineAccountIds, normalizeAccountId, resolveLineAccount } from "./accounts.js";
9
- export type { LineConfig } from "./types.js";