@openclaw/discord 2026.7.2-beta.7 → 2026.8.1-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/dist/{account-inspect-SXiCBCgP.js → account-inspect-CqzrH14k.js} +48 -42
  2. package/dist/account-inspect-api.js +1 -1
  3. package/dist/action-runtime-api.js +1 -1
  4. package/dist/{active-turn-thread-route-MlKWp8RD.js → active-turn-thread-route-fmHl1HNd.js} +9 -11
  5. package/dist/{activities-api-DTKsuDxf.js → activities-api-DS7vpdtp.js} +4 -4
  6. package/dist/activities-api.js +1 -1
  7. package/dist/{allow-list-DzKrtfah.js → allow-list-DnxIlPP2.js} +2 -3
  8. package/dist/{api-DnrK9gML.js → api-DNVbJyEy.js} +7 -2
  9. package/dist/api.js +15 -15
  10. package/dist/{approval-handler.runtime-HymvFTYn.js → approval-handler.runtime-B6yEV79q.js} +5 -5
  11. package/dist/{approval-message-safety-DEyKVsAw.js → approval-message-safety-AcIxvrf3.js} +1 -1
  12. package/dist/{audit-CjsrabP8.js → audit-Db-rlntl.js} +4 -4
  13. package/dist/{channel-vKa-76xY.js → channel-CnnbJSt5.js} +46 -72
  14. package/dist/{channel-actions-uXFTJX3o.js → channel-actions-5s_hjYKd.js} +4 -4
  15. package/dist/{channel-actions.runtime-CIYU90sl.js → channel-actions.runtime-CLKrx6tr.js} +53 -36
  16. package/dist/channel-config-api.js +1 -1
  17. package/dist/channel-plugin-api.js +1 -1
  18. package/dist/{channel.setup-CmcwZ_qd.js → channel.setup-BFAO-V1P.js} +15 -53
  19. package/dist/{config-schema-WHRQcY19.js → config-schema-BgEskFAs.js} +9 -4
  20. package/dist/{directory-config-D_LojtCe.js → directory-config-BVX7Cflc.js} +1 -1
  21. package/dist/directory-contract-api.js +1 -1
  22. package/dist/{directory-live-Bw5Ephzv.js → directory-live-DGIGxpIo.js} +6 -3
  23. package/dist/{doctor-Bc4S1qyd.js → doctor-BzC-TLnB.js} +4 -4
  24. package/dist/{doctor-contract-CCFMIDk9.js → doctor-contract-DLa-BTiU.js} +2 -3
  25. package/dist/doctor-contract-api.js +147 -2
  26. package/dist/{handle-action.guild-admin-D6VRRW-C.js → handle-action.guild-admin-BNVTUISF.js} +4 -7
  27. package/dist/{inbound-event-delivery-CEPlt2uz.js → inbound-event-delivery-De2qxTrP.js} +4 -25
  28. package/dist/index.js +4 -2
  29. package/dist/{message-handler-CeiSulIw.js → message-handler-Unk_f10F.js} +41 -32
  30. package/dist/{message-handler.preflight-DibgQFf2.js → message-handler.preflight-C9zecxR9.js} +50 -26
  31. package/dist/{message-handler.process-Dnc_oz9y.js → message-handler.process-DWQ6UHHu.js} +130 -166
  32. package/dist/{message-utils-BgTwT_q7.js → message-utils-BSCPVgy0.js} +4 -4
  33. package/dist/{model-picker-preference-primitives-D25pnCOu.js → model-picker-preference-primitives-BHT1LkR_.js} +3 -3
  34. package/dist/{outbound-adapter-DtE-i2OJ.js → outbound-adapter-D9nRivT1.js} +91 -32
  35. package/dist/{outbound-components-C7GVyfPh.js → outbound-components-cTzwBJ60.js} +3 -3
  36. package/dist/{outbound-session-route-H-HoyH5U.js → outbound-session-route-DxLkrgKQ.js} +68 -95
  37. package/dist/{pluralkit-CD4B11JB.js → pluralkit-DdiJ9KMK.js} +1 -1
  38. package/dist/{preflight-audio-BjnQZ5yS.js → preflight-audio-DrnqFA8U.js} +22 -28
  39. package/dist/{probe-BeWKhjqX.js → probe-Bl-k5_Ku.js} +36 -12
  40. package/dist/probe.runtime-M9fREKvp.js +2 -0
  41. package/dist/{provider-DfQJX3z5.js → provider-DvSNb-2v.js} +969 -1248
  42. package/dist/{provider-session.runtime-Bo88k0pV.js → provider-session.runtime-BUEqD0rA.js} +3 -3
  43. package/dist/provider.runtime-C9PnJZbZ.js +2 -0
  44. package/dist/realtime-session.runtime-C7wen-aF.js +1340 -0
  45. package/dist/{resolve-allowlist-common-DHERApxi.js → resolve-allowlist-common-D04lpEzb.js} +2 -2
  46. package/dist/{resolve-channels-BjepAj8b.js → resolve-channels-Dm7jEeg6.js} +4 -4
  47. package/dist/{resolve-users-Bc28htgt.js → resolve-users-bktrCUUU.js} +3 -3
  48. package/dist/{chunk-DX4jpFQP.js → retry-CLpJcXXf.js} +291 -68
  49. package/dist/{runtime-_aRC6V2s.js → runtime-DGsSyDTS.js} +30 -25
  50. package/dist/{runtime-BmW_j_hl.js → runtime-DoHjckYm.js} +4 -6
  51. package/dist/runtime-api.actions.js +2 -2
  52. package/dist/runtime-api.js +22 -23
  53. package/dist/runtime-api.lookup.js +5 -5
  54. package/dist/runtime-api.monitor-CHxrFPnW.js +5 -0
  55. package/dist/runtime-api.monitor.js +5 -5
  56. package/dist/runtime-api.send.js +6 -6
  57. package/dist/runtime-api.threads.js +5 -6
  58. package/dist/sdk-runtime-QpY8PvCh.js +370 -0
  59. package/dist/{send-CdkZ6zeW.js → send-B7Q6Oc1I.js} +175 -86
  60. package/dist/{send.components-5uqwkjgE.js → send.components-iJyFXw9L.js} +24 -28
  61. package/dist/{send.outbound-D-80Ej-t.js → send.outbound-DS5tHwfR.js} +37 -24
  62. package/dist/{send.reactions-CtlmGd_o.js → send.reactions-BAn0iiVQ.js} +14 -21
  63. package/dist/{send.receipt-CuwRrpFz.js → send.receipt-IPI1p-SP.js} +19 -1
  64. package/dist/{send.shared-jpvAG_u6.js → send.shared-BmwFjW6T.js} +16 -85
  65. package/dist/{sender-identity-mG_zsdox.js → sender-identity-QtalnCYv.js} +1 -1
  66. package/dist/setup-entry.js +0 -5
  67. package/dist/setup-plugin-api.js +1 -1
  68. package/dist/{shared-CXF1tup1.js → shared-BIXIX6uJ.js} +16 -17
  69. package/dist/{subagent-hooks-Dxy7Fmnq.js → subagent-hooks-CTt5KCJr.js} +2 -2
  70. package/dist/subagent-hooks-api.js +2 -6
  71. package/dist/subagent-progress-DhaE_h8a.js +109 -0
  72. package/dist/{system-events-DdUqf91B.js → system-events-CTqDf6_s.js} +2 -2
  73. package/dist/{target-resolver-C3s_2m0t.js → target-resolver-maOKSqO0.js} +2 -2
  74. package/dist/targets-yUFTHoAx.js +3 -0
  75. package/dist/{thread-bindings-C-M-ly7P.js → thread-bindings-3L8p82GV.js} +5 -7
  76. package/dist/{thread-bindings.manager-DYvSlrva.js → thread-bindings.manager-DCIH6WDC.js} +257 -29
  77. package/dist/{thread-bindings.session-updates-DAIlp7Px.js → thread-bindings.session-updates-bJ2KQFY6.js} +1 -1
  78. package/dist/{thread-bindings.state-Cgi5uRn-.js → thread-bindings.state-aeV8HNgV.js} +2 -15
  79. package/dist/{transcripts-source-DIKGsTGT.js → transcripts-source-CfFMexGt.js} +1 -1
  80. package/dist/transcripts-source-api.js +1 -1
  81. package/dist/{typing--Mzo2kM7.js → typing-CS-nNVoe.js} +1 -1
  82. package/dist/voice-runtime-BEdqNcST.js +2459 -0
  83. package/openclaw.plugin.json +203 -19
  84. package/package.json +15 -9
  85. package/skills/discord/SKILL.md +22 -115
  86. package/dist/legacy-state-migrations-api.js +0 -138
  87. package/dist/manager.runtime-Bjav3pfC.js +0 -3655
  88. package/dist/preflight-audio.runtime-CoCXMM8r.js +0 -7
  89. package/dist/probe.runtime-DqFGFMbZ.js +0 -2
  90. package/dist/provider.runtime-Cy7XZmyh.js +0 -2
  91. package/dist/runtime-api.monitor-CCRubd3-.js +0 -5
  92. package/dist/session-binding-contract-api.js +0 -2
  93. package/dist/subagent-progress-DI3sYLLo.js +0 -664
  94. package/dist/targets-Dv_RN7vT.js +0 -3
  95. package/dist/thread-bindings.discord-api-BoDNqamb.js +0 -246
