@openclaw/discord 2026.8.1-beta.2 → 2026.8.1-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 (100) hide show
  1. package/dist/{account-inspect-CqzrH14k.js → account-inspect-D5xmUpnj.js} +1 -1
  2. package/dist/account-inspect-api.js +1 -1
  3. package/dist/accounts-DNl-oCEw.js +371 -0
  4. package/dist/action-runtime-api.js +1 -1
  5. package/dist/{activities-api-DS7vpdtp.js → activities-api-KCBAmWxD.js} +133 -175
  6. package/dist/activities-api.js +1 -1
  7. package/dist/api.js +17 -17
  8. package/dist/{approval-handler.runtime-B6yEV79q.js → approval-handler.runtime-B12RCYr8.js} +6 -6
  9. package/dist/{approval-message-safety-AcIxvrf3.js → approval-message-safety-XGFPbDoI.js} +89 -3
  10. package/dist/{audit-Db-rlntl.js → audit-Yc7eZDd6.js} +5 -5
  11. package/dist/{channel-actions-5s_hjYKd.js → channel-actions-Dr2QI8Bf.js} +10 -6
  12. package/dist/{channel-actions.runtime-CLKrx6tr.js → channel-actions.runtime-CODTvo7c.js} +53 -68
  13. package/dist/{channel-CnnbJSt5.js → channel-cXYzGc4L.js} +74 -50
  14. package/dist/channel-config-api.js +1 -1
  15. package/dist/channel-plugin-api.js +1 -1
  16. package/dist/{channel.setup-BFAO-V1P.js → channel.setup-CSiwnMgs.js} +5 -5
  17. package/dist/{outbound-session-route-DxLkrgKQ.js → components-ezGKo_Yh.js} +3 -49
  18. package/dist/{config-schema-BgEskFAs.js → config-schema-DC5kDtQ5.js} +33 -7
  19. package/dist/conversation-binding-route-D6rCQ5S0.js +43 -0
  20. package/dist/{directory-config-BVX7Cflc.js → directory-config-XyCfoqLg.js} +2 -2
  21. package/dist/directory-contract-api.js +1 -1
  22. package/dist/{directory-live-DGIGxpIo.js → directory-live-Df0NbFJB.js} +3 -3
  23. package/dist/{doctor-BzC-TLnB.js → doctor-DYY31GrO.js} +33 -12
  24. package/dist/doctor-contract-api.js +3 -3
  25. package/dist/{handle-action.guild-admin-BNVTUISF.js → handle-action.guild-admin-6Tvvinsa.js} +2 -2
  26. package/dist/index.js +3 -4
  27. package/dist/{message-handler-Unk_f10F.js → message-handler-B61q5MOF.js} +82 -6
  28. package/dist/{message-handler.preflight-C9zecxR9.js → message-handler.preflight-Bzg_Hawz.js} +36 -46
  29. package/dist/{message-handler.process-DWQ6UHHu.js → message-handler.process--4_712Ec.js} +159 -183
  30. package/dist/{message-utils-BSCPVgy0.js → message-utils-BXLLnFl6.js} +31 -32
  31. package/dist/{outbound-adapter-D9nRivT1.js → outbound-adapter-DxHTOqiN.js} +83 -53
  32. package/dist/{outbound-components-cTzwBJ60.js → outbound-components-B2PL0ooH.js} +3 -3
  33. package/dist/owner-access-Bg41VzAf.js +107 -0
  34. package/dist/{pluralkit-DdiJ9KMK.js → pluralkit-dUl4v1X3.js} +1 -1
  35. package/dist/{probe-Bl-k5_Ku.js → probe-BTdtVRwU.js} +1 -1
  36. package/dist/{probe.runtime-M9fREKvp.js → probe.runtime-Dq5-PRKT.js} +1 -1
  37. package/dist/{provider-DvSNb-2v.js → provider-DlK_ynqt.js} +356 -967
  38. package/dist/{provider-session.runtime-BUEqD0rA.js → provider-session.runtime-CvvphHvs.js} +3 -3
  39. package/dist/provider.runtime-CzKGRiAF.js +2 -0
  40. package/dist/{realtime-session.runtime-C7wen-aF.js → realtime-session.runtime-ysbMG8v7.js} +24 -13
  41. package/dist/{resolve-allowlist-common-D04lpEzb.js → resolve-allowlist-common-DIVXbD1P.js} +2 -2
  42. package/dist/{resolve-channels-Dm7jEeg6.js → resolve-channels-CGeUoIqb.js} +3 -3
  43. package/dist/{resolve-users-bktrCUUU.js → resolve-users-BtKxLUZv.js} +2 -2
  44. package/dist/{retry-CLpJcXXf.js → retry-DNsVTeTo.js} +18 -64
  45. package/dist/{runtime-DoHjckYm.js → runtime-CQovMsH3.js} +9 -10
  46. package/dist/{runtime-DGsSyDTS.js → runtime-D71_VFLr.js} +29 -43
  47. package/dist/runtime-api.actions.js +2 -2
  48. package/dist/runtime-api.js +22 -21
  49. package/dist/runtime-api.lookup.js +5 -5
  50. package/dist/runtime-api.monitor-CzeTYF32.js +6 -0
  51. package/dist/runtime-api.monitor.js +6 -5
  52. package/dist/runtime-api.send.js +6 -6
  53. package/dist/runtime-api.threads.js +4 -4
  54. package/dist/{sdk-runtime-QpY8PvCh.js → sdk-runtime-37OU6_Yh.js} +3 -4
  55. package/dist/{secret-config-contract-B1akrlyY.js → secret-config-contract-B3i6WxV5.js} +53 -25
  56. package/dist/secret-contract-api.js +1 -1
  57. package/dist/security-audit-contract-api.js +1 -1
  58. package/dist/{security-audit.runtime-CPN0xFYz.js → security-audit.runtime-BVKF9VtY.js} +1 -1
  59. package/dist/{send-B7Q6Oc1I.js → send-rQIffSYu.js} +10 -10
  60. package/dist/{send.components-iJyFXw9L.js → send.components-ChK1wS7w.js} +14 -24
  61. package/dist/{send.outbound-DS5tHwfR.js → send.outbound-HIkgji_7.js} +26 -16
  62. package/dist/{send.reactions-BAn0iiVQ.js → send.reactions-gmJ6yFPo.js} +2 -2
  63. package/dist/{send.receipt-IPI1p-SP.js → send.receipt-Cnhoautb.js} +11 -1
  64. package/dist/{send.shared-BmwFjW6T.js → send.shared-B3fpaLWJ.js} +104 -104
  65. package/dist/{sender-identity-QtalnCYv.js → sender-identity-BJtfyise.js} +1 -1
  66. package/dist/setup-plugin-api.js +1 -1
  67. package/dist/{shared-BIXIX6uJ.js → shared-CaAaoksy.js} +15 -10
  68. package/dist/subagent-hooks-CNT2ZJTJ.js +49 -0
  69. package/dist/subagent-hooks-api.js +2 -2
  70. package/dist/{subagent-progress-DhaE_h8a.js → subagent-progress-FPLqBY1s.js} +5 -4
  71. package/dist/{system-events-CTqDf6_s.js → system-events-Nuwoq_au.js} +2 -2
  72. package/dist/{target-resolver-maOKSqO0.js → target-resolver-DIXShHaZ.js} +3 -3
  73. package/dist/targets-B2pf49zc.js +3 -0
  74. package/dist/{thread-bindings-3L8p82GV.js → thread-bindings-VlymUnbz.js} +29 -26
  75. package/dist/{thread-bindings.manager-DCIH6WDC.js → thread-bindings.manager-CngsgErq.js} +9 -8
  76. package/dist/{thread-bindings.session-updates-bJ2KQFY6.js → thread-bindings.session-updates-CJb-BpPL.js} +1 -1
  77. package/dist/{thread-bindings.state-aeV8HNgV.js → thread-bindings.state-D8OMdk4O.js} +1 -1
  78. package/dist/threading-DU6pgeGm.js +456 -0
  79. package/dist/transcripts-source-DeIMNbRh.js +265 -0
  80. package/dist/transcripts-source-api.js +7 -2
  81. package/dist/{typing-CS-nNVoe.js → typing-oLiS5Z13.js} +1 -1
  82. package/dist/{voice-runtime-BEdqNcST.js → voice-runtime-CjNFaynA.js} +181 -91
  83. package/openclaw.plugin.json +12 -6
  84. package/package.json +4 -6
  85. package/dist/accounts-DJTf1LtA.js +0 -219
  86. package/dist/channel-api-CAJ0wMoV.js +0 -21
  87. package/dist/provider.runtime-C9PnJZbZ.js +0 -2
  88. package/dist/runtime-api.monitor-CHxrFPnW.js +0 -5
  89. package/dist/subagent-hooks-CTt5KCJr.js +0 -120
  90. package/dist/targets-yUFTHoAx.js +0 -3
  91. package/dist/transcripts-source-CfFMexGt.js +0 -123
  92. package/node_modules/p-map/index.d.ts +0 -155
  93. package/node_modules/p-map/index.js +0 -285
  94. package/node_modules/p-map/license +0 -9
  95. package/node_modules/p-map/package.json +0 -57
  96. package/node_modules/p-map/readme.md +0 -190
  97. package/dist/{allow-list-DnxIlPP2.js → allow-list-BDMimASD.js} +1 -1
  98. package/dist/{audit-core-xwjIczO0.js → audit-core-BCX8UeFH.js} +1 -1
  99. package/dist/{doctor-contract-DLa-BTiU.js → doctor-contract-DsWvKIXF.js} +1 -1
  100. package/dist/{security-audit-jGnJF__m.js → security-audit-BfJhAXZp.js} +1 -1
