@openclaw/discord 2026.7.2-beta.2 → 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.
Files changed (85) hide show
  1. package/dist/action-runtime-api.js +1 -1
  2. package/dist/{activities-api-D0D_87n3.js → activities-api-DS1L7KRY.js} +15 -42
  3. package/dist/activities-api.js +1 -1
  4. package/dist/{allow-list-B7qOH5xu.js → allow-list-DzKrtfah.js} +18 -7
  5. package/dist/{api-B88T4rFN.js → api-C43z8vUm.js} +3 -1
  6. package/dist/api.js +25 -16
  7. package/dist/{approval-handler.runtime-B7E1-x5q.js → approval-handler.runtime-BbkfPoGc.js} +5 -6
  8. package/dist/{conversation-identity-BPcbhCAH.js → approval-message-safety-DrLlgIPz.js} +48 -2
  9. package/dist/{audit-CjpnY1yb.js → audit-BC6bgPMX.js} +3 -3
  10. package/dist/{channel-BDfKr14H.js → channel-5MfaC2IE.js} +18 -18
  11. package/dist/{channel-actions-BQct-o4T.js → channel-actions-DicWTbYH.js} +2 -2
  12. package/dist/{channel-actions.runtime-CC4QwYVO.js → channel-actions.runtime-D9Qadn-l.js} +8 -8
  13. package/dist/channel-config-api.js +1 -1
  14. package/dist/channel-plugin-api.js +1 -1
  15. package/dist/{channel.setup-BS4gd8sc.js → channel.setup-CJXfFclP.js} +3 -3
  16. package/dist/{chunk-CHpY_lsO.js → chunk-CWzmeWf_.js} +9 -49
  17. package/dist/{config-schema-CoDck1GW.js → config-schema-BxrgfSMD.js} +4 -0
  18. package/dist/{directory-config-G1QwBIdi.js → directory-config-CmukHSms.js} +1 -1
  19. package/dist/directory-contract-api.js +1 -1
  20. package/dist/{directory-live-nfvekMil.js → directory-live-BYlCRO__.js} +3 -3
  21. package/dist/{doctor-Bq4pJAQk.js → doctor-Ci7USQAW.js} +1 -1
  22. package/dist/{handle-action.guild-admin-LYY75_Oa.js → handle-action.guild-admin-Bsk2YBPs.js} +2 -2
  23. package/dist/index.js +2 -2
  24. package/dist/{manager.runtime-w6VVYQMl.js → manager.runtime-Cc8vS-M7.js} +98 -145
  25. package/dist/message-handler-CWJ-mQvH.js +590 -0
  26. package/dist/{message-handler.preflight-DnAH04Ss.js → message-handler.preflight-DK46_qbS.js} +16 -15
  27. package/dist/{message-handler.process-ClgKz8I5.js → message-handler.process-BK0mjFJH.js} +37 -61
  28. package/dist/{message-utils-BU3gc01v.js → message-utils-Cfe6CZ6N.js} +1 -1
  29. package/dist/{outbound-adapter-ByoXsR-V.js → outbound-adapter-B2_oa-zV.js} +36 -5
  30. package/dist/{outbound-components-7wAolLuS.js → outbound-components-BGhk6HI3.js} +3 -3
  31. package/dist/{outbound-session-route-D4QqePZN.js → outbound-session-route-M2bEY9tI.js} +36 -6
  32. package/dist/{pluralkit-r4wiI2yy.js → pluralkit-CT0VRsZd.js} +1 -1
  33. package/dist/{probe-WKeTYyJX.js → probe-C3SCKyYU.js} +1 -1
  34. package/dist/{probe.runtime-CRY-qUke.js → probe.runtime-D55QqC9u.js} +1 -1
  35. package/dist/{provider-PRlF_lZm.js → provider-HW0G-2l6.js} +868 -794
  36. package/dist/{provider-session.runtime-BZPUZRjn.js → provider-session.runtime-cCfGMsF_.js} +3 -3
  37. package/dist/provider.runtime-BWCRsVoT.js +2 -0
  38. package/dist/{resolve-allowlist-common-QN7VMZaC.js → resolve-allowlist-common-CJlqw_nC.js} +2 -2
  39. package/dist/{resolve-channels-BO9NUPlS.js → resolve-channels-9KcG3mLg.js} +4 -4
  40. package/dist/{resolve-users-CU3oG5-m.js → resolve-users-GCGf3oV0.js} +3 -3
  41. package/dist/{runtime-CCf5nkV3.js → runtime-CD5MRZkD.js} +1 -2
  42. package/dist/{runtime-BsefAQ9q.js → runtime-Z2qkKakn.js} +9 -8
  43. package/dist/runtime-api.actions.js +2 -2
  44. package/dist/runtime-api.js +23 -22
  45. package/dist/runtime-api.lookup.js +5 -5
  46. package/dist/runtime-api.monitor-C3EDYJqk.js +6 -0
  47. package/dist/runtime-api.monitor.js +8 -8
  48. package/dist/runtime-api.send.js +6 -5
  49. package/dist/runtime-api.threads.js +3 -3
  50. package/dist/{secret-config-contract-BDNrRWvd.js → secret-config-contract-B1akrlyY.js} +1 -0
  51. package/dist/secret-contract-api.js +1 -1
  52. package/dist/security-audit-contract-api.js +1 -1
  53. package/dist/{security-audit.runtime-K0nkzjzJ.js → security-audit.runtime-DEEywczv.js} +1 -1
  54. package/dist/{send-JJzVo_sK.js → send-CSRxNNgq.js} +7 -86
  55. package/dist/{send.components-CCRW54gK.js → send.components-DLqzOEPJ.js} +5 -4
  56. package/dist/{send.outbound-Cvulb-k_.js → send.outbound-C1SfX20w.js} +4 -3
  57. package/dist/send.reactions-Cj4ugX3F.js +85 -0
  58. package/dist/send.receipt-CuwRrpFz.js +48 -0
  59. package/dist/{send.shared-XuOTO1dW.js → send.shared-Dber6X57.js} +2 -2
  60. package/dist/{sender-identity-C62lBe18.js → sender-identity-mG_zsdox.js} +1 -1
  61. package/dist/session-binding-contract-api.js +1 -1
  62. package/dist/setup-plugin-api.js +1 -1
  63. package/dist/{shared-Bngr0I-v.js → shared-BEhmAdMY.js} +5 -5
  64. package/dist/{subagent-hooks-mSxRv4AE.js → subagent-hooks-Wrk61DwY.js} +2 -2
  65. package/dist/subagent-hooks-api.js +10 -1
  66. package/dist/subagent-progress-B2fpHe3m.js +662 -0
  67. package/dist/{system-events-BANBRAe3.js → system-events-AhfcKRRb.js} +2 -2
  68. package/dist/{target-resolver-BaEmTxeK.js → target-resolver-vqLA450R.js} +2 -2
  69. package/dist/targets-BjEMIe8t.js +3 -0
  70. package/dist/{thread-bindings-4MV-u8vU.js → thread-bindings-CJQoXuWY.js} +4 -4
  71. package/dist/{thread-bindings.discord-api-DXfXsHGZ.js → thread-bindings.discord-api-mNCWlgvM.js} +4 -4
  72. package/dist/{thread-bindings.manager-DJ4cO5Eu.js → thread-bindings.manager-D1z8mK4b.js} +3 -3
  73. package/dist/{timeouts-D5lWili0.js → timeouts-B9cy6RvQ.js} +1 -6
  74. package/dist/{transcripts-source-TDZcMriu.js → transcripts-source-DjDbt14x.js} +1 -1
  75. package/dist/transcripts-source-api.js +1 -1
  76. package/dist/{typing-CKd2NMWG.js → typing-wxtm1NlF.js} +2 -2
  77. package/npm-shrinkwrap.json +3 -3
  78. package/openclaw.plugin.json +10 -0
  79. package/package.json +4 -4
  80. package/dist/approval-message-safety-C-8BL6Kv.js +0 -47
  81. package/dist/message-handler-DExaghWK.js +0 -331
  82. package/dist/provider.runtime-BX8GcCYx.js +0 -2
  83. package/dist/runtime-api.monitor-DCS_ETft.js +0 -6
  84. package/dist/targets-fjJt3PYG.js +0 -3
  85. package/dist/{security-audit-aLbWmUjl.js → security-audit-DtT0SIns.js} +1 -1