@@ -1,21 +1,21 @@
1
- import { d as discord_exports, gt as deleteChannelMessage, pt as createChannelMessage, t as chunkDiscordTextWithMode, u as resolveDiscordChannelId, vt as editChannelMessage } from "./chunk-DX4jpFQP.js";
1
+ import { St as deleteChannelMessage, a as chunkDiscordTextWithMode, h as discord_exports, m as resolveDiscordChannelId, wt as editChannelMessage, yt as createChannelMessage } from "./retry-CLpJcXXf.js";
2
2
  import { f as resolveDiscordMaxLinesPerMessage } from "./accounts-DJTf1LtA.js";
3
- import { F as createDiscordRestClient, I as createDiscordRuntimeAccountContext, _ as resolveDiscordMessageFlags, d as resolveDiscordTargetChannelId } from "./send.shared-jpvAG_u6.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-D-80Ej-t.js";
6
- import { s as editMessageDiscord } from "./send-CdkZ6zeW.js";
3
+ import { F as createDiscordRestClient, I as createDiscordRuntimeAccountContext, _ as resolveDiscordMessageFlags, d as resolveDiscordTargetChannelId } from "./send.shared-BmwFjW6T.js";
4
+ import { C as resolveTimestampMs, a as normalizeDiscordSlug, r as normalizeDiscordAllowList } from "./allow-list-DnxIlPP2.js";
5
+ import { i as discordTextHasBroadcastMention } from "./send.outbound-DS5tHwfR.js";
6
+ import { c as editMessageDiscord } from "./send-B7Q6Oc1I.js";
7
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-CtlmGd_o.js";
9
- import "./targets-Dv_RN7vT.js";
10
- import { r as resolveDiscordConversationIdentity } from "./approval-message-safety-DEyKVsAw.js";
11
- import { t as beginDiscordInboundEventDeliveryCorrelation } from "./inbound-event-delivery-CEPlt2uz.js";
12
- import { t as DISCORD_TEXT_CHUNK_LIMIT } from "./outbound-adapter-DtE-i2OJ.js";
13
- import { D as resolveDiscordAutoThreadReplyPlan, _ as buildDiscordInboundAccessContext, a as sanitizeDiscordFrontChannelReplyPayloads, c as resolveReplyContext, i as formatDiscordReplySkip, k as resolveDiscordThreadStarter, n as deliverDiscordReply, o as buildDirectLabel, r as formatDiscordReplyDeliveryFailure, s as buildGuildLabel, v as createDiscordSupplementalContextAccessChecker } from "./provider-DfQJX3z5.js";
14
- import { a as formatDiscordMediaText, c as resolveReferencedReplyMediaList, i as resolveDiscordMessageText, u as resolveDiscordMessageStickers } from "./message-utils-BgTwT_q7.js";
15
- import { n as resolveDiscordWebhookId } from "./sender-identity-mG_zsdox.js";
16
- import { t as beginDiscordActiveTurnThreadRoute } from "./active-turn-thread-route-MlKWp8RD.js";
8
+ import { i as removeReactionDiscord, n as reactMessageDiscord } from "./send.reactions-BAn0iiVQ.js";
9
+ import "./targets-yUFTHoAx.js";
10
+ import { r as resolveDiscordConversationIdentity } from "./approval-message-safety-AcIxvrf3.js";
11
+ import { t as discordInboundEventDelivery } from "./inbound-event-delivery-De2qxTrP.js";
12
+ import { t as DISCORD_TEXT_CHUNK_LIMIT } from "./outbound-adapter-D9nRivT1.js";
13
+ import { D as resolveDiscordAutoThreadReplyPlan, _ as buildDiscordInboundAccessContext, a as sanitizeDiscordFrontChannelReplyPayloads, c as resolveReplyContext, i as formatDiscordReplySkip, k as resolveDiscordThreadStarter, n as deliverDiscordReply, o as buildDirectLabel, r as formatDiscordReplyDeliveryFailure, s as buildGuildLabel, v as createDiscordSupplementalContextAccessChecker } from "./provider-DvSNb-2v.js";
14
+ import { a as formatDiscordMediaText, c as resolveReferencedReplyMediaList, i as resolveDiscordMessageText, u as resolveDiscordMessageStickers } from "./message-utils-BSCPVgy0.js";
15
+ import { n as resolveDiscordWebhookId } from "./sender-identity-QtalnCYv.js";
16
+ import { t as beginDiscordActiveTurnThreadRoute } from "./active-turn-thread-route-fmHl1HNd.js";
17
17
  import { n as filterDiscordHistoryEntriesForContext, t as createDiscordHistorySenderProvenance } from "./message-handler.history-CJOsN9w5.js";
