@openclaw/discord 2026.9.8 → 2026.10.1-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/README.md +7 -0
  2. package/dist/.setup/{account-inspect-De8hOUxG.mjs → account-inspect-CjKqkDnH.mjs} +2 -2
  3. package/dist/.setup/{accounts-ChaMcixG.mjs → accounts-DXHCL8Zm.mjs} +9 -32
  4. package/dist/.setup/{active-turn-thread-route-fmHl1HNd.mjs → active-turn-thread-route-C4tp9noA.mjs} +5 -9
  5. package/dist/.setup/{activities-api-tvbsU2e3.mjs → activities-api-BL_hJ0JQ.mjs} +15 -18
  6. package/dist/.setup/{api-DVbJwZVt.mjs → api-_oznjffB.mjs} +1 -1
  7. package/dist/.setup/{approval-handler.runtime-DxCK2Rux.mjs → approval-handler.runtime-G-tMI_uD.mjs} +22 -61
  8. package/dist/.setup/{approval-message-updates-BKFqavHZ.mjs → approval-message-updates-CgRwc2_Q.mjs} +2 -2
  9. package/dist/.setup/{audit-CLg9I71N.mjs → audit-DtvzxONM.mjs} +4 -4
  10. package/dist/.setup/{channel-DxlUVU9t.mjs → channel-Ct3fRxet.mjs} +79 -75
  11. package/dist/.setup/{channel-access-C12aDZ0p.mjs → channel-access-BRp3Y-rF.mjs} +4 -17
  12. package/dist/.setup/{channel-type-DRCrEMss.mjs → channel-type-D1_b5UhU.mjs} +12 -16
  13. package/dist/.setup/{channel.setup-CRo1GjV7.mjs → channel.setup-DBJtugJO.mjs} +14 -34
  14. package/dist/.setup/{components-Cq1PvIpN.mjs → components-CzXLR3QH.mjs} +56 -72
  15. package/dist/.setup/{config-schema-oxELUSDx.mjs → config-schema-CsemBDpS.mjs} +6 -17
  16. package/dist/.setup/{conversation-binding-route-Caz_XuFH.mjs → conversation-binding-route-Bi62ApSt.mjs} +1 -1
  17. package/dist/.setup/{directory-config-esqNn0Eo.mjs → directory-config-BH1LA-gi.mjs} +1 -1
  18. package/dist/.setup/{directory-live-DtKRHuGV.mjs → directory-live-C9xz7IPm.mjs} +10 -13
  19. package/dist/.setup/{discord-0xJYfdDD.mjs → discord-J7aRzq2Q.mjs} +101 -381
  20. package/dist/.setup/{doctor-BCl1H5tl.mjs → doctor-DxSAngJq.mjs} +31 -70
  21. package/dist/.setup/doctor-contract-Bg3NPAMw.mjs +137 -0
  22. package/dist/.setup/{handle-action-CUvQWnE7.mjs → handle-action-DlmFX-_G.mjs} +10 -11
  23. package/dist/.setup/{handle-action.guild-admin-Df-8gVle.mjs → handle-action.guild-admin-BnyqTczR.mjs} +67 -129
  24. package/dist/.setup/{live-policy-config-8Pv20CHc.mjs → live-policy-config-emmPNyh4.mjs} +1 -1
  25. package/dist/.setup/{message-handler-B-Jk4oDk.mjs → message-handler-CDWDjWF0.mjs} +6 -6
  26. package/dist/.setup/{message-handler.preflight-v-__NSDq.mjs → message-handler.preflight-Cop4atEb.mjs} +13 -23
  27. package/dist/.setup/{message-handler.preflight-pluralkit-CWLUBVcx.mjs → message-handler.preflight-pluralkit-D1g3eq0B.mjs} +5 -8
  28. package/dist/.setup/{message-handler.process-BNFFuChn.mjs → message-handler.process-lX7pDqsd.mjs} +57 -96
  29. package/dist/.setup/{outbound-adapter-BobT-kse.mjs → outbound-adapter-BPq0c2wY.mjs} +11 -17
  30. package/dist/.setup/{outbound-session-route-zVGxxceg.mjs → outbound-session-route-DGPPKA0z.mjs} +21 -46
  31. package/dist/.setup/{presence-cache-Di3H3DIU.mjs → presence-cache-Dg3_dADn.mjs} +2 -4
  32. package/dist/.setup/{probe-LYrIHlBF.mjs → probe-DIRY8vh7.mjs} +17 -27
  33. package/dist/.setup/{provider-B_G5hASF.mjs → provider-DIexE7gK.mjs} +273 -446
  34. package/dist/.setup/{provider-session.runtime-BYlTBFD2.mjs → provider-session.runtime-C2UCZz8d.mjs} +3 -3
  35. package/dist/.setup/provider.runtime-Dkzrmmcm.mjs +2 -0
  36. package/dist/.setup/{realtime-session.runtime-oUd9DOcz.mjs → realtime-session.runtime-DvjyeY87.mjs} +6 -8
  37. package/dist/.setup/{receive-recovery-CHPOsnLc.mjs → receive-recovery-GqF2PUN_.mjs} +1 -4
  38. package/dist/.setup/{resolve-allowlist-common-DPdRggu5.mjs → resolve-allowlist-common-DUYRrrVB.mjs} +5 -9
  39. package/dist/.setup/{resolve-channels-BFPNRmVv.mjs → resolve-channels--MUatisx.mjs} +3 -3
  40. package/dist/.setup/{resolve-users-0-aBuCy3.mjs → resolve-users-CxLcDmM0.mjs} +6 -9
  41. package/dist/.setup/{retry-pz_cSha2.mjs → retry-BKzO25k4.mjs} +27 -51
  42. package/dist/.setup/{runtime-sUksZ--Q.mjs → runtime-CerRBfaa.mjs} +2 -2
  43. package/dist/.setup/{runtime-FN000lxA.mjs → runtime-CwUA0RLr.mjs} +228 -255
  44. package/dist/.setup/{runtime-doctor-migrations-CshUGl36.mjs → runtime-doctor-migrations-BPV-R4G9.mjs} +6 -0
  45. package/dist/.setup/{security-audit-Cdaegq7C.mjs → security-audit-D42cp5N7.mjs} +21 -48
  46. package/dist/.setup/{send-CrfEI6Bs.mjs → send-2X7m2Zmw.mjs} +45 -58
  47. package/dist/.setup/{send.components-DxQAMfES.mjs → send.components-RqvgmCs3.mjs} +44 -90
  48. package/dist/.setup/{send.outbound-BISKnb-a.mjs → send.outbound-B4QHSEzm.mjs} +60 -98
  49. package/dist/.setup/{send.shared-DGFkbkQR.mjs → send.shared-BQIUh6Vn.mjs} +13 -20
  50. package/dist/.setup/{sender-identity-B9X5Vb9R.mjs → sender-identity-CooeYfAn.mjs} +1 -1
  51. package/dist/.setup/{session-key-normalization-wJgsKPNF.mjs → session-key-normalization-CCHGNSQw.mjs} +3 -9
  52. package/dist/.setup/setup-plugin-api-nn_giXvZ.mjs +3 -0
  53. package/dist/.setup/{shared-B3wZ4hN-.mjs → shared-CIJn6AEC.mjs} +7 -7
  54. package/dist/.setup/{subagent-hooks-nlUE9ow7.mjs → subagent-hooks-BYlVnxzy.mjs} +4 -9
  55. package/dist/.setup/{system-events-CdeZnvPV.mjs → system-events-CQ3if_pS.mjs} +2 -2
  56. package/dist/.setup/{target-resolver-BuLapkhy.mjs → target-resolver-Dzxf80Y3.mjs} +5 -13
  57. package/dist/.setup/targets-Lf8D55w-.mjs +3 -0
  58. package/dist/.setup/{thread-bindings-D7TfgjR_.mjs → thread-bindings-yNNlcUWE.mjs} +5 -6
  59. package/dist/.setup/{thread-bindings.manager-DN-NissX.mjs → thread-bindings.manager-plk0zJAW.mjs} +14 -20
  60. package/dist/.setup/{thread-bindings.session-updates-CshfKghV.mjs → thread-bindings.session-updates-C9aKtVs6.mjs} +295 -5
  61. package/dist/.setup/{timeouts-D86uWLt_.mjs → timeouts-pun7VJ02.mjs} +2 -15
  62. package/dist/.setup/{transcripts-source-p8EV179h.mjs → transcripts-source-CNWswry-.mjs} +31 -79
  63. package/dist/.setup/typing-CNlSKY5S.mjs +11 -0
  64. package/dist/.setup/{voice-runtime-B46rcwrG.mjs → voice-runtime-CeS6zfY3.mjs} +62 -110
  65. package/dist/account-inspect-api.js +1 -1
  66. package/dist/action-runtime-api.js +1 -1
  67. package/dist/activities-api.js +1 -1
  68. package/dist/api.js +18 -18
  69. package/dist/channel-config-api.js +1 -1
  70. package/dist/channel-plugin-api.js +1 -1
  71. package/dist/control-ui/2afbdab1d3aa65a789d8a3eba666f4b1ec5df07073538fe30d6cf32093a1fb2d/index.js +1 -0
  72. package/dist/directory-contract-api.js +1 -1
  73. package/dist/doctor-contract-api.js +19 -128
  74. package/dist/index.js +1 -1
  75. package/dist/runtime-api.js +20 -21
  76. package/dist/security-audit-contract-api.js +1 -1
  77. package/dist/session-key-api.js +1 -1
  78. package/dist/setup-entry.js +1 -1
  79. package/dist/setup-plugin-api.js +1 -1
  80. package/dist/src/voice/audio-worker.runtime.js +6 -8
  81. package/dist/subagent-hooks-api.js +1 -1
  82. package/dist/transcripts-source-api.js +1 -1
  83. package/node_modules/libopus-wasm/CHANGELOG.md +8 -0
  84. package/node_modules/libopus-wasm/dist/discordjs.d.ts.map +1 -1
  85. package/node_modules/libopus-wasm/dist/discordjs.js +14 -2
  86. package/node_modules/libopus-wasm/dist/generated/libopus.generated.mjs +0 -0
  87. package/node_modules/libopus-wasm/dist/index.d.ts.map +1 -1
  88. package/node_modules/libopus-wasm/dist/index.js +55 -100
  89. package/node_modules/libopus-wasm/package.json +5 -5
  90. package/node_modules/undici/README.md +10 -1
  91. package/node_modules/undici/docs/docs/api/Agent.md +8 -8
  92. package/node_modules/undici/docs/docs/api/DiagnosticsChannel.md +9 -6
  93. package/node_modules/undici/docs/docs/api/Dispatcher.md +9 -0
  94. package/node_modules/undici/docs/docs/api/Errors.md +25 -0
  95. package/node_modules/undici/docs/docs/api/Fetch.md +10 -0
  96. package/node_modules/undici/docs/docs/api/Interceptors.md +4 -3
  97. package/node_modules/undici/docs/docs/api/Pool.md +5 -6
  98. package/node_modules/undici/docs/docs/index.md +10 -1
  99. package/node_modules/undici/lib/api/readable.js +1 -2
  100. package/node_modules/undici/lib/core/request.js +23 -2
  101. package/node_modules/undici/lib/core/util.js +0 -39
  102. package/node_modules/undici/lib/dispatcher/client-h1.js +11 -4
  103. package/node_modules/undici/lib/dispatcher/client-h2.js +52 -8
  104. package/node_modules/undici/lib/dispatcher/client.js +6 -1
  105. package/node_modules/undici/lib/dispatcher/env-http-proxy-agent.js +21 -6
  106. package/node_modules/undici/lib/dispatcher/pool-base.js +63 -2
  107. package/node_modules/undici/lib/dispatcher/pool.js +90 -7
  108. package/node_modules/undici/lib/dispatcher/proxy-agent.js +16 -3
  109. package/node_modules/undici/lib/handler/deduplication-handler.js +24 -11
  110. package/node_modules/undici/lib/handler/redirect-handler.js +5 -0
  111. package/node_modules/undici/lib/handler/retry-handler.js +72 -13
  112. package/node_modules/undici/lib/interceptor/cache.js +4 -1
  113. package/node_modules/undici/lib/interceptor/decompress.js +236 -69
  114. package/node_modules/undici/lib/web/cache/cache.js +17 -8
  115. package/node_modules/undici/lib/web/cache/cachestorage.js +11 -5
  116. package/node_modules/undici/lib/web/cookies/index.js +19 -7
  117. package/node_modules/undici/lib/web/cookies/util.js +3 -1
  118. package/node_modules/undici/lib/web/eventsource/eventsource.js +25 -1
  119. package/node_modules/undici/lib/web/fetch/body.js +22 -15
  120. package/node_modules/undici/lib/web/fetch/data-url.js +6 -6
  121. package/node_modules/undici/lib/web/fetch/formdata.js +30 -36
  122. package/node_modules/undici/lib/web/fetch/headers.js +34 -31
  123. package/node_modules/undici/lib/web/fetch/index.js +46 -25
  124. package/node_modules/undici/lib/web/fetch/request.js +74 -79
  125. package/node_modules/undici/lib/web/fetch/response.js +43 -44
  126. package/node_modules/undici/lib/web/fetch/util.js +7 -7
  127. package/node_modules/undici/lib/web/infra/index.js +16 -1
  128. package/node_modules/undici/lib/web/webidl/index.js +2 -14
  129. package/node_modules/undici/lib/web/websocket/connection.js +33 -12
  130. package/node_modules/undici/lib/web/websocket/events.js +43 -26
  131. package/node_modules/undici/lib/web/websocket/receiver.js +2 -0
  132. package/node_modules/undici/lib/web/websocket/stream/websocketerror.js +13 -10
  133. package/node_modules/undici/lib/web/websocket/stream/websocketstream.js +19 -4
  134. package/node_modules/undici/lib/web/websocket/websocket.js +44 -41
  135. package/node_modules/undici/package.json +1 -1
  136. package/node_modules/undici/types/diagnostics-channel.d.ts +2 -1
  137. package/node_modules/undici/types/interceptors.d.ts +1 -1
  138. package/node_modules/undici/types/webidl.d.ts +13 -7
  139. package/openclaw.plugin.json +6 -0
  140. package/package.json +12 -7
  141. package/dist/.setup/doctor-contract-CvvgwrrG.mjs +0 -409
  142. package/dist/.setup/model-picker-preference-primitives-BHT1LkR_.mjs +0 -37
  143. package/dist/.setup/provider.runtime-CUE3UxER.mjs +0 -2
  144. package/dist/.setup/setup-plugin-api-BQUBxbhe.mjs +0 -3
  145. package/dist/.setup/targets-0KUcEIYx.mjs +0 -3
  146. package/dist/.setup/thread-bindings.state-g6v9zAym.mjs +0 -331
  147. package/dist/.setup/typing-BiHCzBRu.mjs +0 -15