@@ -1,36 +1,35 @@
1
- import { bt as editChannelMessage, f as resolveDiscordChannelId, ht as createChannelMessage, p as discord_exports, t as chunkDiscordTextWithMode, vt as deleteChannelMessage } from "./chunk-CHpY_lsO.js";
1
+ import { d as discord_exports, gt as deleteChannelMessage, pt as createChannelMessage, t as chunkDiscordTextWithMode, u as resolveDiscordChannelId, vt as editChannelMessage } from "./chunk-CWzmeWf_.js";
2
2
  import { f as resolveDiscordMaxLinesPerMessage } from "./accounts-CMd4nzLB.js";
3
- import { C as resolveTimestampMs, a as normalizeDiscordSlug, r as normalizeDiscordAllowList } from "./allow-list-B7qOH5xu.js";
4
- import { F as createDiscordRestClient, I as createDiscordRuntimeAccountContext, _ as resolveDiscordMessageFlags, d as resolveDiscordTargetChannelId } from "./send.shared-XuOTO1dW.js";
5
- import { i as discordTextHasBroadcastMention } from "./send.outbound-Cvulb-k_.js";
6
- import { a as removeReactionDiscord, f as editMessageDiscord, r as reactMessageDiscord } from "./send-JJzVo_sK.js";
7
- import { n as DISCORD_ATTACHMENT_TOTAL_TIMEOUT_MS, t as DISCORD_ATTACHMENT_IDLE_TIMEOUT_MS } from "./timeouts-D5lWili0.js";
8
- import "./targets-fjJt3PYG.js";
9
- import { t as resolveDiscordConversationIdentity } from "./conversation-identity-BPcbhCAH.js";
3
+ import { F as createDiscordRestClient, I as createDiscordRuntimeAccountContext, _ as resolveDiscordMessageFlags, d as resolveDiscordTargetChannelId } from "./send.shared-Dber6X57.js";
4
+ import { C as resolveTimestampMs, a as normalizeDiscordSlug, r as normalizeDiscordAllowList } from "./allow-list-DzKrtfah.js";
5
+ import { i as discordTextHasBroadcastMention } from "./send.outbound-C1SfX20w.js";
6
+ import { s as editMessageDiscord } from "./send-CSRxNNgq.js";
7
+ import { n as DISCORD_ATTACHMENT_TOTAL_TIMEOUT_MS, t as DISCORD_ATTACHMENT_IDLE_TIMEOUT_MS } from "./timeouts-B9cy6RvQ.js";
8
+ import { i as removeReactionDiscord, n as reactMessageDiscord } from "./send.reactions-Cj4ugX3F.js";
9
+ import "./targets-BjEMIe8t.js";
10
+ import { r as resolveDiscordConversationIdentity } from "./approval-message-safety-DrLlgIPz.js";
10
11
  import { t as beginDiscordInboundEventDeliveryCorrelation } from "./inbound-event-delivery-CEPlt2uz.js";