18
- import { t as sendTyping } from "./typing--Mzo2kM7.js";
18
+ import { t as sendTyping } from "./typing-CS-nNVoe.js";
19
19
  import { buildAgentSessionKey, resolveThreadSessionKeys } from "openclaw/plugin-sdk/routing";
20
20
  import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
21
21
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
@@ -24,14 +24,14 @@ import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
24
24
  import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
25
25
  import { resolveChunkMode } from "openclaw/plugin-sdk/reply-chunking";
26
26
  import { convertMarkdownTables, stripInlineDirectiveTagsForDelivery, stripReasoningTagsFromText } from "openclaw/plugin-sdk/text-chunking";
27
- import { bindIngressLifecycleToReplyOptions, buildChannelProgressDraftLine, buildChannelProgressDraftLineForEntry, createChannelMessageReplyPipeline, createChannelProgressDraftCompositor, createFinalizableDraftLifecycle, createTypingCallbacks, defineFinalizableLivePreviewAdapter, deliverWithFinalizableLivePreviewAdapter, isChannelProgressDraftWorkToolName, resolveChannelDraftStreamingChunking, resolveChannelMessageSourceReplyDeliveryMode, resolveChannelPreviewStreamMode, resolveChannelStreamingBlockEnabled, resolveChannelStreamingPreviewCommandText, resolveChannelStreamingPreviewToolProgress, resolveChannelStreamingProgressNarration, resolveChannelStreamingSuppressDefaultToolProgressMessages, resolveTranscriptBackedChannelFinalText } from "openclaw/plugin-sdk/channel-outbound";
27
+ import { bindIngressLifecycleToReplyOptions, buildChannelProgressDraftLine, buildChannelProgressDraftLineForEntry, createChannelMessageReplyPipeline, createChannelProgressDraftCompositor, createChannelProgressReceiptTracker, createFinalizableDraftLifecycle, createTypingCallbacks, defineFinalizableLivePreviewAdapter, deliverWithFinalizableLivePreviewAdapter, resolveChannelDraftStreamingChunking, resolveChannelMessageSourceReplyDeliveryMode, resolveChannelPreviewStreamMode, resolveChannelStreamingBlockEnabled, resolveChannelStreamingPreviewCommandText, resolveChannelStreamingPreviewToolProgress, resolveChannelStreamingProgressNarration, resolveChannelStreamingSuppressDefaultToolProgressMessages, resolveTranscriptBackedChannelFinalText } from "openclaw/plugin-sdk/channel-outbound";
28
28
  import { getAgentScopedMediaLocalRoots } from "openclaw/plugin-sdk/media-runtime";
29
29
  import { getReplyPayloadTtsSupplement, isReplyPayloadNonTerminalToolErrorWarning, resolveSendableOutboundReplyParts } from "openclaw/plugin-sdk/reply-payload";
30
30
  import { evaluateSupplementalContextVisibility } from "openclaw/plugin-sdk/security-runtime";
31
31
  import { resolvePinnedMainDmOwnerFromAllowlist } from "openclaw/plugin-sdk/conversation-runtime";
32
32
  import { EmbeddedBlockChunker, resolveAckReaction, resolveAgentConfig, resolveHumanDelayConfig } from "openclaw/plugin-sdk/agent-runtime";