package/README.md CHANGED
@@ -9,3 +9,10 @@ openclaw plugins install @openclaw/discord
9
9
  ```
10
10
 
11
11
  Configure a Discord bot token and the channels or servers OpenClaw should handle. The plugin lets OpenClaw agents receive Discord messages and respond through the configured Discord app.
12
+
13
+ Configurations using pre-July-2026 `voice.tts.<provider>` keys or per-channel
14
+ `allow`/`agentId` fields require an intermediate upgrade. Install OpenClaw
15
+ `2026.9.7` and run `openclaw doctor --fix` before upgrading again. Current Doctor
16
+ preserves these old settings and reports the exact path instead of rewriting
17
+ them. Supported configurations use `voice.tts.providers`, channel `enabled`,
18
+ and top-level `bindings`.
@@ -1,6 +1,6 @@
1
- import { _ as inspectDiscordAccountTokenState, o as mergeDiscordAccountConfig, r as listDiscordAccountIds, s as resolveDefaultDiscordAccountId, u as resolveDiscordAccountConfig, v as resolveDiscordAccountAvailability } from "./accounts-ChaMcixG.mjs";
2
- import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-id";
1
+ import { _ as inspectDiscordAccountTokenState, o as mergeDiscordAccountConfig, r as listDiscordAccountIds, s as resolveDefaultDiscordAccountId, u as resolveDiscordAccountConfig, v as resolveDiscordAccountAvailability } from "./accounts-DXHCL8Zm.mjs";
3
2
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
3
+ import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-id";
4
4
  import { normalizeSecretInputString } from "openclaw/plugin-sdk/secret-input";
5
5
  //#region extensions/discord/src/account-inspect.ts
6
6
  function inspectDiscordAccountPrimary(params) {
@@ -1,9 +1,9 @@
1
+ import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
1
2
  import { createAccountActionGate, createAccountListHelpers } from "openclaw/plugin-sdk/account-helpers";
2
3
  import { normalizeAccountId } from "openclaw/plugin-sdk/account-id";
3
4
  import { mapAllowFromEntries, normalizeChannelDmPolicy } from "openclaw/plugin-sdk/channel-config-helpers";
4
5
  import { resolveConfiguredFromCredentialStatuses } from "openclaw/plugin-sdk/channel-status";
5
6
  import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1, normalizeAccountId as normalizeAccountId$1, resolveAccountEntry } from "openclaw/plugin-sdk/routing";
6
- import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
7
7
  import { hasConfiguredSecretInput, normalizeResolvedSecretInputString, normalizeSecretInputString, resolveSecretInputString } from "openclaw/plugin-sdk/secret-input";
8
8
  import { getRuntimeConfigSnapshot, getRuntimeConfigSourceSnapshot, selectApplicableRuntimeConfig } from "openclaw/plugin-sdk/runtime-config-snapshot";
9
9
  //#region extensions/discord/src/account-token-inspect.ts
@@ -22,43 +22,20 @@ function inspectDiscordConfiguredToken(value) {
22
22
  return null;
23
23
  }
24
24
  function inspectDiscordAccountTokenState(params) {
25
- const accountToken = inspectDiscordConfiguredToken(params.accountToken);
26
- if (accountToken) return {
25
+ const configuredToken = inspectDiscordConfiguredToken(params.accountToken) ?? (params.hasAccountToken ? null : inspectDiscordConfiguredToken(params.channelToken));
26
+ if (configuredToken) return {
27
27
  ...params.base,
28
- ...accountToken,
29
- configured: true,
30
- config: params.config
31
- };
32
- if (params.hasAccountToken) return {
33
- ...params.base,
34
- token: "",
35
- tokenSource: "none",
36
- tokenStatus: "missing",
37
- configured: false,
38
- config: params.config
39
- };
40
- const channelToken = inspectDiscordConfiguredToken(params.channelToken);
41
- if (channelToken) return {
42
- ...params.base,
43
- ...channelToken,
44
- configured: true,
45
- config: params.config
46
- };
47
- const fallback = params.resolveFallbackToken();
48
- if (fallback.token) return {
49
- ...params.base,
50
- token: fallback.token,
51
- tokenSource: fallback.source,
52
- tokenStatus: "available",
28
+ ...configuredToken,
53
29
  configured: true,
54
30
  config: params.config
55
31
  };
32
+ const fallback = params.hasAccountToken ? void 0 : params.resolveFallbackToken();
56
33
  return {
57
34
  ...params.base,
58
- token: "",
59
- tokenSource: "none",
60
- tokenStatus: "missing",
61
- configured: false,
35
+ token: fallback?.token || "",
36
+ tokenSource: fallback?.token ? fallback.source : "none",
37
+ tokenStatus: fallback?.token ? "available" : "missing",
38
+ configured: Boolean(fallback?.token),
62
39
  config: params.config
63
40
  };
64
41
  }
@@ -28,17 +28,13 @@ async function notifyDiscordActiveTurnThreadCreated(params) {
28
28
  return true;
29
29
  }
30
30
  function notifyDiscordActiveTurnThreadReplyDelivered(params) {
31
- const route = findDiscordActiveTurnThreadReplyRoute(params);
32
- const threadId = normalizeOptionalString(params.threadId ?? void 0);
33
- if (!route || !threadId) return false;
34
- route.onThreadReplyDelivered?.(threadId);
35
- return true;
36
- }
37
- function findDiscordActiveTurnThreadReplyRoute(params) {
38
31
  const key = normalizeOptionalString(params.sessionKey ?? void 0);
39
32
  const threadId = normalizeOptionalString(params.threadId);
40
- if (!key || !threadId) return;
41
- return Array.from(activeRoutes.get(key) ?? []).find((route) => Boolean(route.adoptedThreadId) && route.adoptedThreadId === threadId && (!route.accountId || !params.accountId || route.accountId === params.accountId));
33
+ if (!key || !threadId) return false;
34
+ const route = Array.from(activeRoutes.get(key) ?? []).find((candidate) => candidate.adoptedThreadId === threadId && (!candidate.accountId || !params.accountId || candidate.accountId === params.accountId));
35
+ if (!route) return false;
36
+ route.onThreadReplyDelivered?.(threadId);
37
+ return true;
42
38
  }
43
39
  //#endregion
44
40
  export { notifyDiscordActiveTurnThreadCreated as n, notifyDiscordActiveTurnThreadReplyDelivered as r, beginDiscordActiveTurnThreadRoute as t };
@@ -1,11 +1,12 @@
1
- import { S as parseDiscordActivityCustomId, i as buildDiscordPresentationComponents } from "./components-Cq1PvIpN.mjs";
2
- import { D as getDiscordEndpointRuntime } from "./channel-type-DRCrEMss.mjs";
3
- import { c as resolveDiscordAccount } from "./accounts-ChaMcixG.mjs";
4
- import { r as sendDiscordComponentMessage } from "./send.components-DxQAMfES.mjs";
5
- import { x as resolveDiscordChannelId$1 } from "./retry-pz_cSha2.mjs";
6
- import { r as setDiscordActivitiesRuntime, t as DiscordActivitiesRuntime } from "./runtime-sUksZ--Q.mjs";
1
+ import { S as parseDiscordActivityCustomId, i as buildDiscordPresentationComponents } from "./components-CzXLR3QH.mjs";
2
+ import { O as getDiscordEndpointRuntime } from "./channel-type-D1_b5UhU.mjs";
3
+ import { c as resolveDiscordAccount } from "./accounts-DXHCL8Zm.mjs";
4
+ import { r as sendDiscordComponentMessage } from "./send.components-RqvgmCs3.mjs";
5
+ import { x as resolveDiscordChannelId$1 } from "./retry-BKzO25k4.mjs";
6
+ import { r as setDiscordActivitiesRuntime, t as DiscordActivitiesRuntime } from "./runtime-CerRBfaa.mjs";
7
7
  import fs from "node:fs/promises";
8
8
  import { logError } from "openclaw/plugin-sdk/logging-core";
9
+ import { asOptionalRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
9
10
  import { resolveRequestClientIp } from "openclaw/plugin-sdk/webhook-ingress";
10
11
  import { WEBHOOK_BODY_READ_DEFAULTS, readJsonBodyWithLimit, sendHttpRequestRejection } from "openclaw/plugin-sdk/webhook-request-guards";
11
12
  import { WIDGET_CDN_ORIGINS } from "openclaw/plugin-sdk/widget-html";
@@ -21,15 +22,11 @@ const JSON_MAX_BYTES = 65536;
21
22
  const INSTANCE_ID_MAX_LENGTH = 256;
22
23
  function normalizeInstanceId(value) {
23
24
  const instanceId = value?.trim();
24
- let hasControlCharacter = false;
25
- for (let index = 0; index < (instanceId?.length ?? 0); index += 1) {
26
- const codePoint = instanceId?.charCodeAt(index) ?? 0;
27
- if (codePoint < 32 || codePoint === 127) {
28
- hasControlCharacter = true;
29
- break;
30
- }
25
+ if (!instanceId || instanceId.length > INSTANCE_ID_MAX_LENGTH) return;
26
+ for (let index = 0; index < instanceId.length; index += 1) {
27
+ const codePoint = instanceId.charCodeAt(index);
28
+ if (codePoint < 32 || codePoint === 127) return;
31
29
  }
32
- if (!instanceId || instanceId.length > INSTANCE_ID_MAX_LENGTH || hasControlCharacter) return;
33
30
  return instanceId;
34
31
  }
35
32
  async function fetchDiscordJson(params) {
@@ -337,7 +334,7 @@ function createDiscordActivityHttpHandler(deps) {
337
334
  await sendHttpRequestRejection(req, res, timedOut ? 408 : 413, jsonBody({ error: timedOut ? "request body timeout" : "request body too large" }), JSON_CONTENT_TYPE);
338
335
  return true;
339
336
  }
340
- const body = bodyResult.ok && bodyResult.value && typeof bodyResult.value === "object" && !Array.isArray(bodyResult.value) ? bodyResult.value : null;
337
+ const body = bodyResult.ok ? asOptionalRecord(bodyResult.value) : void 0;
341
338
  const code = typeof body?.code === "string" ? body.code.trim() : "";
342
339
  if (!code) return respondJson(res, 401, { error: "invalid authorization code" });
343
340
  const reservation = limiter.reserveGlobal();
@@ -520,7 +517,7 @@ function resolveDiscordPresentationRoute(context, runtime) {
520
517
  };
521
518
  }
522
519
  /** Presents a canonical core widget document in the active Discord channel. */
523
- function createDiscordWidgetPresenter(runtime, deps = {}) {
520
+ function createDiscordWidgetPresenter(runtime) {
524
521
  return {
525
522
  target: "current_channel",
526
523
  description: "Post an Activity launch button in the current Discord channel",
@@ -562,7 +559,7 @@ function createDiscordWidgetPresenter(runtime, deps = {}) {
562
559
  title,
563
560
  channelId: route.channelId,
564
561
  accountId: route.account.accountId,
565
- createdAt: (deps.now ?? Date.now)()
562
+ createdAt: Date.now()
566
563
  });
567
564
  let result;
568
565
  let deliveredResult;
@@ -590,7 +587,7 @@ function createDiscordWidgetPresenter(runtime, deps = {}) {
590
587
  }]
591
588
  }] });
592
589
  if (!components) throw new Error("Discord widget launch button could not be rendered");
593
- result = await (deps.sendComponentMessage ?? sendDiscordComponentMessage)(`channel:${route.channelId}`, {
590
+ result = await sendDiscordComponentMessage(`channel:${route.channelId}`, {
594
591
  ...components,
595
592
  text: title
596
593
  }, {
@@ -1,4 +1,4 @@
1
- import { D as getDiscordEndpointRuntime, T as parseDiscordRetryAfterBodySeconds } from "./channel-type-DRCrEMss.mjs";
1
+ import { E as parseDiscordRetryAfterBodySeconds, O as getDiscordEndpointRuntime } from "./channel-type-D1_b5UhU.mjs";
2
2
  import { redactToolPayloadText } from "openclaw/plugin-sdk/logging-core";
3
3
  import { resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
4
4
  import { captureChannelReadAuthority, resolveFetch } from "openclaw/plugin-sdk/fetch-runtime";
@@ -1,35 +1,15 @@
1
- import { s as buildExecApprovalCustomId } from "./components-Cq1PvIpN.mjs";
2
- import { A as serializePayload, B as Container, J as Separator, K as Row, R as Button, X as TextDisplay, ct as createChannelMessage, dt as deleteChannelMessage, pt as editChannelMessage, rt as createUserDmChannel, tt as stripUndefinedFields } from "./discord-0xJYfdDD.mjs";
3
- import { s as findGraphemeChunkEnd } from "./retry-pz_cSha2.mjs";
4
- import { D as createDiscordMessageNonce, M as createDiscordClient } from "./send.shared-DGFkbkQR.mjs";
5
- import { D as isDiscordExecApprovalClientEnabled, c as formatDiscordApprovalDisplayValue, s as DISCORD_APPROVAL_ALLOWED_MENTIONS } from "./outbound-session-route-zVGxxceg.mjs";
6
- import { a as shouldHandleDiscordApprovalRequest } from "./channel-DxlUVU9t.mjs";
7
- import { t as discordApprovalMessageUpdates } from "./approval-message-updates-BKFqavHZ.mjs";
1
+ import { s as buildExecApprovalCustomId } from "./components-CzXLR3QH.mjs";
2
+ import { A as serializePayload, B as Container, J as Separator, K as Row, R as Button, X as TextDisplay, lt as deleteChannelMessage, rt as createUserDmChannel, tt as stripUndefinedFields, ut as editChannelMessage } from "./discord-J7aRzq2Q.mjs";
3
+ import { s as findGraphemeChunkEnd } from "./retry-BKzO25k4.mjs";
4
+ import { D as createDiscordMessageNonce, M as createDiscordClient } from "./send.shared-BQIUh6Vn.mjs";
5
+ import { D as isDiscordExecApprovalClientEnabled, c as formatDiscordApprovalDisplayValue, s as DISCORD_APPROVAL_ALLOWED_MENTIONS } from "./outbound-session-route-DGPPKA0z.mjs";
6
+ import { a as shouldHandleDiscordApprovalRequest } from "./channel-Ct3fRxet.mjs";
7
+ import { t as discordApprovalMessageUpdates } from "./approval-message-updates-CgRwc2_Q.mjs";
8
8
  import { logDebug, logError } from "openclaw/plugin-sdk/logging-core";
9
- import { ButtonStyle } from "discord-api-types/v10";
10
9
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
10
+ import { ButtonStyle, Routes } from "discord-api-types/v10";
11
11
  import { createChannelApprovalNativeRuntimeAdapter } from "openclaw/plugin-sdk/approval-handler-runtime";
12
12
  import { formatChannelApprovalResolvedLabel } from "openclaw/plugin-sdk/approval-runtime";
13
- //#region extensions/discord/src/ui-colors.ts
14
- function normalizeDiscordAccentColor(raw) {
15
- const trimmed = (raw ?? "").trim();
16
- if (!trimmed) return null;
17
- const normalized = trimmed.startsWith("#") ? trimmed : `#${trimmed}`;
18
- if (!/^#[0-9a-fA-F]{6}$/.test(normalized)) return null;
19
- return normalized.toUpperCase();
20
- }
21
- //#endregion
22
- //#region extensions/discord/src/ui.ts
23
- var DiscordUiContainer = class extends Container {
24
- constructor(params) {
25
- const accentColor = normalizeDiscordAccentColor(params.accentColor) ?? "#5865F2";
26
- super(params.components, {
27
- accentColor,
28
- spoiler: params.spoiler
29
- });
30
- }
31
- };
32
- //#endregion
33
13
  //#region extensions/discord/src/approval-handler.runtime.ts