11
- import { t as DISCORD_TEXT_CHUNK_LIMIT } from "./outbound-adapter-ByoXsR-V.js";
12
- import { D as resolveDiscordThreadStarter, T as resolveDiscordAutoThreadReplyPlan, _ as createDiscordSupplementalContextAccessChecker, a as buildDirectLabel, g as buildDiscordInboundAccessContext, i as sanitizeDiscordFrontChannelReplyPayloads, n as deliverDiscordReply, o as buildGuildLabel, r as formatDiscordReplyDeliveryFailure, s as resolveReplyContext } from "./provider-PRlF_lZm.js";
13
- import { r as resolveDiscordMessageText, s as resolveReferencedReplyMediaList } from "./message-utils-BU3gc01v.js";
14
- import { n as DiscordRetryableInboundError } from "./message-handler-DExaghWK.js";
15
- import { t as sendTyping } from "./typing-CKd2NMWG.js";
12
+ import { t as DISCORD_TEXT_CHUNK_LIMIT } from "./outbound-adapter-B2_oa-zV.js";
13
+ import { E as resolveDiscordAutoThreadReplyPlan, O as resolveDiscordThreadStarter, _ as createDiscordSupplementalContextAccessChecker, a as buildDirectLabel, g as buildDiscordInboundAccessContext, i as sanitizeDiscordFrontChannelReplyPayloads, n as deliverDiscordReply, o as buildGuildLabel, r as formatDiscordReplyDeliveryFailure, s as resolveReplyContext } from "./provider-HW0G-2l6.js";
14
+ import { r as resolveDiscordMessageText, s as resolveReferencedReplyMediaList } from "./message-utils-Cfe6CZ6N.js";
15
+ import { t as sendTyping } from "./typing-wxtm1NlF.js";
16
16
  import { buildAgentSessionKey, resolveThreadSessionKeys } from "openclaw/plugin-sdk/routing";
17
17
  import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
