@openclaw/line 2026.7.2-beta.1 → 2026.7.2-beta.3

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.
@@ -0,0 +1,2 @@
1
+ import { t as monitorLineProvider } from "./monitor-Bk-lpoOZ.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-CixmAKiG.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-D1vapcdP.js";
2
2
  export { buildTemplateMessageFromPayload, createQuickReplyItems, processLineMessage, pushFlexMessage, pushLocationMessage, pushMessageLine, pushMessagesLine, pushTemplateMessage, pushTextMessageWithQuickReplies, sendMessageLine };
@@ -2,7 +2,7 @@ import { i as createMediaPlayerCard, l as createAgendaCard, n as createAppleTvRe
2
2
  import { normalizeAccountId } from "openclaw/plugin-sdk/account-id";
3
3
  import { resolveAccountEntry } from "openclaw/plugin-sdk/account-resolution";
4
4
  import { normalizeLowercaseStringOrEmpty, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
5
- import { buildChannelConfigSchema, requireOpenAllowFrom } from "openclaw/plugin-sdk/channel-config-schema";
5
+ import { DmPolicySchema, GroupPolicySchema, buildChannelConfigSchema, buildGroupEntrySchema, buildMultiAccountChannelSchema, requireOpenAllowFrom } from "openclaw/plugin-sdk/channel-config-schema";
6
6
  import { requireChannelOpenAllowFrom } from "openclaw/plugin-sdk/extension-shared";
7
7
  import { z } from "zod";
8
8
  import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";
@@ -49,17 +49,6 @@ function resolveExactLineGroupConfigKey(params) {
49
49
  }
50
50
  //#endregion
51
51
  //#region extensions/line/src/config-schema.ts
52
- const DmPolicySchema = z.enum([
53
- "open",
54
- "allowlist",
55
- "pairing",
56
- "disabled"
57
- ]);
58
- const GroupPolicySchema = z.enum([
59
- "open",
60
- "allowlist",
61
- "disabled"
62
- ]);
63
52
  const ThreadBindingsSchema = z.object({
64
53
  enabled: z.boolean().optional(),
65
54
  idleHours: z.number().optional(),
@@ -85,34 +74,21 @@ const LineCommonConfigSchemaBase = z.object({
85
74
  webhookPath: z.string().optional(),
86
75
  threadBindings: ThreadBindingsSchema.optional()
87
76
  });
88
- const LineGroupConfigSchema = z.object({
89
- enabled: z.boolean().optional(),
90
- allowFrom: z.array(z.union([z.string(), z.number()])).optional(),
91
- requireMention: z.boolean().optional(),
92
- systemPrompt: z.string().optional(),
93
- skills: z.array(z.string()).optional()
94
- }).strict();
95
- const LineAccountConfigSchema = LineCommonConfigSchemaBase.extend({ groups: z.record(z.string(), LineGroupConfigSchema.optional()).optional() }).strict().superRefine((value, ctx) => {
96
- requireChannelOpenAllowFrom({
97
- channel: "line",
98
- policy: value.dmPolicy,
99
- allowFrom: value.allowFrom,
100
- ctx,
101
- requireOpenAllowFrom
102
- });
77
+ const LineGroupConfigSchema = buildGroupEntrySchema().omit({
78
+ tools: true,
79
+ toolsBySender: true
103
80
  });
104
- const LineConfigSchema = LineCommonConfigSchemaBase.extend({
105
- accounts: z.record(z.string(), LineAccountConfigSchema.optional()).optional(),
106
- defaultAccount: z.string().optional(),
107
- groups: z.record(z.string(), LineGroupConfigSchema.optional()).optional()
108
- }).strict().superRefine((value, ctx) => {
109
- requireChannelOpenAllowFrom({
110
- channel: "line",
111
- policy: value.dmPolicy,
112
- allowFrom: value.allowFrom,
113
- ctx,
114
- requireOpenAllowFrom
115
- });
81
+ const LineConfigSchema = buildMultiAccountChannelSchema(LineCommonConfigSchemaBase.extend({ groups: z.record(z.string(), LineGroupConfigSchema.optional()).optional() }).strict(), {
82
+ optionalAccount: true,
83
+ refine: (value, ctx) => {
84
+ requireChannelOpenAllowFrom({
85
+ channel: "line",
86
+ policy: value.dmPolicy,
87
+ allowFrom: value.allowFrom,
88
+ ctx,
89
+ requireOpenAllowFrom
90
+ });
91
+ }
116
92
  });
117
93
  const LineChannelConfigSchema = buildChannelConfigSchema(LineConfigSchema);
118
94
  //#endregion
@@ -129,9 +105,9 @@ async function validateLineMediaUrl(url) {
129
105
  try {
130
106
  parsed = new URL(url);
131
107
  } catch {
132
- throw new Error(`LINE outbound media URL must be a valid URL: ${url}`);
108
+ throw new Error("LINE outbound media URL must be a valid URL");
133
109
  }
134
- if (parsed.protocol !== "https:") throw new Error(`LINE outbound media URL must use HTTPS: ${url}`);
110
+ if (parsed.protocol !== "https:") throw new Error("LINE outbound media URL must use HTTPS");
135
111
  if (url.length > 2e3) throw new Error(`LINE outbound media URL must be 2000 chars or less (got ${url.length})`);
136
112
  await resolvePinnedHostnameWithPolicy(parsed.hostname, { policy: LINE_OUTBOUND_MEDIA_SSRF_POLICY });
137
113
  }
@@ -166,13 +142,47 @@ async function resolveLineOutboundMedia(mediaUrl, opts = {}) {
166
142
  ...opts.trackingId ? { trackingId: opts.trackingId } : {}
167
143
  };
168
144
  }
145
+ let parsed;
169
146
  try {
170
- if (new URL(trimmedUrl).protocol !== "https:") throw new Error(`LINE outbound media URL must use HTTPS: ${trimmedUrl}`);
171
- } catch (e) {
172
- if (e instanceof Error && e.message.startsWith("LINE outbound")) throw e;
173
- }
147
+ parsed = new URL(trimmedUrl);
148
+ } catch {}
149
+ if (parsed) throw new Error("LINE outbound media URL must use HTTPS");
174
150
  throw new Error("LINE outbound media currently requires a public HTTPS URL");
175
151
  }
152
+ function isLineUserTarget(target) {
153
+ const normalized = target.trim().replace(/^line:(group|room|user):/i, "").replace(/^line:/i, "");
154
+ return /^U/i.test(normalized);
155
+ }
156
+ function hasLineSpecificMediaOptions(lineData) {
157
+ return lineData.mediaKind !== void 0 || Boolean(lineData.previewImageUrl?.trim()) || typeof lineData.durationMs === "number" || Boolean(lineData.trackingId?.trim());
158
+ }
159
+ function buildLineMediaMessageObject(resolved, opts) {
160
+ switch (resolved.mediaKind) {
161
+ case "video": {
162
+ const previewImageUrl = resolved.previewImageUrl?.trim();
163
+ if (!previewImageUrl) throw new Error("LINE video messages require previewImageUrl to reference an image URL");
164
+ return {
165
+ type: "video",
166
+ originalContentUrl: resolved.mediaUrl,
167
+ previewImageUrl,
168
+ ...opts?.allowTrackingId && resolved.trackingId ? { trackingId: resolved.trackingId } : {}
169
+ };
170
+ }
171
+ case "audio": return {
172
+ type: "audio",
173
+ originalContentUrl: resolved.mediaUrl,
174
+ duration: resolved.durationMs ?? 6e4
175
+ };
176
+ default: return {
177
+ type: "image",
178
+ originalContentUrl: resolved.mediaUrl,
179
+ previewImageUrl: resolved.previewImageUrl ?? resolved.mediaUrl
180
+ };
181
+ }
182
+ }
183
+ async function buildLineMediaMessage(mediaUrl, opts, target) {
184
+ return buildLineMediaMessageObject(await resolveLineOutboundMedia(mediaUrl, opts), { allowTrackingId: isLineUserTarget(target) });
185
+ }
176
186
  //#endregion
177
187
  //#region extensions/line/src/quick-reply-fallback.ts
178
188
  function buildLineQuickReplyFallbackText(labels) {
@@ -420,7 +430,7 @@ function parseLineDirectives(payload) {
420
430
  const parts = expectDefined(agendaMatch[1], "agenda directive body").split("|").map((s) => s.trim());
421
431
  if (parts.length >= 2) {
422
432
  const title = expectDefined(parts[0], "agenda title field");
423
- const events = expectDefined(parts[1], "agenda events field").split(",").map((eventStr) => {
433
+ const events = normalizeStringEntries(expectDefined(parts[1], "agenda events field").split(",")).map((eventStr) => {
424
434
  const trimmed = eventStr.trim();
425
435
  const colonIdx = trimmed.lastIndexOf(":");
426
436
  if (colonIdx > 0) return {
@@ -447,14 +457,15 @@ function parseLineDirectives(payload) {
447
457
  const deviceName = expectDefined(parts[0], "device name field");
448
458
  const [, deviceType, status, controlsStr] = parts;
449
459
  const deviceKey = toSlug(deviceName || "device");
450
- const controls = controlsStr ? controlsStr.split(",").map((ctrlStr) => {
460
+ const controls = controlsStr ? normalizeStringEntries(controlsStr.split(",")).flatMap((ctrlStr) => {
451
461
  const controlParts = ctrlStr.split(":").map((s) => s.trim());
452
462
  const label = expectDefined(controlParts[0], "device control label");
463
+ if (!label) return [];
453
464
  const action = controlParts[1] || normalizeLowercaseStringOrEmpty(label).replace(/\s+/g, "_");
454
- return {
465
+ return [{
455
466
  label,
456
467
  data: lineActionData(action, { "line.device": deviceKey })
457
- };
468
+ }];
458
469
  }) : [];
459
470
  const card = createDeviceControlCard({
460
471
  deviceName: deviceName || "Device",
@@ -481,4 +492,4 @@ function hasLineDirectives(text) {
481
492
  return /\[\[(quick_replies|location|confirm|buttons|media_player|event|agenda|device|appletv_remote):/i.test(text);
482
493
  }
483
494
  //#endregion
484
- export { resolveLineOutboundMedia as a, setLineRuntime as c, resolveExactLineGroupConfigKey as d, resolveLineGroupConfigEntry as f, buildLineQuickReplyFallbackText as i, LineChannelConfigSchema as l, resolveLineGroupsConfig as m, parseLineDirectives as n, validateLineMediaUrl as o, resolveLineGroupLookupIds as p, createLineSendReceipt as r, getLineRuntime as s, hasLineDirectives as t, LineConfigSchema as u };
495
+ export { buildLineMediaMessage as a, validateLineMediaUrl as c, LineChannelConfigSchema as d, LineConfigSchema as f, resolveLineGroupsConfig as g, resolveLineGroupLookupIds as h, buildLineQuickReplyFallbackText as i, getLineRuntime as l, resolveLineGroupConfigEntry as m, parseLineDirectives as n, hasLineSpecificMediaOptions as o, resolveExactLineGroupConfigKey as p, createLineSendReceipt as r, resolveLineOutboundMedia as s, hasLineDirectives as t, setLineRuntime as u };
@@ -1,16 +1,15 @@
1
- import { i as resolveLineAccount, n as normalizeAccountId, r as resolveDefaultLineAccountId, t as listLineAccountIds } from "./accounts-DJVOv1JI.js";
2
- import { c as setLineRuntime, d as resolveExactLineGroupConfigKey, f as resolveLineGroupConfigEntry, l as LineChannelConfigSchema, m as resolveLineGroupsConfig, n as parseLineDirectives, p as resolveLineGroupLookupIds, t as hasLineDirectives, u as LineConfigSchema } from "./reply-payload-transform-BsbwCJGH.js";
1
+ import { i as resolveLineAccount, n as normalizeAccountId, r as resolveDefaultLineAccountId, t as listLineAccountIds } from "./accounts-BUBOoW5Q.js";
2
+ import { d as LineChannelConfigSchema, f as LineConfigSchema, g as resolveLineGroupsConfig, h as resolveLineGroupLookupIds, m as resolveLineGroupConfigEntry, n as parseLineDirectives, p as resolveExactLineGroupConfigKey, t as hasLineDirectives, u as setLineRuntime } from "./reply-payload-transform-r9sa-TYT.js";
3
3
  import { _ as createNotificationBubble, a as datetimePickerAction, c as uriAction, d as createReceiptCard, f as createActionCard, g as createListCard, h as createInfoCard, i as createMediaPlayerCard, l as createAgendaCard, m as createImageCard, n as createAppleTvRemoteCard, o as messageAction, p as createCarousel, r as createDeviceControlCard, s as postbackAction, t as toFlexMessage, u as createEventCard } from "./flex-templates-K1lS9i8L.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-q3UE2J1g.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-Bk-lpoOZ.js";
5
5
  import { t as probeLineBot } from "./probe-BslD77tJ.js";
6
- import { A as buildTemplateMessageFromPayload, B as createYesNoConfirm, C as pushMessagesLine, D as sendMessageLine, E as replyMessageLine, F as createImageCarousel, I as createImageCarouselColumn, L as createLinkMenu, M as createButtonTemplate, N as createCarouselColumn, O as showLoadingAnimation, P as createConfirmTemplate, R as createProductCarousel, S as pushMessageLine, T as pushTextMessageWithQuickReplies, _ as getUserDisplayName, a as extractLinks, b as pushImageMessage, c as processLineMessage, d as createFlexMessage, f as createImageMessage, g as createVideoMessage, h as createTextMessageWithQuickReplies, i as extractCodeBlocks, j as createButtonMenu, k as resolveLineChannelAccessToken, l as stripMarkdown, m as createQuickReplyItems, n as convertLinksToFlexBubble, o as extractMarkdownTables, p as createLocationMessage, r as convertTableToFlexBubble, s as hasMarkdownToConvert, t as convertCodeBlockToFlexBubble, u as createAudioMessage, v as getUserProfile, w as pushTemplateMessage, x as pushLocationMessage, y as pushFlexMessage, z as createTemplateCarousel } from "./markdown-to-line-CixmAKiG.js";
6
+ import { A as buildTemplateMessageFromPayload, B as createYesNoConfirm, C as pushMessagesLine, D as sendMessageLine, E as replyMessageLine, F as createImageCarousel, I as createImageCarouselColumn, L as createLinkMenu, M as createButtonTemplate, N as createCarouselColumn, O as showLoadingAnimation, P as createConfirmTemplate, R as createProductCarousel, S as pushMessageLine, T as pushTextMessageWithQuickReplies, _ as getUserDisplayName, a as extractLinks, b as pushImageMessage, c as processLineMessage, d as createFlexMessage, f as createImageMessage, g as createVideoMessage, h as createTextMessageWithQuickReplies, i as extractCodeBlocks, j as createButtonMenu, k as resolveLineChannelAccessToken, l as stripMarkdown, m as createQuickReplyItems, n as convertLinksToFlexBubble, o as extractMarkdownTables, p as createLocationMessage, r as convertTableToFlexBubble, s as hasMarkdownToConvert, t as convertCodeBlockToFlexBubble, u as createAudioMessage, v as getUserProfile, w as pushTemplateMessage, x as pushLocationMessage, y as pushFlexMessage, z as createTemplateCarousel } from "./markdown-to-line-D1vapcdP.js";
7
7
  import { clearAccountEntryFields } from "openclaw/plugin-sdk/core";
8
8
  import { buildChannelConfigSchema } from "openclaw/plugin-sdk/channel-config-schema";
9
- import { createMessageReceiveContext } from "openclaw/plugin-sdk/channel-outbound";
10
9
  import { DEFAULT_ACCOUNT_ID, formatDocsLink, setSetupChannelEnabled, splitSetupEntries } from "openclaw/plugin-sdk/setup";
11
10
  import { buildComputedAccountStatusSnapshot, buildTokenChannelStatusSummary } from "openclaw/plugin-sdk/status-helpers";
12
- import { messagingApi } from "@line/bot-sdk";
13
11
  import { danger, logVerbose } from "openclaw/plugin-sdk/runtime-env";
12
+ import { messagingApi } from "@line/bot-sdk";
14
13
  import { getAgentScopedMediaLocalRoots } from "openclaw/plugin-sdk/agent-media-payload";
15
14
  import { mimeTypeFromFilePath } from "openclaw/plugin-sdk/media-mime";
16
15
  import { loadWebMediaRaw } from "openclaw/plugin-sdk/web-media";
@@ -25,13 +24,9 @@ function parseWebhookBody(rawBody) {
25
24
  if (!rawBody) return null;
26
25
  return parseLineWebhookBody(rawBody);
27
26
  }
28
- function logLineWebhookDispatchError(runtime, err) {
29
- runtime?.error?.(danger(`line webhook dispatch failed: ${String(err)}`));
30
- }
31
27
  function createLineWebhookMiddleware(options) {
32
28
  const { channelSecret, onEvents, runtime } = options;
33
29
  return async (req, res, _next) => {
34
- let receiveContext;
35
30
  try {
36
31
  const signature = req.headers["x-line-signature"];
37
32
  if (!signature || typeof signature !== "string") {
@@ -57,22 +52,12 @@ function createLineWebhookMiddleware(options) {
57
52
  res.status(400).json({ error: "Invalid webhook payload" });
58
53
  return;
59
54
  }
60
- receiveContext = createMessageReceiveContext({
61
- id: `${Date.now()}:line:webhook`,
62
- channel: "line",
63
- message: body,
64
- ackPolicy: "after_receive_record",
65
- onAck: () => {
66
- res.status(200).json({ status: "ok" });
67
- }
68
- });
69
- if (receiveContext.shouldAckAfter("receive_record")) await receiveContext.ack();
70
55
  if (body.events && body.events.length > 0) {
71
56
  logVerbose(`line: received ${body.events.length} webhook events`);
72
- Promise.resolve().then(() => onEvents(body)).catch((err) => logLineWebhookDispatchError(runtime, err));
57
+ await onEvents(body);
73
58
  }
59
+ res.status(200).json({ status: "ok" });
74
60
  } catch (err) {
75
- await receiveContext?.nack(err);
76
61
  runtime?.error?.(danger(`line webhook error: ${String(err)}`));
77
62
  if (!res.headersSent) res.status(500).json({ error: "Internal server error" });
78
63
  }
package/dist/setup-api.js CHANGED
@@ -1,2 +1,2 @@
1
- import { n as lineSetupAdapter, t as lineSetupWizard } from "./setup-surface-Bc36YSS3.js";
1
+ import { n as lineSetupAdapter, t as lineSetupWizard } from "./setup-surface-BEt4mazl.js";
2
2
  export { lineSetupAdapter, lineSetupWizard };
@@ -1,8 +1,9 @@
1
- import { i as resolveLineAccount, n as normalizeAccountId, r as resolveDefaultLineAccountId, t as listLineAccountIds } from "./accounts-DJVOv1JI.js";
1
+ import { i as resolveLineAccount, n as normalizeAccountId, r as resolveDefaultLineAccountId, t as listLineAccountIds } from "./accounts-BUBOoW5Q.js";
2
2
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
3
- import { DEFAULT_ACCOUNT_ID, createAllowFromSection, createSetupInputPresenceValidator, createSetupTranslator, createStandardChannelSetupStatus, formatDocsLink, mergeAllowFromEntries, setSetupChannelEnabled, splitSetupEntries } from "openclaw/plugin-sdk/setup";
3
+ import { DEFAULT_ACCOUNT_ID, createAllowFromSection, createSetupInputPresenceValidator, createSetupTranslator, createStandardChannelSetupStatus, defineTokenCredential, formatDocsLink, mergeAllowFromEntries, setSetupChannelEnabled, splitSetupEntries } from "openclaw/plugin-sdk/setup";
4
4
  //#region extensions/line/src/account-helpers.ts
5
5
  function hasLineCredentials(account) {
6
+ if (account.tokenStatus && account.signingSecretStatus) return account.tokenStatus !== "missing" && account.signingSecretStatus !== "missing";
6
7
  return Boolean(account.channelAccessToken?.trim() && account.channelSecret?.trim());
7
8
  }
8
9
  function parseLineAllowFromId(raw) {
@@ -173,8 +174,10 @@ const lineSetupWizard = {
173
174
  lines: LINE_SETUP_HELP_LINES,
174
175
  shouldShow: ({ cfg, accountId }) => !isLineConfigured(cfg, accountId ?? resolveDefaultLineAccountId(cfg))
175
176
  },
176
- credentials: [{
177
+ credentials: [defineTokenCredential({
177
178
  inputKey: "token",
179
+ configKey: "channelAccessToken",
180
+ configuredFields: ["channelAccessToken", "tokenFile"],
178
181
  providerHint: channel,
179
182
  credentialLabel: t("wizard.line.channelAccessToken"),
180
183
  preferredEnvVar: "LINE_CHANNEL_ACCESS_TOKEN",
@@ -184,34 +187,30 @@ const lineSetupWizard = {
184
187
  keepPrompt: t("wizard.line.tokenKeepPrompt"),
185
188
  inputPrompt: t("wizard.line.tokenInputPrompt"),
186
189
  allowEnv: ({ accountId }) => accountId === DEFAULT_ACCOUNT_ID,
187
- inspect: ({ cfg, accountId }) => {
188
- const resolved = resolveLineAccount({
189
- cfg,
190
- accountId
191
- });
192
- return {
193
- accountConfigured: Boolean(normalizeOptionalString(resolved.channelAccessToken) && normalizeOptionalString(resolved.channelSecret)),
194
- hasConfiguredValue: Boolean(normalizeOptionalString(resolved.config.channelAccessToken) ?? normalizeOptionalString(resolved.config.tokenFile)),
195
- resolvedValue: normalizeOptionalString(resolved.channelAccessToken),
196
- envValue: accountId === DEFAULT_ACCOUNT_ID ? normalizeOptionalString(process.env.LINE_CHANNEL_ACCESS_TOKEN) : void 0
197
- };
198
- },
199
- applyUseEnv: ({ cfg, accountId }) => patchLineAccountConfig({
190
+ resolveAccount: ({ cfg, accountId }) => resolveLineAccount({
200
191
  cfg,
201
- accountId,
202
- enabled: true,
203
- clearFields: ["channelAccessToken", "tokenFile"],
204
- patch: {}
192
+ accountId
205
193
  }),
206
- applySet: ({ cfg, accountId, resolvedValue }) => patchLineAccountConfig({
194
+ accountConfigured: (account) => Boolean(normalizeOptionalString(account.channelAccessToken) && normalizeOptionalString(account.channelSecret)),
195
+ hasConfiguredValue: (account) => Boolean(normalizeOptionalString(account.config.channelAccessToken) ?? normalizeOptionalString(account.config.tokenFile)),
196
+ resolvedValue: (account) => normalizeOptionalString(account.channelAccessToken),
197
+ envValue: ({ accountId }) => accountId === DEFAULT_ACCOUNT_ID ? normalizeOptionalString(process.env.LINE_CHANNEL_ACCESS_TOKEN) : void 0,
198
+ patchAccount: ({ cfg, accountId, patch, clearFields }) => patchLineAccountConfig({
207
199
  cfg,
208
200
  accountId,
209
201
  enabled: true,
202
+ clearFields,
203
+ patch
204
+ }),
205
+ useEnv: { clearFields: ["channelAccessToken", "tokenFile"] },
206
+ set: {
210
207
  clearFields: ["tokenFile"],
211
- patch: { channelAccessToken: resolvedValue }
212
- })
213
- }, {
208
+ value: "resolved"
209
+ }
210
+ }), defineTokenCredential({
214
211
  inputKey: "password",
212
+ configKey: "channelSecret",
213
+ configuredFields: ["channelSecret", "secretFile"],
215
214
  providerHint: "line-secret",
216
215
  credentialLabel: t("wizard.line.channelSecret"),
217
216
  preferredEnvVar: "LINE_CHANNEL_SECRET",
@@ -221,33 +220,27 @@ const lineSetupWizard = {
221
220
  keepPrompt: t("wizard.line.secretKeepPrompt"),
222
221
  inputPrompt: t("wizard.line.secretInputPrompt"),
223
222
  allowEnv: ({ accountId }) => accountId === DEFAULT_ACCOUNT_ID,
224
- inspect: ({ cfg, accountId }) => {
225
- const resolved = resolveLineAccount({
226
- cfg,
227
- accountId
228
- });
229
- return {
230
- accountConfigured: Boolean(normalizeOptionalString(resolved.channelAccessToken) && normalizeOptionalString(resolved.channelSecret)),
231
- hasConfiguredValue: Boolean(normalizeOptionalString(resolved.config.channelSecret) ?? normalizeOptionalString(resolved.config.secretFile)),
232
- resolvedValue: normalizeOptionalString(resolved.channelSecret),
233
- envValue: accountId === DEFAULT_ACCOUNT_ID ? normalizeOptionalString(process.env.LINE_CHANNEL_SECRET) : void 0
234
- };
235
- },
236
- applyUseEnv: ({ cfg, accountId }) => patchLineAccountConfig({
223
+ resolveAccount: ({ cfg, accountId }) => resolveLineAccount({
237
224
  cfg,
238
- accountId,
239
- enabled: true,
240
- clearFields: ["channelSecret", "secretFile"],
241
- patch: {}
225
+ accountId
242
226
  }),
243
- applySet: ({ cfg, accountId, resolvedValue }) => patchLineAccountConfig({
227
+ accountConfigured: (account) => Boolean(normalizeOptionalString(account.channelAccessToken) && normalizeOptionalString(account.channelSecret)),
228
+ hasConfiguredValue: (account) => Boolean(normalizeOptionalString(account.config.channelSecret) ?? normalizeOptionalString(account.config.secretFile)),
229
+ resolvedValue: (account) => normalizeOptionalString(account.channelSecret),
230
+ envValue: ({ accountId }) => accountId === DEFAULT_ACCOUNT_ID ? normalizeOptionalString(process.env.LINE_CHANNEL_SECRET) : void 0,
231
+ patchAccount: ({ cfg, accountId, patch, clearFields }) => patchLineAccountConfig({
244
232
  cfg,
245
233
  accountId,
246
234
  enabled: true,
235
+ clearFields,
236
+ patch
237
+ }),
238
+ useEnv: { clearFields: ["channelSecret", "secretFile"] },
239
+ set: {
247
240
  clearFields: ["secretFile"],
248
- patch: { channelSecret: resolvedValue }
249
- })
250
- }],
241
+ value: "resolved"
242
+ }
243
+ })],
251
244
  allowFrom: createAllowFromSection({
252
245
  helpTitle: t("wizard.line.allowlistTitle"),
253
246
  helpLines: LINE_ALLOW_FROM_HELP_LINES,
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@openclaw/line",
3
- "version": "2026.7.2-beta.1",
3
+ "version": "2026.7.2-beta.3",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@openclaw/line",
9
- "version": "2026.7.2-beta.1",
9
+ "version": "2026.7.2-beta.3",
10
10
  "dependencies": {
11
11
  "@line/bot-sdk": "11.1.0",
12
12
  "zod": "4.4.3"
13
13
  },
14
14
  "peerDependencies": {
15
- "openclaw": ">=2026.7.2-beta.1"
15
+ "openclaw": ">=2026.7.2-beta.3"
16
16
  },
17
17
  "peerDependenciesMeta": {
18
18
  "openclaw": {
@@ -74,9 +74,9 @@
74
74
  "default": "pairing",
75
75
  "type": "string",
76
76
  "enum": [
77
- "open",
78
- "allowlist",
79
77
  "pairing",
78
+ "allowlist",
79
+ "open",
80
80
  "disabled"
81
81
  ]
82
82
  },
@@ -85,8 +85,8 @@
85
85
  "type": "string",
86
86
  "enum": [
87
87
  "open",
88
- "allowlist",
89
- "disabled"
88
+ "disabled",
89
+ "allowlist"
90
90
  ]
91
91
  },
92
92
  "responsePrefix": {
@@ -129,6 +129,46 @@
129
129
  },
130
130
  "additionalProperties": false
131
131
  },
132
+ "groups": {
133
+ "type": "object",
134
+ "propertyNames": {
135
+ "type": "string"
136
+ },
137
+ "additionalProperties": {
138
+ "type": "object",
139
+ "properties": {
140
+ "requireMention": {
141
+ "type": "boolean"
142
+ },
143
+ "skills": {
144
+ "type": "array",
145
+ "items": {
146
+ "type": "string"
147
+ }
148
+ },
149
+ "enabled": {
150
+ "type": "boolean"
151
+ },
152
+ "allowFrom": {
153
+ "type": "array",
154
+ "items": {
155
+ "anyOf": [
156
+ {
157
+ "type": "string"
158
+ },
159
+ {
160
+ "type": "number"
161
+ }
162
+ ]
163
+ }
164
+ },
165
+ "systemPrompt": {
166
+ "type": "string"
167
+ }
168
+ },
169
+ "additionalProperties": false
170
+ }
171
+ },
132
172
  "accounts": {
133
173
  "type": "object",
134
174
  "propertyNames": {
@@ -185,9 +225,9 @@
185
225
  "default": "pairing",
186
226
  "type": "string",
187
227
  "enum": [
188
- "open",
189
- "allowlist",
190
228
  "pairing",
229
+ "allowlist",
230
+ "open",
191
231
  "disabled"
192
232
  ]
193
233
  },
@@ -196,8 +236,8 @@
196
236
  "type": "string",
197
237
  "enum": [
198
238
  "open",
199
- "allowlist",
200
- "disabled"
239
+ "disabled",
240
+ "allowlist"
201
241
  ]
202
242
  },
203
243
  "responsePrefix": {
@@ -248,6 +288,15 @@
248
288
  "additionalProperties": {
249
289
  "type": "object",
250
290
  "properties": {
291
+ "requireMention": {
292
+ "type": "boolean"
293
+ },
294
+ "skills": {
295
+ "type": "array",
296
+ "items": {
297
+ "type": "string"
298
+ }
299
+ },
251
300
  "enabled": {
252
301
  "type": "boolean"
253
302
  },
@@ -264,17 +313,8 @@
264
313
  ]
265
314
  }
266
315
  },
267
- "requireMention": {
268
- "type": "boolean"
269
- },
270
316
  "systemPrompt": {
271
317
  "type": "string"
272
- },
273
- "skills": {
274
- "type": "array",
275
- "items": {
276
- "type": "string"
277
- }
278
318
  }
279
319
  },
280
320
  "additionalProperties": false
@@ -290,46 +330,6 @@
290
330
  },
291
331
  "defaultAccount": {
292
332
  "type": "string"
293
- },
294
- "groups": {
295
- "type": "object",
296
- "propertyNames": {
297
- "type": "string"
298
- },
299
- "additionalProperties": {
300
- "type": "object",
301
- "properties": {
302
- "enabled": {
303
- "type": "boolean"
304
- },
305
- "allowFrom": {
306
- "type": "array",
307
- "items": {
308
- "anyOf": [
309
- {
310
- "type": "string"
311
- },
312
- {
313
- "type": "number"
314
- }
315
- ]
316
- }
317
- },
318
- "requireMention": {
319
- "type": "boolean"
320
- },
321
- "systemPrompt": {
322
- "type": "string"
323
- },
324
- "skills": {
325
- "type": "array",
326
- "items": {
327
- "type": "string"
328
- }
329
- }
330
- },
331
- "additionalProperties": false
332
- }
333
333
  }
334
334
  },
335
335
  "required": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/line",
3
- "version": "2026.7.2-beta.1",
3
+ "version": "2026.7.2-beta.3",
4
4
  "description": "OpenClaw LINE channel plugin for LINE Bot API chats.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -12,7 +12,7 @@
12
12
  "zod": "4.4.3"
13
13
  },
14
14
  "peerDependencies": {
15
- "openclaw": ">=2026.7.2-beta.1"
15
+ "openclaw": ">=2026.7.2-beta.3"
16
16
  },
17
17
  "peerDependenciesMeta": {
18
18
  "openclaw": {
@@ -42,10 +42,10 @@
42
42
  "minHostVersion": ">=2026.4.10"
43
43
  },
44
44
  "compat": {
45
- "pluginApi": ">=2026.7.2-beta.1"
45
+ "pluginApi": ">=2026.7.2-beta.3"
46
46
  },
47
47
  "build": {
48
- "openclawVersion": "2026.7.2-beta.1"
48
+ "openclawVersion": "2026.7.2-beta.3"
49
49
  },
50
50
  "release": {
51
51
  "publishToClawHub": true,
@@ -1,4 +0,0 @@
1
- import { t as monitorLineProvider } from "./monitor-q3UE2J1g.js";
2
- import { t as probeLineBot } from "./probe-BslD77tJ.js";
3
- import { S as pushMessageLine } from "./markdown-to-line-CixmAKiG.js";
4
- export { monitorLineProvider, probeLineBot, pushMessageLine };
@@ -1,2 +0,0 @@
1
- import { t as monitorLineProvider } from "./monitor-q3UE2J1g.js";
2
- export { monitorLineProvider };