@openclaw/discord 2026.9.8 → 2026.10.1-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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-BilYSrRF.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-access-C12aDZ0p.mjs → channel-access-BRp3Y-rF.mjs} +4 -17
  11. package/dist/.setup/{channel-type-DRCrEMss.mjs → channel-type-D1_b5UhU.mjs} +12 -16
  12. package/dist/.setup/{channel-DxlUVU9t.mjs → channel-z5lQMS_9.mjs} +79 -75
  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-BNToPZrx.mjs} +7 -6
  26. package/dist/.setup/{message-handler.preflight-v-__NSDq.mjs → message-handler.preflight-D0BcCyI7.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-CThRmCWK.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-D2OKMo0f.mjs} +273 -446
  34. package/dist/.setup/{provider-session.runtime-BYlTBFD2.mjs → provider-session.runtime-BupCTZQv.mjs} +3 -3
  35. package/dist/.setup/provider.runtime-BaW_JnfU.mjs +2 -0
  36. package/dist/.setup/{realtime-session.runtime-oUd9DOcz.mjs → realtime-session.runtime-D5RSC8Mm.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-Bc75quiH.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
@@ -1,21 +1,21 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-B4FMCO8f.mjs";
2
- import { Nt as getGuildVoiceState, l as ReadyListener, p as VoiceStateUpdateListener, t as discord_exports, u as ResumedListener, y as isUnknownDiscordVoiceStateError } from "./discord-0xJYfdDD.mjs";
3
- import { S as formatDiscordUserTag, g as resolveDiscordOwnerAccess, o as normalizeDiscordSlug } from "./channel-type-DRCrEMss.mjs";
2
+ import { l as ReadyListener, p as VoiceStateUpdateListener, t as discord_exports, u as ResumedListener, vt as getGuildVoiceState, y as isUnknownDiscordVoiceStateError } from "./discord-J7aRzq2Q.mjs";
3
+ import { C as formatDiscordUserTag, _ as resolveDiscordOwnerAccess, s as normalizeDiscordSlug } from "./channel-type-D1_b5UhU.mjs";
4
4
  import { t as getDiscordRuntime } from "./runtime-DgnVQ7zW.mjs";
5
- import { b as parseDiscordTarget } from "./retry-pz_cSha2.mjs";
6
- import { o as formatMention } from "./send.outbound-BISKnb-a.mjs";
7
- import { a as resolveDiscordVoiceEnabled, c as resolveDiscordVoiceAccessTarget, o as authorizeDiscordVoiceIngress, r as resolveDiscordTranscriptsCapture, s as resolveDiscordVoiceAccess, t as bindDiscordCaptureReceipts } from "./transcripts-source-p8EV179h.mjs";
8
- import { a as noteVoiceDecryptFailure, n as analyzeVoiceReceiveError, p as writeVoiceWavFile, r as createVoiceReceiveRecoveryState, s as resetVoiceReceiveRecoveryState, t as DECRYPT_FAILURE_WINDOW_MS, v as restoreDiscordAudioError } from "./receive-recovery-CHPOsnLc.mjs";
9
- import { C as buildDiscordGroupSystemPrompt, _ as resolveDiscordVoiceMode, d as MIN_SEGMENT_SECONDS, f as VOICE_CONNECT_READY_TIMEOUT_MS, g as logVoiceVerbose, h as isVoiceChannel, m as isDiscordRealtimeVoiceMode, p as VOICE_RECONNECT_GRACE_MS, u as CAPTURE_FINALIZE_GRACE_MS, v as resolveVoiceTimeoutMs } from "./provider-B_G5hASF.mjs";
5
+ import { b as parseDiscordTarget } from "./retry-BKzO25k4.mjs";
6
+ import { o as formatMention } from "./send.outbound-B4QHSEzm.mjs";
7
+ import { a as resolveDiscordVoiceEnabled, c as resolveDiscordVoiceAccessTarget, o as authorizeDiscordVoiceIngress, r as resolveDiscordTranscriptsCapture, s as resolveDiscordVoiceAccess, t as bindDiscordCaptureReceipts } from "./transcripts-source-CNWswry-.mjs";
8
+ import { a as noteVoiceDecryptFailure, n as analyzeVoiceReceiveError, p as writeVoiceWavFile, r as createVoiceReceiveRecoveryState, s as resetVoiceReceiveRecoveryState, t as DECRYPT_FAILURE_WINDOW_MS, v as restoreDiscordAudioError } from "./receive-recovery-GqF2PUN_.mjs";
9
+ import { C as buildDiscordGroupSystemPrompt, _ as resolveDiscordVoiceMode, d as MIN_SEGMENT_SECONDS, f as VOICE_CONNECT_READY_TIMEOUT_MS, g as logVoiceVerbose, h as isVoiceChannel, m as isDiscordRealtimeVoiceMode, p as VOICE_RECONNECT_GRACE_MS, u as CAPTURE_FINALIZE_GRACE_MS, v as resolveVoiceTimeoutMs } from "./provider-D2OKMo0f.mjs";
10
+ import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
10
11
  import { randomUUID } from "node:crypto";
11
- import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
12
12
  import { asDateTimestampMs, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
13
13
  import { formatErrorMessage } from "openclaw/plugin-sdk/ssrf-runtime";
14
14
  import { formatErrorMessage as formatErrorMessage$1, readErrorName, toErrorObject } from "openclaw/plugin-sdk/error-runtime";
15
15
  import { resolveAgentRoute } from "openclaw/plugin-sdk/routing";
16
- import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
17
16
  import { createSubsystemLogger, logVerbose } from "openclaw/plugin-sdk/runtime-env";
18
17
  import { escapeRegExp, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
18
+ import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
19
19
  import { stripInlineDirectiveTagsForDisplay } from "openclaw/plugin-sdk/text-chunking";
20
20
  import { unlinkIfExists } from "openclaw/plugin-sdk/media-runtime";
21
21
  import { Worker } from "node:worker_threads";
@@ -790,8 +790,14 @@ var DiscordVoiceSpeakerContextResolver = class {
790
790
  this.cache = /* @__PURE__ */ new Map();
791
791
  }
792
792
  async resolveContext(guildId, userId) {
793
- const cached = this.getCachedContext(guildId, userId);
794
- if (cached) return cached;
793
+ const key = `${guildId}:${userId}`;
794
+ const cached = this.cache.get(key);
795
+ if (cached) {
796
+ const now = asDateTimestampMs(Date.now());
797
+ const expiresAt = asDateTimestampMs(cached.expiresAt);
798
+ if (now !== void 0 && expiresAt !== void 0 && expiresAt > now) return { ...cached.context };
799
+ this.cache.delete(key);
800
+ }
795
801
  const identity = await this.resolveIdentity(guildId, userId);
796
802
  const context = {
797
803
  id: identity.id,
@@ -804,7 +810,11 @@ var DiscordVoiceSpeakerContextResolver = class {
804
810
  allowNameMatching: false
805
811
  }).ownerAllowed
806
812
  };
807
- this.setCachedContext(guildId, userId, context);
813
+ const expiresAt = resolveExpiresAtMsFromDurationMs(SPEAKER_CONTEXT_CACHE_TTL_MS);
814
+ if (expiresAt !== void 0) this.cache.set(key, {
815
+ context: { ...context },
816
+ expiresAt
817
+ });
808
818
  return context;
809
819
  }
810
820
  async resolveIdentity(guildId, userId) {
@@ -838,29 +848,6 @@ var DiscordVoiceSpeakerContextResolver = class {
838
848
  }
839
849
  }
840
850
  }
841
- resolveCacheKey(guildId, userId) {
842
- return `${guildId}:${userId}`;
843
- }
844
- getCachedContext(guildId, userId) {
845
- const key = this.resolveCacheKey(guildId, userId);
846
- const cached = this.cache.get(key);
847
- if (!cached) return;
848
- const now = asDateTimestampMs(Date.now());
849
- const expiresAt = asDateTimestampMs(cached.expiresAt);
850
- if (now === void 0 || expiresAt === void 0 || expiresAt <= now) {
851
- this.cache.delete(key);
852
- return;
853
- }
854
- return { ...cached.context };
855
- }
856
- setCachedContext(guildId, userId, context) {
857
- const key = this.resolveCacheKey(guildId, userId);
858
- const expiresAt = resolveExpiresAtMsFromDurationMs(SPEAKER_CONTEXT_CACHE_TTL_MS);
859
- if (expiresAt !== void 0) this.cache.set(key, {
860
- context: { ...context },
861
- expiresAt
862
- });
863
- }
864
851
  };