18
18
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
19
- import { isDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/dangerous-name-runtime";
20
19
  import { danger, logVerbose, shouldLogVerbose, sleep, sleepWithAbort } from "openclaw/plugin-sdk/runtime-env";
21
20
  import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
22
21
  import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
23
22
  import { resolveChunkMode } from "openclaw/plugin-sdk/reply-chunking";
24
23
  import { convertMarkdownTables, stripInlineDirectiveTagsForDelivery, stripReasoningTagsFromText } from "openclaw/plugin-sdk/text-chunking";
25
- import { buildChannelProgressDraftLine, buildChannelProgressDraftLineForEntry, createChannelMessageReplyPipeline, createChannelProgressDraftCompositor, createFinalizableDraftLifecycle, createTypingCallbacks, defineFinalizableLivePreviewAdapter, deliverWithFinalizableLivePreviewAdapter, isChannelProgressDraftWorkToolName, resolveChannelDraftStreamingChunking, resolveChannelMessageSourceReplyDeliveryMode, resolveChannelPreviewStreamMode, resolveChannelProgressDraftConfig, resolveChannelStreamingBlockEnabled, resolveChannelStreamingPreviewCommandText, resolveChannelStreamingPreviewToolProgress, resolveChannelStreamingProgressNarration, resolveChannelStreamingSuppressDefaultToolProgressMessages, resolveTranscriptBackedChannelFinalText } from "openclaw/plugin-sdk/channel-outbound";
24
+ import { bindIngressLifecycleToReplyOptions, buildChannelProgressDraftLine, buildChannelProgressDraftLineForEntry, createChannelMessageReplyPipeline, createChannelProgressDraftCompositor, createFinalizableDraftLifecycle, createTypingCallbacks, defineFinalizableLivePreviewAdapter, deliverWithFinalizableLivePreviewAdapter, isChannelProgressDraftWorkToolName, resolveChannelDraftStreamingChunking, resolveChannelMessageSourceReplyDeliveryMode, resolveChannelPreviewStreamMode, resolveChannelProgressDraftConfig, resolveChannelStreamingBlockEnabled, resolveChannelStreamingPreviewCommandText, resolveChannelStreamingPreviewToolProgress, resolveChannelStreamingProgressNarration, resolveChannelStreamingSuppressDefaultToolProgressMessages, resolveTranscriptBackedChannelFinalText } from "openclaw/plugin-sdk/channel-outbound";
26
25
  import { getAgentScopedMediaLocalRoots } from "openclaw/plugin-sdk/media-runtime";
27
26
  import { getReplyPayloadTtsSupplement, isReplyPayloadNonTerminalToolErrorWarning, resolveSendableOutboundReplyParts } from "openclaw/plugin-sdk/reply-payload";
28
- import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
29
27
  import { evaluateSupplementalContextVisibility } from "openclaw/plugin-sdk/security-runtime";
30
- import { recordInboundSession, resolvePinnedMainDmOwnerFromAllowlist } from "openclaw/plugin-sdk/conversation-runtime";
28
+ import { resolvePinnedMainDmOwnerFromAllowlist } from "openclaw/plugin-sdk/conversation-runtime";
31
29
  import { EmbeddedBlockChunker, resolveAckReaction, resolveHumanDelayConfig } from "openclaw/plugin-sdk/agent-runtime";
30
+ import { isDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/dangerous-name-runtime";
32
31
  import { getSessionEntry, readSessionUpdatedAt, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
33
- import { buildChannelInboundEventContext, dispatchChannelInboundReply, formatInboundEnvelope, hasFinalInboundReplyDispatch, resolveEnvelopeFormatOptions, toHistoryMediaEntries, toInboundMediaFacts } from "openclaw/plugin-sdk/channel-inbound";
32
+ import { buildChannelInboundEventContext, dispatchChannelInboundTurn, formatInboundEnvelope, hasFinalInboundReplyDispatch, resolveEnvelopeFormatOptions, toHistoryMediaEntries, toInboundMediaFacts } from "openclaw/plugin-sdk/channel-inbound";
34
33
  import { DEFAULT_TIMING, createStatusReactionController, logAckFailure, logTypingFailure, shouldAckReaction } from "openclaw/plugin-sdk/channel-feedback";
35
34
  import { createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
36
35
  import { readLatestAssistantTextByIdentity } from "openclaw/plugin-sdk/session-transcript-runtime";
@@ -73,44 +72,13 @@ function queueInitialDiscordAckReaction(params) {
73
72
  //#endregion
74
73
  //#region extensions/discord/src/monitor/message-handler.retry.ts
75
74
  const REPLY_SESSION_INIT_CONFLICT_MESSAGE_RE = /^reply session initialization conflicted for \S+$/u;
76
- const DISCORD_SESSION_INIT_CONFLICT_RETRY_DELAYS_MS = [
77
- 250,
78
- 1e3,
79
- 2500
80
- ];
81
75
  const DISCORD_SESSION_CONFLICT_FAILURE_TEXT = "⚠️ Couldn't process this message because the session stayed busy. Please try again in a moment.";
82
76
  function isReplySessionInitConflictError(error) {
83
77
  const message = error instanceof Error ? error.message : String(error);
84
78
  return REPLY_SESSION_INIT_CONFLICT_MESSAGE_RE.test(message);
85
79
  }
86
- var DiscordReplySessionConflictExhaustedError = class extends DiscordRetryableInboundError {
87
- constructor(message, options) {
88
- super(message, options);
89
- this.name = "DiscordReplySessionConflictExhaustedError";
90
- }
91
- };
92
- async function dispatchDiscordReplyWithSessionConflictRetry(params) {
93
- for (let retryIndex = 0;; retryIndex += 1) try {
94
- return await params.dispatch();
95
- } catch (error) {
96
- if (!isReplySessionInitConflictError(error)) throw error;
97
- const delayMs = DISCORD_SESSION_INIT_CONFLICT_RETRY_DELAYS_MS[retryIndex];
98
- if (delayMs === void 0) throw new DiscordReplySessionConflictExhaustedError(`discord: reply session init conflict persisted after shared and channel retries: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
99
- params.onRetry?.(retryIndex + 1, delayMs);
100
- await sleepWithAbort(delayMs, params.abortSignal);
101
- }
102
- }
103
- function withDiscordSessionRetry(dispatch, abortSignal) {
104
- return (dispatchParams) => dispatchDiscordReplyWithSessionConflictRetry({
105
- dispatch: () => dispatch(dispatchParams),
106
- abortSignal,
107
- onRetry: (attempt, delayMs) => {
108
- logVerbose(`discord: reply session init conflict; retrying dispatch ${attempt} after ${delayMs}ms`);
109
- }
110
- });
111
- }
112
80
  async function completeDiscordSessionConflict(error, deliver, onDeliveryError) {
113
- if (!(error instanceof DiscordReplySessionConflictExhaustedError)) return false;
81
+ if (!isReplySessionInitConflictError(error)) return false;
114
82
  try {
115
83
  await deliver({
116
84
  text: DISCORD_SESSION_CONFLICT_FAILURE_TEXT,
@@ -119,7 +87,7 @@ async function completeDiscordSessionConflict(error, deliver, onDeliveryError) {
119
87
  return true;
120
88
  } catch (deliveryError) {
121
89
  onDeliveryError(deliveryError, { kind: "final" });
122
- return false;
90
+ throw new Error(`discord: reply session init conflict exhausted and terminal notice failed: ${String(deliveryError)}`, { cause: deliveryError });
123
91
  }
124
92
  }
125
93
  function removeDiscordReplayHistoryEntry(historyMap, historyKey, messageId) {
@@ -353,6 +321,7 @@ async function buildDiscordMessageProcessContext(params) {
353
321
  },
354
322
  route: {
355
323
  agentId: route.agentId,
324
+ dmScope: route.dmScope,
356
325
  accountId: route.accountId,
357
326
  routeSessionKey: route.sessionKey,
358
327
  dispatchSessionKey: effectiveSessionKey,
@@ -900,7 +869,6 @@ function createDiscordReplyTypingFeedback(params) {
900
869
  }
901
870
  //#endregion
902
871
  //#region extensions/discord/src/monitor/message-handler.process.ts
903
- const loadReplyRuntime = createLazyRuntimeModule(() => import("openclaw/plugin-sdk/reply-runtime"));
904
872
  const TARGETED_ONLY_ALLOWED_MENTIONS = { parse: ["users", "roles"] };
905
873
  function isProcessAborted(abortSignal) {
906
874
  return Boolean(abortSignal?.aborted);
@@ -928,7 +896,7 @@ async function processDiscordMessage(ctx, observer) {
928
896
  }
929
897
  async function processDiscordMessageInner(ctx, observer) {
930
898
  const dispatchStartedAt = Date.now();
931
- const { cfg, discordConfig, accountId, token, runtime, guildHistories, historyLimit, textLimit, replyToMode, ackReactionScope, message, messageChannelId, isGuildMessage, isDirectMessage, isGroupDm, messageText, shouldRequireMention, canDetectMention, effectiveWasMentioned, shouldBypassMention, channelConfig, threadBindings, route, abortSignal, preparedMedia: mediaList } = ctx;
899
+ const { cfg, discordConfig, accountId, token, runtime, guildHistories, historyLimit, textLimit, replyToMode, ackReactionScope, message, messageChannelId, isGuildMessage, isDirectMessage, isGroupDm, messageText, shouldRequireMention, canDetectMention, effectiveWasMentioned, shouldBypassMention, channelConfig, threadBindings, route, abortSignal, turnAdoptionLifecycle, preparedMedia: mediaList } = ctx;
932
900
  if (isProcessAborted(abortSignal)) return;
933
901
  const text = messageText;
934
902
  if (!text) {
@@ -937,7 +905,6 @@ async function processDiscordMessageInner(ctx, observer) {
937
905
  }
938
906
  const boundThreadId = ctx.threadBinding?.conversation?.conversationId?.trim();
939
907
  if (boundThreadId && typeof threadBindings.touchThread === "function") threadBindings.touchThread({ threadId: boundThreadId });
940
- const { dispatchReplyWithBufferedBlockDispatcher: dispatchReply } = await loadReplyRuntime();
941
908
  const sourceReplyDeliveryMode = resolveChannelMessageSourceReplyDeliveryMode({
942
909
  cfg,
943
910
  ctx: {
@@ -1536,17 +1503,25 @@ async function processDiscordMessageInner(ctx, observer) {
1536
1503
  dispatchAborted = true;
1537
1504
  return;
1538
1505
  }
1539
- const preparedResult = await dispatchChannelInboundReply({
1506
+ const preparedResult = await dispatchChannelInboundTurn({
1540
1507
  cfg,
1541
1508
  channel: "discord",
1542
1509
  accountId: route.accountId,
1543
- agentId: route.agentId,
1544
- routeSessionKey: persistedSessionKey,
1545
- storePath: turn.storePath,
1510
+ route: {
1511
+ agentId: route.agentId,
1512
+ sessionKey: persistedSessionKey
1513
+ },
1546
1514
  ctxPayload,
1547
- recordInboundSession,
1548
1515
  afterRecord: queueInitialAckReactionAfterRecord,
1549
- dispatchReplyWithBufferedBlockDispatcher: withDiscordSessionRetry(dispatchReply, abortSignal),
1516
+ sessionInitRetry: {
1517
+ delaysMs: [
1518
+ 250,
1519
+ 1e3,
1520
+ 2500
1521
+ ],
1522
+ signal: abortSignal,
1523
+ sleep: sleepWithAbort
1524
+ },
1550
1525
  dispatcherOptions: {
1551
1526
  ...replyPipeline,
1552
1527
  humanDelay: resolveHumanDelayConfig(cfg, route.agentId),
@@ -1566,6 +1541,7 @@ async function processDiscordMessageInner(ctx, observer) {
1566
1541
  limit: historyLimit
1567
1542
  },
1568
1543
  replyOptions: {
1544
+ ...turnAdoptionLifecycle ? bindIngressLifecycleToReplyOptions(turnAdoptionLifecycle) : {},
1569
1545
  abortSignal,
1570
1546
  skillFilter: channelConfig?.skills,
1571
1547
  sourceReplyDeliveryMode,
@@ -1643,7 +1619,7 @@ async function processDiscordMessageInner(ctx, observer) {
1643
1619
  },
1644
1620
  onPlanUpdate: async (payload) => {
1645
1621
  if (payload.phase !== "update") return;
1646
- await draftPreview.pushPlanProgress(payload.planSteps, { explanation: payload.explanation });
1622
+ await draftPreview.pushPlanProgress(payload.steps, { explanation: payload.explanation });
1647
1623
  },
1648
1624
  onApprovalEvent: async (payload) => {
1649
1625
  if (payload.phase !== "requested") return;
@@ -1,4 +1,4 @@
1
- import { u as resolveDiscordChannelInfoSafe } from "./thread-bindings.discord-api-DXfXsHGZ.js";
1
+ import { u as resolveDiscordChannelInfoSafe } from "./thread-bindings.discord-api-mNCWlgvM.js";
2
2
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalString, normalizeOptionalStringifiedId, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
3
3
  import { ComponentType, StickerFormatType } from "discord-api-types/v10";
4
4
  import { asDateTimestampMs, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
@@ -1,6 +1,8 @@
1
- import { n as createDiscordSendReceipt, o as resolveDiscordReplyReference, t as chunkDiscordTextWithMode, u as normalizeDiscordOutboundTarget } from "./chunk-CHpY_lsO.js";
1
+ import { c as normalizeDiscordOutboundTarget, i as resolveDiscordReplyReference, t as chunkDiscordTextWithMode } from "./chunk-CWzmeWf_.js";
2
+ import { t as createDiscordSendReceipt } from "./send.receipt-CuwRrpFz.js";
3
+ import { n as formatDiscordApprovalDisplayValue } from "./approval-message-safety-DrLlgIPz.js";
2
4
  import { n as notifyDiscordInboundEventOutboundPayloadSuccess } from "./inbound-event-delivery-CEPlt2uz.js";
3
- import { a as sendDiscordComponentMessageLazy, i as resolveDiscordComponentSpec, n as buildDiscordPresentationPayload, t as DISCORD_PRESENTATION_CAPABILITIES } from "./outbound-components-7wAolLuS.js";
5
+ import { a as sendDiscordComponentMessageLazy, i as resolveDiscordComponentSpec, n as buildDiscordPresentationPayload, t as DISCORD_PRESENTATION_CAPABILITIES } from "./outbound-components-BGhk6HI3.js";
4
6
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalString, normalizeOptionalStringifiedId } from "openclaw/plugin-sdk/string-coerce-runtime";
5
7
  import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
6
8
  import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
@@ -8,6 +10,7 @@ import { createReplyToFanout, resolveOutboundSendDep } from "openclaw/plugin-sdk
8
10
  import { getReplyPayloadTtsSupplement, resolvePayloadMediaUrls, sendPayloadMediaSequenceOrFallback, sendTextMediaPayload } from "openclaw/plugin-sdk/reply-payload";
9
11
  import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
10
12
  import { attachChannelToResult, createAttachedChannelResultAdapter } from "openclaw/plugin-sdk/channel-send-result";
13
+ import { questionGatewayRuntime } from "openclaw/plugin-sdk/question-gateway-runtime";
11
14
  //#region extensions/discord/src/media-detection.ts
12
15
  const DISCORD_VIDEO_MEDIA_EXTENSIONS = /* @__PURE__ */ new Set([
13
16
  ".avi",
@@ -56,7 +59,7 @@ function normalizeDiscordApprovalPayload(payload) {
56
59
  }
57
60
  //#endregion
58
61
  //#region extensions/discord/src/outbound-send-context.ts
59
- const loadDiscordSendRuntime = createLazyRuntimeModule(() => import("./send-JJzVo_sK.js").then((n) => n.t));
62
+ const loadDiscordSendRuntime = createLazyRuntimeModule(() => import("./send-CSRxNNgq.js").then((n) => n.t));
60
63
  function resolveDiscordOutboundTarget(params) {
61
64
  if (params.threadId == null) return params.to;
62
65
  const threadId = normalizeOptionalStringifiedId(params.threadId) ?? "";
@@ -241,7 +244,8 @@ const DISCORD_INTERNAL_RUNTIME_SCAFFOLDING_TAG_RE = /<\s*\/?\s*(?:system-reminde
241
244
  function stripDiscordInternalRuntimeScaffolding(text) {
242
245
  return text.replace(DISCORD_INTERNAL_RUNTIME_SCAFFOLDING_BLOCK_RE, "").replace(DISCORD_INTERNAL_RUNTIME_SCAFFOLDING_SELF_CLOSING_RE, "").replace(DISCORD_INTERNAL_RUNTIME_SCAFFOLDING_TAG_RE, "");
243
246
  }
244
- const loadDiscordThreadBindings = createLazyRuntimeModule(() => import("./thread-bindings-4MV-u8vU.js").then((n) => n.t));
247
+ const loadDiscordThreadBindings = createLazyRuntimeModule(() => import("./thread-bindings-CJQoXuWY.js").then((n) => n.t));
248
+ const loadDiscordComponentSendRuntime = createLazyRuntimeModule(() => import("./send.components-DLqzOEPJ.js").then((n) => n.i));
245
249
  function resolveDiscordWebhookIdentity(params) {
246
250
  const usernameRaw = normalizeOptionalString(params.identity?.name);
247
251
  const fallbackUsername = normalizeOptionalString(params.binding.label) ?? params.binding.agentId;
@@ -411,7 +415,7 @@ const discordOutbound = {
411
415
  cfg
412
416
  })
413
417
  }),
414
- afterDeliverPayload: async ({ target, payload }) => {
418
+ afterDeliverPayload: async ({ cfg, target, payload, results }) => {
415
419
  notifyDiscordInboundEventOutboundPayloadSuccess({
416
420
  payload,
417
421
  to: resolveDiscordOutboundTarget({
@@ -420,6 +424,33 @@ const discordOutbound = {
420
424
  }),
421
425
  accountId: target.accountId
422
426
  });
427
+ const questionId = questionGatewayRuntime.readAskUserQuestionId(payload);
428
+ const result = results.find((candidate) => candidate.channel === "discord" && candidate.messageId);
429
+ const componentSpec = questionId ? await resolveDiscordComponentSpec(payload) : void 0;
430
+ if (questionId && result && componentSpec) {
431
+ const to = resolveDiscordOutboundTarget({
432
+ to: target.to,
433
+ threadId: target.threadId
434
+ });
435
+ questionGatewayRuntime.registerChannelDelivery({
436
+ questionId,
437
+ deliveryId: `discord:${target.accountId ?? "default"}:${result.channelId ?? to}:${result.messageId}`,
438
+ finalize: async (statusLine) => {
439
+ const { editDiscordComponentMessage } = await loadDiscordComponentSendRuntime();
440
+ await editDiscordComponentMessage(to, result.messageId, {
441
+ ...componentSpec,
442
+ blocks: [...(componentSpec.blocks ?? []).filter((block) => block.type !== "actions"), {
443
+ type: "text",
444
+ text: `-# ${formatDiscordApprovalDisplayValue(statusLine)}`
445
+ }],
446
+ modal: void 0
447
+ }, {
448
+ cfg,
449
+ accountId: target.accountId ?? void 0
450
+ });
451
+ }
452
+ });
453
+ }
423
454
  const threadId = normalizeOptionalStringifiedId(target.threadId);