34
14
  function resolveHandlerContext(params) {
35
15
  const context = params.context;
@@ -104,30 +84,19 @@ function createApprovalContainer(params) {
104
84
  divider: false,
105
85
  spacing: "small"
106
86
  }), new TextDisplay(`-# ${footer}`));
107
- return new DiscordUiContainer({
108
- cfg: params.cfg,
109
- accountId: params.accountId,
110
- components,
111
- accentColor
112
- });
87
+ return new Container(components, { accentColor });
113
88
  }
114
- async function updateMessage(params) {
115
- try {
89
+ async function finalizeMessage(params) {
90
+ if (params.cleanupAfterResolve) try {
116
91
  const { rest, request: discordRequest } = createDiscordClient({
117
92
  cfg: params.cfg,
118
93
  token: params.token,
119
94
  accountId: params.accountId
120
95
  });
121
- const payload = buildExecApprovalPayload(params.container);
122
- await discordApprovalMessageUpdates.enqueue(params.messageId, () => discordRequest(() => editChannelMessage(rest, params.channelId, params.messageId, { body: stripUndefinedFields(serializePayload(payload)) }), "update-approval"));
123
- } catch (err) {
124
- logError(`discord approvals: failed to update message: ${String(err)}`);
125
- }
126
- }
127
- async function finalizeMessage(params) {
128
- if (!params.cleanupAfterResolve) {
129
- await updateMessage(params);
96
+ await discordApprovalMessageUpdates.enqueue(params.messageId, () => discordRequest(() => deleteChannelMessage(rest, params.channelId, params.messageId), "delete-approval"));
130
97
  return;
98
+ } catch (err) {
99
+ logError(`discord approvals: failed to delete message: ${String(err)}`);
131
100
  }
132
101
  try {
133
102
  const { rest, request: discordRequest } = createDiscordClient({
@@ -135,22 +104,17 @@ async function finalizeMessage(params) {
135
104
  token: params.token,
136
105
  accountId: params.accountId
137
106
  });
138
- await discordApprovalMessageUpdates.enqueue(params.messageId, () => discordRequest(() => deleteChannelMessage(rest, params.channelId, params.messageId), "delete-approval"));
107
+ const payload = buildExecApprovalPayload(params.container);
108
+ await discordApprovalMessageUpdates.enqueue(params.messageId, () => discordRequest(() => editChannelMessage(rest, params.channelId, params.messageId, { body: stripUndefinedFields(serializePayload(payload)) }), "update-approval"));
139
109
  } catch (err) {
140
- logError(`discord approvals: failed to delete message: ${String(err)}`);
141
- await updateMessage(params);
110
+ logError(`discord approvals: failed to update message: ${String(err)}`);
142
111
  }
143
112
  }
144
113
  function buildTerminalApprovalResult(params) {
145
- const resolved = resolveHandlerContext(params);
146
- if (!resolved) return { kind: "delete" };
114
+ if (!resolveHandlerContext(params)) return { kind: "delete" };
147
115
  return {
148
116
  kind: "update",
149
- payload: createApprovalContainer({
150
- view: params.view,
151
- cfg: params.cfg,
152
- accountId: resolved.accountId
153
- })
117
+ payload: createApprovalContainer({ view: params.view })
154
118
  };
155
119
  }
156
120
  const discordApprovalNativeRuntime = createChannelApprovalNativeRuntimeAdapter({
@@ -180,16 +144,13 @@ const discordApprovalNativeRuntime = createChannelApprovalNativeRuntimeAdapter({
180
144
  },
181
145
  presentation: {
182
146
  buildPendingPayload: ({ cfg, accountId, context, view }) => {
183
- const resolved = resolveHandlerContext({
147
+ if (!resolveHandlerContext({
184
148
  cfg,
185
149
  accountId,
186
150
  context
187
- });
188
- if (!resolved) return { body: {} };
151
+ })) return { body: {} };
189
152
  const container = createApprovalContainer({
190
153
  view,
191
- cfg,
192
- accountId: resolved.accountId,
193
154
  actionRow: createApprovalActionRow(view)
194
155
  });
195
156
  return { body: stripUndefinedFields(serializePayload(buildExecApprovalPayload(container))) };
@@ -248,7 +209,7 @@ const discordApprovalNativeRuntime = createChannelApprovalNativeRuntimeAdapter({
248
209
  nonce: createDiscordMessageNonce(),
249
210
  enforce_nonce: true
250
211
  };
251
- const message = await discordRequest(() => createChannelMessage(rest, preparedTarget.discordChannelId, { body }), plannedTarget.surface === "origin" ? "send-approval-channel" : "send-approval", { safety: "nonce-protected-create" });
212
+ const message = await discordRequest(() => rest.post(Routes.channelMessages(preparedTarget.discordChannelId), { body }), plannedTarget.surface === "origin" ? "send-approval-channel" : "send-approval", { safety: "nonce-protected-create" });
252
213
  if (!message?.id) {
253
214
  if (plannedTarget.surface === "origin") logError("discord approvals: failed to send to channel");
254
215
  else if (preparedTarget.recipientUserId) logError(`discord approvals: failed to send message to user ${preparedTarget.recipientUserId}`);
@@ -1,5 +1,5 @@
1
- import { c as parseExecApprovalData } from "./components-Cq1PvIpN.mjs";
2
- import { et as parseCustomId } from "./discord-0xJYfdDD.mjs";
1
+ import { c as parseExecApprovalData } from "./components-CzXLR3QH.mjs";
2
+ import { et as parseCustomId } from "./discord-J7aRzq2Q.mjs";
3
3
  import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
4
4
  //#region extensions/discord/src/approval-message-updates.ts
5
5
  const discordApprovalMessageUpdates = new KeyedAsyncQueue();
@@ -1,8 +1,8 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-B4FMCO8f.mjs";
2
- import { b as fetchChannelPermissionsDiscord } from "./send.shared-DGFkbkQR.mjs";
3
- import { t as inspectDiscordAccount } from "./account-inspect-De8hOUxG.mjs";
4
- import "./send-CrfEI6Bs.mjs";
5
- import { C as collectDiscordAuditChannelIdsForAccount, S as auditDiscordChannelPermissionsWithFetcher } from "./outbound-session-route-zVGxxceg.mjs";
2
+ import { b as fetchChannelPermissionsDiscord } from "./send.shared-BQIUh6Vn.mjs";
3
+ import { t as inspectDiscordAccount } from "./account-inspect-CjKqkDnH.mjs";
4
+ import "./send-2X7m2Zmw.mjs";
5
+ import { C as collectDiscordAuditChannelIdsForAccount, S as auditDiscordChannelPermissionsWithFetcher } from "./outbound-session-route-DGPPKA0z.mjs";
6
6
  //#region extensions/discord/src/audit.ts
7
7
  var audit_exports = /* @__PURE__ */ __exportAll({
8
8
  auditDiscordChannelPermissions: () => auditDiscordChannelPermissions,
@@ -1,20 +1,20 @@
1
- import { C as withDiscordRequestAuthority } from "./discord-0xJYfdDD.mjs";
2
- import { c as resolveDiscordAccount, i as listDiscordStartupAccountIds, l as resolveDiscordAccountAllowFrom, r as listDiscordAccountIds, s as resolveDefaultDiscordAccountId, u as resolveDiscordAccountConfig } from "./accounts-ChaMcixG.mjs";
1
+ import { C as withDiscordRequestAuthority } from "./discord-J7aRzq2Q.mjs";
2
+ import { c as resolveDiscordAccount, i as listDiscordStartupAccountIds, l as resolveDiscordAccountAllowFrom, r as listDiscordAccountIds, s as resolveDefaultDiscordAccountId, u as resolveDiscordAccountConfig } from "./accounts-DXHCL8Zm.mjs";
3
3
  import { t as getDiscordRuntime } from "./runtime-DgnVQ7zW.mjs";
4
- import { _ as matchesDiscordToolContextTarget, b as parseDiscordTarget, g as looksLikeDiscordTargetId, v as normalizeDiscordMessagingTarget } from "./retry-pz_cSha2.mjs";
5
- import { u as withAbortTimeout } from "./timeouts-D86uWLt_.mjs";
6
- import { D as isDiscordExecApprovalClientEnabled, E as isDiscordExecApprovalApprover, O as shouldSuppressLocalDiscordExecApprovalPrompt, T as getDiscordExecApprovalApprovers, _ as resolveDiscordRuntimeBindingConversationId, f as resolveDiscordConversationRoute, t as resolveDiscordOutboundSessionRoute, v as discordMessageActions, w as resolveRequiredDiscordChannelPermissions } from "./outbound-session-route-zVGxxceg.mjs";
7
- import { a as normalizeDiscordAcpConversationId, c as resolveDiscordInboundConversation, i as matchDiscordAcpConversation, n as discordOutbound, o as resolveDiscordAttachedOutboundTarget, r as buildDiscordCrossContextPresentation, s as resolveDiscordCommandConversation } from "./outbound-adapter-BobT-kse.mjs";
4
+ import { _ as matchesDiscordToolContextTarget, b as parseDiscordTarget, g as looksLikeDiscordTargetId, v as normalizeDiscordMessagingTarget } from "./retry-BKzO25k4.mjs";
5
+ import { l as withAbortTimeout } from "./timeouts-pun7VJ02.mjs";
6
+ import { D as isDiscordExecApprovalClientEnabled, E as isDiscordExecApprovalApprover, O as shouldSuppressLocalDiscordExecApprovalPrompt, T as getDiscordExecApprovalApprovers, _ as resolveDiscordRuntimeBindingConversationId, f as resolveDiscordConversationRoute, t as resolveDiscordOutboundSessionRoute, v as discordMessageActions, w as resolveRequiredDiscordChannelPermissions } from "./outbound-session-route-DGPPKA0z.mjs";
7
+ import { a as normalizeDiscordAcpConversationId, c as resolveDiscordInboundConversation, i as matchDiscordAcpConversation, n as discordOutbound, o as resolveDiscordAttachedOutboundTarget, r as buildDiscordCrossContextPresentation, s as resolveDiscordCommandConversation } from "./outbound-adapter-BPq0c2wY.mjs";
8
8
  import { r as openDiscordCommandDeployHashStore } from "./command-deploy-store-DFkBTViB.mjs";
9
- import { t as resolveDiscordConversationBindingRoute } from "./conversation-binding-route-Caz_XuFH.mjs";
10
- import { a as discordSecurityAdapter, i as discordSetupContract, n as discordConfigAdapter, t as createDiscordPluginBase } from "./shared-B3wZ4hN-.mjs";
11
- import { t as normalizeExplicitDiscordSessionKey } from "./session-key-normalization-wJgsKPNF.mjs";
12
- import { i as setThreadBindingMaxAgeBySessionKeyAsync, n as setThreadBindingIdleTimeoutBySessionKeyAsync, r as setThreadBindingMaxAgeBySessionKey, t as setThreadBindingIdleTimeoutBySessionKey } from "./thread-bindings.session-updates-CshfKghV.mjs";
9
+ import { t as resolveDiscordConversationBindingRoute } from "./conversation-binding-route-Bi62ApSt.mjs";
10
+ import { a as discordSecurityAdapter, i as discordSetupContract, n as discordConfigAdapter, t as createDiscordPluginBase } from "./shared-CIJn6AEC.mjs";
11
+ import { t as normalizeExplicitDiscordSessionKey } from "./session-key-normalization-CCHGNSQw.mjs";
12
+ import { i as setThreadBindingMaxAgeBySessionKeyAsync, n as setThreadBindingIdleTimeoutBySessionKeyAsync, r as setThreadBindingMaxAgeBySessionKey, t as setThreadBindingIdleTimeoutBySessionKey } from "./thread-bindings.session-updates-C9aKtVs6.mjs";
13
13
  import { t as defaultTopLevelPlacement } from "./thread-binding-api-BDZJD4na.mjs";
14
+ import { normalizeLowercaseStringOrEmpty, normalizeOptionalString, normalizeOptionalTrimmedStringList } from "openclaw/plugin-sdk/string-coerce-runtime";
14
15
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
15
16
  import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-id";
16
17
  import { PAIRING_APPROVED_MESSAGE, buildTokenChannelStatusSummary, projectCredentialSnapshotFields, resolveConfiguredFromCredentialStatuses } from "openclaw/plugin-sdk/channel-status";
17
- import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
18
18
  import { createRuntimeConfigReader } from "openclaw/plugin-sdk/runtime-config-snapshot";
19
19
  import { sleepWithAbort } from "openclaw/plugin-sdk/runtime-env";
20
20
  import { createChannelMessageAdapterFromOutbound } from "openclaw/plugin-sdk/channel-outbound";
@@ -196,7 +196,7 @@ function createDiscordApprovalCapability() {
196
196
  accountId,
197
197
  request
198
198
  }),
199
- load: async () => (await import("./approval-handler.runtime-DxCK2Rux.mjs")).discordApprovalNativeRuntime
199
+ load: async () => (await import("./approval-handler.runtime-G-tMI_uD.mjs")).discordApprovalNativeRuntime
200
200
  })
201
201
  });
202
202
  }
@@ -207,22 +207,22 @@ function getDiscordApprovalCapability() {
207
207
  }
208
208
  //#endregion
209
209
  //#region extensions/discord/src/channel.loaders.ts
210
- const loadDiscordDirectoryConfigModule = createLazyRuntimeModule(() => import("./directory-config-esqNn0Eo.mjs").then((n) => n.t));
211
- const loadDiscordResolveChannelsModule = createLazyRuntimeModule(() => import("./resolve-channels-BFPNRmVv.mjs").then((n) => n.n));
212
- const loadDiscordResolveUsersModule = createLazyRuntimeModule(() => import("./resolve-users-0-aBuCy3.mjs").then((n) => n.n));
213
- const loadDiscordThreadBindingsManagerModule = createLazyRuntimeModule(() => import("./thread-bindings.manager-DN-NissX.mjs").then((n) => n.r));
214
- const loadDiscordTargetResolverModule = createLazyRuntimeModule(() => import("./target-resolver-BuLapkhy.mjs").then((n) => n.r));
215
- const loadDiscordProviderRuntime = createLazyRuntimeModule(() => import("./provider.runtime-CUE3UxER.mjs"));
216
- const loadDiscordProbeRuntime = createLazyRuntimeModule(() => import("./probe-LYrIHlBF.mjs").then((n) => n.o));
210
+ const loadDiscordDirectoryConfigModule = createLazyRuntimeModule(() => import("./directory-config-BH1LA-gi.mjs").then((n) => n.t));
211
+ const loadDiscordResolveChannelsModule = createLazyRuntimeModule(() => import("./resolve-channels--MUatisx.mjs").then((n) => n.n));
212
+ const loadDiscordResolveUsersModule = createLazyRuntimeModule(() => import("./resolve-users-CxLcDmM0.mjs").then((n) => n.n));
213
+ const loadDiscordThreadBindingsManagerModule = createLazyRuntimeModule(() => import("./thread-bindings.manager-plk0zJAW.mjs").then((n) => n.r));
214
+ const loadDiscordTargetResolverModule = createLazyRuntimeModule(() => import("./target-resolver-Dzxf80Y3.mjs").then((n) => n.r));
215
+ const loadDiscordProviderRuntime = createLazyRuntimeModule(() => import("./provider.runtime-Dkzrmmcm.mjs"));
216
+ const loadDiscordProbeRuntime = createLazyRuntimeModule(() => import("./probe-DIRY8vh7.mjs").then((n) => n.o));
217
217
  async function probeDiscordStatusAccount(params) {
218
218
  const startedAtMs = Date.now();
219
219
  const runtime = await loadDiscordProbeRuntime();
220
220
  const remainingMs = Math.max(1, params.timeoutMs - Math.max(0, Date.now() - startedAtMs));
221
221
  return await runtime.probeDiscord(params.token, remainingMs, { includeApplication: true });
222
222
  }
223
- const loadDiscordAuditModule = createLazyRuntimeModule(() => import("./audit-CLg9I71N.mjs").then((n) => n.n));
224
- const loadDiscordSendModule = createLazyRuntimeModule(() => import("./send-CrfEI6Bs.mjs").then((n) => n.t));
225
- const loadDiscordDirectoryLiveModule = createLazyRuntimeModule(() => import("./directory-live-DtKRHuGV.mjs").then((n) => n.t));
223
+ const loadDiscordAuditModule = createLazyRuntimeModule(() => import("./audit-DtvzxONM.mjs").then((n) => n.n));
224
+ const loadDiscordSendModule = createLazyRuntimeModule(() => import("./send-2X7m2Zmw.mjs").then((n) => n.t));
225
+ const loadDiscordDirectoryLiveModule = createLazyRuntimeModule(() => import("./directory-live-C9xz7IPm.mjs").then((n) => n.t));
226
226
  //#endregion
227
227
  //#region extensions/discord/src/conversation-route-owner.ts
228
228
  function inspectDiscordConversationRouteOwner(params) {
@@ -359,20 +359,15 @@ function readDiscordPermissionsAuditSummary(value) {
359
359
  if (!isRecord$1(entry)) return null;
360
360
  const channelId = normalizeOptionalString(entry.channelId);
361
361
  if (!channelId) return null;
362
- const ok = typeof entry.ok === "boolean" ? entry.ok : void 0;
363
- const missing = Array.isArray(entry.missing) ? entry.missing.map((v) => normalizeOptionalString(v)).filter(Boolean) : void 0;
364
- const error = normalizeOptionalString(entry.error) ?? null;
365
- const matchKey = normalizeOptionalString(entry.matchKey);
366
- const matchSource = normalizeOptionalString(entry.matchSource);
367
362
  return {
368
363
  channelId,
369
- ok,
370
- missing: missing?.length ? missing : void 0,
371
- error,
372
- matchKey,
373
- matchSource
364
+ ok: typeof entry.ok === "boolean" ? entry.ok : void 0,
365
+ missing: normalizeOptionalTrimmedStringList(entry.missing),
366
+ error: normalizeOptionalString(entry.error) ?? null,
367
+ matchKey: normalizeOptionalString(entry.matchKey),
368
+ matchSource: normalizeOptionalString(entry.matchSource)
374
369
  };
375
- }).filter(Boolean) : void 0
370
+ }).filter((entry) => entry !== null) : void 0
376
371
  };
377
372
  }
378
373
  function collectDiscordStatusIssues(accounts) {
@@ -857,51 +852,55 @@ const discordPlugin = createChatChannelPlugin({
857
852
  };
858
853
  }
859
854
  }),
860
- gateway: { startAccount: async (ctx) => {
861
- const readConfig = createRuntimeConfigReader(ctx.cfg);
862
- const account = ctx.account;
863
- if (account.tokenStatus === "configured_unavailable") throw new Error(`Discord bot token configured for account "${account.accountId}" is unavailable; resolve SecretRefs against the active runtime snapshot before using this account.`);
864
- const startupDelayMs = resolveDiscordStartupDelayMs(ctx.cfg, account.accountId);
865
- if (startupDelayMs > 0) {
866
- ctx.log?.info(`[${account.accountId}] delaying provider startup ${Math.round(startupDelayMs / 1e3)}s to reduce Discord startup rate limits`);
855
+ gateway: {
856
+ apiVersion: 2,
857
+ startAccount: async (ctx) => {
858
+ const readConfig = createRuntimeConfigReader(ctx.cfg);
859
+ const account = ctx.account;
860
+ if (account.tokenStatus === "configured_unavailable") throw new Error(`Discord bot token configured for account "${account.accountId}" is unavailable; resolve SecretRefs against the active runtime snapshot before using this account.`);
861
+ const startupDelayMs = resolveDiscordStartupDelayMs(ctx.cfg, account.accountId);
862
+ if (startupDelayMs > 0) {
863
+ ctx.log?.info(`[${account.accountId}] delaying provider startup ${Math.round(startupDelayMs / 1e3)}s to reduce Discord startup rate limits`);
864
+ try {
865
+ await sleepWithAbort(startupDelayMs, ctx.abortSignal);
866
+ } catch {
867
+ return;
868
+ }
869
+ }
870
+ const token = account.token.trim();
871
+ startDiscordStartupProbe({
872
+ accountId: account.accountId,
873
+ token,
874
+ abortSignal: ctx.abortSignal,
875
+ setStatus: ctx.setStatus,
876
+ log: ctx.log
877
+ });
878
+ ctx.log?.info(`[${account.accountId}] starting provider`);
879
+ let commandDeployHashStore;
867
880
  try {
868
- await sleepWithAbort(startupDelayMs, ctx.abortSignal);
869
- } catch {
870
- return;
881
+ commandDeployHashStore = openDiscordCommandDeployHashStore(getDiscordRuntime().state.openKeyedStore);
882
+ } catch (error) {
883
+ ctx.log?.warn?.(`[${account.accountId}] Discord command deploy cache unavailable; continuing without persistence: ${formatErrorMessage(error)}`);
871
884
  }
872
- }
873
- const token = account.token.trim();
874
- startDiscordStartupProbe({
875
- accountId: account.accountId,
876
- token,
877
- abortSignal: ctx.abortSignal,
878
- setStatus: ctx.setStatus,
879
- log: ctx.log
880
- });
881
- ctx.log?.info(`[${account.accountId}] starting provider`);
882
- let commandDeployHashStore;
883
- try {
884
- commandDeployHashStore = openDiscordCommandDeployHashStore(getDiscordRuntime().state.openKeyedStore);
885
- } catch (error) {
886
- ctx.log?.warn?.(`[${account.accountId}] Discord command deploy cache unavailable; continuing without persistence: ${formatErrorMessage(error)}`);
887
- }
888
- return (await loadDiscordProviderRuntime()).monitorDiscordProvider({
889
- token,
890
- accountId: account.accountId,
891
- config: ctx.cfg,
892
- readConfig,
893
- runtime: ctx.runtime,
894
- channelRuntime: ctx.channelRuntime,
895
- abortSignal: ctx.abortSignal,
896
- mediaMaxMb: account.config.mediaMaxMb,
897
- historyLimit: account.config.historyLimit,
898
- setStatus: (patch) => ctx.setStatus({
885
+ return (await loadDiscordProviderRuntime()).monitorDiscordProvider({
886
+ scheduler: ctx.scheduler,
887
+ token,
899
888
  accountId: account.accountId,
900
- ...patch
901
- }),
902
- commandDeployHashStore
903
- });
904
- } }
889
+ config: ctx.cfg,
890
+ readConfig,
891
+ runtime: ctx.runtime,
892
+ channelRuntime: ctx.channelRuntime,
893
+ abortSignal: ctx.abortSignal,
894
+ mediaMaxMb: account.config.mediaMaxMb,
895
+ historyLimit: account.config.historyLimit,
896
+ setStatus: (patch) => ctx.setStatus({
897
+ accountId: account.accountId,
898
+ ...patch
899
+ }),
900
+ commandDeployHashStore
901
+ });
902
+ }
903
+ }
905
904
  },