33
33
  import { isDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/dangerous-name-runtime";
34
- import { buildChannelInboundEventContext, dispatchChannelInboundTurn, formatInboundEnvelope, hasFinalInboundReplyDispatch, resolveEnvelopeFormatOptions, toHistoryMediaEntries, toInboundMediaFactsWithMetadata } from "openclaw/plugin-sdk/channel-inbound";
34
+ import { buildChannelInboundEventContext, dispatchChannelInboundTurn, formatInboundEnvelope, formatInboundMediaUnavailableText, hasFinalInboundReplyDispatch, readAgentRunTerminalOutcome, resolveEnvelopeFormatOptions, toHistoryMediaEntries, toInboundMediaFactsWithMetadata } from "openclaw/plugin-sdk/channel-inbound";
35
35
  import { getSessionEntry, readSessionUpdatedAt, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
36
36
  import { getGlobalHookRunner } from "openclaw/plugin-sdk/plugin-runtime";
37
37
  import { buildHistoryContextFromEntries, buildInboundHistoryFromEntries, createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
@@ -78,7 +78,7 @@ function isContextAborted(abortSignal) {
78
78
  }
79
79
  async function buildDiscordMessageProcessContext(params) {
80
80
  const { ctx, text, mediaList } = params;
81
- const { cfg, discordConfig, accountId, runtime, botUserId, mediaMaxBytes, discordRestFetch, abortSignal, guildHistories, historyLimit, replyToMode, message, author, sender, canonicalMessageId, data, client, channelInfo, channelName, messageChannelId, isGuildMessage, isDirectMessage, baseText, preflightAudioTranscript, threadChannel, threadParentId, threadParentName, threadParentType, threadName, displayChannelSlug, guildInfo, guildSlug, memberRoleIds, channelConfig, baseSessionKey, boundSessionKey, route, commandAuthorized } = ctx;
81
+ const { cfg, discordConfig, accountId, runtime, botUserId, mediaMaxBytes, discordRestFetch, abortSignal, guildHistories, historyLimit, replyToMode, message, author, sender, canonicalMessageId, data, client, channelInfo, channelName, messageChannelId, isGuildMessage, isDirectMessage, baseText, preflightAudioTranscript, threadChannel, threadParentId, threadParentName, threadParentType, threadName, displayChannelSlug, guildInfo, guildSlug, memberRoleIds, channelConfig, baseSessionKey, boundSessionKey, route, commandAuthorized, resolveChannelIngress } = ctx;
82
82
  const fromLabel = isDirectMessage ? buildDirectLabel(author) : buildGuildLabel({
83
83
  guild: data.guild ?? void 0,
84
84
  channelName: channelName ?? messageChannelId,
@@ -129,11 +129,17 @@ async function buildDiscordMessageProcessContext(params) {
129
129
  });
130
130
  const channelHistory = createChannelHistoryWindow({ historyMap: guildHistories });
131
131
  let visibleChannelHistory;
132
+ const unavailableMediaCount = mediaList.filter((media) => !media.path).length;
133
+ const appendMediaUnavailableNotice = (body) => unavailableMediaCount > 0 ? formatInboundMediaUnavailableText({
134
+ body,
135
+ notice: `[discord ${unavailableMediaCount > 1 ? `${unavailableMediaCount} attachments` : "attachment"} unavailable]`
136
+ }) : body;
137
+ const bodyWithMediaNotice = appendMediaUnavailableNotice(text) ?? text;
132
138
  let combinedBody = formatInboundEnvelope({
133
139
  channel: "Discord",
134
140
  from: fromLabel,
135
141
  timestamp: resolveTimestampMs(message.timestamp),
136
- body: text,
142
+ body: bodyWithMediaNotice,
137
143
  chatType: isDirectMessage ? "direct" : "channel",
138
144
  senderLabel,
139
145
  previousTimestamp,
@@ -270,7 +276,17 @@ async function buildDiscordMessageProcessContext(params) {
270
276
  storePath,
271
277
  sessionKey: effectiveSessionKey
272
278
  });
273
- const ctxPayload = await buildChannelInboundEventContext({
279
+ const channelIngress = await resolveChannelIngress({
280
+ agentId: route.agentId,
281
+ sessionKey: effectiveSessionKey,
282
+ messageId: canonicalMessageId ?? message.id,
283
+ inboundEventKind: ctx.inboundEventKind
284
+ }, {
285
+ parentId: threadChannel ? threadParentId : void 0,
286
+ threadId: threadChannel?.id ?? autoThreadContext?.createdThreadId ?? void 0
287
+ });
288
+ const ctxPayload = await (ctx.buildContext ?? buildChannelInboundEventContext)({
289
+ channelIngress,
274
290
  channel: "discord",
275
291
  resolveSupplementalMedia: true,
276
292
  contextVisibility: contextVisibilityMode,
@@ -314,7 +330,7 @@ async function buildDiscordMessageProcessContext(params) {
314
330
  inboundEventKind: ctx.inboundEventKind,
315
331
  body: combinedBody,
316
332
  rawBody: preflightAudioTranscript ?? baseText,
317
- bodyForAgent: preflightAudioTranscript ?? baseText ?? text,
333
+ bodyForAgent: appendMediaUnavailableNotice(preflightAudioTranscript ?? baseText ?? text),
318
334
  commandBody: preflightAudioTranscript ?? baseText,
319
335
  inboundHistory
320
336
  },
@@ -437,7 +453,7 @@ function isFailedProgress(payload) {
437
453
  }
438
454
  function createDiscordMessageProgressRuntime(params) {
439
455
  const { ctx, draftPreview } = params;
440
- const { cfg, discordConfig, route, abortSignal } = ctx;
456
+ const { cfg, route, abortSignal } = ctx;
441
457
  const reasoningLevel = (() => {
442
458
  const normalizedAgentId = (route.agentId ?? "").trim().toLowerCase() || "main";
443
459
  const cfgDefault = cfg.agents?.list?.find((entry) => ((entry?.id ?? "").trim().toLowerCase() || "main") === normalizedAgentId)?.reasoningDefault ?? cfg.agents?.defaults?.reasoningDefault;
@@ -459,41 +475,9 @@ function createDiscordMessageProgressRuntime(params) {
459
475
  const reasoningDurableEnabled = reasoningLevel === "on";
460
476
  const reasoningWindowEnabled = reasoningLevel === "stream";
461
477
  let shouldYieldDraftCommentary = () => false;
462
- let progressTurnStartedAt = Date.now();
463
- let progressReasoningSteps = 0;
464
- let progressToolCalls = 0;
465
- let progressCommentaryNotes = 0;
466
- const seenCommentaryIds = /* @__PURE__ */ new Set();
467
- let lastCommentaryNoteText = "";
468
- const noteWindowCommentary = (itemId, noteText) => {
469
- const trimmed = noteText?.trim();
470
- if (!trimmed) return;
471
- if (itemId) {
472
- if (seenCommentaryIds.has(itemId)) return;
473
- seenCommentaryIds.add(itemId);
474
- progressCommentaryNotes += 1;
475
- return;
476
- }
477
- if (trimmed !== lastCommentaryNoteText) {
478
- lastCommentaryNoteText = trimmed;
479
- progressCommentaryNotes += 1;
480
- }
481
- };
482
- let windowReasoningOpen = false;
483
- const closePendingWindowThought = () => {
484
- if (windowReasoningOpen) {
485
- windowReasoningOpen = false;
486
- progressReasoningSteps += 1;
487
- }
488
- };
478
+ const progressReceipt = createChannelProgressReceiptTracker();
489
479
  const resetTurnState = () => {
490
- progressTurnStartedAt = Date.now();
491
- progressReasoningSteps = 0;
492
- progressToolCalls = 0;
493
- progressCommentaryNotes = 0;
494
- seenCommentaryIds.clear();
495
- lastCommentaryNoteText = "";
496
- windowReasoningOpen = false;
480
+ progressReceipt.reset();
497
481
  };
498
482
  const handleAssistantMessageBoundary = () => {
499
483
  if (draftPreview.handleAssistantMessageBoundary()) {
@@ -501,28 +485,30 @@ function createDiscordMessageProgressRuntime(params) {
501
485
  params.onTurnReset();
502
486
  }
503
487
  };
504
- const buildProgressSummaryLine = () => {
505
- closePendingWindowThought();
506
- const seconds = Math.max(1, Math.round((Date.now() - progressTurnStartedAt) / 1e3));
507
- return `-# ${[
508
- ...progressReasoningSteps > 0 ? [`🧠 ${progressReasoningSteps} thought${progressReasoningSteps === 1 ? "" : "s"}`] : [],
509
- ...progressCommentaryNotes > 0 ? [`💬 ${progressCommentaryNotes} note${progressCommentaryNotes === 1 ? "" : "s"}`] : [],
510
- ...progressToolCalls > 0 ? [`🛠️ ${progressToolCalls} tool call${progressToolCalls === 1 ? "" : "s"}`] : [],
511
- `⏱️ ${seconds}s`
512
- ].join(" · ")}`;
513
- };
488
+ const buildProgressSummaryLine = () => `-# ${progressReceipt.buildSummaryLine()}`;
514
489
  return {
515
490
  replyOptions: {
516
- onAssistantMessageStart: draftPreview.draftStream ? handleAssistantMessageBoundary : void 0,
491
+ onAssistantMessageStart: draftPreview.draftStream ? () => {
492
+ handleAssistantMessageBoundary();
493
+ return false;
494
+ } : void 0,
517
495
  onReasoningEnd: draftPreview.draftStream ? () => {
518
- closePendingWindowThought();
496
+ progressReceipt.closeReasoning();
519
497
  handleAssistantMessageBoundary();
498
+ return false;
499
+ } : void 0,
500
+ onQueuedFollowupAdmitted: draftPreview.draftStream ? () => {
501
+ if (draftPreview.handleQueuedFollowupAdmitted()) {
502
+ resetTurnState();
503
+ params.onTurnReset();
504
+ }
520
505
  } : void 0,
521
506
  suppressDefaultToolProgressMessages: params.sourceRepliesAreToolOnly && params.reactions.statusReactionsExplicitlyEnabled || draftPreview.suppressDefaultToolProgressMessages ? true : void 0,
522
507
  allowToolLifecycleWhenProgressHidden: params.reactions.statusReactionsEnabled ? true : void 0,
523
508
  commentaryProgressEnabled: draftPreview.isProgressMode ? draftPreview.commentaryProgressEnabled : void 0,
524
509
  progressPreambleEnabled: draftPreview.draftStream && draftPreview.isProgressMode ? true : void 0,
525
510
  commentaryPayloadsEnabled: draftPreview.isProgressMode ? draftPreview.commentaryProgressEnabled : void 0,
511
+ shouldDeliverCommentaryPayloads: draftPreview.isProgressMode && draftPreview.commentaryProgressEnabled ? () => shouldYieldDraftCommentary() : void 0,
526
512
  reasoningPayloadsEnabled: reasoningDurableEnabled,
527
513
  onVerboseProgressVisibility: (isActive) => {
528
514
  shouldYieldDraftCommentary = isActive;
@@ -535,97 +521,53 @@ function createDiscordMessageProgressRuntime(params) {
535
521
  isProgressDraftVisible: draftPreview.narrationProgressEnabled ? () => draftPreview.isProgressDraftVisible : void 0,
536
522
  narrationHideCommandText: draftPreview.narrationHideCommandText ? true : void 0,
537
523
  onReasoningStream: async (payload) => {
538
- if (payload?.requiresReasoningProgressOptIn === true && !reasoningWindowEnabled) return;
539
- if (payload?.text) windowReasoningOpen = true;
524
+ if (payload?.requiresReasoningProgressOptIn === true && !reasoningWindowEnabled) return false;
525
+ if (payload?.text) progressReceipt.noteReasoning();
540
526
  await params.reactions.controller.setThinking();
541
- await draftPreview.pushReasoningProgress(payload?.text, { snapshot: payload?.isReasoningSnapshot === true });
527
+ return await draftPreview.pushReasoningProgress(payload?.text, { snapshot: payload?.isReasoningSnapshot === true });
542
528
  },
543
529
  streamReasoningInNonStreamModes: reasoningWindowEnabled,
544
530
  onToolStart: async (payload) => {
545
- if (isProcessAborted$1(abortSignal)) return;
531
+ if (isProcessAborted$1(abortSignal)) return false;
546
532
  await params.reactions.maybeBindToToolReaction(payload);
547
533
  await params.reactions.controller.setTool(payload.name);
548
- if (payload.phase === "start") closePendingWindowThought();
549
- if (payload.phase === "start" && isChannelProgressDraftWorkToolName(payload.name)) progressToolCalls += 1;
550
- await draftPreview.pushToolProgress(buildChannelProgressDraftLineForEntry(discordConfig, {
551
- event: "tool",
552
- itemId: payload.itemId,
553
- toolCallId: payload.toolCallId,
554
- name: payload.name,
555
- phase: payload.phase,
556
- args: payload.args
557
- }, payload.detailMode ? { detailMode: payload.detailMode } : void 0), { toolName: payload.name });
534
+ if (payload.phase === "start") progressReceipt.noteToolCall(payload.name);
535
+ return await draftPreview.pushToolEvent(payload);
558
536
  },
559
537
  onItemEvent: async (payload) => {
560
538
  if (isFailedProgress(payload)) return false;
561
539
  if (payload.kind === "preamble") {
562
540
  if (shouldYieldDraftCommentary()) return;
563
- return await draftPreview.pushPreambleItemEvent(payload, noteWindowCommentary);
541
+ return await draftPreview.pushPreambleItemEvent(payload, (itemId, text) => {
542
+ progressReceipt.noteCommentary(itemId, text);
543
+ });
564
544
  }
565
- await draftPreview.pushToolProgress(buildChannelProgressDraftLineForEntry(discordConfig, {
566
- event: "item",
567
- itemId: payload.itemId,
568
- toolCallId: payload.toolCallId,
569
- itemKind: payload.kind,
570
- title: payload.title,
571
- name: payload.name,
572
- phase: payload.phase,
573
- status: payload.status,
574
- summary: payload.summary,
575
- progressText: payload.progressText,
576
- meta: payload.meta
577
- }));
545
+ return await draftPreview.pushItemEvent(payload);
578
546
  },
579
547
  onPlanUpdate: async (payload) => {
580
- if (payload.phase === "update") await draftPreview.pushPlanProgress(payload.steps, { explanation: payload.explanation });
548
+ if (payload.phase === "update") return await draftPreview.pushPlanProgress(payload.steps, { explanation: payload.explanation });
549
+ return false;
581
550
  },
582
551
  onApprovalEvent: async (payload) => {
583
- if (payload.phase === "requested") await draftPreview.pushToolProgress(buildChannelProgressDraftLine({
584
- event: "approval",
585
- phase: payload.phase,
586
- title: payload.title,
587
- command: payload.command,
588
- reason: payload.reason,
589
- message: payload.message
590
- }));
552
+ return await draftPreview.pushApprovalEvent(payload);
591
553
  },
592
554
  onCommandOutput: async (payload) => {
593
555
  if (isFailedProgress(payload)) return false;
594
- if (payload.phase !== "end") return;
595
- await draftPreview.pushToolProgress(buildChannelProgressDraftLine({
596
- event: "command-output",
597
- itemId: payload.itemId,
598
- toolCallId: payload.toolCallId,
599
- phase: payload.phase,
600
- title: payload.title,
601
- name: payload.name,
602
- status: payload.status,
603
- exitCode: payload.exitCode
604
- }));
556
+ return await draftPreview.pushCommandOutputEvent(payload);
605
557
  },
606
558
  onPatchSummary: async (payload) => {
607
- if (payload.phase !== "end") return;
608
- await draftPreview.pushToolProgress(buildChannelProgressDraftLine({
609
- event: "patch",
610
- itemId: payload.itemId,
611
- toolCallId: payload.toolCallId,
612
- phase: payload.phase,
613
- title: payload.title,
614
- name: payload.name,
615
- added: payload.added,
616
- modified: payload.modified,
617
- deleted: payload.deleted,
618
- summary: payload.summary
619
- }));
559
+ return await draftPreview.pushPatchEvent(payload);
620
560
  },
621
561
  onCompactionStart: async () => {
622
562
  if (!isProcessAborted$1(abortSignal)) await params.reactions.controller.setCompacting();
563
+ return false;
623
564
  },
624
565
  onCompactionEnd: async () => {
625
566
  if (!isProcessAborted$1(abortSignal)) {
626
567
  params.reactions.controller.cancelPending();
627
568
  await params.reactions.controller.setThinking();
628
569
  }
570
+ return false;
629
571
  }
630
572
  },
631
573
  buildProgressSummaryLine
@@ -1029,7 +971,6 @@ function createDiscordDraftStream(params) {
1029
971
  //#endregion
1030
972
  //#region extensions/discord/src/preview-streaming.ts
1031
973
  function resolveDiscordPreviewStreamMode(params = {}) {
1032
- if (params.streaming === void 0) return "progress";
1033
974
  return resolveChannelPreviewStreamMode(params, "off");
1034
975
  }
1035
976
  //#endregion
@@ -1039,9 +980,13 @@ function createDiscordDraftPreviewController(params) {
1039
980
  const hookRunner = getGlobalHookRunner();
1040
981
  const allowProviderPreview = !((hookRunner?.hasHooks("reply_payload_sending") ?? false) || (hookRunner?.hasHooks("message_sending") ?? false));
1041
982
  const draftMaxChars = Math.min(params.textLimit, 2e3);
1042
- const accountBlockStreamingEnabled = resolveChannelStreamingBlockEnabled(params.discordConfig) ?? params.cfg.agents?.defaults?.blockStreamingDefault === "on";
1043
983
  const canStreamProgressDraftForToolOnlySource = params.sourceRepliesAreToolOnly && discordStreamMode === "progress";
1044
- const draftStream = allowProviderPreview && (!params.sourceRepliesAreToolOnly || canStreamProgressDraftForToolOnlySource) && discordStreamMode !== "off" && !accountBlockStreamingEnabled ? createDiscordDraftStream({
984
+ const previewAvailable = allowProviderPreview && (!params.sourceRepliesAreToolOnly || canStreamProgressDraftForToolOnlySource) && discordStreamMode !== "off";
985
+ const accountBlockStreamingEnabled = resolveChannelStreamingBlockEnabled(params.discordConfig, {
986
+ previewAvailable,
987
+ blockStreamingDefault: params.cfg.agents?.defaults?.blockStreamingDefault
988
+ });
989
+ const draftStream = previewAvailable && !accountBlockStreamingEnabled ? createDiscordDraftStream({
1045
990
  rest: params.deliveryRest,
1046
991
  channelId: params.deliverChannelId,
1047
992
  maxChars: draftMaxChars,
@@ -1080,13 +1025,16 @@ function createDiscordDraftPreviewController(params) {
1080
1025
  commentaryLinePrefix: "💬 ",
1081
1026
  reasoningGate: previewToolProgressEnabled,
1082
1027
  commentaryItalics: false,
1028
+ buildProgressEventLine: (input, options) => input.event === "tool" || input.event === "item" || input.event === "command-output" ? buildChannelProgressDraftLineForEntry(params.discordConfig, input, options) : buildChannelProgressDraftLine(input, options),
1083
1029
  update: async (previewText, options) => {
1030
+ if (!draftStream) return false;
1084
1031
  lastPartialText = previewText;
1085
1032
  draftText = previewText;
1086
1033
  hasStreamedMessage = true;
1087
1034
  draftChunker?.reset();
1088
- draftStream?.update(previewText);
1089
- if (options?.flush) await draftStream?.flush();
1035
+ draftStream.update(previewText);
1036
+ if (options?.flush) await draftStream.flush();
1037
+ return Boolean(draftStream.messageId());
1090
1038
  },
1091
1039
  deleteCurrent: async () => {
1092
1040
  lastPartialText = "";
@@ -1111,7 +1059,22 @@ function createDiscordDraftPreviewController(params) {
1111
1059
  resetProgressState();
1112
1060
  };
1113
1061
  const pushPreambleHeadline = async (text, options) => {
1114
- if (discordStreamMode === "progress") await progressDraft.pushPreambleHeadline(text, options);
1062
+ if (discordStreamMode === "progress") return await progressDraft.pushPreambleHeadline(text, options);
1063
+ return false;
1064
+ };
1065
+ const beginNewProgressTurn = (options) => {
1066
+ const beganNewTurn = progressDraft.beginNewTurn(options);
1067
+ if (beganNewTurn) {
1068
+ progressDraftCollapsed = false;
1069
+ progressDraftStartedBeforeFinal = false;
1070
+ finalReplyDelivered = false;
1071
+ finalizedViaPreviewMessage = false;
1072
+ progressNarratorLifecycle?.beginTurn();
1073
+ }
1074
+ if (discordStreamMode === "progress") {
1075
+ if (beganNewTurn) draftStream?.forceNewMessage("discard");
1076
+ } else forceNewMessageIfNeeded();
1077
+ return beganNewTurn;
1115
1078
  };
1116
1079
  return {
1117
1080
  draftStream,
@@ -1171,26 +1134,33 @@ function createDiscordDraftPreviewController(params) {
1171
1134
  return true;
1172
1135
  },
1173
1136
  disableBlockStreamingForDraft: draftStream ? true : void 0,
1137
+ pushToolEvent: progressDraft.pushToolEvent,
1138
+ pushItemEvent: progressDraft.pushItemEvent,
1139
+ pushApprovalEvent: progressDraft.pushApprovalEvent,
1140
+ pushCommandOutputEvent: progressDraft.pushCommandOutputEvent,
1141
+ pushPatchEvent: progressDraft.pushPatchEvent,
1174
1142
  async pushToolProgress(line, options) {
1175
- await progressDraft.pushToolProgress(line, options);
1143
+ return await progressDraft.pushToolProgress(line, options);
1176
1144
  },
1177
1145
  async pushPlanProgress(steps, options) {
1178
- await progressDraft.pushPlanProgress(steps, options);
1146
+ return await progressDraft.pushPlanProgress(steps, options);
1179
1147
  },
1180
1148
  async pushReasoningProgress(text, options) {
1181
- await progressDraft.pushReasoningProgress(text, options);
1149
+ return await progressDraft.pushReasoningProgress(text, options);
1182
1150
  },
1183
1151
  async pushNarrationProgress(text) {
1184
- await progressDraft.pushNarrationProgress(text);
1152
+ return await progressDraft.pushNarrationProgress(text);
1185
1153
  },
1186
1154
  pushPreambleHeadline,
1187
1155
  async pushPreambleItemEvent(payload, noteCommentary) {
1188
- await pushPreambleHeadline(payload.progressText, { itemId: payload.itemId });
1189
- if (!progressDraft.commentaryProgressEnabled) return;
1190
- if (await progressDraft.pushCommentaryProgress(payload.progressText, { itemId: payload.itemId })) noteCommentary(payload.itemId, payload.progressText);
1156
+ const headlineAccepted = await pushPreambleHeadline(payload.progressText, { itemId: payload.itemId });
1157
+ if (!progressDraft.commentaryProgressEnabled) return headlineAccepted;
1158
+ const commentaryAccepted = await progressDraft.pushCommentaryProgress(payload.progressText, { itemId: payload.itemId });
1159
+ if (commentaryAccepted) noteCommentary(payload.itemId, payload.progressText);
1160
+ return headlineAccepted || commentaryAccepted;
1191
1161
  },
1192
1162
  async pushCommentaryProgress(text, options) {
1193
- await progressDraft.pushCommentaryProgress(text, options);
1163
+ return await progressDraft.pushCommentaryProgress(text, options);
1194
1164
  },
1195
1165
  resolvePreviewFinalText(text) {
1196
1166
  if (typeof text !== "string") return;
@@ -1248,20 +1218,10 @@ function createDiscordDraftPreviewController(params) {
1248
1218
  });
1249
1219
  },
1250
1220
  handleAssistantMessageBoundary() {
1251
- const beganNewTurn = progressDraft.beginNewTurn();
1252
- if (beganNewTurn) {
1253
- progressDraftCollapsed = false;
1254
- progressDraftStartedBeforeFinal = false;
1255
- finalReplyDelivered = false;
1256
- finalizedViaPreviewMessage = false;
1257
- progressNarratorLifecycle?.beginTurn();
1258
- }
1259
- if (discordStreamMode === "progress") {
1260
- if (beganNewTurn) draftStream?.forceNewMessage("discard");
1261
- return beganNewTurn;
1262
- }
1263
- forceNewMessageIfNeeded();
1264
- return beganNewTurn;
1221
+ return beginNewProgressTurn();
1222
+ },
1223
+ handleQueuedFollowupAdmitted() {
1224
+ return beginNewProgressTurn({ force: true });
1265
1225
  },
1266
1226
  async flush() {
1267
1227
  if (!draftStream) return;
@@ -1391,7 +1351,7 @@ function createDiscordMessageReplyRuntime(params) {
1391
1351
  limit: historyLimit
1392
1352
  });
1393
1353
  };
1394
- const beginDeliveryCorrelation = () => params.isRoomEvent ? beginDiscordInboundEventDeliveryCorrelation(ctxPayload.SessionKey, {
1354
+ const beginDeliveryCorrelation = () => params.isRoomEvent ? discordInboundEventDelivery.begin(ctxPayload.SessionKey, {
1395
1355
  outboundTo: messageChannelId,
1396
1356
  outboundAccountId: route.accountId,
1397
1357
  markInboundEventDelivered: clearGroupHistory
@@ -1510,7 +1470,7 @@ async function processDiscordMessage(ctx, observer) {
1510
1470
  }
1511
1471
  async function processDiscordMessageInner(ctx, observer) {
1512
1472
  const dispatchStartedAt = Date.now();
1513
- const { cfg, accountId, token, runtime, guildHistories, historyLimit, textLimit, replyToMode, message, messageChannelId, canonicalMessageId, isGuildMessage, isDirectMessage, isGroupDm, messageText, channelConfig, threadBindings, route, abortSignal, turnAdoptionLifecycle, preparedMedia: mediaList } = ctx;
1473
+ const { cfg, accountId, token, runtime, textLimit, replyToMode, message, messageChannelId, isGuildMessage, isDirectMessage, isGroupDm, messageText, threadBindings, route, abortSignal, turnAdoptionLifecycle, preparedMedia: mediaList } = ctx;
1514
1474
  if (isProcessAborted(abortSignal)) return;
1515
1475
  const text = messageText;
1516
1476
  if (!text && mediaList.length === 0) {
@@ -1549,7 +1509,7 @@ async function processDiscordMessageInner(ctx, observer) {
1549
1509
  sessionKey: ctxPayload.SessionKey,
1550
1510
  accountId,
1551
1511
  sourceChannelId: messageChannelId,
1552
- sourceMessageId: canonicalMessageId ?? message.id,
1512
+ sourceMessageId: ctx.canonicalMessageId ?? message.id,
1553
1513
  sourceReplyReference,
1554
1514
  log: logVerbose
1555
1515
  });
@@ -1668,7 +1628,8 @@ async function processDiscordMessageInner(ctx, observer) {
1668
1628
  sessionKey: ctxPayload.SessionKey,
1669
1629
  threadBindings,
1670
1630
  mediaLocalRoots,
1671
- kind: "block"
1631
+ kind: "block",
1632
+ bindPendingFinalDelivery: info.bindPendingFinalDelivery
1672
1633
  });
1673
1634
  if (result.visibleReplySent) replyReference.markSent();
1674
1635
  return result;
@@ -1767,7 +1728,8 @@ async function processDiscordMessageInner(ctx, observer) {
1767
1728
  threadBindings,
1768
1729
  mediaLocalRoots,
1769
1730
  allowedMentions,
1770
- kind: info.kind
1731
+ kind: info.kind,
1732
+ bindPendingFinalDelivery: info.bindPendingFinalDelivery
1771
1733
  })).visibleReplySent;
1772
1734
  },
1773
1735
  onNormalDelivered: () => {
@@ -1809,7 +1771,8 @@ async function processDiscordMessageInner(ctx, observer) {
1809
1771
  sessionKey: ctxPayload.SessionKey,
1810
1772
  threadBindings,
1811
1773
  mediaLocalRoots,
1812
- kind: info.kind
1774
+ kind: info.kind,
1775
+ bindPendingFinalDelivery: info.bindPendingFinalDelivery
1813
1776
  });
1814
1777
  if (!result.visibleReplySent) return result;
1815
1778
  replyReference.markSent();
@@ -1891,13 +1854,13 @@ async function processDiscordMessageInner(ctx, observer) {
1891
1854
  history: isRoomEvent ? void 0 : {
1892
1855
  isGroup: isGuildMessage,
1893
1856
  historyKey: messageChannelId,
1894
- historyMap: guildHistories,
1895
- limit: historyLimit
1857
+ historyMap: ctx.guildHistories,
1858
+ limit: ctx.historyLimit
1896
1859
  },
1897
1860
  replyOptions: {
1898
1861
  ...turnAdoptionLifecycle ? bindIngressLifecycleToReplyOptions(turnAdoptionLifecycle) : {},
1899
1862
  abortSignal,
1900
- skillFilter: channelConfig?.skills,
1863
+ skillFilter: ctx.channelConfig?.skills,
1901
1864
  sourceReplyDeliveryMode,
1902
1865
  typingKeepalive: shouldDisableCoreTypingKeepalive ? false : void 0,
1903
1866
  queuedDeliveryCorrelations: isRoomEvent ? [{ begin: beginQueuedDeliveryCorrelation }] : void 0,
@@ -1932,6 +1895,7 @@ async function processDiscordMessageInner(ctx, observer) {
1932
1895
  activeThreadRoute.end();
1933
1896
  endDeliveryCorrelation();
1934
1897
  await draftPreview.cleanup();
1898
+ dispatchError ||= readAgentRunTerminalOutcome(dispatchResult) === "failed";
1935
1899
  const finalDeliveryFailed = (dispatchResult?.failedCounts?.final ?? 0) > 0;
1936
1900
  await reactions.finish({
1937
1901
  dispatchAborted,
@@ -1,8 +1,8 @@
1
- import { f as resolveDiscordChannelInfoSafe } from "./thread-bindings.discord-api-BoDNqamb.js";
1
+ import { c as resolveDiscordChannelInfoSafe } from "./thread-bindings.manager-DCIH6WDC.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";
5
- import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
5
+ import { getChildLogger, logVerbose } from "openclaw/plugin-sdk/runtime-env";
6
6
  import { saveRemoteMedia } from "openclaw/plugin-sdk/media-runtime";
7
7
  import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
8
8
  import { formatMediaPlaceholderText } from "openclaw/plugin-sdk/channel-inbound";
@@ -368,7 +368,7 @@ async function appendResolvedMediaFromAttachments(params) {
368
368
  });
369
369
  } catch (err) {
370
370
  const id = attachment.id ?? attachmentUrl;
371
- logVerbose(`${params.errorPrefix} ${id}: ${String(err)}`);
371
+ getChildLogger({ module: "discord-media" }).warn(`${params.errorPrefix} ${id}: ${String(err)}`);
372
372
  const classification = resolveDiscordMediaClassification({ attachment });
373
373
  params.out.push({ ...classification });
374
374
  }
@@ -442,7 +442,7 @@ async function appendResolvedMediaFromStickers(params) {
442
442
  lastError = err;
443
443
  }
444
444
  if (lastError) {
445
- logVerbose(`${params.errorPrefix} ${sticker.id}: ${formatStickerError(lastError)}`);
445
+ getChildLogger({ module: "discord-media" }).warn(`${params.errorPrefix} ${sticker.id}: ${formatStickerError(lastError)}`);
446
446
  if (candidates[0]) params.out.push({
447
447
  contentType: inferStickerContentType(sticker),
448
448
  kind: "sticker"
@@ -1,5 +1,5 @@
1
1
  import { createHash } from "node:crypto";
2
- import { normalizeProviderId } from "openclaw/plugin-sdk/provider-model-shared";
2
+ import { normalizeProviderId } from "openclaw/plugin-sdk/model-ref-parse";
3
3
  //#region extensions/discord/src/monitor/model-picker-preference-primitives.ts
4
4
  function normalizeModelRef(raw) {
5
5
  const value = raw?.trim();
@@ -29,9 +29,9 @@ function hashSegment(value, length) {
29
29
  function buildPreferenceModelKey(scopeKey, modelRef) {
30
30
  return `v1:${hashSegment(scopeKey, 32)}:${hashSegment(modelRef, 24)}`;
31
31
  }
32
- function timestampMs(value) {
32
+ function preferenceTimestampMs(value) {
33
33
  const parsed = typeof value === "string" ? Date.parse(value) : NaN;
34
34
  return Number.isFinite(parsed) ? parsed : 0;
35
35
  }
36
36
  //#endregion
37
- export { timestampMs as i, normalizeModelRef as n, sanitizeRecentModels as r, buildPreferenceModelKey as t };
37
+ export { sanitizeRecentModels as i, normalizeModelRef as n, preferenceTimestampMs as r, buildPreferenceModelKey as t };