424
455
  if (!threadId) return;
425
456
  const { getThreadBindingManager } = await loadDiscordThreadBindings();
@@ -1,4 +1,4 @@
1
- import { m as readDiscordComponentSpec } from "./outbound-session-route-D4QqePZN.js";
1
+ import { h as readDiscordComponentSpec } from "./outbound-session-route-M2bEY9tI.js";
2
2
  import { createLazyRuntimeModule, createLazyRuntimeNamedExport } from "openclaw/plugin-sdk/lazy-runtime";
3
3
  //#region extensions/discord/src/outbound-components.ts
4
4
  const DISCORD_MESSAGE_COMPONENT_LIMIT = 40;
@@ -30,11 +30,11 @@ const DISCORD_PRESENTATION_CAPABILITIES = {
30
30
  }
31
31
  }
32
32
  };
33
- const loadDiscordComponentSend = createLazyRuntimeNamedExport(() => import("./send.components-CCRW54gK.js").then((n) => n.i), "sendDiscordComponentMessage");
33
+ const loadDiscordComponentSend = createLazyRuntimeNamedExport(() => import("./send.components-DLqzOEPJ.js").then((n) => n.i), "sendDiscordComponentMessage");
34
34
  async function sendDiscordComponentMessageLazy(...args) {
35
35
  return await (await loadDiscordComponentSend())(...args);
36
36
  }