906
905
  pairing: { text: {
907
906
  idLabel: "discordUserId",
@@ -917,6 +916,11 @@ const discordPlugin = createChatChannelPlugin({
917
916
  security: discordSecurityAdapter,
918
917
  threading: {
919
918
  matchesToolContextTarget: matchesDiscordToolContextTarget,
919
+ resolveAutoThreadId: ({ to, toolContext }) => {
920
+ const threadId = normalizeOptionalString(toolContext?.currentThreadTs);
921
+ if (!threadId) return;
922
+ return normalizeDiscordMessagingTarget(to) === `channel:${threadId}` ? threadId : void 0;
923
+ },
920
924
  scopedAccountReplyToMode: {
921
925
  resolveAccount: (cfg, accountId) => resolveDiscordAccount({
922
926
  cfg,
@@ -16,18 +16,8 @@ function resolveDiscordChannelNumberPropertySafe(channel, key) {
16
16
  const value = readDiscordChannelPropertySafe(channel, key);
17
17
  return typeof value === "number" ? value : void 0;
18
18
  }
19
- const DISCORD_CHANNEL_SNAKE_CASE_ALIASES = {
20
- ownerId: "owner_id",
21
- parentId: "parent_id"
22
- };
23
- function resolveDiscordChannelStringWithAliasSafe(channel, camelKey) {
24
- const camelValue = resolveDiscordChannelStringPropertySafe(channel, camelKey);
25
- if (camelValue !== void 0) return camelValue;
26
- const snakeKey = DISCORD_CHANNEL_SNAKE_CASE_ALIASES[camelKey];
27
- if (!snakeKey) return;
28
- const directSnakeValue = resolveDiscordChannelStringPropertySafe(channel, snakeKey);
29
- if (directSnakeValue !== void 0) return directSnakeValue;
30
- return resolveDiscordChannelStringPropertySafe(readDiscordChannelPropertySafe(channel, "rawData"), snakeKey);
19
+ function resolveDiscordChannelStringWithAliasSafe(channel, camelKey, snakeKey) {
20
+ return resolveDiscordChannelStringPropertySafe(channel, camelKey) ?? resolveDiscordChannelStringPropertySafe(channel, snakeKey) ?? resolveDiscordChannelStringPropertySafe(readDiscordChannelPropertySafe(channel, "rawData"), snakeKey);
31
21
  }
32
22
  function resolveDiscordChannelNameSafe(channel) {
33
23
  return resolveDiscordChannelStringPropertySafe(channel, "name");
@@ -39,10 +29,7 @@ function resolveDiscordChannelTopicSafe(channel) {
39
29
  return resolveDiscordChannelStringPropertySafe(channel, "topic");
40
30
  }
41
31
  function resolveDiscordChannelParentIdSafe(channel) {
42
- return resolveDiscordChannelStringWithAliasSafe(channel, "parentId");
43
- }
44
- function resolveDiscordChannelOwnerIdSafe(channel) {
45
- return resolveDiscordChannelStringWithAliasSafe(channel, "ownerId");
32
+ return resolveDiscordChannelStringWithAliasSafe(channel, "parentId", "parent_id");
46
33
  }
47
34
  function resolveDiscordChannelParentSafe(channel) {
48
35
  return readDiscordChannelPropertySafe(channel, "parent");
@@ -54,7 +41,7 @@ function resolveDiscordChannelInfoSafe(channel) {
54
41
  topic: resolveDiscordChannelTopicSafe(channel),
55
42
  type: resolveDiscordChannelNumberPropertySafe(channel, "type"),
56
43
  parentId: resolveDiscordChannelParentIdSafe(channel),
57
- ownerId: resolveDiscordChannelOwnerIdSafe(channel),
44
+ ownerId: resolveDiscordChannelStringWithAliasSafe(channel, "ownerId", "owner_id"),
58
45
  parentName: resolveDiscordChannelNameSafe(parent)
59
46
  };
60
47
  }