@@ -1,53 +1,18 @@
1
- import { A as RequestClient, Dt as getThreadMember, H as serializePayload, Ht as getGuild, Tt as getChannel, U as Embed, Ut as getGuildMember, a as chunkDiscordTextWithMode, ft as stripUndefinedFields, ht as getCurrentUser, mt as createUserDmChannel, n as createDiscordRetryRunner, s as resolveDiscordReplyMessageId, yt as createChannelMessage } from "./retry-CLpJcXXf.js";
2
- import { a as mergeDiscordAccountConfig, p as normalizeDiscordToken, s as resolveDiscordAccount } from "./accounts-DJTf1LtA.js";
3
- import { t as parseAndResolveDiscordTarget } from "./target-resolver-maOKSqO0.js";
4
- import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
5
- import { normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
1
+ import { B as hasDiscordV2Components, Et as getThreadMember, H as Embed, Ht as getGuildMember, O as RequestClient, V as serializePayload, Vt as getGuild, a as chunkDiscordTextWithMode, mt as getCurrentUser, n as createDiscordRetryRunner, pt as createUserDmChannel, s as resolveDiscordReplyMessageId, vt as createChannelMessage, wt as getChannel } from "./retry-DNsVTeTo.js";
2
+ import { c as resolveDiscordAccount, m as normalizeDiscordToken, o as mergeDiscordAccountConfig } from "./accounts-DNl-oCEw.js";
3
+ import { t as parseAndResolveDiscordTarget } from "./target-resolver-DIXShHaZ.js";
6
4
  import { ChannelType, MessageFlags, PermissionFlagsBits } from "discord-api-types/v10";
7
5
  import { randomBytes } from "node:crypto";
8
6
  import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
7
+ import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
8
+ import { normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
9
+ import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
9
10
  import { makeProxyFetch } from "openclaw/plugin-sdk/fetch-runtime";
10
11
  import { danger } from "openclaw/plugin-sdk/runtime-env";
11
- import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
12
12
  import { PollLayoutType } from "discord-api-types/payloads/v10";
13
13
  import { buildOutboundMediaLoadOptions, extensionForMime, normalizePollDurationHours, normalizePollInput } from "openclaw/plugin-sdk/media-runtime";
14
14
  import { resolveTextChunksWithFallback } from "openclaw/plugin-sdk/reply-payload";
15
15
  import { loadWebMedia } from "openclaw/plugin-sdk/web-media";
16
- //#region extensions/discord/src/proxy-fetch.ts
17
- function resolveDiscordProxyUrl(account, cfg) {
18
- const accountProxy = normalizeOptionalString(account.config.proxy);
19
- if (accountProxy) return accountProxy;
20
- return normalizeOptionalString(cfg?.channels?.discord?.proxy);
21
- }
22
- function resolveDiscordProxyFetchByUrl(proxyUrl, runtime) {
23
- return withValidatedDiscordProxy(proxyUrl, runtime, (proxy) => makeProxyFetch(proxy));
24
- }
25
- function resolveDiscordProxyFetchForAccount(account, cfg, runtime) {
26
- return resolveDiscordProxyFetchByUrl(resolveDiscordProxyUrl(account, cfg), runtime);
27
- }
28
- function withValidatedDiscordProxy(proxyUrl, runtime, createValue) {
29
- const proxy = proxyUrl?.trim();
30
- if (!proxy) return;
31
- try {
32
- validateDiscordProxyUrl(proxy);
33
- return createValue(proxy);
34
- } catch (err) {
35
- runtime?.error?.(danger(`discord: invalid rest proxy: ${String(err)}`));
36
- return;
37
- }
38
- }
39
- function validateDiscordProxyUrl(proxyUrl) {
40
- let parsed;
41
- try {
42
- parsed = new URL(proxyUrl);
43
- } catch {
44
- throw new Error("Proxy URL must be a valid http or https URL");
45
- }
46
- if (!["http:", "https:"].includes(parsed.protocol)) throw new Error("Proxy URL must use http or https");
47
- if (!parsed.hostname) throw new Error("Proxy URL must include a host");
48
- return proxyUrl;
49
- }
50
- //#endregion
51
16
  //#region extensions/discord/src/recipient-resolution.ts
52
17
  async function parseAndResolveRecipient(raw, cfg, accountId, parseOptions = {}) {
53
18
  if (!cfg) throw new Error("Discord recipient resolution requires a resolved runtime config. Load and resolve config at the command or gateway boundary, then pass cfg through the runtime path.");
@@ -97,6 +62,41 @@ function clearGateways() {
97
62
  gatewayRegistry.clear();
98
63
  }
99
64
  //#endregion
65
+ //#region extensions/discord/src/proxy-fetch.ts
66
+ function resolveDiscordProxyUrl(account, cfg) {
67
+ const accountProxy = normalizeOptionalString(account.config.proxy);
68
+ if (accountProxy) return accountProxy;
69
+ return normalizeOptionalString(cfg?.channels?.discord?.proxy);
70
+ }
71
+ function resolveDiscordProxyFetchByUrl(proxyUrl, runtime) {
72
+ return withValidatedDiscordProxy(proxyUrl, runtime, (proxy) => makeProxyFetch(proxy));
73
+ }
74
+ function resolveDiscordProxyFetchForAccount(account, cfg, runtime) {
75
+ return resolveDiscordProxyFetchByUrl(resolveDiscordProxyUrl(account, cfg), runtime);
76
+ }
77
+ function withValidatedDiscordProxy(proxyUrl, runtime, createValue) {
78
+ const proxy = proxyUrl?.trim();
79
+ if (!proxy) return;
80
+ try {
81
+ validateDiscordProxyUrl(proxy);
82
+ return createValue(proxy);
83
+ } catch (err) {
84
+ runtime?.error?.(danger(`discord: invalid rest proxy: ${String(err)}`));
85
+ return;
86
+ }
87
+ }
88
+ function validateDiscordProxyUrl(proxyUrl) {
89
+ let parsed;
90
+ try {
91
+ parsed = new URL(proxyUrl);
92
+ } catch {
93
+ throw new Error("Proxy URL must be a valid http or https URL");
94
+ }
95
+ if (!["http:", "https:"].includes(parsed.protocol)) throw new Error("Proxy URL must use http or https");
96
+ if (!parsed.hostname) throw new Error("Proxy URL must include a host");
97
+ return proxyUrl;
98
+ }
99
+ //#endregion
100
100
  //#region extensions/discord/src/proxy-request-client.ts
101
101
  const DISCORD_REST_TIMEOUT_MS = 15e3;
102
102
  function createDiscordRequestClient(token, options) {
@@ -199,6 +199,59 @@ function resolveDiscordRest(opts) {
199
199
  return createDiscordRestClient(opts).rest;
200
200
  }
201
201
  //#endregion
202
+ //#region extensions/discord/src/send.message-request.ts
203
+ const SUPPRESS_EMBEDS_FLAG = MessageFlags.SuppressEmbeds;
204
+ const SUPPRESS_NOTIFICATIONS_FLAG = MessageFlags.SuppressNotifications;
205
+ function createDiscordMessageNonce() {
206
+ return randomBytes(12).toString("hex");
207
+ }
208
+ function resolveDiscordSendComponents(params) {
209
+ if (!params.components || !params.isFirst) return;
210
+ return typeof params.components === "function" ? params.components(params.text) : params.components;
211
+ }
212
+ function normalizeDiscordEmbeds(embeds) {
213
+ if (!embeds?.length) return;
214
+ return embeds.map((embed) => embed instanceof Embed ? embed : new Embed(embed));
215
+ }
216
+ function resolveDiscordSendEmbeds(params) {
217
+ if (!params.embeds || !params.isFirst) return;
218
+ return normalizeDiscordEmbeds(params.embeds);
219
+ }
220
+ function buildDiscordMessagePayload(params) {
221
+ const payload = {};
222
+ const hasV2 = hasDiscordV2Components(params.components);
223
+ const trimmed = params.text.trim();
224
+ if (!hasV2 && trimmed) payload.content = params.text;
225
+ if (params.components?.length) payload.components = params.components;
226
+ if (!hasV2 && params.embeds?.length) payload.embeds = params.embeds;
227
+ if (params.allowedMentions) payload.allowed_mentions = params.allowedMentions;
228
+ if (params.flags !== void 0) payload.flags = params.flags;
229
+ if (params.files?.length) payload.files = params.files;
230
+ return payload;
231
+ }
232
+ function resolveDiscordMessageFlags(params) {
233
+ let flags = 0;
234
+ if (params.suppressEmbeds) flags |= SUPPRESS_EMBEDS_FLAG;
235
+ if (params.silent) flags |= SUPPRESS_NOTIFICATIONS_FLAG;
236
+ return flags || void 0;
237
+ }
238
+ function resolveDiscordSuppressEmbeds(params) {
239
+ return params.override ?? params.configured ?? true;
240
+ }
241
+ function buildDiscordMessageRequest(params) {
242
+ const payload = buildDiscordMessagePayload(params);
243
+ const nonce = params.endpoint === "create-message" ? params.nonce ?? createDiscordMessageNonce() : void 0;
244
+ return {
245
+ ...serializePayload(payload),
246
+ ...params.replyTo ? { message_reference: {
247
+ message_id: params.replyTo,
248
+ fail_if_not_exists: false
249
+ } } : {},
250
+ ...nonce !== void 0 ? { nonce } : {},
251
+ ...nonce ? { enforce_nonce: true } : {}
252
+ };
253
+ }
254
+ //#endregion
202
255
  //#region extensions/discord/src/send.permissions.ts
203
256
  const PERMISSION_ENTRIES = Object.entries(PermissionFlagsBits).filter(([, value]) => typeof value === "bigint");
204
257
  const ALL_PERMISSIONS = PERMISSION_ENTRIES.reduce((acc, [, value]) => acc | value, 0n);
@@ -453,62 +506,6 @@ const DISCORD_MAX_EMOJI_BYTES = 256 * 1024;
453
506
  const DISCORD_MAX_STICKER_BYTES = 512 * 1024;
454
507
  const DISCORD_MAX_EVENT_COVER_BYTES = 8 * 1024 * 1024;
455
508
  //#endregion
456
- //#region extensions/discord/src/send.message-request.ts
457
- const SUPPRESS_EMBEDS_FLAG = MessageFlags.SuppressEmbeds;
458
- const SUPPRESS_NOTIFICATIONS_FLAG = MessageFlags.SuppressNotifications;
459
- function createDiscordMessageNonce() {
460
- return randomBytes(12).toString("hex");
461
- }
462
- function resolveDiscordSendComponents(params) {
463
- if (!params.components || !params.isFirst) return;
464
- return typeof params.components === "function" ? params.components(params.text) : params.components;
465
- }
466
- function normalizeDiscordEmbeds(embeds) {
467
- if (!embeds?.length) return;
468
- return embeds.map((embed) => embed instanceof Embed ? embed : new Embed(embed));
469
- }
470
- function resolveDiscordSendEmbeds(params) {
471
- if (!params.embeds || !params.isFirst) return;
472
- return normalizeDiscordEmbeds(params.embeds);
473
- }
474
- function buildDiscordMessagePayload(params) {
475
- const payload = {};
476
- const hasV2 = hasV2Components(params.components);
477
- const trimmed = params.text.trim();
478
- if (!hasV2 && trimmed) payload.content = params.text;
479
- if (params.components?.length) payload.components = params.components;
480
- if (!hasV2 && params.embeds?.length) payload.embeds = params.embeds;
481
- if (params.allowedMentions) payload.allowed_mentions = params.allowedMentions;
482
- if (params.flags !== void 0) payload.flags = params.flags;
483
- if (params.files?.length) payload.files = params.files;
484
- return payload;
485
- }
486
- function resolveDiscordMessageFlags(params) {
487
- let flags = 0;
488
- if (params.suppressEmbeds) flags |= SUPPRESS_EMBEDS_FLAG;
489
- if (params.silent) flags |= SUPPRESS_NOTIFICATIONS_FLAG;
490
- return flags || void 0;
491
- }
492
- function resolveDiscordSuppressEmbeds(params) {
493
- return params.override ?? params.configured ?? true;
494
- }
495
- function buildDiscordMessageRequest(params) {
496
- const payload = buildDiscordMessagePayload(params);
497
- const nonce = params.endpoint === "create-message" ? params.nonce ?? createDiscordMessageNonce() : void 0;
498
- return stripUndefinedFields({
499
- ...serializePayload(payload),
500
- ...params.replyTo ? { message_reference: {
501
- message_id: params.replyTo,
502
- fail_if_not_exists: false
503
- } } : {},
504
- nonce,
505
- enforce_nonce: nonce ? true : void 0
506
- });
507
- }
508
- function hasV2Components(components) {
509
- return Boolean(components?.some((component) => "isV2" in component && component.isV2));
510
- }
511
- //#endregion
512
509
  //#region extensions/discord/src/send.shared.ts
513
510
  const DISCORD_TEXT_LIMIT = 2e3;
514
511
  const DISCORD_MAX_STICKERS = 3;
@@ -638,14 +635,13 @@ function buildDiscordTextChunks(text, opts = {}) {
638
635
  }
639
636
  async function sendDiscordText(params) {
640
637
  const { rest, channelId, text, request, reply, maxLinesPerMessage, components, embeds, allowedMentions, chunkMode, silent, suppressEmbeds, maxChars, onResult, onPlatformSendDispatch } = params;
641
- if (!text.trim()) throw new Error("Message must be non-empty for Discord sends");
642
638
  const chunks = buildDiscordTextChunks(text, {
643
639
  maxLinesPerMessage,
644
640
  chunkMode,
645
641
  maxChars
646
642
  });
643
+ if (!chunks.length) chunks.push("");
647
644
  const sendChunk = async (chunk, isFirst) => {
648
- const chunkReplyTo = resolveDiscordReplyMessageId(reply, isFirst);
649
645
  const chunkComponents = resolveDiscordSendComponents({
650
646
  components,
651
647
  text: chunk,
@@ -655,6 +651,9 @@ async function sendDiscordText(params) {
655
651
  embeds,
656
652
  isFirst
657
653
  });
654
+ if (!chunk.trim() && !chunkComponents?.length && !chunkEmbeds?.length) throw new Error("Message must be non-empty for Discord sends");
655
+ const chunkReplyTo = resolveDiscordReplyMessageId(reply, isFirst);
656
+ const kind = chunkComponents?.length || chunkEmbeds?.length ? "card" : "text";
658
657
  const flags = resolveDiscordMessageFlags({
659
658
  silent,
660
659
  suppressEmbeds: suppressEmbeds && !chunkEmbeds?.length
@@ -671,12 +670,13 @@ async function sendDiscordText(params) {
671
670
  await onPlatformSendDispatch?.();
672
671
  return {
673
672
  result: await request(() => createChannelMessage(rest, channelId, { body }), "text", { safety: "nonce-protected-create" }),
674
- replyToId: chunkReplyTo
673
+ replyToId: chunkReplyTo,
674
+ kind
675
675
  };
676
676
  };
677
677
  if (chunks.length === 1) {
678
- const { result, replyToId } = await sendChunk(expectDefined(chunks.at(0), "single Discord text chunk"), true);
679
- await onResult?.(result, "text", replyToId);
678
+ const { result, replyToId, kind } = await sendChunk(expectDefined(chunks.at(0), "single Discord text chunk"), true);
679
+ await onResult?.(result, kind, replyToId);
680
680
  return {
681
681
  ...result,
682
682
  platformMessageIds: result.id ? [result.id] : []
@@ -687,7 +687,7 @@ async function sendDiscordText(params) {
687
687
  for (const [index, chunk] of chunks.entries()) {
688
688
  const sent = await sendChunk(chunk, index === 0);
689
689
  last = sent.result;
690
- await onResult?.(last, "text", sent.replyToId);
690
+ await onResult?.(last, sent.kind, sent.replyToId);
691
691
  if (last.id) platformMessageIds.push(last.id);
692
692
  }
693
693
  if (!last) throw new Error("Discord send failed (empty chunk result)");
@@ -793,4 +793,4 @@ function formatReactionEmoji(emoji) {
793
793
  return buildReactionIdentifier(emoji);
794
794
  }
795
795
  //#endregion
796
- export { hasAllGuildPermissionsDiscord as A, clearGateways as B, DISCORD_MAX_STICKER_BYTES as C, canViewDiscordGuildChannel as D, canManageGuildRoleDiscord as E, createDiscordRestClient as F, resolveDiscordProxyFetchForAccount as G, registerGateway as H, createDiscordRuntimeAccountContext as I, validateDiscordProxyUrl as K, resolveDiscordClientAccountContext as L, hasAnyGuildPermissionDiscord as M, isThreadChannelType as N, fetchChannelPermissionsDiscord as O, createDiscordClient as P, resolveDiscordRest as R, DISCORD_MAX_EVENT_COVER_BYTES as S, canManageGuildMemberRoleDiscord as T, unregisterGateway as U, getGateway as V, parseAndResolveChannelRecipient as W, resolveDiscordMessageFlags as _, normalizeDiscordPollInput as a, resolveDiscordSuppressEmbeds as b, normalizeStickerIds as c, resolveDiscordTargetChannelId as d, sendDiscordMedia as f, createDiscordMessageNonce as g, buildDiscordMessageRequest as h, formatReactionEmoji as i, hasAnyChannelPermissionDiscord as j, fetchMemberGuildPermissionsDiscord as k, resolveChannelId as l, SUPPRESS_NOTIFICATIONS_FLAG as m, buildDiscordTextChunks as n, normalizeEmojiName as o, sendDiscordText as p, withValidatedDiscordProxy as q, buildReactionIdentifier as r, normalizeReactionEmoji as s, buildDiscordSendError as t, resolveDiscordChannel as u, resolveDiscordSendComponents as v, DiscordSendError as w, DISCORD_MAX_EMOJI_BYTES as x, resolveDiscordSendEmbeds as y, DISCORD_REST_TIMEOUT_MS as z };
796
+ export { resolveDiscordMessageFlags as A, resolveDiscordProxyFetchForAccount as B, hasAllGuildPermissionsDiscord as C, SUPPRESS_NOTIFICATIONS_FLAG as D, isThreadChannelType as E, createDiscordRestClient as F, registerGateway as G, withValidatedDiscordProxy as H, createDiscordRuntimeAccountContext as I, unregisterGateway as K, resolveDiscordClientAccountContext as L, resolveDiscordSendEmbeds as M, resolveDiscordSuppressEmbeds as N, buildDiscordMessageRequest as O, createDiscordClient as P, resolveDiscordRest as R, fetchMemberGuildPermissionsDiscord as S, hasAnyGuildPermissionDiscord as T, clearGateways as U, validateDiscordProxyUrl as V, getGateway as W, DiscordSendError as _, normalizeDiscordPollInput as a, canViewDiscordGuildChannel as b, normalizeStickerIds as c, resolveDiscordTargetChannelId as d, sendDiscordMedia as f, DISCORD_MAX_STICKER_BYTES as g, DISCORD_MAX_EVENT_COVER_BYTES as h, formatReactionEmoji as i, resolveDiscordSendComponents as j, createDiscordMessageNonce as k, resolveChannelId as l, DISCORD_MAX_EMOJI_BYTES as m, buildDiscordTextChunks as n, normalizeEmojiName as o, sendDiscordText as p, parseAndResolveChannelRecipient as q, buildReactionIdentifier as r, normalizeReactionEmoji as s, buildDiscordSendError as t, resolveDiscordChannel as u, canManageGuildMemberRoleDiscord as v, hasAnyChannelPermissionDiscord as w, fetchChannelPermissionsDiscord as x, canManageGuildRoleDiscord as y, DISCORD_REST_TIMEOUT_MS as z };
@@ -1,4 +1,4 @@
1
- import { x as formatDiscordUserTag } from "./allow-list-DnxIlPP2.js";
1
+ import { x as formatDiscordUserTag } from "./allow-list-BDMimASD.js";
2
2
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
3
3
  //#region extensions/discord/src/monitor/sender-identity.ts
4
4
  function resolveDiscordWebhookId(message) {
@@ -1,2 +1,2 @@
1
- import { t as discordSetupPlugin } from "./channel.setup-BFAO-V1P.js";
1
+ import { t as discordSetupPlugin } from "./channel.setup-CSiwnMgs.js";
2
2
  export { discordSetupPlugin };
@@ -1,9 +1,8 @@
1
- import { a as mergeDiscordAccountConfig, c as resolveDiscordAccountAllowFrom, d as resolveDiscordAccountDmPolicy, n as isDiscordAccountEnabledForRuntime, o as resolveDefaultDiscordAccountId, r as listDiscordAccountIds, s as resolveDiscordAccount, u as resolveDiscordAccountDisabledReason } from "./accounts-DJTf1LtA.js";
2
- import { t as DiscordChannelConfigSchema } from "./config-schema-BgEskFAs.js";
3
- import { i as getChatChannelMeta, o as resolveConfiguredFromCredentialStatuses } from "./channel-api-CAJ0wMoV.js";
4
- import { t as inspectDiscordAccount } from "./account-inspect-CqzrH14k.js";
5
- import { n as normalizeCompatibilityConfig } from "./doctor-contract-DLa-BTiU.js";
6
- import { n as secretTargetRegistryEntries, t as collectRuntimeConfigAssignments } from "./secret-config-contract-B1akrlyY.js";
1
+ import { t as DiscordChannelConfigSchema } from "./config-schema-DC5kDtQ5.js";
2
+ import { I as resolveConfiguredFromCredentialStatuses, P as getChatChannelMeta, c as resolveDiscordAccount, d as resolveDiscordAccountDisabledReason, f as resolveDiscordAccountDmPolicy, l as resolveDiscordAccountAllowFrom, n as isDiscordAccountEnabledForRuntime, o as mergeDiscordAccountConfig, r as listDiscordAccountIds, s as resolveDefaultDiscordAccountId } from "./accounts-DNl-oCEw.js";
3
+ import { t as inspectDiscordAccount } from "./account-inspect-D5xmUpnj.js";
4
+ import { n as normalizeCompatibilityConfig } from "./doctor-contract-DsWvKIXF.js";
5
+ import { r as secretTargetRegistryEntries, t as collectRuntimeConfigAssignments } from "./secret-config-contract-B3i6WxV5.js";
7
6
  import { n as unsupportedSecretRefSurfacePatterns, t as collectUnsupportedSecretRefConfigCandidates } from "./security-contract-DSHk7I2w.js";
8
7
  import { t as deriveLegacySessionChatType } from "./session-contract-BO5tlIdl.js";
9
8
  import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
@@ -11,7 +10,7 @@ import { normalizeAccountId } from "openclaw/plugin-sdk/account-id";
11
10
  import { adaptScopedAccountAccessor, createScopedChannelConfigAdapter, createScopedDmSecurityResolver } from "openclaw/plugin-sdk/channel-config-helpers";
12
11
  import { formatAllowFromLowercase } from "openclaw/plugin-sdk/allow-from";
13
12
  import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
14
- import { createOpenProviderConfiguredRouteWarningCollector } from "openclaw/plugin-sdk/channel-policy";
13
+ import { createConditionalWarningCollector, createOpenProviderConfiguredRouteWarningCollector } from "openclaw/plugin-sdk/channel-policy";
15
14
  import { defineChannelSetupContract } from "openclaw/plugin-sdk/channel-setup";
16
15
  import { createEnvPatchedAccountSetupAdapter } from "openclaw/plugin-sdk/setup-runtime";
17
16
  //#region extensions/discord/src/security.ts
@@ -48,10 +47,16 @@ const collectDiscordSecurityWarnings = createOpenProviderConfiguredRouteWarningC
48
47
  remediation: "Set channels.discord.groupPolicy=\"allowlist\" and configure channels.discord.guilds.<id>.channels"
49
48
  }
50
49
  });
51
- const loadDiscordSecurityAuditModule = createLazyRuntimeModule(() => import("./security-audit.runtime-CPN0xFYz.js"));
50
+ const collectDiscordSecurityFindings = createConditionalWarningCollector.findings({
51
+ collectWarnings: collectDiscordSecurityWarnings,
52
+ checkId: "channels.discord.groups.open",
53
+ severity: "critical",
54
+ title: "Discord security warning"
55
+ });
56
+ const loadDiscordSecurityAuditModule = createLazyRuntimeModule(() => import("./security-audit.runtime-BVKF9VtY.js"));
52
57
  const discordSecurityAdapter = {
53
58
  resolveDmPolicy: resolveDiscordDmPolicy,
54
- collectWarnings: collectDiscordSecurityWarnings,
59
+ collectWarnings: collectDiscordSecurityFindings,
55
60
  collectAuditFindings: async (params) => (await loadDiscordSecurityAuditModule()).collectDiscordSecurityAuditFindings(params)
56
61
  };
57
62
  const discordSetupContract = defineChannelSetupContract({
@@ -87,7 +92,7 @@ const DISCORD_LEGACY_CONFIG_RULES = [];
87
92
  //#endregion
88
93
  //#region extensions/discord/src/shared.ts
89
94
  const DISCORD_CHANNEL = "discord";
90
- const loadDiscordDoctorModule = createLazyRuntimeModule(() => import("./doctor-BzC-TLnB.js"));
95
+ const loadDiscordDoctorModule = createLazyRuntimeModule(() => import("./doctor-DYY31GrO.js"));
91
96
  const discordDoctor = {
92
97
  dmAllowFromMode: "topOnly",
93
98
  groupModel: "route",
@@ -0,0 +1,49 @@
1
+ import { en as __exportAll } from "./retry-DNsVTeTo.js";
2
+ import { o as unbindThreadBindingsBySessionKey, r as listThreadBindingsBySessionKey } from "./thread-bindings-VlymUnbz.js";
3
+ import { normalizeOptionalLowercaseString, normalizeOptionalStringifiedId } from "openclaw/plugin-sdk/string-coerce-runtime";
4
+ //#region extensions/discord/src/subagent-hooks.ts
5
+ var subagent_hooks_exports = /* @__PURE__ */ __exportAll({
6
+ handleDiscordSubagentDeliveryTarget: () => handleDiscordSubagentDeliveryTarget,
7
+ handleDiscordSubagentEnded: () => handleDiscordSubagentEnded
8
+ });
9
+ function normalizeThreadBindingTargetKind(raw) {
10
+ const normalized = normalizeOptionalLowercaseString(raw);
11
+ if (normalized === "subagent" || normalized === "acp") return normalized;
12
+ }
13
+ function handleDiscordSubagentEnded(event) {
14
+ unbindThreadBindingsBySessionKey({
15
+ targetSessionKey: event.targetSessionKey,
16
+ accountId: event.accountId,
17
+ targetKind: normalizeThreadBindingTargetKind(event.targetKind),
18
+ reason: event.reason,
19
+ sendFarewell: event.sendFarewell
20
+ });
21
+ }
22
+ function handleDiscordSubagentDeliveryTarget(event) {
23
+ if (!event.expectsCompletionMessage) return;
24
+ if (normalizeOptionalLowercaseString(event.requesterOrigin?.channel) !== "discord") return;
25
+ const requesterAccountId = event.requesterOrigin?.accountId?.trim();
26
+ const requesterThreadId = event.requesterOrigin?.threadId != null && event.requesterOrigin.threadId !== "" ? normalizeOptionalStringifiedId(event.requesterOrigin.threadId) ?? "" : "";
27
+ const bindings = listThreadBindingsBySessionKey({
28
+ targetSessionKey: event.childSessionKey,
29
+ ...requesterAccountId ? { accountId: requesterAccountId } : {},
30
+ targetKind: "subagent"
31
+ });
32
+ if (bindings.length === 0) return;
33
+ let binding;
34
+ if (requesterThreadId) binding = bindings.find((entry) => {
35
+ if (entry.threadId !== requesterThreadId) return false;
36
+ if (requesterAccountId && entry.accountId !== requesterAccountId) return false;
37
+ return true;
38
+ });
39
+ if (!binding && bindings.length === 1) binding = bindings[0];
40
+ if (!binding) return;
41
+ return { origin: {
42
+ channel: "discord",
43
+ accountId: binding.accountId,
44
+ to: `channel:${binding.threadId}`,
45
+ threadId: binding.threadId
46
+ } };
47
+ }
48
+ //#endregion
49
+ export { handleDiscordSubagentEnded as n, subagent_hooks_exports as r, handleDiscordSubagentDeliveryTarget as t };
@@ -1,7 +1,7 @@
1
1
  import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
2
2
  //#region extensions/discord/subagent-hooks-api.ts
3
- const loadDiscordSubagentHooksModule = createLazyRuntimeModule(() => import("./subagent-hooks-CTt5KCJr.js").then((n) => n.i));
4
- const loadDiscordSubagentProgressModule = createLazyRuntimeModule(() => import("./subagent-progress-DhaE_h8a.js"));
3
+ const loadDiscordSubagentHooksModule = createLazyRuntimeModule(() => import("./subagent-hooks-CNT2ZJTJ.js").then((n) => n.r));
4
+ const loadDiscordSubagentProgressModule = createLazyRuntimeModule(() => import("./subagent-progress-FPLqBY1s.js"));
5
5
  function registerDiscordSubagentHooks(api) {
6
6
  api.on("gateway_start", async () => {
7
7
  const { recoverDiscordSubagentProgress } = await loadDiscordSubagentProgressModule();
@@ -1,6 +1,7 @@
1
- import { l as resolveDiscordAccountConfig, s as resolveDiscordAccount } from "./accounts-DJTf1LtA.js";
2
- import { i as removeReactionDiscord } from "./send.reactions-BAn0iiVQ.js";
1
+ import { c as resolveDiscordAccount, u as resolveDiscordAccountConfig } from "./accounts-DNl-oCEw.js";
2
+ import { i as removeReactionDiscord } from "./send.reactions-gmJ6yFPo.js";
3
3
  import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/routing";
4
+ import { listAgentIds, resolveAgentConfig } from "openclaw/plugin-sdk/agent-scope-runtime";
4
5
  import { DEFAULT_EMOJIS } from "openclaw/plugin-sdk/channel-feedback";
5
6
  //#region extensions/discord/src/subagent-progress.ts
6
7
  const PROGRESS_STORE_TTL_MS = 10080 * 6e4;
@@ -28,8 +29,8 @@ function logFailure(api, action, error) {
28
29
  function reservedReactionEmojis(api, accountAckReaction) {
29
30
  const reserved = new Set(Object.values(DEFAULT_EMOJIS));
30
31
  for (const emoji of [api.config.messages?.ackReaction, accountAckReaction]) if (emoji?.trim()) reserved.add(emoji.trim());
31
- for (const agent of api.config.agents?.list ?? []) {
32
- const emoji = agent.identity?.emoji?.trim();
32
+ for (const agentId of listAgentIds(api.config)) {
33
+ const emoji = resolveAgentConfig(api.config, agentId)?.identity?.emoji?.trim();
33
34
  if (emoji) reserved.add(emoji);
34
35
  }
35
36
  return reserved;
@@ -1,5 +1,5 @@
1
- import { h as discord_exports } from "./retry-CLpJcXXf.js";
2
- import { x as formatDiscordUserTag } from "./allow-list-DnxIlPP2.js";
1
+ import { p as discord_exports } from "./retry-DNsVTeTo.js";
2
+ import { x as formatDiscordUserTag } from "./allow-list-BDMimASD.js";
3
3
  //#region extensions/discord/src/monitor/system-events.ts
4
4
  function resolveDiscordSystemEvent(message, location) {
5
5
  switch (message.type) {
@@ -1,6 +1,6 @@
1
- import { l as allowFromContainsDiscordUserId, p as parseDiscordTarget, tn as __exportAll } from "./retry-CLpJcXXf.js";
2
- import { c as resolveDiscordAccountAllowFrom, s as resolveDiscordAccount } from "./accounts-DJTf1LtA.js";
3
- import { a as rememberDiscordDirectoryUser, r as listDiscordDirectoryPeersLive } from "./directory-live-DGIGxpIo.js";
1
+ import { en as __exportAll, l as allowFromContainsDiscordUserId } from "./retry-DNsVTeTo.js";
2
+ import { c as resolveDiscordAccount, k as parseDiscordTarget, l as resolveDiscordAccountAllowFrom } from "./accounts-DNl-oCEw.js";
3
+ import { a as rememberDiscordDirectoryUser, r as listDiscordDirectoryPeersLive } from "./directory-live-Df0NbFJB.js";
4
4
  import { buildMessagingTarget } from "openclaw/plugin-sdk/channel-targets";
5
5
  //#region extensions/discord/src/send-target-parsing.ts
6
6
  const parseDiscordSendTarget = (raw, options = {}) => parseDiscordTarget(raw, options);
@@ -0,0 +1,3 @@
1
+ import "./accounts-DNl-oCEw.js";
2
+ import "./target-resolver-DIXShHaZ.js";
3
+ export {};
@@ -1,13 +1,14 @@
1
- import { p as parseDiscordTarget, tn as __exportAll } from "./retry-CLpJcXXf.js";
2
- import "./targets-yUFTHoAx.js";
3
- import { C as resolveThreadBindingMaxAgeExpiresAt, O as shouldPersistBindingMutations, S as resolveThreadBindingInactivityExpiresAt, T as saveBindingsToDisk, h as refreshUnboundThreadWebhookIdentity, m as normalizeThreadId, n as MANAGERS_BY_ACCOUNT_ID, t as BINDINGS_BY_THREAD_ID, u as getThreadBindingToken, v as removeBindingRecord, w as resolveThreadBindingMaxAgeMs$1, x as resolveThreadBindingIdleTimeoutMs$1 } from "./thread-bindings.state-aeV8HNgV.js";
4
- import { n as setThreadBindingMaxAgeBySessionKey, r as resolveBindingIdsForTargetSession, t as setThreadBindingIdleTimeoutBySessionKey } from "./thread-bindings.session-updates-bJ2KQFY6.js";
5
- import { _ as resolveThreadBindingThreadName, g as resolveThreadBindingIntroText, h as formatThreadBindingDurationLabel, m as resolveThreadBindingPersonaFromRecord, n as createThreadBindingManager, o as resolveChannelIdForBinding, p as resolveThreadBindingPersona, r as getThreadBindingManager, t as createNoopThreadBindingManager } from "./thread-bindings.manager-DCIH6WDC.js";
1
+ import { en as __exportAll } from "./retry-DNsVTeTo.js";
2
+ import { k as parseDiscordTarget } from "./accounts-DNl-oCEw.js";
3
+ import "./targets-B2pf49zc.js";
4
+ import { C as resolveThreadBindingMaxAgeExpiresAt, O as shouldPersistBindingMutations, S as resolveThreadBindingInactivityExpiresAt, T as saveBindingsToDisk, h as refreshUnboundThreadWebhookIdentity, m as normalizeThreadId, n as MANAGERS_BY_ACCOUNT_ID, t as BINDINGS_BY_THREAD_ID, u as getThreadBindingToken, v as removeBindingRecord, w as resolveThreadBindingMaxAgeMs$1, x as resolveThreadBindingIdleTimeoutMs$1 } from "./thread-bindings.state-D8OMdk4O.js";
5
+ import { n as setThreadBindingMaxAgeBySessionKey, r as resolveBindingIdsForTargetSession, t as setThreadBindingIdleTimeoutBySessionKey } from "./thread-bindings.session-updates-CJb-BpPL.js";
6
+ import { _ as resolveThreadBindingThreadName, g as resolveThreadBindingIntroText, h as formatThreadBindingDurationLabel, m as resolveThreadBindingPersonaFromRecord, n as createThreadBindingManager, o as resolveChannelIdForBinding, p as resolveThreadBindingPersona, r as getThreadBindingManager, t as createNoopThreadBindingManager } from "./thread-bindings.manager-CngsgErq.js";
6
7
  import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
7
8
  import { normalizeOptionalLowercaseString, normalizeOptionalString, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
8
9
  import { resolveThreadBindingIdleTimeoutMs, resolveThreadBindingMaxAgeMs, resolveThreadBindingsEnabled } from "openclaw/plugin-sdk/conversation-runtime";
9
10
  import { readAcpSessionEntry } from "openclaw/plugin-sdk/acp-runtime";
10
- import pMap from "p-map";
11
+ import { runTasksWithConcurrency } from "openclaw/plugin-sdk/concurrency-runtime";
11
12
  //#region extensions/discord/src/monitor/thread-bindings.config.ts
12
13
  function resolveDiscordThreadBindingIdleTimeoutMs(params) {
13
14
  const accountId = normalizeAccountId(params.accountId);
@@ -160,27 +161,29 @@ async function reconcileAcpThreadBindingsOnStartup(params) {
160
161
  });
161
162
  }
162
163
  if (params.healthProbe && probeTargets.length > 0) {
163
- const probeResults = await pMap(probeTargets, async ({ binding, sessionKey, session }) => {
164
- try {
165
- return {
166
- binding,
167
- status: (await params.healthProbe?.({
168
- cfg: params.cfg,
169
- accountId: manager.accountId,
170
- sessionKey,
164
+ const { results: probeResults } = await runTasksWithConcurrency({
165
+ tasks: probeTargets.map(({ binding, sessionKey, session }) => async () => {
166
+ try {
167
+ return {
171
168
  binding,
172
- session
173
- }))?.status ?? "uncertain"
174
- };
175
- } catch {
176
- return {
177
- binding,
178
- status: "uncertain"
179
- };
180
- }
181
- }, {
182
- concurrency: ACP_STARTUP_HEALTH_PROBE_CONCURRENCY_LIMIT,
183
- stopOnError: true
169
+ status: (await params.healthProbe?.({
170
+ cfg: params.cfg,
171
+ accountId: manager.accountId,
172
+ sessionKey,
173
+ binding,
174
+ session
175
+ }))?.status ?? "uncertain"
176
+ };
177
+ } catch {
178
+ return {
179
+ binding,
180
+ status: "uncertain"
181
+ };
182
+ }
183
+ }),
184
+ limit: ACP_STARTUP_HEALTH_PROBE_CONCURRENCY_LIMIT,
185
+ errorMode: "stop",
186
+ throwOnError: true
184
187
  });
185
188
  for (const probeResult of probeResults) if (probeResult.status === "stale") staleBindings.push(probeResult.binding);
186
189
  }
@@ -1,13 +1,14 @@
1
- import { Tt as getChannel, m as resolveDiscordChannelId, pt as createChannelWebhook, tn as __exportAll } from "./retry-CLpJcXXf.js";
2
- import { F as createDiscordRestClient } from "./send.shared-BmwFjW6T.js";
3
- import { t as sendMessageDiscord } from "./send.outbound-DS5tHwfR.js";
4
- import { i as sendWebhookMessageDiscord, o as createThreadDiscord } from "./send-B7Q6Oc1I.js";
5
- import { A as toReusableWebhookKey, C as resolveThreadBindingMaxAgeExpiresAt, D as shouldDefaultPersist, E as setBindingRecord, S as resolveThreadBindingInactivityExpiresAt, T as saveBindingsToDisk, _ as rememberThreadBindingToken, b as resolveBindingRecordKey, c as ensureBindingsLoaded, f as normalizeTargetKind, g as rememberReusableWebhook, h as refreshUnboundThreadWebhookIdentity, i as REUSABLE_WEBHOOKS_BY_ACCOUNT_CHANNEL, l as forgetThreadBindingToken, m as normalizeThreadId, n as MANAGERS_BY_ACCOUNT_ID, p as normalizeThreadBindingDurationMs, r as PERSIST_BY_ACCOUNT_ID, s as THREAD_BINDING_TOUCH_PERSIST_MIN_INTERVAL_MS, t as BINDINGS_BY_THREAD_ID, u as getThreadBindingToken, v as removeBindingRecord, w as resolveThreadBindingMaxAgeMs$1, x as resolveThreadBindingIdleTimeoutMs$1, y as resolveBindingIdsForSession } from "./thread-bindings.state-aeV8HNgV.js";
1
+ import { en as __exportAll, ft as createChannelWebhook, wt as getChannel } from "./retry-DNsVTeTo.js";
2
+ import { A as resolveDiscordChannelId } from "./accounts-DNl-oCEw.js";
3
+ import { F as createDiscordRestClient } from "./send.shared-B3fpaLWJ.js";
4
+ import { t as sendMessageDiscord } from "./send.outbound-HIkgji_7.js";
5
+ import { i as sendWebhookMessageDiscord, o as createThreadDiscord } from "./send-rQIffSYu.js";
6
+ import { A as toReusableWebhookKey, C as resolveThreadBindingMaxAgeExpiresAt, D as shouldDefaultPersist, E as setBindingRecord, S as resolveThreadBindingInactivityExpiresAt, T as saveBindingsToDisk, _ as rememberThreadBindingToken, b as resolveBindingRecordKey, c as ensureBindingsLoaded, f as normalizeTargetKind, g as rememberReusableWebhook, h as refreshUnboundThreadWebhookIdentity, i as REUSABLE_WEBHOOKS_BY_ACCOUNT_CHANNEL, l as forgetThreadBindingToken, m as normalizeThreadId, n as MANAGERS_BY_ACCOUNT_ID, p as normalizeThreadBindingDurationMs, r as PERSIST_BY_ACCOUNT_ID, s as THREAD_BINDING_TOUCH_PERSIST_MIN_INTERVAL_MS, t as BINDINGS_BY_THREAD_ID, u as getThreadBindingToken, v as removeBindingRecord, w as resolveThreadBindingMaxAgeMs$1, x as resolveThreadBindingIdleTimeoutMs$1, y as resolveBindingIdsForSession } from "./thread-bindings.state-D8OMdk4O.js";
7
+ import { ChannelType } from "discord-api-types/v10";
8
+ import { parseStrictNonNegativeInteger } from "openclaw/plugin-sdk/number-runtime";
6
9
  import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
7
10
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
8
11
  import { getRuntimeConfigSnapshot } from "openclaw/plugin-sdk/runtime-config-snapshot";
9
- import { ChannelType } from "discord-api-types/v10";
10
- import { parseStrictNonNegativeInteger as parseStrictNonNegativeInteger$1 } from "openclaw/plugin-sdk/number-runtime";
11
12
  import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
12
13
  import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
13
14
  import { SYSTEM_MARK } from "openclaw/plugin-sdk/text-chunking";
@@ -125,7 +126,7 @@ function summarizeDiscordError(err) {
125
126
  return "error";
126
127
  }
127
128
  function extractNumericDiscordErrorValue(value) {
128
- return parseStrictNonNegativeInteger$1(value);
129
+ return parseStrictNonNegativeInteger(value);
129
130
  }
130
131
  function extractDiscordErrorStatus(err) {
131
132
  if (!err || typeof err !== "object") return;
@@ -1,4 +1,4 @@
1
- import { E as setBindingRecord, O as shouldPersistBindingMutations, T as saveBindingsToDisk, c as ensureBindingsLoaded, t as BINDINGS_BY_THREAD_ID, y as resolveBindingIdsForSession } from "./thread-bindings.state-aeV8HNgV.js";
1
+ import { E as setBindingRecord, O as shouldPersistBindingMutations, T as saveBindingsToDisk, c as ensureBindingsLoaded, t as BINDINGS_BY_THREAD_ID, y as resolveBindingIdsForSession } from "./thread-bindings.state-D8OMdk4O.js";
2
2
  import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
3
3
  //#region extensions/discord/src/monitor/thread-bindings.session-shared.ts
4
4
  function normalizeNonNegativeMs(raw) {
@@ -223,7 +223,7 @@ function shouldPersistBindingMutations() {
223
223
  function toPersistedBindingRecord(record) {
224
224
  const serialized = JSON.stringify(record);
225
225
  if (!serialized) return { ...record };
226
- return JSON.parse(serialized);
226
+ return normalizePersistedBinding(record.threadId, JSON.parse(serialized)) ?? { ...record };
227
227
  }
228
228
  function saveBindingsToDisk(params = {}) {
229
229
  if (!params.force && !shouldPersistAnyBindingState()) return;