@openclaw/line 2026.8.2 → 2026.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/api.js CHANGED
@@ -1,4 +1,4 @@
1
- import { n as lineChannelPluginCommon, t as linePlugin } from "./channel-CLCy4jAa.js";
1
+ import { n as lineChannelPluginCommon, t as linePlugin } from "./channel-CF2AeULJ.js";
2
2
  import { r as lineSetupContract, t as lineSetupWizard } from "./setup-surface-CDlgkTKi.js";
3
3
  //#region extensions/line/src/channel.setup.ts
4
4
  const lineSetupPlugin = {
@@ -1,5 +1,5 @@
1
- import { c as createActionCard, d as createListCard, l as createImageCard, s as createReceiptCard, u as createInfoCard } from "./send-retry-CUvrarfE.js";
2
- import { t as createFlexMessage } from "./send-wVUV00WS.js";
1
+ import { d as createActionCard, f as createImageCard, m as createListCard, p as createInfoCard, u as createReceiptCard } from "./send-retry-ChpfJ-LM.js";
2
+ import { t as createFlexMessage } from "./send-CQQxpxPp.js";
3
3
  import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
4
4
  import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
5
5
  //#region extensions/line/src/card-command.ts
@@ -1,7 +1,7 @@
1
1
  import { i as resolveLineAccount, r as resolveDefaultLineAccountId, t as listLineAccountIds } from "./accounts-BBEFMYbY.js";
2
2
  import { t as hasLineCredentials } from "./account-helpers-BSUyZwLm.js";
3
- import { _ as LineChannelConfigSchema, a as renderLineCard, d as resolveExactLineGroupConfigKey, h as getLineRuntime, n as createLineQuickReply, o as renderLinePresentation, p as resolveLineGroupLookupIds, r as lineMessageActions, t as LINE_PRESENTATION_CAPABILITIES, u as buildLineQuickReplyFallbackText } from "./rich-messages-CIP7xn5E.js";
4
- import { i as createLineSendReceipt, n as resolveLineNonDispatchRetryable, y as buildLineMediaMessage } from "./send-retry-CUvrarfE.js";
3
+ import { _ as LineChannelConfigSchema, a as renderLineCard, d as resolveExactLineGroupConfigKey, h as getLineRuntime, n as createLineQuickReply, o as renderLinePresentation, p as resolveLineGroupLookupIds, r as lineMessageActions, t as LINE_PRESENTATION_CAPABILITIES, u as buildLineQuickReplyFallbackText } from "./rich-messages-DY1AGKAJ.js";
4
+ import { s as createLineSendReceipt, t as explainLineRefusal, w as buildLineMediaMessage } from "./send-retry-ChpfJ-LM.js";
5
5
  import { r as lineSetupContract, t as lineSetupWizard } from "./setup-surface-CDlgkTKi.js";
6
6
  import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
7
7
  import { buildDmGroupAccountAllowlistAdapter, createFlatAllowlistOverrideResolver } from "openclaw/plugin-sdk/allowlist-config-edit";
@@ -119,8 +119,8 @@ const lineChannelPluginCommon = {
119
119
  };
120
120
  //#endregion
121
121
  //#region extensions/line/src/gateway.ts
122
- const loadLineProbeRuntime$1 = createLazyRuntimeModule(() => import("./probe.runtime-DTxBWvKz.js"));
123
- const loadLineMonitorRuntime = createLazyRuntimeModule(() => import("./monitor.runtime-CV8EjkIT.js"));
122
+ const loadLineProbeRuntime$1 = createLazyRuntimeModule(() => import("./probe.runtime-CbtMgU4s.js"));
123
+ const loadLineMonitorRuntime = createLazyRuntimeModule(() => import("./monitor.runtime-Mgecav_D.js"));
124
124
  const lineGatewayAdapter = {
125
125
  startAccount: async (ctx) => {
126
126
  const account = ctx.account;
@@ -211,7 +211,7 @@ function inferLineTargetChatType(target) {
211
211
  }
212
212
  //#endregion
213
213
  //#region extensions/line/src/outbound.ts
214
- const loadLineOutboundRuntime = createLazyRuntimeModule(() => import("./outbound.runtime-DLqcz_BQ.js"));
214
+ const loadLineOutboundRuntime = createLazyRuntimeModule(() => import("./outbound.runtime-CGqyJ-Ug.js"));
215
215
  const lineOutboundAdapter = {
216
216
  deliveryMode: "direct",
217
217
  chunker: (text, limit) => getLineRuntime().channel.text.chunkMarkdownText(text, limit),
@@ -248,10 +248,14 @@ const lineOutboundAdapter = {
248
248
  try {
249
249
  result = await resultPromise;
250
250
  } catch (error) {
251
- const retryable = isChannelPartialDeliveryError(error) ? void 0 : resolveLineNonDispatchRetryable(error);
252
- throw lastResult === null && retryable !== void 0 ? new PlatformMessageNotDispatchedError(error instanceof Error ? error.message : "LINE rejected the message", {
251
+ const refusal = lastResult !== null || isChannelPartialDeliveryError(error) ? void 0 : await explainLineRefusal({
252
+ error,
253
+ cfg,
254
+ accountId
255
+ });
256
+ throw refusal?.retryable !== void 0 ? new PlatformMessageNotDispatchedError(refusal.reason, {
253
257
  cause: error,
254
- retryable
258
+ retryable: refusal.retryable
255
259
  }) : error;
256
260
  }
257
261
  lastResult = result;
@@ -444,7 +448,7 @@ const lineMessageAdapter = defineChannelMessageAdapter({
444
448
  });
445
449
  //#endregion
446
450
  //#region extensions/line/src/status.ts
447
- const loadLineProbeRuntime = createLazyRuntimeModule(() => import("./probe.runtime-DTxBWvKz.js"));
451
+ const loadLineProbeRuntime = createLazyRuntimeModule(() => import("./probe.runtime-CbtMgU4s.js"));
448
452
  const collectLineStatusIssues = createDependentCredentialStatusIssueCollector({
449
453
  channel: "line",
450
454
  dependencySourceKey: "tokenSource",
@@ -456,7 +460,7 @@ const lineStatusAdapter = createComputedAccountStatusAdapter({
456
460
  collectStatusIssues: collectLineStatusIssues,
457
461
  buildChannelSummary: ({ snapshot }) => buildTokenChannelStatusSummary(snapshot),
458
462
  probeAccount: async ({ account, timeoutMs }) => await (await loadLineProbeRuntime()).probeLineBot(account.channelAccessToken, timeoutMs),
459
- resolveAccountSnapshot: ({ account }) => ({
463
+ resolveAccountSnapshot: ({ account, probe }) => ({
460
464
  accountId: account.accountId,
461
465
  name: account.name,
462
466
  enabled: account.enabled,
@@ -466,13 +470,14 @@ const lineStatusAdapter = createComputedAccountStatusAdapter({
466
470
  signingSecretSource: account.signingSecretSource,
467
471
  tokenStatus: account.tokenStatus,
468
472
  signingSecretStatus: account.signingSecretStatus,
469
- mode: "webhook"
473
+ mode: "webhook",
474
+ ...probe?.quota ? { quota: probe.quota } : {}
470
475
  }
471
476
  })
472
477
  });
473
478
  //#endregion
474
479
  //#region extensions/line/src/channel.ts
475
- const loadLineChannelRuntime = createLazyRuntimeModule(() => import("./channel.runtime-Ih7sq1GN.js"));
480
+ const loadLineChannelRuntime = createLazyRuntimeModule(() => import("./channel.runtime-BF4Wk2dM.js"));
476
481
  const lineSecurityAdapter = createRestrictSendersChannelSecurity({
477
482
  channelKey: "line",
478
483
  resolveDmPolicy: (account) => account.config.dmPolicy,
@@ -593,13 +598,16 @@ const linePlugin = createChatChannelPlugin({
593
598
  actions: lineMessageActions,
594
599
  bindings: lineBindingsAdapter,
595
600
  conversationBindings: { defaultTopLevelPlacement: "current" },
596
- agentPrompt: { messageToolHints: () => [
597
- "",
598
- "### LINE structured output",
599
- "Use `presentation.blocks` for buttons, yes/no choices, and selectable options; LINE maps them to Flex controls or quick replies.",
600
- "Use `channelData.line.location` for a location pin and `channelData.line.card` for one LINE-specific card. Supported card types are `media_player`, `event`, `agenda`, `device`, and `appletv_remote`.",
601
- "Send rich output with the structured message fields. Double-bracket marker text has no special meaning."
602
- ] }
601
+ agentPrompt: {
602
+ messageToolCapabilities: () => ["inlineButtons"],
603
+ messageToolHints: () => [
604
+ "",
605
+ "### LINE structured output",
606
+ "Use `presentation.blocks` for buttons, yes/no choices, and selectable options; LINE maps them to Flex controls or quick replies.",
607
+ "Use `channelData.line.location` for a location pin and `channelData.line.card` for one LINE-specific card. Supported card types are `media_player`, `event`, `agenda`, `device`, and `appletv_remote`.",
608
+ "Send rich output with the structured message fields. Double-bracket marker text has no special meaning."
609
+ ]
610
+ }
603
611
  },
604
612
  pairing: { text: {
605
613
  idLabel: "lineUserId",
@@ -1,2 +1,2 @@
1
- import { t as linePlugin } from "./channel-CLCy4jAa.js";
1
+ import { t as linePlugin } from "./channel-CF2AeULJ.js";
2
2
  export { linePlugin };
@@ -1,4 +1,4 @@
1
- import { t as monitorLineProvider } from "./monitor-CSpwQCBI.js";
2
- import { t as probeLineBot } from "./probe-4gc_YQ2L.js";
3
- import { _ as showLoadingAnimation, d as pushMessageLine } from "./send-wVUV00WS.js";
1
+ import { a as probeLineBot } from "./send-retry-ChpfJ-LM.js";
2
+ import { t as monitorLineProvider } from "./monitor-D0fHFXCi.js";
3
+ import { _ as showLoadingAnimation, d as pushMessageLine } from "./send-CQQxpxPp.js";
4
4
  export { monitorLineProvider, probeLineBot, pushMessageLine, showLoadingAnimation };
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { defineBundledChannelEntry } from "openclaw/plugin-sdk/channel-entry-contract";
2
2
  import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
3
3
  //#region extensions/line/index.ts
4
- const loadLineCardCommand = createLazyRuntimeModule(() => import("./card-command-DS6A5V6o.js"));
4
+ const loadLineCardCommand = createLazyRuntimeModule(() => import("./card-command-pwvE48Wb.js"));
5
5
  var line_default = defineBundledChannelEntry({
6
6
  id: "line",
7
7
  name: "LINE",
@@ -1,4 +1,4 @@
1
- import { g as postbackAction, m as normalizeLineAction, p as messageAction, s as createReceiptCard, v as uriAction } from "./send-retry-CUvrarfE.js";
1
+ import { C as toFlexMessage, S as fitsLineFlexBubble, _ as normalizeLineAction, g as messageAction, u as createReceiptCard, x as uriAction, y as postbackAction } from "./send-retry-ChpfJ-LM.js";
2
2
  import { markdownToIRWithMeta, stripMarkdown, stripMarkdown as stripMarkdown$1 } from "openclaw/plugin-sdk/text-chunking";
3
3
  import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
4
4
  //#region extensions/line/src/template-messages.ts
@@ -145,18 +145,6 @@ function buildTemplateMessageFromPayload(payload) {
145
145
  }
146
146
  }
147
147
  //#endregion
148
- //#region extensions/line/src/flex-templates/message.ts
149
- /**
150
- * Wrap a FlexContainer in a FlexMessage
151
- */
152
- function toFlexMessage(altText, contents) {
153
- return {
154
- type: "flex",
155
- altText,
156
- contents
157
- };
158
- }
159
- //#endregion
160
148
  //#region extensions/line/src/markdown-to-line.ts
161
149
  const LINE_MARKDOWN_OPTIONS = {
162
150
  assistantTranscriptRoleHeaders: true,
@@ -168,7 +156,6 @@ const LINE_MARKDOWN_OPTIONS = {
168
156
  preserveSourceBlockSpacing: true
169
157
  };
170
158
  const TRANSCRIPT_ROLE_PREFIX = "[assistant-authored transcript] ";
171
- const LINE_FLEX_BUBBLE_MAX_BYTES = 3e4;
172
159
  const LINE_FLEX_CODE_CARD_MAX_CHARS = 2e3;
173
160
  function parseLineMarkdown(text, tableMode = "block") {
174
161
  return markdownToIRWithMeta(text, {
@@ -462,7 +449,7 @@ function processLineMessage(text) {
462
449
  const plainTextInsertions = [];
463
450
  for (const table of tables) {
464
451
  const bubble = table.rowCells.length > 10 && (table.headers.length !== 2 || table.rowCells.length > 12 || [table.headerCells, ...table.rowCells].some((cells) => cells.some((cell) => renderTableCell(cell, "-").hasMarkup))) ? void 0 : convertTableToFlexBubble(toMarkdownTable(table));
465
- if (!bubble || Buffer.byteLength(JSON.stringify(bubble), "utf8") > LINE_FLEX_BUBBLE_MAX_BYTES) {
452
+ if (!bubble || !fitsLineFlexBubble(bubble)) {
466
453
  plainTextInsertions.push({
467
454
  position: table.placeholderOffset,
468
455
  text: `\n\n${formatOversizedTableAsBullets(table)}\n\n`
@@ -503,4 +490,4 @@ function hasMarkdownToConvert(text) {
503
490
  return tables.length > 0 || ir.styles.length > 0 || ir.links.length > 0 || /<\/?u>/i.test(ir.text) || ir.text !== text.trimEnd();
504
491
  }
505
492
  //#endregion
506
- export { stripMarkdown$1 as a, createButtonTemplate as c, createTemplateCarousel as d, processLineMessage as i, createCarouselColumn as l, convertTableToFlexBubble as n, toFlexMessage as o, hasMarkdownToConvert as r, buildTemplateMessageFromPayload as s, convertCodeBlockToFlexBubble as t, createConfirmTemplate as u };
493
+ export { stripMarkdown$1 as a, createCarouselColumn as c, processLineMessage as i, createConfirmTemplate as l, convertTableToFlexBubble as n, buildTemplateMessageFromPayload as o, hasMarkdownToConvert as r, createButtonTemplate as s, convertCodeBlockToFlexBubble as t, createTemplateCarousel as u };
@@ -1,9 +1,9 @@
1
1
  import { i as resolveLineAccount, r as resolveDefaultLineAccountId } from "./accounts-BBEFMYbY.js";
2
- import { f as resolveLineGroupConfigEntry, h as getLineRuntime, i as prepareLineReplyPayload, n as createLineQuickReply, u as buildLineQuickReplyFallbackText } from "./rich-messages-CIP7xn5E.js";
3
- import { n as resolveLineNonDispatchRetryable, t as findLineHttpError, y as buildLineMediaMessage } from "./send-retry-CUvrarfE.js";
2
+ import { f as resolveLineGroupConfigEntry, h as getLineRuntime, i as prepareLineReplyPayload, n as createLineQuickReply, u as buildLineQuickReplyFallbackText } from "./rich-messages-DY1AGKAJ.js";
3
+ import { n as findLineHttpError, r as resolveLineNonDispatchRetryable, t as explainLineRefusal, w as buildLineMediaMessage } from "./send-retry-ChpfJ-LM.js";
4
4
  import { a as eventIdFor, n as LINE_WEBHOOK_SPOOL_INVALID_PAYLOAD_MESSAGE, o as laneKeyFor, r as LineWebhookPayloadError, t as LINE_WEBHOOK_SPOOL_INVALID_EVENT_REASON } from "./webhook-spool-contract-1rY8OJw8.js";
5
- import { i as processLineMessage, s as buildTemplateMessageFromPayload } from "./markdown-to-line--jytmFan.js";
6
- import { _ as showLoadingAnimation, a as getLineGroupName, d as pushMessageLine, f as pushMessagesLine, h as replyMessageLine, n as createLocationMessage, o as getUserDisplayName, s as getUserProfile, t as createFlexMessage, v as quotesLineBotMessage } from "./send-wVUV00WS.js";
5
+ import { i as processLineMessage, o as buildTemplateMessageFromPayload } from "./markdown-to-line-B-sj-7II.js";
6
+ import { _ as showLoadingAnimation, a as getLineGroupName, d as pushMessageLine, f as pushMessagesLine, h as replyMessageLine, n as createLocationMessage, o as getUserDisplayName, s as getUserProfile, t as createFlexMessage, v as quotesLineBotMessage } from "./send-CQQxpxPp.js";
7
7
  import { createChannelPairingChallengeIssuer } from "openclaw/plugin-sdk/channel-pairing";
8
8
  import { normalizeOptionalString, normalizeStringEntries, readNonEmptyStringPreservingWhitespace } from "openclaw/plugin-sdk/string-coerce-runtime";
9
9
  import { DEFAULT_INGRESS_ADOPTION_STALL_MS, DEFAULT_INGRESS_RETRY_MAX_ATTEMPTS, bindIngressLifecycleToReplyOptions, createChannelIngressMonitor } from "openclaw/plugin-sdk/channel-outbound";
@@ -13,19 +13,19 @@ import { resolveSendableOutboundReplyParts } from "openclaw/plugin-sdk/reply-pay
13
13
  import { sanitizeAssistantVisibleText } from "openclaw/plugin-sdk/text-chunking";
14
14
  import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
15
15
  import { classifyTransientNetworkErrorCode } from "openclaw/plugin-sdk/retry-runtime";
16
+ import { fetchWithRuntimeDispatcherOrMockedGlobal } from "openclaw/plugin-sdk/runtime-fetch";
16
17
  import { firstDefined } from "openclaw/plugin-sdk/allow-from";
17
18
  import { setTimeout as setTimeout$1 } from "node:timers/promises";
18
19
  import { MediaFetchError } from "openclaw/plugin-sdk/media-runtime";
19
20
  import { saveMediaStream } from "openclaw/plugin-sdk/media-store";
20
21
  import { createNonExitingRuntime, danger, logVerbose, shouldLogVerbose, waitForAbortSignal, warn } from "openclaw/plugin-sdk/runtime-env";
21
- import { fetchWithRuntimeDispatcherOrMockedGlobal } from "openclaw/plugin-sdk/runtime-fetch";
22
22
  import crypto from "node:crypto";
23
23
  import { recordChannelActivity } from "openclaw/plugin-sdk/channel-activity-runtime";
24
24
  import { resolveHumanDelayConfig } from "openclaw/plugin-sdk/agent-runtime";
25
25
  import { channelReadyPatch, channelStoppedPatch } from "openclaw/plugin-sdk/gateway-runtime";
26
26
  import { chunkMarkdownText } from "openclaw/plugin-sdk/reply-runtime";
27
- import { canonicalizeWebhookRouteKey, isRequestBodyLimitError, normalizePluginHttpPath, normalizeWebhookPath, registerWebhookTargetWithPluginRoute, requestBodyErrorToText, resolveSingleWebhookTarget } from "openclaw/plugin-sdk/webhook-ingress";
28
- import { beginWebhookRequestPipelineOrReject, createWebhookInFlightLimiter, isRequestBodyLimitError as isRequestBodyLimitError$1, readRequestBodyWithLimit, requestBodyErrorToText as requestBodyErrorToText$1, runDetachedWebhookWork } from "openclaw/plugin-sdk/webhook-request-guards";
27
+ import { canonicalizeWebhookRouteKey, normalizePluginHttpPath, normalizeWebhookPath, registerWebhookTargetWithPluginRoute, resolveSingleWebhookTarget } from "openclaw/plugin-sdk/webhook-ingress";
28
+ import { beginWebhookRequestPipelineOrReject, createWebhookInFlightLimiter, isRequestBodyLimitError, readRequestBodyWithLimit, requestBodyErrorToText, runDetachedWebhookWork, sendHttpRequestRejection } from "openclaw/plugin-sdk/webhook-request-guards";
29
29
  import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
30
30
  import { DEFAULT_GROUP_HISTORY_LIMIT, createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
31
31
  import { getRuntimeConfig, getRuntimeConfigSnapshot, getRuntimeConfigSourceSnapshot, selectApplicableRuntimeConfig } from "openclaw/plugin-sdk/runtime-config-snapshot";
@@ -333,7 +333,15 @@ async function deliverLineAutoReply(params) {
333
333
  }
334
334
  }
335
335
  if (deliveryError !== void 0) {
336
- if (!visibleReplySent) throw toLineDeliveryError(deliveryError);
336
+ if (!visibleReplySent) {
337
+ const named = toLineDeliveryError(deliveryError);
338
+ const refusal = await explainLineRefusal({
339
+ error: named,
340
+ cfg: params.cfg,
341
+ accountId
342
+ });
343
+ throw refusal.reason !== named.message ? new Error(refusal.reason, { cause: deliveryError }) : named;
344
+ }
337
345
  return {
338
346
  status: "partial",
339
347
  replyTokenUsed,
@@ -580,7 +588,10 @@ async function finalizeLineInboundContext(params) {
580
588
  commandBody: params.commandBody ?? params.rawBody,
581
589
  inboundHistory: params.inboundHistory
582
590
  },
583
- access: { commands: { authorized: params.commandAuthorized } },
591
+ access: {
592
+ commands: { authorized: params.commandAuthorized },
593
+ mentions: params.mentions
594
+ },
584
595
  media,
585
596
  extra: {
586
597
  ...params.locationContext,
@@ -678,15 +689,16 @@ async function buildLineMessageContext(params) {
678
689
  rawBody,
679
690
  agentBody,
680
691
  commandBody: resolveLineMentionStrippedText(message) || rawBody,
692
+ mentions: params.mentions,
681
693
  timestamp,
682
694
  messageSid: messageId,
683
695
  commandAuthorized,
684
- channelIngress: params.resolveChannelIngress ? await params.resolveChannelIngress({
696
+ channelIngress: await params.resolveChannelIngress?.({
685
697
  agentId: route.agentId,
686
698
  sessionKey: route.sessionKey,
687
699
  messageId,
688
700
  inboundEventKind: "user_request"
689
- }) : params.channelIngress,
701
+ }),
690
702
  buildContext: params.buildContext,
691
703
  media: mediaFacts,
692
704
  locationContext,
@@ -750,12 +762,12 @@ async function buildLinePostbackContext(params) {
750
762
  timestamp,
751
763
  messageSid,
752
764
  commandAuthorized,
753
- channelIngress: params.resolveChannelIngress ? await params.resolveChannelIngress({
765
+ channelIngress: await params.resolveChannelIngress?.({
754
766
  agentId: route.agentId,
755
767
  sessionKey: route.sessionKey,
756
768
  messageId: messageSid,
757
769
  inboundEventKind: "user_request"
758
- }) : params.channelIngress,
770
+ }),
759
771
  buildContext: params.buildContext,
760
772
  media: [],
761
773
  verboseLog: { kind: "postback" }
@@ -893,12 +905,7 @@ async function resolveLineEventAdmission(event, context) {
893
905
  const groupPolicy = runtimeGroupPolicy === "disabled" ? "disabled" : groupConfig?.allowFrom !== void 0 ? "allowlist" : runtimeGroupPolicy;
894
906
  const groupAllowFrom = normalizeStringEntries(firstDefined(groupConfig?.allowFrom, account.config.groupAllowFrom));
895
907
  const mentionFacts = (() => {
896
- if (!isGroup || event.type !== "message") return {
897
- canDetectMention: false,
898
- wasMentioned: false,
899
- hasAnyMention: false,
900
- implicitMentionKinds: []
901
- };
908
+ if (!isGroup || event.type !== "message") return;
902
909
  const peerId = groupId ?? roomId ?? userId ?? "unknown";
903
910
  const { agentId } = resolveAgentRoute({
904
911
  cfg,
@@ -915,6 +922,7 @@ async function resolveLineEventAdmission(event, context) {
915
922
  return {
916
923
  canDetectMention: event.message.type === "text",
917
924
  wasMentioned: wasMentionedByNative || wasMentionedByPattern,
925
+ explicitlyMentionedBot: wasMentionedByNative,
918
926
  hasAnyMention: hasAnyLineMention(event.message),
919
927
  implicitMentionKinds: implicitMentionKindWhen("quoted_bot", quotesLineBotMessage(account.accountId, resolveLineQuotedMessageId(event.message)))
920
928
  };
@@ -940,12 +948,7 @@ async function resolveLineEventAdmission(event, context) {
940
948
  id: "line:group-config",
941
949
  enabled: false
942
950
  } } : {},
943
- mentionFacts: isGroup && event.type === "message" ? {
944
- canDetectMention: mentionFacts.canDetectMention,
945
- wasMentioned: mentionFacts.wasMentioned,
946
- hasAnyMention: mentionFacts.hasAnyMention,
947
- implicitMentionKinds: mentionFacts.implicitMentionKinds
948
- } : void 0,
951
+ mentionFacts,
949
952
  event: { kind: event.type === "join" ? "system" : event.type },
950
953
  dmPolicy,
951
954
  groupPolicy,
@@ -981,7 +984,12 @@ async function resolveLineEventAdmission(event, context) {
981
984
  } : null;
982
985
  if (access.senderAccess.decision === "allow" && (access.ingress.admission === "dispatch" || access.ingress.admission === "observe" || access.ingress.admission === "skip")) return {
983
986
  access,
984
- resolveBoundAccess: resolveAccess
987
+ resolveBoundAccess: resolveAccess,
988
+ mentions: mentionFacts ? {
989
+ ...mentionFacts,
990
+ wasMentioned: access.activationAccess.effectiveWasMentioned ?? mentionFacts.wasMentioned,
991
+ requireMention
992
+ } : void 0
985
993
  };
986
994
  if (access.senderAccess.decision === "allow") {
987
995
  logVerbose(`Blocked line event (${access.ingress.reasonCode})`);
@@ -1109,6 +1117,7 @@ async function handleMessageEvent(event, context) {
1109
1117
  commandAuthorized: decision.access.commandAccess.authorized,
1110
1118
  resolveChannelIngress: decision.resolveBoundAccess,
1111
1119
  inboundHistory: historyReservation.inboundHistory,
1120
+ mentions: decision.mentions,
1112
1121
  buildContext: context.buildContext
1113
1122
  });
1114
1123
  if (!messageContext) {
@@ -1494,9 +1503,22 @@ const LINE_WEBHOOK_PREAUTH_BODY_TIMEOUT_MS$1 = 5e3;
1494
1503
  async function readLineWebhookRequestBody(req, maxBytes = LINE_WEBHOOK_MAX_BODY_BYTES, timeoutMs = LINE_WEBHOOK_PREAUTH_BODY_TIMEOUT_MS$1) {
1495
1504
  return await readRequestBodyWithLimit(req, {
1496
1505
  maxBytes,
1497
- timeoutMs
1506
+ timeoutMs,
1507
+ destroyOnLimit: false
1498
1508
  });
1499
1509
  }
1510
+ /**
1511
+ * Answer a body-limit failure through the connection owner.
1512
+ *
1513
+ * The reader defers destruction for these two codes, so the connection is already fenced
1514
+ * and only the owner can still write: responding directly would race the teardown and LINE
1515
+ * would see a reset instead of the status.
1516
+ */
1517
+ async function rejectLineWebhookRequest(req, res, error) {
1518
+ if (!isRequestBodyLimitError(error, "PAYLOAD_TOO_LARGE") && !isRequestBodyLimitError(error, "REQUEST_BODY_TIMEOUT")) return false;
1519
+ await sendHttpRequestRejection(req, res, error.statusCode, JSON.stringify({ error: requestBodyErrorToText(error.code) }), "application/json");
1520
+ return true;
1521
+ }
1500
1522
  function createLineNodeWebhookHandler(params) {
1501
1523
  const maxBodyBytes = params.maxBodyBytes ?? LINE_WEBHOOK_MAX_BODY_BYTES;
1502
1524
  const readBody = params.readBody ?? readLineWebhookRequestBody;
@@ -1553,18 +1575,7 @@ function createLineNodeWebhookHandler(params) {
1553
1575
  res.setHeader("Content-Type", "application/json");
1554
1576
  res.end(JSON.stringify({ status: "ok" }));
1555
1577
  } catch (err) {
1556
- if (isRequestBodyLimitError$1(err, "PAYLOAD_TOO_LARGE")) {
1557
- res.statusCode = 413;
1558
- res.setHeader("Content-Type", "application/json");
1559
- res.end(JSON.stringify({ error: "Payload too large" }));
1560
- return;
1561
- }
1562
- if (isRequestBodyLimitError$1(err, "REQUEST_BODY_TIMEOUT")) {
1563
- res.statusCode = 408;
1564
- res.setHeader("Content-Type", "application/json");
1565
- res.end(JSON.stringify({ error: requestBodyErrorToText$1("REQUEST_BODY_TIMEOUT") }));
1566
- return;
1567
- }
1578
+ if (await rejectLineWebhookRequest(req, res, err)) return;
1568
1579
  params.runtime.error?.(danger(`line webhook error: ${formatErrorMessage(err)}`));
1569
1580
  if (!res.headersSent) {
1570
1581
  res.statusCode = 500;
@@ -1816,18 +1827,7 @@ async function monitorLineProvider(opts) {
1816
1827
  res.setHeader("Content-Type", "application/json");
1817
1828
  res.end(JSON.stringify({ status: "ok" }));
1818
1829
  } catch (err) {
1819
- if (isRequestBodyLimitError(err, "PAYLOAD_TOO_LARGE")) {
1820
- res.statusCode = 413;
1821
- res.setHeader("Content-Type", "application/json");
1822
- res.end(JSON.stringify({ error: "Payload too large" }));
1823
- return;
1824
- }
1825
- if (isRequestBodyLimitError(err, "REQUEST_BODY_TIMEOUT")) {
1826
- res.statusCode = 408;
1827
- res.setHeader("Content-Type", "application/json");
1828
- res.end(JSON.stringify({ error: requestBodyErrorToText("REQUEST_BODY_TIMEOUT") }));
1829
- return;
1830
- }
1830
+ if (await rejectLineWebhookRequest(req, res, err)) return;
1831
1831
  runtime.error?.(danger(`line webhook error: ${formatErrorMessage(err)}`));
1832
1832
  if (!res.headersSent) {
1833
1833
  res.statusCode = 500;
@@ -0,0 +1,2 @@
1
+ import { t as monitorLineProvider } from "./monitor-D0fHFXCi.js";
2
+ export { monitorLineProvider };
@@ -1,3 +1,3 @@
1
- import { i as processLineMessage, s as buildTemplateMessageFromPayload } from "./markdown-to-line--jytmFan.js";
2
- import { c as pushFlexMessage, d as pushMessageLine, f as pushMessagesLine, g as sendMessageLine, m as pushTextMessageWithQuickReplies, n as createLocationMessage, p as pushTemplateMessage, r as createQuickReplyItems, t as createFlexMessage, u as pushLocationMessage } from "./send-wVUV00WS.js";
1
+ import { i as processLineMessage, o as buildTemplateMessageFromPayload } from "./markdown-to-line-B-sj-7II.js";
2
+ import { c as pushFlexMessage, d as pushMessageLine, f as pushMessagesLine, g as sendMessageLine, m as pushTextMessageWithQuickReplies, n as createLocationMessage, p as pushTemplateMessage, r as createQuickReplyItems, t as createFlexMessage, u as pushLocationMessage } from "./send-CQQxpxPp.js";
3
3
  export { buildTemplateMessageFromPayload, createFlexMessage, createLocationMessage, createQuickReplyItems, processLineMessage, pushFlexMessage, pushLocationMessage, pushMessageLine, pushMessagesLine, pushTemplateMessage, pushTextMessageWithQuickReplies, sendMessageLine };
@@ -0,0 +1,2 @@
1
+ import { a as probeLineBot } from "./send-retry-ChpfJ-LM.js";
2
+ export { probeLineBot };