37
- const loadDiscordSharedInteractive = createLazyRuntimeModule(() => import("./outbound-session-route-D4QqePZN.js").then((n) => n.o));
37
+ const loadDiscordSharedInteractive = createLazyRuntimeModule(() => import("./outbound-session-route-M2bEY9tI.js").then((n) => n.o));
38
38
  function addPayloadTextFallback(spec, payload) {
39
39
  return spec.text ? spec : {
40
40
  ...spec,
@@ -1,9 +1,9 @@
1
- import { $ as RoleSelectMenu, G as TextInput, H as Label, J as Container, K as Button, Q as MentionableSelectMenu, U as Modal, V as CheckboxGroup, W as RadioGroup, X as LinkButton, Y as File, Z as MediaGallery, Zt as __exportAll, at as Thumbnail, ct as parseCustomId, d as parseDiscordTarget, et as Row, it as TextDisplay, nt as Separator, ot as UserSelectMenu, q as ChannelSelectMenu, rt as StringSelectMenu, tt as Section } from "./chunk-CHpY_lsO.js";
1
+ import { $ as Section, B as Label, G as ChannelSelectMenu, H as RadioGroup, J as LinkButton, K as Container, Q as Row, U as TextInput, V as Modal, W as Button, X as MentionableSelectMenu, Y as MediaGallery, Yt as __exportAll, Z as RoleSelectMenu, et as Separator, it as UserSelectMenu, l as parseDiscordTarget, nt as TextDisplay, ot as parseCustomId, q as File, rt as Thumbnail, tt as StringSelectMenu, z as CheckboxGroup } from "./chunk-CWzmeWf_.js";
2
2
  import { buildOutboundBaseSessionKey } from "openclaw/plugin-sdk/routing";
3
3
  import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
4
4
  import { ButtonStyle, MessageFlags, TextInputStyle } from "discord-api-types/v10";
5
5
  import crypto from "node:crypto";
6
- import { reduceInteractiveReply, resolveMessagePresentationButtonAction, resolveMessagePresentationOptionAction } from "openclaw/plugin-sdk/interactive-runtime";
6
+ import { reduceLegacyInteractiveReply, resolveMessagePresentationButtonAction, resolveMessagePresentationOptionAction } from "openclaw/plugin-sdk/interactive-runtime";
7
7
  import { buildApprovalResolutionRef } from "openclaw/plugin-sdk/approval-reference-runtime";
8
8
  import { buildThreadAwareOutboundSessionRoute } from "openclaw/plugin-sdk/channel-core";
9
9
  //#region extensions/discord/src/custom-id-codec.ts
@@ -889,6 +889,24 @@ function parseExecApprovalData(data) {
889
889
  };
890
890
  }
891
891
  //#endregion
892
+ //#region extensions/discord/src/question-custom-id.ts
893
+ const DISCORD_QUESTION_CUSTOM_ID_MAX_CHARS = 100;
894
+ const QUESTION_RECORD_ID_PATTERN = /^ask_[a-f0-9]{32}$/u;
895
+ function buildDiscordQuestionCustomId(callback) {
896
+ if (!QUESTION_RECORD_ID_PATTERN.test(callback.questionId) || !Number.isInteger(callback.optionIndex) || callback.optionIndex < 0 || callback.optionIndex > 3) return;
897
+ const customId = `ocq:id=${callback.questionId};i=${callback.optionIndex}`;
898
+ return customId.length <= DISCORD_QUESTION_CUSTOM_ID_MAX_CHARS ? customId : void 0;
899
+ }
900
+ function parseDiscordQuestionData(data) {
901
+ const questionId = typeof data.id === "string" ? data.id : "";
902
+ const rawIndex = typeof data.i === "string" ? data.i : typeof data.i === "number" ? String(data.i) : "";
903
+ if (!QUESTION_RECORD_ID_PATTERN.test(questionId) || !/^[0-3]$/u.test(rawIndex)) return null;
904
+ return {
905
+ questionId,
906
+ optionIndex: Number(rawIndex)
907
+ };
908
+ }
909
+ //#endregion
892
910
  //#region extensions/discord/src/shared-interactive.ts
893
911
  var shared_interactive_exports = /* @__PURE__ */ __exportAll({
894
912
  buildDiscordInteractiveComponents: () => buildDiscordInteractiveComponents,
@@ -909,7 +927,7 @@ function resolveDiscordSelectCallbackDataKind(options) {
909
927
  if (renderableOptions.some((option) => option.action)) return "mixed";
910
928
  }
911
929
  const DISCORD_INTERACTIVE_BUTTON_ROW_SIZE = 5;
912
- function buildDiscordButtonComponent(button) {
930
+ function buildDiscordButtonComponent(button, optionIndex) {
913
931
  const action = resolveMessagePresentationButtonAction(button);
914
932
  if (!action) return;
915
933
  if (action.type === "approval") {
@@ -922,6 +940,18 @@ function buildDiscordButtonComponent(button) {
922
940
  ...button.disabled === true ? { disabled: true } : {}
923
941
  };
924
942
  }
943
+ if (action.type === "question") {
944
+ const internalCustomId = buildDiscordQuestionCustomId({
945
+ questionId: action.questionId,
946
+ optionIndex
947
+ });
948
+ return internalCustomId ? {
949
+ label: button.label,
950
+ style: resolveDiscordInteractiveButtonStyle(button.style),
951
+ internalCustomId,
952
+ ...button.disabled === true ? { disabled: true } : {}
953
+ } : void 0;
954
+ }
925
955
  if (action.type === "web-app" && action.widgetId && isValidDiscordActivityWidgetId(action.widgetId)) return {
926
956
  label: button.label,
927
957
  style: resolveDiscordInteractiveButtonStyle(button.style),
@@ -944,7 +974,7 @@ function buildDiscordButtonComponent(button) {
944
974
  return component;
945
975
  }
946
976
  function appendDiscordButtonBlocks(blocks, buttons) {
947
- const components = buttons.map((button) => buildDiscordButtonComponent(button)).filter((button) => Boolean(button));
977
+ const components = buttons.map((button, optionIndex) => buildDiscordButtonComponent(button, optionIndex)).filter((button) => Boolean(button));
948
978
  for (let index = 0; index < components.length; index += DISCORD_INTERACTIVE_BUTTON_ROW_SIZE) blocks.push({
949
979
  type: "actions",
950
980
  buttons: components.slice(index, index + DISCORD_INTERACTIVE_BUTTON_ROW_SIZE)
@@ -954,7 +984,7 @@ function appendDiscordButtonBlocks(blocks, buttons) {
954
984
  * @deprecated Use buildDiscordPresentationComponents with MessagePresentation.
955
985
  */
956
986
  function buildDiscordInteractiveComponents(interactive) {
957
- const blocks = reduceInteractiveReply(interactive, [], (state, block) => {
987
+ const blocks = reduceLegacyInteractiveReply(interactive, [], (state, block) => {
958
988
  if (block.type === "text") {
959
989
  const text = block.text.trim();
960
990
  if (text) state.push({
@@ -1112,4 +1142,4 @@ function resolveDiscordOutboundTargetKindHint(params) {
1112
1142
  return "channel";
1113
1143
  }
1114
1144
  //#endregion
1115
- export { parseDiscordComponentCustomId as C, decodeCustomIdComponent as D, parseDiscordModalCustomIdForInteraction as E, encodeCustomIdComponent as O, parseDiscordActivityCustomIdForInteraction as S, parseDiscordModalCustomId as T, DISCORD_MODAL_CUSTOM_ID_KEY as _, buildDiscordPresentationComponents as a, buildDiscordModalCustomId as b, parseExecApprovalData as c, buildDiscordComponentMessage as d, buildDiscordComponentMessageFlags as f, DISCORD_COMPONENT_CUSTOM_ID_KEY as g, resolveDiscordComponentAttachmentName as h, buildDiscordInteractiveComponents as i, DiscordFormModal as l, readDiscordComponentSpec as m, components_exports as n, shared_interactive_exports as o, DISCORD_COMPONENT_ATTACHMENT_PREFIX as p, formatDiscordComponentEventText as r, buildExecApprovalCustomId as s, resolveDiscordOutboundSessionRoute as t, createDiscordFormModal as u, buildDiscordActivityCustomId as v, parseDiscordComponentCustomIdForInteraction as w, parseDiscordActivityCustomId as x, buildDiscordComponentCustomId as y };
1145
+ export { parseDiscordActivityCustomIdForInteraction as C, parseDiscordModalCustomIdForInteraction as D, parseDiscordModalCustomId as E, decodeCustomIdComponent as O, parseDiscordActivityCustomId as S, parseDiscordComponentCustomIdForInteraction as T, DISCORD_COMPONENT_CUSTOM_ID_KEY as _, buildDiscordPresentationComponents as a, buildDiscordComponentCustomId as b, buildExecApprovalCustomId as c, createDiscordFormModal as d, buildDiscordComponentMessage as f, resolveDiscordComponentAttachmentName as g, readDiscordComponentSpec as h, buildDiscordInteractiveComponents as i, encodeCustomIdComponent as k, parseExecApprovalData as l, DISCORD_COMPONENT_ATTACHMENT_PREFIX as m, components_exports as n, shared_interactive_exports as o, buildDiscordComponentMessageFlags as p, formatDiscordComponentEventText as r, parseDiscordQuestionData as s, resolveDiscordOutboundSessionRoute as t, DiscordFormModal as u, DISCORD_MODAL_CUSTOM_ID_KEY as v, parseDiscordComponentCustomId as w, buildDiscordModalCustomId as x, buildDiscordActivityCustomId as y };
@@ -1,4 +1,4 @@
1
- import { Zt as __exportAll } from "./chunk-CHpY_lsO.js";
1
+ import { Yt as __exportAll } from "./chunk-CWzmeWf_.js";
2
2
  import { readProviderJsonResponse, readResponseTextLimited } from "openclaw/plugin-sdk/provider-http";
3
3
  import { resolveFetch } from "openclaw/plugin-sdk/fetch-runtime";
4
4
  import { buildTimeoutAbortSignal } from "openclaw/plugin-sdk/extension-shared";
@@ -1,5 +1,5 @@
1
1
  import { p as normalizeDiscordToken } from "./accounts-CMd4nzLB.js";
2
- import { n as DiscordApiError, r as fetchDiscord } from "./api-B88T4rFN.js";
2
+ import { n as DiscordApiError, r as fetchDiscord } from "./api-C43z8vUm.js";
3
3
  import { readResponseWithLimit } from "openclaw/plugin-sdk/response-limit-runtime";
4
4
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
5
5
  import { resolveFetch } from "openclaw/plugin-sdk/fetch-runtime";
@@ -1,2 +1,2 @@
1
- import { a as resolveDiscordPrivilegedIntentsFromFlags, i as probeDiscord, n as fetchDiscordApplicationSummary, r as parseApplicationIdFromToken, t as fetchDiscordApplicationId } from "./probe-WKeTYyJX.js";
1
+ import { a as resolveDiscordPrivilegedIntentsFromFlags, i as probeDiscord, n as fetchDiscordApplicationSummary, r as parseApplicationIdFromToken, t as fetchDiscordApplicationId } from "./probe-C3SCKyYU.js";
2
2
  export { fetchDiscordApplicationId, fetchDiscordApplicationSummary, parseApplicationIdFromToken, probeDiscord, resolveDiscordPrivilegedIntentsFromFlags };