865
852
  //#endregion
866
853
  //#region extensions/discord/src/voice/voice-following.ts
@@ -884,9 +871,7 @@ function normalizeVoiceChannelResidencies(entries) {
884
871
  function normalizeDiscordUserIds(entries) {
885
872
  const ids = /* @__PURE__ */ new Set();
886
873
  for (const entry of entries ?? []) {
887
- const trimmed = entry.trim();
888
- const withoutDiscordPrefix = trimmed.startsWith("discord:") ? trimmed.slice(8) : trimmed;
889
- const id = (withoutDiscordPrefix.startsWith("user:") ? withoutDiscordPrefix.slice(5) : withoutDiscordPrefix).trim();
874
+ const id = entry.trim().replace(/^discord:/, "").replace(/^user:/, "").trim();
890
875
  if (id) ids.add(id);
891
876
  }
892
877
  return ids;
@@ -903,19 +888,28 @@ var DiscordVoiceFollowing = class {
903
888
  this.params = params;
904
889
  this.followedUserChannels = /* @__PURE__ */ new Map();
905
890
  this.followedVoiceGuilds = /* @__PURE__ */ new Set();
906
- this.followUsersReconcileTimer = null;
907
891
  this.followUsersReconcileTask = null;
908
892
  this.followUsersReconcileGuildCursor = 0;
909
893
  this.followUsersReconcileBotGuildCursor = 0;
910
894
  this.followUsersReconcileUserCursors = /* @__PURE__ */ new Map();
911
895
  this.followEventGenerations = /* @__PURE__ */ new Map();
896
+ this.scheduler = params.scheduler.scope();
912
897
  this.followUserIds = params.discordConfig.voice?.followUsersEnabled !== false ? normalizeDiscordUserIds(params.discordConfig.voice?.followUsers) : /* @__PURE__ */ new Set();
913
898
  }
914
899
  isFollowedUser(userId) {
915
900
  return this.followUserIds.has(userId);
916
901
  }
917
902
  async startReconciliation() {
918
- this.ensureFollowUsersReconcileTimer();
903
+ if (this.followUserIds.size === 0 || this.scheduler.signal.aborted) return;
904
+ this.scheduler.schedule({
905
+ id: "follow-users",
906
+ mode: "earliest",
907
+ delayMs: FOLLOW_USERS_RECONCILE_INTERVAL_MS,
908
+ everyMs: FOLLOW_USERS_RECONCILE_INTERVAL_MS,
909
+ run: () => this.reconcileFollowedUsers("interval").catch((err) => {
910
+ logger$7.warn(`discord voice: follow user reconciliation failed: ${formatErrorMessage(err)}`);
911
+ })
912
+ });
919
913
  await this.reconcileFollowedUsers("startup");
920
914
  }
921
915
  async handleBotVoiceStateUpdate(params) {
@@ -945,7 +939,7 @@ var DiscordVoiceFollowing = class {
945
939
  }
946
940
  }
947
941
  async handleFollowedUserVoiceStateUpdate(params) {
948
- if (!this.params.voiceEnabled || this.params.destroyed()) return;
942
+ if (!this.params.voiceEnabled || this.scheduler.signal.aborted) return;
949
943
  const { guildId, channelId, userId } = params;
950
944
  const followKey = `${guildId}:${userId}`;
951
945
  const eventGeneration = (this.followEventGenerations.get(followKey) ?? 0) + 1;
@@ -954,29 +948,19 @@ var DiscordVoiceFollowing = class {
954
948
  const previousFollowedChannelId = this.followedUserChannels.get(followKey)?.channelId;
955
949
  const existing = this.params.getSession(guildId);
956
950
  const wasFollowedVoiceSession = this.followedUserChannels.has(followKey) || this.followedVoiceGuilds.has(guildId);
957
- if (!channelId) {
958
- this.followedUserChannels.delete(followKey);
959
- if (existing && wasFollowedVoiceSession && !this.hasFollowedUserInChannel(existing)) await this.handoffToAnotherFollowedUserOrLeave({
960
- guildId,
961
- userId,
962
- existing,
963
- reason: "disconnected"
964
- });
965
- else if (!existing && wasFollowedVoiceSession && this.params.hasVoiceLifecycle(guildId)) await this.params.leave({ guildId });
966
- return;
967
- }
968
- if (!this.params.isAllowedVoiceChannel({
951
+ if (!channelId || !this.params.isAllowedVoiceChannel({
969
952
  guildId,
970
953
  channelId
971
954
  })) {
972
955
  this.followedUserChannels.delete(followKey);
973
- logger$7.warn(`discord voice: followed user joined non-allowed channel guild=${guildId} user=${userId} channel=${channelId}; ignoring`);
956
+ if (channelId) logger$7.warn(`discord voice: followed user joined non-allowed channel guild=${guildId} user=${userId} channel=${channelId}; ignoring`);
974
957
  if (existing && wasFollowedVoiceSession && !this.hasFollowedUserInChannel(existing)) await this.handoffToAnotherFollowedUserOrLeave({
975
958
  guildId,
976
959
  userId,
977
960
  existing,
978
- reason: "joined non-allowed channel"
961
+ reason: channelId ? "joined non-allowed channel" : "disconnected"
979
962
  });
963
+ else if (!channelId && !existing && wasFollowedVoiceSession && this.params.hasVoiceLifecycle(guildId)) await this.params.leave({ guildId });
980
964
  return;
981
965
  }
982
966
  this.followedUserChannels.set(followKey, {
@@ -1009,11 +993,9 @@ var DiscordVoiceFollowing = class {
1009
993
  }
1010
994
  this.followedVoiceGuilds.add(guildId);
1011
995
  }
1012
- destroy() {
1013
- if (this.followUsersReconcileTimer) {
1014
- clearInterval(this.followUsersReconcileTimer);
1015
- this.followUsersReconcileTimer = null;
1016
- }
996
+ async destroy() {
997
+ await this.scheduler.stop();
998
+ await this.followUsersReconcileTask;
1017
999
  this.followedUserChannels.clear();
1018
1000
  this.followedVoiceGuilds.clear();
1019
1001
  this.followEventGenerations.clear();
@@ -1035,18 +1017,8 @@ var DiscordVoiceFollowing = class {
1035
1017
  for (const entry of this.params.listSessions()) guildIds.add(entry.guildId);
1036
1018
  return Array.from(guildIds);
1037
1019
  }
1038
- ensureFollowUsersReconcileTimer() {
1039
- if (this.followUserIds.size === 0 || this.params.destroyed()) return;
1040
- if (this.followUsersReconcileTimer) return;
1041
- this.followUsersReconcileTimer = setInterval(() => {
1042
- this.reconcileFollowedUsers("interval").catch((err) => {
1043
- logger$7.warn(`discord voice: follow user reconciliation failed: ${formatErrorMessage(err)}`);
1044
- });
1045
- }, FOLLOW_USERS_RECONCILE_INTERVAL_MS);
1046
- this.followUsersReconcileTimer.unref?.();
1047
- }
1048
1020
  async reconcileFollowedUsers(reason) {
1049
- if (this.followUserIds.size === 0 || this.params.destroyed()) return;
1021
+ if (this.followUserIds.size === 0 || this.scheduler.signal.aborted) return;
1050
1022
  if (this.followUsersReconcileTask) return this.followUsersReconcileTask;
1051
1023
  this.followUsersReconcileTask = this.runFollowedUsersReconcile(reason).finally(() => {
1052
1024
  this.followUsersReconcileTask = null;
@@ -1054,7 +1026,7 @@ var DiscordVoiceFollowing = class {
1054
1026
  return this.followUsersReconcileTask;
1055
1027
  }
1056
1028
  async runFollowedUsersReconcile(reason) {
1057
- if (this.params.destroyed()) return;
1029
+ if (this.scheduler.signal.aborted) return;
1058
1030
  const guildIds = this.resolveFollowGuildIds();
1059
1031
  if (guildIds.length === 0) {
1060
1032
  logVoiceVerbose(`follow user reconcile skipped reason=${reason}: no Discord guild ids are configured`);
@@ -1071,7 +1043,7 @@ var DiscordVoiceFollowing = class {
1071
1043
  }
1072
1044
  logFollowUserReconcileVerbose(reason, `follow user reconcile reason=${reason}: no voice state guild ${plan.guildId} user ${userId}: ${formatErrorMessage(err)}`);
1073
1045
  });
1074
- if (this.params.destroyed()) return;
1046
+ if (this.scheduler.signal.aborted) return;
1075
1047
  if (voiceState === "transient-error") continue;
1076
1048
  const channelId = voiceState?.channel_id?.trim();
1077
1049
  await this.handleFollowedUserVoiceStateUpdate({
@@ -1081,7 +1053,7 @@ var DiscordVoiceFollowing = class {
1081
1053
  });
1082
1054
  }
1083
1055
  if (plan.checkBotVoiceState) {
1084
- if (this.params.destroyed()) return;
1056
+ if (this.scheduler.signal.aborted) return;
1085
1057
  await this.disconnectStaleFollowedBotVoiceState({
1086
1058
  guildId: plan.guildId,
1087
1059
  reason
@@ -1099,7 +1071,8 @@ var DiscordVoiceFollowing = class {
1099
1071
  for (let offset = 0; offset < guildLimit && remainingLookups > 0; offset += 1) {
1100
1072
  if (this.params.botUserId() && remainingLookups === 1) break;
1101
1073
  const guildId = expectDefined(guildIds[(start + offset) % guildIds.length], "voice reconciliation guild index");
1102
- const userLimit = this.resolveFollowUserReconcileUserLookupLimit(followedUserIds.length, remainingLookups);
1074
+ let userLimit = Math.min(followedUserIds.length, remainingLookups);
1075
+ if (this.params.botUserId() && followedUserIds.length > userLimit && remainingLookups > 1) userLimit = remainingLookups - 1;
1103
1076
  if (userLimit <= 0) break;
1104
1077
  const selection = this.selectFollowUserReconcileUserIds(guildId, followedUserIds, userLimit);
1105
1078
  plans.push({
@@ -1130,11 +1103,6 @@ var DiscordVoiceFollowing = class {
1130
1103
  }
1131
1104
  this.followUsersReconcileBotGuildCursor = (start + scanned) % guildIds.length;
1132
1105
  }
1133
- resolveFollowUserReconcileUserLookupLimit(followedUserCount, remainingLookups) {
1134
- const userLimit = Math.min(followedUserCount, remainingLookups);
1135
- if (this.params.botUserId() && followedUserCount > userLimit && remainingLookups > 1) return remainingLookups - 1;
1136
- return userLimit;
1137
- }
1138
1106
  selectFollowUserReconcileUserIds(guildId, followedUserIds, limit) {
1139
1107
  if (followedUserIds.length <= limit) {
1140
1108
  this.followUsersReconcileUserCursors.set(guildId, 0);
@@ -1178,7 +1146,7 @@ var DiscordVoiceFollowing = class {
1178
1146
  await this.params.leave({ guildId: params.guildId });
1179
1147
  }
1180
1148
  async disconnectStaleFollowedBotVoiceState(params) {
1181
- if (this.params.destroyed()) return;
1149
+ if (this.scheduler.signal.aborted) return;
1182
1150
  const { guildId, reason } = params;
1183
1151
  if (Array.from(this.followedUserChannels.values()).some((entry) => entry.guildId === guildId)) return;
1184
1152
  const existing = this.params.getSession(guildId);
@@ -1198,7 +1166,7 @@ var DiscordVoiceFollowing = class {
1198
1166
  }
1199
1167
  logFollowUserReconcileVerbose(reason, `follow user reconcile reason=${reason}: no bot voice state guild ${guildId}: ${formatErrorMessage(err)}`);
1200
1168
  });
1201
- if (this.params.destroyed() || botVoiceState === "transient-error") return;
1169
+ if (this.scheduler.signal.aborted || botVoiceState === "transient-error") return;
1202
1170
  const botChannelId = botVoiceState?.channel_id?.trim();
1203
1171
  if (!botChannelId) return;
1204
1172
  const gateway = this.params.client.getPlugin("voice")?.getGateway(guildId);
@@ -1225,9 +1193,6 @@ var DiscordVoiceFollowing = class {
1225
1193
  };
1226
1194
  //#endregion
1227
1195
  //#region extensions/discord/src/voice/capture-state.ts
1228
- function createVoiceCaptureState() {
1229
- return /* @__PURE__ */ new Map();
1230
- }
1231
1196
  function stopVoiceCaptureState(state) {
1232
1197
  const captures = [...state.values()];
1233
1198
  state.clear();
@@ -1268,13 +1233,12 @@ function finishVoiceCapture(state, userId, capture) {
1268
1233
  return true;
1269
1234
  }
1270
1235
  function scheduleVoiceCaptureFinalize(params) {
1271
- const { state, userId, delayMs, onFinalize } = params;
1236
+ const { state, userId, delayMs } = params;
1272
1237
  const capture = state.get(userId);
1273
1238
  if (!capture) return false;
1274
1239
  clearVoiceCaptureFinalizeTimer(capture);
1275
1240
  capture.finalizeTimer = setTimeout(() => {
1276
1241
  if (!finishVoiceCapture(state, userId, capture)) return;
1277
- onFinalize?.(capture);
1278
1242
  capture.stream?.destroy();
1279
1243
  }, delayMs);
1280
1244
  return true;
@@ -1282,9 +1246,6 @@ function scheduleVoiceCaptureFinalize(params) {
1282
1246
  //#endregion
1283
1247
  //#region extensions/discord/src/voice/sanitize.ts
1284
1248
  const SPEECH_EMOJI_RE = /(?:\p{Extended_Pictographic}(?:\uFE0F|\u200D|\p{Extended_Pictographic}|\p{Emoji_Modifier})*)+/gu;
1285
- function stripEmojiForSpeech(text) {
1286
- return text.replace(SPEECH_EMOJI_RE, " ").replace(/\s+([?!.,:;])/g, "$1").replace(/[ \t]{2,}/g, " ").replace(/ *\n */g, "\n").trim();
1287
- }
1288
1249
  function sanitizeVoiceReplyTextForSpeech(text, speakerLabel) {
1289
1250
  let cleaned = stripInlineDirectiveTagsForDisplay(text).text.trim();
1290
1251
  if (!cleaned) return "";
@@ -1293,7 +1254,7 @@ function sanitizeVoiceReplyTextForSpeech(text, speakerLabel) {
1293
1254
  const prefix = new RegExp(`^${escapeRegExp(label)}\\s*:\\s*`, "i");
1294
1255
  cleaned = cleaned.replace(prefix, "").trim();
1295
1256
  }
1296
- return stripEmojiForSpeech(cleaned);
1257
+ return cleaned.replace(SPEECH_EMOJI_RE, " ").replace(/\s+([?!.,:;])/g, "$1").replace(/[ \t]{2,}/g, " ").replace(/ *\n */g, "\n").trim();
1297
1258
  }
1298
1259
  //#endregion
1299
1260
  //#region extensions/discord/src/voice/tts.ts
@@ -1650,7 +1611,7 @@ var DiscordVoiceReceive = class {
1650
1611
  this.params = params;
1651
1612
  this.daveRecoveryAttempts = /* @__PURE__ */ new Map();
1652
1613
  }
1653
- scheduleCaptureFinalize(entry, userId, _reason) {
1614
+ scheduleCaptureFinalize(entry, userId) {
1654
1615
  if (entry.capture.get(userId)?.stream) return;
1655
1616
  scheduleVoiceCaptureFinalize({
1656
1617
  state: entry.capture,
@@ -2138,9 +2099,6 @@ var DiscordAudioTransport = class extends EventEmitter {
2138
2099
  expirySeconds
2139
2100
  });
2140
2101
  }
2141
- stopPlayback() {
2142
- this.send({ type: "player-stop" });
2143
- }
2144
2102
  async play(input) {
2145
2103
  if (this.stopping || this.terminal) throw new Error("Discord voice session stopped before playback.");
2146
2104
  const id = this.allocateId();
@@ -2193,7 +2151,7 @@ var DiscordAudioTransport = class extends EventEmitter {
2193
2151
  try {
2194
2152
  await Promise.all([pump, complete]);
2195
2153
  } catch (error) {
2196
- this.stopPlayback();
2154
+ this.send({ type: "player-stop" });
2197
2155
  throw error;
2198
2156
  } finally {
2199
2157
  abort.abort();
@@ -2765,7 +2723,7 @@ var DiscordVoiceSessions = class {
2765
2723
  conversations: new DiscordVoiceConversationQueue(),
2766
2724
  audioInputBudget,
2767
2725
  ttsStreamFallbackWarned: false,
2768
- capture: createVoiceCaptureState(),
2726
+ capture: /* @__PURE__ */ new Map(),
2769
2727
  get transcripts() {
2770
2728
  return getTranscripts(entry);
2771
2729
  },
@@ -2782,7 +2740,7 @@ var DiscordVoiceSessions = class {
2782
2740
  if (speaking) this.params.receive.handleSpeakingStart(entry, userId).catch((error) => {
2783
2741
  logger$2.warn("discord voice: capture failed: " + formatErrorMessage(error));
2784
2742
  });
2785
- else this.params.receive.scheduleCaptureFinalize(entry, userId, "speaker end");
2743
+ else this.params.receive.scheduleCaptureFinalize(entry, userId);
2786
2744
  };
2787
2745
  const destroyedHandler = () => {
2788
2746
  stopEntry("audio worker stopped");
@@ -2855,7 +2813,7 @@ var DiscordVoiceSessions = class {
2855
2813
  ok: false,
2856
2814
  message: "Discord realtime voice session stopped before startup completed."
2857
2815
  };
2858
- const { DiscordRealtimeVoiceSession } = await import("./realtime-session.runtime-oUd9DOcz.mjs");
2816
+ const { DiscordRealtimeVoiceSession } = await import("./realtime-session.runtime-D5RSC8Mm.mjs");
2859
2817
  const realtime = new DiscordRealtimeVoiceSession({
2860
2818
  accountId: this.params.accountId,
2861
2819
  bootstrapContextInstructions,
@@ -2982,9 +2940,6 @@ const DISCORD_VOICE_FATAL_AUTOJOIN_ERROR_PATTERNS = [
2982
2940
  "permission denied",
2983
2941
  "forbidden"
2984
2942
  ];
2985
- function formatAutoJoinFailureKey(entry) {
2986
- return `${entry.guildId}:${entry.channelId}`;
2987
- }
2988
2943
  function isFatalAutoJoinFailure(message) {
2989
2944
  const normalized = message.toLowerCase();
2990
2945
  return DISCORD_VOICE_FATAL_AUTOJOIN_ERROR_PATTERNS.some((pattern) => normalized.includes(pattern));
@@ -3039,12 +2994,12 @@ var DiscordVoiceManager = class {
3039
2994
  speakerContext
3040
2995
  });
3041
2996
  this.following = new DiscordVoiceFollowing({
2997
+ scheduler: params.scheduler,
3042
2998
  allowedChannels: this.allowedChannels,
3043
2999
  autoJoinChannels: this.autoJoinChannels,
3044
3000
  botUserId: () => this.botUserId,
3045
3001
  client: params.client,
3046
3002
  deleteRecoveryAttempt: (guildId) => this.receive.daveRecoveryAttempts.delete(guildId),
3047
- destroyed: () => this.destroyed,
3048
3003
  stopTransport: (guildId) => this.voiceSessions.stopTransport(guildId),
3049
3004
  discordConfig: params.discordConfig,
3050
3005
  getRecoveryAttempt: (guildId) => this.receive.daveRecoveryAttempts.get(guildId),
@@ -3323,10 +3278,7 @@ var DiscordVoiceManager = class {
3323
3278
  instance: entry
3324
3279
  });
3325
3280
  if (result.ok) {
3326
- this.fatalAutoJoinFailures.delete(formatAutoJoinFailureKey({
3327
- guildId,
3328
- channelId
3329
- }));
3281
+ this.fatalAutoJoinFailures.delete(`${guildId}:${channelId}`);
3330
3282
  if (waitingForOccupancy()) {
3331
3283
  await this.leave({
3332
3284
  guildId,
@@ -3407,7 +3359,7 @@ var DiscordVoiceManager = class {
3407
3359
  async destroy() {
3408
3360
  this.destroyed = true;
3409
3361
  this.occupancyWatchers.clear();
3410
- this.following.destroy();
3362
+ const followingStopped = this.following.destroy();
3411
3363
  for (const entry of this.sessions.values()) entry.stop();
3412
3364
  for (const [guildId, lifecycle] of this.guildLifecycles) this.guildLifecycles.set(guildId, {
3413
3365
  status: "stopped",
@@ -3415,7 +3367,7 @@ var DiscordVoiceManager = class {
3415
3367
  reason: "manager destroyed"
3416
3368
  });
3417
3369
  this.receive.daveRecoveryAttempts.clear();
3418
- await this.voiceSessions.waitForStops();
3370
+ await Promise.all([followingStopped, this.voiceSessions.waitForStops()]);
3419
3371
  }
3420
3372
  isEntryCurrent(entry) {
3421
3373
  const lifecycle = this.guildLifecycles.get(entry.guildId);
@@ -3451,7 +3403,7 @@ var DiscordVoiceManager = class {
3451
3403
  ok: false,
3452
3404
  message: "Discord voice join was cancelled."
3453
3405
  };
3454
- const failureKey = formatAutoJoinFailureKey(entry);
3406
+ const failureKey = `${entry.guildId}:${entry.channelId}`;
3455
3407
  const fatalFailure = this.fatalAutoJoinFailures.get(failureKey);
3456
3408
  if (fatalFailure) {
3457
3409
  if (!fatalFailure.skipLogged) {
@@ -1,4 +1,4 @@
1
- import { t as inspectDiscordAccount } from "./.setup/account-inspect-De8hOUxG.mjs";
1
+ import { t as inspectDiscordAccount } from "./.setup/account-inspect-CjKqkDnH.mjs";
2
2
  //#region extensions/discord/account-inspect-api.ts
3
3
  function inspectDiscordReadOnlyAccount(cfg, accountId) {
4
4
  return inspectDiscordAccount({
@@ -1,2 +1,2 @@
1
- import { t as handleDiscordAction } from "./.setup/runtime-FN000lxA.mjs";
1
+ import { t as handleDiscordAction } from "./.setup/runtime-CwUA0RLr.mjs";
2
2
  export { handleDiscordAction };
@@ -1,2 +1,2 @@
1
- import { t as registerDiscordActivities } from "./.setup/activities-api-tvbsU2e3.mjs";
1
+ import { t as registerDiscordActivities } from "./.setup/activities-api-BL_hJ0JQ.mjs";
2
2
  export { registerDiscordActivities };
package/dist/api.js CHANGED
@@ -1,24 +1,24 @@
1
- import { D as parseDiscordModalCustomIdForInteraction, E as parseDiscordModalCustomId, T as parseDiscordComponentCustomIdForInteraction, _ as DISCORD_COMPONENT_CUSTOM_ID_KEY, b as buildDiscordComponentCustomId, d as buildDiscordComponentMessage, f as buildDiscordComponentMessageFlags, g as resolveDiscordComponentAttachmentName, h as readDiscordComponentSpec, l as DiscordFormModal, n as formatDiscordComponentEventText, p as DISCORD_COMPONENT_ATTACHMENT_PREFIX, r as buildDiscordInteractiveComponents, u as createDiscordFormModal, v as DISCORD_MODAL_CUSTOM_ID_KEY, w as parseDiscordComponentCustomId, x as buildDiscordModalCustomId } from "./.setup/components-Cq1PvIpN.mjs";
2
- import { a as listEnabledDiscordAccounts, c as resolveDiscordAccount, o as mergeDiscordAccountConfig, p as resolveDiscordMaxLinesPerMessage, r as listDiscordAccountIds, s as resolveDefaultDiscordAccountId, t as createDiscordActionGate, u as resolveDiscordAccountConfig } from "./.setup/accounts-ChaMcixG.mjs";
3
- import { i as requestDiscord, n as DiscordApiError, r as fetchDiscord } from "./.setup/api-DVbJwZVt.mjs";
4
- import { b as parseDiscordTarget, g as looksLikeDiscordTargetId, v as normalizeDiscordMessagingTarget, x as resolveDiscordChannelId, y as normalizeDiscordOutboundTarget } from "./.setup/retry-pz_cSha2.mjs";
5
- import { n as resolveDiscordTarget } from "./.setup/target-resolver-BuLapkhy.mjs";
6
- import { t as inspectDiscordAccount } from "./.setup/account-inspect-De8hOUxG.mjs";
7
- import { i as DISCORD_DEFAULT_LISTENER_TIMEOUT_MS, n as DISCORD_ATTACHMENT_TOTAL_TIMEOUT_MS, r as DISCORD_DEFAULT_INBOUND_WORKER_TIMEOUT_MS, t as DISCORD_ATTACHMENT_IDLE_TIMEOUT_MS } from "./.setup/timeouts-D86uWLt_.mjs";
8
- import "./.setup/targets-0KUcEIYx.mjs";
9
- import { D as isDiscordExecApprovalClientEnabled, E as isDiscordExecApprovalApprover, O as shouldSuppressLocalDiscordExecApprovalPrompt, T as getDiscordExecApprovalApprovers } from "./.setup/outbound-session-route-zVGxxceg.mjs";
10
- import { i as resolveDiscordGroupToolPolicy, n as collectDiscordStatusIssues, r as resolveDiscordGroupRequireMention, t as discordPlugin } from "./.setup/channel-DxlUVU9t.mjs";
11
- import { t as normalizeExplicitDiscordSessionKey } from "./.setup/session-key-normalization-wJgsKPNF.mjs";
12
- import { t as discordSetupPlugin } from "./.setup/channel.setup-CRo1GjV7.mjs";
13
- import { n as handleDiscordSubagentEnded, t as handleDiscordSubagentDeliveryTarget } from "./.setup/subagent-hooks-nlUE9ow7.mjs";
14
- import { t as tryHandleDiscordMessageActionGuildAdmin } from "./.setup/handle-action.guild-admin-Df-8gVle.mjs";
15
- import { n as listDiscordDirectoryGroupsFromConfig, r as listDiscordDirectoryPeersFromConfig } from "./.setup/directory-config-esqNn0Eo.mjs";
1
+ import { D as parseDiscordModalCustomIdForInteraction, E as parseDiscordModalCustomId, T as parseDiscordComponentCustomIdForInteraction, _ as DISCORD_COMPONENT_CUSTOM_ID_KEY, b as buildDiscordComponentCustomId, d as buildDiscordComponentMessage, f as buildDiscordComponentMessageFlags, g as resolveDiscordComponentAttachmentName, h as readDiscordComponentSpec, l as DiscordFormModal, n as formatDiscordComponentEventText, p as DISCORD_COMPONENT_ATTACHMENT_PREFIX, r as buildDiscordInteractiveComponents, u as createDiscordFormModal, v as DISCORD_MODAL_CUSTOM_ID_KEY, w as parseDiscordComponentCustomId, x as buildDiscordModalCustomId } from "./.setup/components-CzXLR3QH.mjs";
2
+ import { a as listEnabledDiscordAccounts, c as resolveDiscordAccount, o as mergeDiscordAccountConfig, p as resolveDiscordMaxLinesPerMessage, r as listDiscordAccountIds, s as resolveDefaultDiscordAccountId, t as createDiscordActionGate, u as resolveDiscordAccountConfig } from "./.setup/accounts-DXHCL8Zm.mjs";
3
+ import { i as requestDiscord, n as DiscordApiError, r as fetchDiscord } from "./.setup/api-_oznjffB.mjs";
4
+ import { b as parseDiscordTarget, g as looksLikeDiscordTargetId, v as normalizeDiscordMessagingTarget, x as resolveDiscordChannelId, y as normalizeDiscordOutboundTarget } from "./.setup/retry-BKzO25k4.mjs";
5
+ import { n as resolveDiscordTarget } from "./.setup/target-resolver-Dzxf80Y3.mjs";
6
+ import { i as DISCORD_DEFAULT_LISTENER_TIMEOUT_MS, n as DISCORD_ATTACHMENT_TOTAL_TIMEOUT_MS, r as DISCORD_DEFAULT_INBOUND_WORKER_TIMEOUT_MS, t as DISCORD_ATTACHMENT_IDLE_TIMEOUT_MS } from "./.setup/timeouts-pun7VJ02.mjs";
7
+ import { t as inspectDiscordAccount } from "./.setup/account-inspect-CjKqkDnH.mjs";
8
+ import "./.setup/targets-Lf8D55w-.mjs";
9
+ import { D as isDiscordExecApprovalClientEnabled, E as isDiscordExecApprovalApprover, O as shouldSuppressLocalDiscordExecApprovalPrompt, T as getDiscordExecApprovalApprovers } from "./.setup/outbound-session-route-DGPPKA0z.mjs";
10
+ import { i as resolveDiscordGroupToolPolicy, n as collectDiscordStatusIssues, r as resolveDiscordGroupRequireMention, t as discordPlugin } from "./.setup/channel-z5lQMS_9.mjs";
11
+ import { t as normalizeExplicitDiscordSessionKey } from "./.setup/session-key-normalization-CCHGNSQw.mjs";
12
+ import { t as discordSetupPlugin } from "./.setup/channel.setup-DBJtugJO.mjs";
13
+ import { n as handleDiscordSubagentEnded, t as handleDiscordSubagentDeliveryTarget } from "./.setup/subagent-hooks-BYlVnxzy.mjs";
14
+ import { t as tryHandleDiscordMessageActionGuildAdmin } from "./.setup/handle-action.guild-admin-BnyqTczR.mjs";
15
+ import { n as listDiscordDirectoryGroupsFromConfig, r as listDiscordDirectoryPeersFromConfig } from "./.setup/directory-config-BH1LA-gi.mjs";
16
16
  import { t as fetchPluralKitMessageInfo } from "./.setup/pluralkit-a6_NLfH9.mjs";
17
- import { i as probeDiscord, n as fetchDiscordApplicationSummary, r as parseApplicationIdFromToken, s as resolveDiscordPrivilegedIntentsFromFlags, t as fetchDiscordApplicationId } from "./.setup/probe-LYrIHlBF.mjs";
18
- import { t as collectDiscordSecurityAuditFindings } from "./.setup/security-audit-Cdaegq7C.mjs";
17
+ import { i as probeDiscord, n as fetchDiscordApplicationSummary, r as parseApplicationIdFromToken, s as resolveDiscordPrivilegedIntentsFromFlags, t as fetchDiscordApplicationId } from "./.setup/probe-DIRY8vh7.mjs";
18
+ import { t as collectDiscordSecurityAuditFindings } from "./.setup/security-audit-D42cp5N7.mjs";
19
19
  import { resolveOpenProviderRuntimeGroupPolicy as resolveDiscordRuntimeGroupPolicy } from "openclaw/plugin-sdk/runtime-group-policy";
20
20
  //#region extensions/discord/api.ts
21
- const handleDiscordMessageAction = async (...args) => (await import("./.setup/handle-action-CUvQWnE7.mjs")).handleDiscordMessageAction(...args);
21
+ const handleDiscordMessageAction = async (...args) => (await import("./.setup/handle-action-DlmFX-_G.mjs")).handleDiscordMessageAction(...args);
22
22
  /**
23
23
  * @deprecated Shipped `@openclaw/discord/api` compatibility only. Use native
24
24
  * `AbortSignal.any` after filtering optional signals. Removal with the next
@@ -1,2 +1,2 @@
1
- import { t as DiscordChannelConfigSchema } from "./.setup/config-schema-oxELUSDx.mjs";
1
+ import { t as DiscordChannelConfigSchema } from "./.setup/config-schema-CsemBDpS.mjs";
2
2
  export { DiscordChannelConfigSchema };
@@ -1,2 +1,2 @@
1
- import { t as discordPlugin } from "./.setup/channel-DxlUVU9t.mjs";
1
+ import { t as discordPlugin } from "./.setup/channel-z5lQMS_9.mjs";
2
2
  export { discordPlugin };
@@ -0,0 +1 @@
1
+ function l(i){return(o,s)=>{let e=document.createElement("a");e.className="plugin-session-header-link",e.target="_blank",e.rel="noopener noreferrer",e.dataset.linkReaderExternal="";let d=!1,a=()=>{d=!0,e.removeAttribute("href"),e.remove()},p=n=>{if(d)return;let t=n.presented&&!n.signal.aborted&&n.props.session?i(n.props.session):void 0,r=t?URL.parse(t.url):null;if(!t||!r||r.protocol!=="https:"&&r.protocol!=="http:"){e.removeAttribute("href"),e.remove();return}e.href=r.href,e.textContent=`${t.label} \u2197`,e.parentNode!==o&&o.append(e)};return s.signal.addEventListener("abort",a,{once:!0}),p(s),{update:p,dispose(){s.signal.removeEventListener("abort",a),a()}}}}var b={id:"discord",activate(i){return i.ui.registerAccessory({id:"conversation-origin",placement:"session-header",mount:l(({conversationLink:o})=>o&&URL.parse(o.url)?.hostname==="discord.com"?o:void 0)})}};export{b as default};
@@ -1,4 +1,4 @@
1
- import { n as listDiscordDirectoryGroupsFromConfig, r as listDiscordDirectoryPeersFromConfig } from "./.setup/directory-config-esqNn0Eo.mjs";
1
+ import { n as listDiscordDirectoryGroupsFromConfig, r as listDiscordDirectoryPeersFromConfig } from "./.setup/directory-config-BH1LA-gi.mjs";
2
2
  //#region extensions/discord/directory-contract-api.ts
3
3
  const discordDirectoryContractPlugin = {
4
4
  id: "discord",