@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,12 +1,13 @@
1
1
  import { n as __reExport, t as __exportAll } from "./rolldown-runtime-B4FMCO8f.mjs";
2
- import { D as getDiscordEndpointRuntime, T as parseDiscordRetryAfterBodySeconds } from "./channel-type-DRCrEMss.mjs";
2
+ import { E as parseDiscordRetryAfterBodySeconds, O as getDiscordEndpointRuntime } from "./channel-type-D1_b5UhU.mjs";
3
3
  import { redactIdentifier, redactSensitiveFieldValue } from "openclaw/plugin-sdk/logging-core";
4
+ import { asOptionalObjectRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
4
5
  import { ApplicationCommandOptionType, ApplicationCommandType, ButtonStyle, ComponentType, GatewayDispatchEvents, InteractionContextType, InteractionResponseType, InteractionType, MessageFlags, Routes, TextInputStyle } from "discord-api-types/v10";
5
6
  import { Type } from "typebox";
6
7
  import { Check } from "typebox/value";
7
8
  import { createHash } from "node:crypto";
8
- import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
9
- import { asDateTimestampMs, clampTimerTimeoutMs, parseStrictNonNegativeInteger, resolveExpiresAtMsFromDurationMs, resolveIntegerOption, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
9
+ import { asDateTimestampMs, clampTimerTimeoutMs, parseStrictNonNegativeInteger as parseStrictNonNegativeInteger$1, resolveExpiresAtMsFromDurationMs, resolveIntegerOption, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
10
+ import { raceWithTimeout } from "openclaw/plugin-sdk/time-runtime";
10
11
  import { inspect } from "node:util";
11
12
  import { gunzipSync } from "node:zlib";
12
13
  import { captureChannelReadAuthority } from "openclaw/plugin-sdk/fetch-runtime";
@@ -24,65 +25,17 @@ const discordGuildEmojiListSchema = Type.Array(Type.Object({
24
25
  async function getGuild(rest, guildId) {
25
26
  return await rest.get(Routes.guild(guildId));
26
27
  }
27
- async function createGuildChannel(rest, guildId, data) {
28
- return await rest.post(Routes.guildChannels(guildId), data);
29
- }
30
- async function moveGuildChannels(rest, guildId, data) {
31
- await rest.patch(Routes.guildChannels(guildId), data);
32
- }
33
28
  async function getGuildMember(rest, guildId, userId) {
34
29
  return await rest.get(Routes.guildMember(guildId, userId));
35
30
  }
36
- async function listGuildRoles(rest, guildId) {
37
- return await rest.get(Routes.guildRoles(guildId));
38
- }
39
- async function listGuildChannels(rest, guildId) {
40
- return await rest.get(Routes.guildChannels(guildId));
41
- }
42
- async function putChannelPermission(rest, channelId, targetId, data) {
43
- await rest.put(Routes.channelPermission(channelId, targetId), data);
44
- }
45
- async function deleteChannelPermission(rest, channelId, targetId) {
46
- await rest.delete(Routes.channelPermission(channelId, targetId));
47
- }
48
- async function listGuildActiveThreads(rest, guildId) {
49
- return await rest.get(Routes.guildActiveThreads(guildId));
50
- }
51
31
  async function getGuildVoiceState(rest, guildId, userId) {
52
32
  return await rest.get(Routes.guildVoiceState(guildId, userId));
53
33
  }
54
- async function listGuildScheduledEvents(rest, guildId) {
55
- return await rest.get(Routes.guildScheduledEvents(guildId));
56
- }
57
- async function createGuildScheduledEvent(rest, guildId, body) {
58
- return await rest.post(Routes.guildScheduledEvents(guildId), { body });
59
- }
60
- async function timeoutGuildMember(rest, guildId, userId, data) {
61
- return await rest.patch(Routes.guildMember(guildId, userId), data);
62
- }
63
- async function addGuildMemberRole(rest, guildId, userId, roleId) {
64
- await rest.put(Routes.guildMemberRole(guildId, userId, roleId));
65
- }
66
- async function removeGuildMemberRole(rest, guildId, userId, roleId) {
67
- await rest.delete(Routes.guildMemberRole(guildId, userId, roleId));
68
- }
69
- async function removeGuildMember(rest, guildId, userId, data) {
70
- await rest.delete(Routes.guildMember(guildId, userId), data);
71
- }
72
- async function createGuildBan(rest, guildId, userId, data) {
73
- await rest.put(Routes.guildBan(guildId, userId), data);
74
- }
75
34
  async function listGuildEmojis(rest, guildId) {
76
35
  const emojis = await rest.get(Routes.guildEmojis(guildId));
77
36
  if (!Check(discordGuildEmojiListSchema, emojis)) throw new Error("Invalid Discord guild emoji response.");
78
37
  return emojis;
79
38
  }
80
- async function createGuildEmoji(rest, guildId, data) {
81
- return await rest.post(Routes.guildEmojis(guildId), data);
82
- }
83
- async function createGuildSticker(rest, guildId, data) {
84
- return await rest.post(Routes.guildStickers(guildId), data);
85
- }
86
39
  //#endregion
87
40
  //#region extensions/discord/src/internal/api.messages.ts
88
41
  function normalizeDiscordMessageId(messageId) {
@@ -96,21 +49,9 @@ async function getChannel(rest, channelId) {
96
49
  async function getThreadMember(rest, threadId, userId) {
97
50
  return await rest.get(Routes.threadMembers(threadId, userId));
98
51
  }
99
- async function editChannel(rest, channelId, data) {
100
- return await rest.patch(Routes.channel(channelId), data);
101
- }
102
- async function deleteChannel(rest, channelId) {
103
- await rest.delete(Routes.channel(channelId));
104
- }
105
- async function listChannelMessages(rest, channelId, query) {
106
- return await rest.get(Routes.channelMessages(channelId), query);
107
- }
108
52
  async function getChannelMessage(rest, channelId, messageId) {
109
53
  return await rest.get(Routes.channelMessage(channelId, normalizeDiscordMessageId(messageId)));
110
54
  }
111
- async function createChannelMessage(rest, channelId, data) {
112
- return await rest.post(Routes.channelMessages(channelId), data);
113
- }
114
55
  async function editChannelMessage(rest, channelId, messageId, data) {
115
56
  return await rest.patch(Routes.channelMessage(channelId, normalizeDiscordMessageId(messageId)), data);
116
57
  }
@@ -123,22 +64,10 @@ async function pinChannelMessage(rest, channelId, messageId) {
123
64
  async function unpinChannelMessage(rest, channelId, messageId) {
124
65
  await rest.delete(Routes.channelPin(channelId, normalizeDiscordMessageId(messageId)));
125
66
  }
126
- async function listChannelPins(rest, channelId) {
127
- return await rest.get(Routes.channelPins(channelId));
128
- }
129
- async function sendChannelTyping(rest, channelId) {
130
- await rest.post(Routes.channelTyping(channelId));
131
- }
132
67
  async function createThread(rest, channelId, data, messageId) {
133
68
  const route = messageId === void 0 ? Routes.threads(channelId) : Routes.threads(channelId, normalizeDiscordMessageId(messageId));
134
69
  return await rest.post(route, data);
135
70
  }
136
- async function listChannelArchivedThreads(rest, channelId, query) {
137
- return await rest.get(Routes.channelThreads(channelId, "public"), query);
138
- }
139
- async function searchGuildMessages(rest, guildId, params) {
140
- return await rest.get(`/guilds/${guildId}/messages/search?${params.toString()}`);
141
- }
142
71
  //#endregion
143
72
  //#region extensions/discord/src/internal/api.reactions.ts
144
73
  async function createOwnMessageReaction(rest, channelId, messageId, encodedEmoji) {
@@ -210,10 +139,7 @@ function stableComparableObject(value, pathValue = []) {
210
139
  if (pathValue.includes("options") && optionComparisonOmittedFields.has(key)) return false;
211
140
  if ((key === "required" || key === "autocomplete") && entry === false) return false;
212
141
  return true;
213
- }).toSorted(([a], [b]) => a.localeCompare(b)).map(([key, entry]) => [key, shouldNormalizeDescriptionValue(pathValue, key, entry) ? normalizeDescriptionForComparison(entry) : stableComparableObject(entry, [...pathValue, key])]));
214
- }
215
- function shouldNormalizeDescriptionValue(pathLocal, key, entry) {
216
- return typeof entry === "string" && (key === "description" || pathLocal.at(-1) === "description_localizations");
142
+ }).toSorted(([a], [b]) => a.localeCompare(b)).map(([key, entry]) => [key, typeof entry === "string" && (key === "description" || pathValue.at(-1) === "description_localizations") ? normalizeDescriptionForComparison(entry) : stableComparableObject(entry, [...pathValue, key])]));
217
143
  }
218
144
  /**
219
145
  * Normalize descriptions to match Discord's server-side storage semantics.
@@ -233,39 +159,21 @@ const DISCORD_APPLICATION_COMMAND_LIMIT_REACHED = 30032;
233
159
  var DiscordCommandDeployer = class {
234
160
  constructor(params) {
235
161
  this.params = params;
236
- this.hashes = /* @__PURE__ */ new Map();
237
- this.loadedKeys = /* @__PURE__ */ new Set();
238
- }
239
- async deploy(options = {}) {
240
- const commands = this.params.commands.filter((command) => command.name !== "*");
241
- const serializedGlobal = commands.filter((command) => !command.guildIds).map((command) => command.serialize());
242
- for (const [guildId, entries] of groupGuildCommands(commands)) await this.putCommandSetIfChanged(this.scopedCacheKey(`guild:${guildId}`), entries, () => this.rest.put(Routes.applicationGuildCommands(this.params.clientId, guildId), { body: entries }), options);
243
- if (this.params.devGuilds?.length) {
244
- for (const guildId of this.params.devGuilds) {
245
- const entries = commands.map((command) => command.serialize());
246
- await this.putCommandSetIfChanged(this.scopedCacheKey(`dev-guild:${guildId}`), entries, () => this.rest.put(Routes.applicationGuildCommands(this.params.clientId, guildId), { body: entries }), options);
247
- }
248
- return {
249
- mode: options.mode ?? "reconcile",
250
- usedDevGuilds: true
251
- };
252
- }
253
- const mode = options.mode === "overwrite" ? "overwrite" : "reconcile";
254
- await this.putCommandSetIfChanged(this.scopedCacheKey(`global:${mode}`), serializedGlobal, () => mode === "overwrite" ? this.rest.put(Routes.applicationCommands(this.params.clientId), { body: serializedGlobal }) : this.reconcileGlobalCommands(serializedGlobal), options);
255
- return {
256
- mode,
257
- usedDevGuilds: false
258
- };
162
+ this.hashLoaded = false;
259
163
  }
260
- /**
261
- * Scope cache keys by Discord application id so multi-bot setups that share a
262
- * single command-deploy store still reconcile each application separately. The
263
- * prior unscoped `global:reconcile` / `guild:<id>` keys let a later account
264
- * with an identical command set reuse the first account's hash and skip its
265
- * own application's reconcile entirely (#77359).
266
- */
267
- scopedCacheKey(suffix) {
268
- return `app:${this.params.clientId}:${suffix}`;
164
+ async deploy() {
165
+ const commands = this.params.commands.filter((command) => command.name !== "*").map((command) => command.serialize());
166
+ const hash = stableCommandSetHash(commands);
167
+ await this.loadPersistedHash();
168
+ if (this.hash === hash) return;
169
+ await this.reconcileGlobalCommands(commands);
170
+ this.hash = hash;
171
+ try {
172
+ await this.params.hashStore?.register(this.cacheKey, hash);
173
+ } catch {}
174
+ }
175
+ get cacheKey() {
176
+ return `app:${this.params.clientId}:global:reconcile`;
269
177
  }
270
178
  async reconcileGlobalCommands(desired) {
271
179
  const existing = await this.rest.get(Routes.applicationCommands(this.params.clientId));
@@ -291,37 +199,18 @@ var DiscordCommandDeployer = class {
291
199
  }
292
200
  for (const command of existing) if (!desiredKeys.has(stableCommandKey(command))) await this.rest.delete(Routes.applicationCommand(this.params.clientId, command.id));
293
201
  }
294
- async putCommandSetIfChanged(key, commands, deploy, options) {
295
- const hash = stableCommandSetHash(commands);
296
- await this.loadPersistedHash(key);
297
- if (!options.force && this.hashes.get(key) === hash) return;
298
- await deploy();
299
- this.hashes.set(key, hash);
300
- try {
301
- await this.params.hashStore?.register(key, hash);
302
- } catch {}
303
- }
304
- async loadPersistedHash(key) {
305
- if (this.loadedKeys.has(key)) return;
306
- this.loadedKeys.add(key);
202
+ async loadPersistedHash() {
203
+ if (this.hashLoaded) return;
204
+ this.hashLoaded = true;
307
205
  try {
308
- const hash = await this.params.hashStore?.lookup(key);
309
- if (typeof hash === "string" && hash.trim()) this.hashes.set(key, hash);
206
+ const hash = await this.params.hashStore?.lookup(this.cacheKey);
207
+ if (typeof hash === "string" && hash.trim()) this.hash = hash;
310
208
  } catch {}
311
209
  }
312
210
  get rest() {
313
211
  return this.params.rest();
314
212
  }
315
213
  };
316
- function groupGuildCommands(commands) {
317
- const guildCommands = /* @__PURE__ */ new Map();
318
- for (const command of commands) for (const guildId of command.guildIds ?? []) {
319
- const entries = guildCommands.get(guildId) ?? [];
320
- entries.push(command.serialize());
321
- guildCommands.set(guildId, entries);
322
- }
323
- return guildCommands;
324
- }
325
214
  function stableCommandKey(command) {
326
215
  return `${command.type ?? ApplicationCommandType.ChatInput}:${command.name}`;
327
216
  }
@@ -340,11 +229,9 @@ function stripUndefinedFields(value) {
340
229
  //#endregion
341
230
  //#region extensions/discord/src/internal/components.base.ts
342
231
  function parseCustomId(id) {
343
- const [rawKeyValue, ...parts] = id.split(";");
344
- const rawKey = expectDefined(rawKeyValue, "custom id split first segment");
345
- const [keyPart, firstValue] = rawKey.split("=");
346
- const definedKeyPart = expectDefined(keyPart, "custom id key segment");
347
- const key = definedKeyPart.includes(":") ? expectDefined(definedKeyPart.split(":").at(0), "namespaced custom id key") : definedKeyPart;
232
+ const [rawKey = "", ...parts] = id.split(";");
233
+ const [keyPart = "", firstValue] = rawKey.split("=");
234
+ const key = keyPart.split(":", 1)[0] ?? "";
348
235
  const data = {};
349
236
  const entries = firstValue === void 0 ? parts : [rawKey.slice(key.length + 1), ...parts];
350
237
  for (const entry of entries) {
@@ -753,7 +640,7 @@ var ComponentRegistry = class {
753
640
  this.wildcardEntries = [];
754
641
  }
755
642
  register(entry) {
756
- const key = parseRegistryKey(entry.customId, entry.customIdParser);
643
+ const key = (entry.customIdParser ?? parseCustomId)(entry.customId).key;
757
644
  if (key === "*") {
758
645
  if (!this.wildcardEntries.includes(entry)) this.wildcardEntries.push(entry);
759
646
  return;
@@ -769,19 +656,13 @@ var ComponentRegistry = class {
769
656
  const match = entries.find((entry) => {
770
657
  if (options?.componentType !== void 0 && entry.type !== options.componentType) return false;
771
658
  const parser = entry.customIdParser ?? parseCustomId;
772
- return parseRegistryKey(entry.customId, parser) === parseRegistryKey(customId, parser);
659
+ return parser(entry.customId).key === parser(customId).key;
773
660
  });
774
661
  if (match) return match;
775
662
  }
776
- return this.wildcardEntries.find((entry) => {
777
- if (options?.componentType !== void 0 && entry.type !== options.componentType) return false;
778
- return true;
779
- });
663
+ return this.wildcardEntries.find((entry) => options?.componentType === void 0 || entry.type === options.componentType);
780
664
  }
781
665
  };
782
- function parseRegistryKey(customId, parser = parseCustomId) {
783
- return parser(customId).key;
784
- }
785
666
  //#endregion
786
667
  //#region extensions/discord/src/internal/structures.ts
787
668
  var Base = class {
@@ -1142,7 +1023,9 @@ var DiscordEventQueue = class {
1142
1023
  async runJob(job, listenerPromise) {
1143
1024
  const startedAt = Date.now();
1144
1025
  try {
1145
- await this.runWithTimeout(listenerPromise);
1026
+ await raceWithTimeout(listenerPromise, this.options.listenerTimeout, () => {
1027
+ throw createListenerTimeoutError(this.options.listenerTimeout);
1028
+ }, { ref: false });
1146
1029
  this.logSlowListener(job, Date.now() - startedAt);
1147
1030
  return "completed";
1148
1031
  } catch (error) {
@@ -1155,19 +1038,6 @@ var DiscordEventQueue = class {
1155
1038
  return "failed";
1156
1039
  }
1157
1040
  }
1158
- async runWithTimeout(listenerPromise) {
1159
- let timeout;
1160
- try {
1161
- await Promise.race([listenerPromise, new Promise((_, reject) => {
1162
- timeout = setTimeout(() => {
1163
- reject(createListenerTimeoutError(this.options.listenerTimeout));
1164
- }, this.options.listenerTimeout);
1165
- timeout.unref?.();
1166
- })]);
1167
- } finally {
1168
- if (timeout) clearTimeout(timeout);
1169
- }
1170
- }
1171
1041
  logSlowListener(job, durationMs) {
1172
1042
  if (durationMs < this.options.slowListenerThreshold) return;
1173
1043
  console.warn(`[EventQueue] Slow listener detected: ${job.listenerName} took ${durationMs}ms for event ${job.eventType}`);
@@ -1202,13 +1072,10 @@ function findSelectedSubcommand(subcommands, interaction) {
1202
1072
  const subcommandName = readRawCommandOptions(interaction).find((option) => option.type === ApplicationCommandOptionType.Subcommand)?.name;
1203
1073
  return typeof subcommandName === "string" ? subcommands.find((command) => command.name === subcommandName) : void 0;
1204
1074
  }
1205
- function findCommandOption(options, name) {
1206
- if (!name) return;
1207
- return options?.find((option) => option.name === name);
1208
- }
1209
1075
  function resolveFocusedCommandOptionAutocompleteHandler(command, interaction) {
1210
1076
  const focusedName = interaction.options.getFocused()?.name;
1211
- const autocomplete = findCommandOption(command.commandKind === "group" ? findSelectedSubcommand(command.subcommands, interaction)?.options : command.options, focusedName)?.autocomplete;
1077
+ const options = command.commandKind === "group" ? findSelectedSubcommand(command.subcommands, interaction)?.options : command.options;
1078
+ const autocomplete = focusedName ? options?.find((option) => option.name === focusedName)?.autocomplete : void 0;
1212
1079
  return typeof autocomplete === "function" ? autocomplete : void 0;
1213
1080
  }
1214
1081
  var BaseCommand = class {
@@ -1303,24 +1170,24 @@ var OptionsHandler = class {
1303
1170
  this.client = client;
1304
1171
  this.resolvedChannels = resolvedChannels;
1305
1172
  }
1306
- getString(name) {
1173
+ value(name) {
1307
1174
  const option = findOption(this.rawOptions, (entry) => entry.name === name);
1308
- const value = option && "value" in option ? option.value : void 0;
1175
+ return option && "value" in option ? option.value : void 0;
1176
+ }
1177
+ getString(name) {
1178
+ const value = this.value(name);
1309
1179
  return typeof value === "string" ? value : null;
1310
1180
  }
1311
1181
  getNumber(name) {
1312
- const option = findOption(this.rawOptions, (entry) => entry.name === name);
1313
- const value = option && "value" in option ? option.value : void 0;
1182
+ const value = this.value(name);
1314
1183
  return typeof value === "number" ? value : null;
1315
1184
  }
1316
1185
  getBoolean(name) {
1317
- const option = findOption(this.rawOptions, (entry) => entry.name === name);
1318
- const value = option && "value" in option ? option.value : void 0;
1186
+ const value = this.value(name);
1319
1187
  return typeof value === "boolean" ? value : null;
1320
1188
  }
1321
1189
  async getChannel(name, required = false) {
1322
- const option = findOption(this.rawOptions, (entry) => entry.name === name);
1323
- const value = option && "value" in option ? option.value : void 0;
1190
+ const value = this.value(name);
1324
1191
  const id = typeof value === "string" ? value : void 0;
1325
1192
  const resolved = id ? this.resolvedChannels?.[id] : void 0;
1326
1193
  if (resolved) return channelFactory(this.client, resolved);
@@ -1334,36 +1201,6 @@ var OptionsHandler = class {
1334
1201
  };
1335
1202
  //#endregion
1336
1203
  //#region extensions/discord/src/internal/interaction-response.ts
1337
- var InteractionResponseController = class {
1338
- constructor() {
1339
- this.state = "unacknowledged";
1340
- }
1341
- get acknowledged() {
1342
- return this.state !== "unacknowledged";
1343
- }
1344
- recordCallback(type) {
1345
- if (type === InteractionResponseType.DeferredChannelMessageWithSource) {
1346
- this.state = "deferred";
1347
- return;
1348
- }
1349
- if (type === InteractionResponseType.DeferredMessageUpdate) {
1350
- this.state = "deferred-update";
1351
- return;
1352
- }
1353
- this.state = "replied";
1354
- }
1355
- nextReplyAction() {
1356
- if (this.state === "deferred" || this.state === "deferred-update") return "edit";
1357
- if (this.state === "unacknowledged") return "initial";
1358
- return "follow-up";
1359
- }
1360
- recordReplyEdit() {
1361
- this.state = "replied";
1362
- }
1363
- recordReplyDelete() {
1364
- this.state = "replied";
1365
- }
1366
- };
1367
1204
  function needsComponentsV2Query(body) {
1368
1205
  return body !== null && typeof body === "object" && "flags" in body && typeof body.flags === "number" && (body.flags & MessageFlags.IsComponentsV2) !== 0;
1369
1206
  }
@@ -1466,7 +1303,7 @@ var BaseInteraction = class {
1466
1303
  this.client = client;
1467
1304
  this.rawData = rawData;
1468
1305
  this.message = null;
1469
- this.response = new InteractionResponseController();
1306
+ this.currentResponseState = "unacknowledged";
1470
1307
  this.pendingResponse = Promise.resolve();
1471
1308
  this.sentFollowUp = false;
1472
1309
  this.id = rawData.id;
@@ -1477,19 +1314,14 @@ var BaseInteraction = class {
1477
1314
  this.channel = "channel" in rawData && rawData.channel ? channelFactory(client, rawData.channel) : null;
1478
1315
  }
1479
1316
  get acknowledged() {
1480
- return this.response.acknowledged;
1317
+ return this.currentResponseState !== "unacknowledged";
1481
1318
  }
1482
1319
  get responseState() {
1483
- return this.response.state;
1320
+ return this.currentResponseState;
1484
1321
  }
1485
1322
  set responseState(nextState) {
1486
- this.response.state = nextState;
1323
+ this.currentResponseState = nextState;
1487
1324
  }
1488
- /**
1489
- * True once a follow-up message has been delivered. Follow-ups are visible to
1490
- * the user but never advance `responseState`, so this is the only record that
1491
- * the interaction has already produced output.
1492
- */
1493
1325
  get hasSentFollowUp() {
1494
1326
  return this.sentFollowUp;
1495
1327
  }
@@ -1499,12 +1331,12 @@ var BaseInteraction = class {
1499
1331
  return result;
1500
1332
  }
1501
1333
  async performCallback(type, data) {
1502
- if (this.response.acknowledged) throw new Error("Discord interaction has already been acknowledged.");
1334
+ if (this.currentResponseState !== "unacknowledged") throw new Error("Discord interaction has already been acknowledged.");
1503
1335
  const result = await this.client.rest.post(Routes.interactionCallback(this.id, this.token), { body: data === void 0 ? { type } : {
1504
1336
  type,
1505
1337
  data
1506
1338
  } });
1507
- this.response.recordCallback(type);
1339
+ this.currentResponseState = type === InteractionResponseType.DeferredChannelMessageWithSource ? "deferred" : type === InteractionResponseType.DeferredMessageUpdate ? "deferred-update" : "replied";
1508
1340
  return result;
1509
1341
  }
1510
1342
  async callback(type, data) {
@@ -1512,9 +1344,8 @@ var BaseInteraction = class {
1512
1344
  }
1513
1345
  async reply(payload) {
1514
1346
  return await this.enqueueResponse(async () => {
1515
- const action = this.response.nextReplyAction();
1516
- if (action === "edit") return await this.performReplyEdit(payload);
1517
- if (action === "follow-up") return await this.performFollowUp(payload);
1347
+ if (this.currentResponseState === "deferred" || this.currentResponseState === "deferred-update") return await this.performReplyEdit(payload);
1348
+ if (this.currentResponseState !== "unacknowledged") return await this.performFollowUp(payload);
1518
1349
  return await this.performCallback(InteractionResponseType.ChannelMessageWithSource, serializePayload(payload));
1519
1350
  });
1520
1351
  }
@@ -1527,17 +1358,6 @@ var BaseInteraction = class {
1527
1358
  async editReply(payload) {
1528
1359
  return await this.enqueueResponse(() => this.performReplyEdit(payload));
1529
1360
  }
1530
- /**
1531
- * Edits the deferred placeholder only if this interaction is still an
1532
- * unanswered spinner when the queue reaches this operation.
1533
- *
1534
- * Both conditions are re-read inside the queue. A follow-up that was still in
1535
- * flight when the caller decided to report will have settled — and recorded
1536
- * itself in `sentFollowUp` — by the time this runs, so the decision cannot be
1537
- * made against state that is about to change.
1538
- *
1539
- * Resolves true when the edit was sent.
1540
- */
1541
1361
  async editDeferredPlaceholderIfUnanswered(payload) {
1542
1362
  return await this.enqueueResponse(async () => {
1543
1363
  if (this.responseState !== "deferred" || this.sentFollowUp) return false;
@@ -1549,13 +1369,13 @@ var BaseInteraction = class {
1549
1369
  const body = serializePayload(payload);
1550
1370
  const query = needsComponentsV2Query(body) ? { with_components: true } : void 0;
1551
1371
  const result = query ? await this.client.rest.patch(this.originalReplyRoute, { body }, query) : await this.client.rest.patch(this.originalReplyRoute, { body });
1552
- this.response.recordReplyEdit();
1372
+ this.currentResponseState = "replied";
1553
1373
  return result;
1554
1374
  }
1555
1375
  async deleteReply() {
1556
1376
  return await this.enqueueResponse(async () => {
1557
1377
  const result = await this.client.rest.delete(this.originalReplyRoute);
1558
- this.response.recordReplyDelete();
1378
+ this.currentResponseState = "replied";
1559
1379
  return result;
1560
1380
  });
1561
1381
  }
@@ -1728,6 +1548,9 @@ function captureDiscordRequestAuthority() {
1728
1548
  }
1729
1549
  //#endregion
1730
1550
  //#region extensions/discord/src/internal/rest-body.ts
1551
+ function fileBlob(file) {
1552
+ return file.data instanceof Blob ? file.data : new Blob([file.data], { type: typeof file.contentType === "string" ? file.contentType : void 0 });
1553
+ }
1731
1554
  function serializeRequestBody(data, headers) {
1732
1555
  if (data?.headers) for (const [key, value] of Object.entries(data.headers)) headers.set(key, value);
1733
1556
  if (data?.body == null) return;
@@ -1748,24 +1571,22 @@ function serializeRequestBody(data, headers) {
1748
1571
  for (const file of files) {
1749
1572
  const item = file;
1750
1573
  const name = typeof item.name === "string" && item.name ? item.name : "file";
1751
- const blob = item.data instanceof Blob ? item.data : new Blob([item.data], { type: typeof item.contentType === "string" ? item.contentType : void 0 });
1752
- formData.append(typeof item.fieldName === "string" && item.fieldName ? item.fieldName : "file", blob, name);
1574
+ formData.append(typeof item.fieldName === "string" && item.fieldName ? item.fieldName : "file", fileBlob(item), name);
1753
1575
  }
1754
1576
  return formData;
1755
1577
  }
1756
- const payloadJson = topLevelFiles ? { ...bodyObject } : {
1578
+ const payloadFilesContainer = { ...filesContainer };
1579
+ const payloadJson = topLevelFiles ? payloadFilesContainer : {
1757
1580
  ...bodyObject,
1758
- data: { ...nestedData }
1581
+ data: payloadFilesContainer
1759
1582
  };
1760
- const payloadFilesContainer = topLevelFiles ? payloadJson : payloadJson.data ?? {};
1761
1583
  const formData = new FormData();
1762
1584
  const existingAttachments = Array.isArray(payloadFilesContainer.attachments) ? [...payloadFilesContainer.attachments] : [];
1763
1585
  const uploaded = files.map((file, index) => {
1764
1586
  const item = file;
1765
1587
  const name = typeof item.name === "string" && item.name ? item.name : `file-${index}`;
1766
- const blob = item.data instanceof Blob ? item.data : new Blob([item.data], { type: typeof item.contentType === "string" ? item.contentType : void 0 });
1767
1588
  const id = existingAttachments.length + index;
1768
- formData.append(`files[${id}]`, blob, name);
1589
+ formData.append(`files[${id}]`, fileBlob(item), name);
1769
1590
  const attachment = {
1770
1591
  id,
1771
1592
  filename: name
@@ -1872,19 +1693,17 @@ function redactDiscordErrorBody(body, fieldKey = "", sensitiveAncestorKey, state
1872
1693
  return redacted;
1873
1694
  }
1874
1695
  function readDiscordCode(body) {
1875
- const value = body && typeof body === "object" && "code" in body ? body.code : void 0;
1876
- return parseStrictNonNegativeInteger(value);
1696
+ return parseStrictNonNegativeInteger$1(asOptionalObjectRecord(body)?.code);
1877
1697
  }
1878
1698
  function readDiscordMessage(body, fallback) {
1879
- const value = body && typeof body === "object" && "message" in body ? body.message : void 0;
1699
+ const value = asOptionalObjectRecord(body)?.message;
1880
1700
  return typeof value === "string" && value.trim() ? value : fallback;
1881
1701
  }
1882
1702
  function isUnknownDiscordVoiceStateError(err) {
1883
- return (err && typeof err === "object" && "discordCode" in err ? parseStrictNonNegativeInteger(err.discordCode) : void 0) === DISCORD_UNKNOWN_VOICE_STATE || /unknown voice state/i.test(formatErrorMessage(err));
1703
+ return parseStrictNonNegativeInteger$1(asOptionalObjectRecord(err)?.discordCode) === DISCORD_UNKNOWN_VOICE_STATE || /unknown voice state/i.test(formatErrorMessage(err));
1884
1704
  }
1885
1705
  function readRetryAfter(body, response, fallbackSeconds = 0) {
1886
- const bodyValue = body && typeof body === "object" && "retry_after" in body ? body.retry_after : void 0;
1887
- return parseDiscordRetryAfterBodySeconds(bodyValue) ?? parseRetryAfterHeaderSeconds(response.headers.get("Retry-After")) ?? fallbackSeconds;
1706
+ return parseDiscordRetryAfterBodySeconds(asOptionalObjectRecord(body)?.retry_after) ?? parseRetryAfterHeaderSeconds(response.headers.get("Retry-After")) ?? fallbackSeconds;
1888
1707
  }
1889
1708
  function readDiscordRateLimitBucket(response) {
1890
1709
  const value = response.headers.get("X-RateLimit-Bucket")?.trim();
@@ -1971,30 +1790,27 @@ function appendQuery(path, query) {
1971
1790
  //#endregion
1972
1791
  //#region extensions/discord/src/internal/rest-scheduler.ts
1973
1792
  const INVALID_REQUEST_WINDOW_MS = 6e5;
1793
+ const MAX_QUEUE_SIZE = 1e3;
1794
+ const MAX_CONCURRENT_WORKERS = 4;
1795
+ const MAX_RATE_LIMIT_RETRIES = 3;
1796
+ const BACKGROUND_STALE_AFTER_MS = 2e4;
1974
1797
  const requestPriorities = [
1975
1798
  "critical",
1976
1799
  "standard",
1977
1800
  "background"
1978
1801
  ];
1979
- function normalizeRestSchedulerOptions(options) {
1980
- return {
1981
- lanes: {
1982
- critical: normalizeLaneOptions(options.lanes.critical),
1983
- standard: normalizeLaneOptions(options.lanes.standard),
1984
- background: normalizeLaneOptions(options.lanes.background)
1985
- },
1986
- maxConcurrency: resolveIntegerOption(options.maxConcurrency, 1, { min: 1 }),
1987
- maxQueueSize: resolveIntegerOption(options.maxQueueSize, 1, { min: 1 }),
1988
- maxRateLimitRetries: resolveIntegerOption(options.maxRateLimitRetries, 0, { min: 0 })
1989
- };
1990
- }
1991
- function normalizeLaneOptions(options) {
1992
- return {
1993
- maxQueueSize: resolveIntegerOption(options.maxQueueSize, 1, { min: 1 }),
1994
- ...options.staleAfterMs === void 0 ? {} : { staleAfterMs: resolveIntegerOption(options.staleAfterMs, 0, { min: 0 }) },
1995
- weight: resolveIntegerOption(options.weight, 1, { min: 1 })
1996
- };
1997
- }
1802
+ const laneSchedule = [
1803
+ "critical",
1804
+ "critical",
1805
+ "critical",
1806
+ "critical",
1807
+ "critical",
1808
+ "critical",
1809
+ "standard",
1810
+ "standard",
1811
+ "standard",
1812
+ "background"
1813
+ ];
1998
1814
  function createLaneQueues() {
1999
1815
  return {
2000
1816
  critical: [],
@@ -2006,7 +1822,7 @@ function countPending(bucket) {
2006
1822
  return requestPriorities.reduce((count, lane) => count + bucket.pending[lane].length, 0);
2007
1823
  }
2008
1824
  var RestScheduler = class {
2009
- constructor(options, executor) {
1825
+ constructor(executor) {
2010
1826
  this.executor = executor;
2011
1827
  this.activeWorkers = 0;
2012
1828
  this.buckets = /* @__PURE__ */ new Map();
@@ -2026,16 +1842,9 @@ var RestScheduler = class {
2026
1842
  this.queueGeneration = 0;
2027
1843
  this.queuedRequests = 0;
2028
1844
  this.routeBuckets = /* @__PURE__ */ new Map();
2029
- this.options = normalizeRestSchedulerOptions(options);
2030
- this.laneSchedule = this.buildLaneSchedule(this.options.lanes);
2031
1845
  }
2032
1846
  enqueue(params) {
2033
- if (this.queuedRequests >= this.options.maxQueueSize) throw new Error("Discord request queue is full");
2034
- const laneOptions = this.options.lanes[params.priority];
2035
- if (this.queuedByLane[params.priority] >= laneOptions.maxQueueSize) {
2036
- this.laneDropped[params.priority] += 1;
2037
- throw new Error(`Discord ${params.priority} request queue is full (${this.queuedByLane[params.priority]} / ${laneOptions.maxQueueSize})`);
2038
- }
1847
+ if (this.queuedRequests >= MAX_QUEUE_SIZE) throw new Error("Discord request queue is full");
2039
1848
  const routeKey = createRouteKey(params.method, params.path);
2040
1849
  const bucket = this.getBucket(this.routeBuckets.get(routeKey) ?? routeKey);
2041
1850
  return new Promise((resolve, reject) => {
@@ -2100,7 +1909,7 @@ var RestScheduler = class {
2100
1909
  droppedByLane: { ...this.laneDropped },
2101
1910
  oldestQueuedByLane: Object.fromEntries(requestPriorities.map((lane) => [lane, this.getOldestQueuedAge(lane)])),
2102
1911
  activeWorkers: this.activeWorkers,
2103
- maxConcurrentWorkers: this.options.maxConcurrency
1912
+ maxConcurrentWorkers: MAX_CONCURRENT_WORKERS
2104
1913
  };
2105
1914
  }
2106
1915
  getBucket(key) {
@@ -2124,19 +1933,6 @@ var RestScheduler = class {
2124
1933
  isBucketRateLimited(bucket, now = Date.now()) {
2125
1934
  return bucket.remaining === 0 && bucket.resetAt > now;
2126
1935
  }
2127
- pruneRouteMapping(routeKey) {
2128
- const bucketKey = this.routeBuckets.get(routeKey);
2129
- if (!bucketKey) return;
2130
- this.routeBuckets.delete(routeKey);
2131
- this.buckets.get(bucketKey)?.routeKeys.delete(routeKey);
2132
- }
2133
- pruneIdleRouteMappings(bucketKey, bucket, now = Date.now()) {
2134
- if (bucket.active > 0 || countPending(bucket) > 0 || this.isBucketRateLimited(bucket, now)) return;
2135
- for (const routeKey of Array.from(bucket.routeKeys)) if (this.routeBuckets.get(routeKey) === bucketKey) this.pruneRouteMapping(routeKey);
2136
- }
2137
- shouldPruneIdleBucket(key) {
2138
- return this.routeBuckets.get(key) !== key && !this.hasBucketReference(key);
2139
- }
2140
1936
  bindRouteToBucket(routeKey, bucketKey) {
2141
1937
  const target = this.getBucket(bucketKey);
2142
1938
  target.routeKeys.add(routeKey);
@@ -2205,7 +2001,7 @@ var RestScheduler = class {
2205
2001
  }
2206
2002
  drainQueues() {
2207
2003
  let nextDelayMs = Number.POSITIVE_INFINITY;
2208
- while (this.activeWorkers < this.options.maxConcurrency) {
2004
+ while (this.activeWorkers < MAX_CONCURRENT_WORKERS) {
2209
2005
  const next = this.takeNextQueuedRequest();
2210
2006
  if (!next.queued) {
2211
2007
  if (next.waitMs !== void 0) nextDelayMs = Math.min(nextDelayMs, next.waitMs);
@@ -2226,8 +2022,8 @@ var RestScheduler = class {
2226
2022
  let nextDelayMs;
2227
2023
  const buckets = Array.from(this.buckets.values()).filter((bucket) => countPending(bucket) > 0);
2228
2024
  if (buckets.length === 0) return {};
2229
- for (let laneOffset = 0; laneOffset < this.laneSchedule.length; laneOffset += 1) {
2230
- const lane = this.laneSchedule[(this.laneCursor + laneOffset) % this.laneSchedule.length];
2025
+ for (let laneOffset = 0; laneOffset < laneSchedule.length; laneOffset += 1) {
2026
+ const lane = laneSchedule[(this.laneCursor + laneOffset) % laneSchedule.length];
2231
2027
  if (!lane || this.queuedByLane[lane] <= 0) continue;
2232
2028
  for (const bucket of buckets) {
2233
2029
  const queue = bucket.pending[lane];
@@ -2242,7 +2038,7 @@ var RestScheduler = class {
2242
2038
  const queued = queue.shift();
2243
2039
  if (!queued) continue;
2244
2040
  this.queuedByLane[lane] = Math.max(0, this.queuedByLane[lane] - 1);
2245
- this.laneCursor = (this.laneCursor + laneOffset + 1) % this.laneSchedule.length;
2041
+ this.laneCursor = (this.laneCursor + laneOffset + 1) % laneSchedule.length;
2246
2042
  return {
2247
2043
  bucket,
2248
2044
  queued
@@ -2253,9 +2049,7 @@ var RestScheduler = class {
2253
2049
  }
2254
2050
  dropStaleHeadRequests(queue, lane, now) {
2255
2051
  if (lane !== "background") return;
2256
- const staleAfterMs = this.options.lanes[lane].staleAfterMs;
2257
- if (!staleAfterMs || staleAfterMs <= 0) return;
2258
- while (queue.length > 0 && now - (queue[0]?.enqueuedAt ?? now) > staleAfterMs) {
2052
+ while (queue.length > 0 && now - (queue[0]?.enqueuedAt ?? now) > BACKGROUND_STALE_AFTER_MS) {
2259
2053
  const stale = queue.shift();
2260
2054
  if (!stale) continue;
2261
2055
  this.queuedRequests = Math.max(0, this.queuedRequests - 1);
@@ -2268,8 +2062,11 @@ var RestScheduler = class {
2268
2062
  for (const [key, bucket] of this.buckets) {
2269
2063
  if (bucket.active !== 0 || countPending(bucket) > 0) continue;
2270
2064
  if (this.isBucketRateLimited(bucket, now)) continue;
2271
- this.pruneIdleRouteMappings(key, bucket, now);
2272
- if (this.shouldPruneIdleBucket(key)) this.buckets.delete(key);
2065
+ for (const routeKey of bucket.routeKeys) if (this.routeBuckets.get(routeKey) === key) {
2066
+ this.routeBuckets.delete(routeKey);
2067
+ bucket.routeKeys.delete(routeKey);
2068
+ }
2069
+ if (this.routeBuckets.get(key) !== key && !this.hasBucketReference(key)) this.buckets.delete(key);
2273
2070
  }
2274
2071
  }
2275
2072
  async runQueuedRequest(queued, bucket) {
@@ -2293,7 +2090,7 @@ var RestScheduler = class {
2293
2090
  }
2294
2091
  }
2295
2092
  requeueRateLimitedRequest(queued) {
2296
- if (queued.generation !== this.queueGeneration || queued.retryCount >= this.options.maxRateLimitRetries) return false;
2093
+ if (queued.generation !== this.queueGeneration || queued.retryCount >= MAX_RATE_LIMIT_RETRIES) return false;
2297
2094
  const bucketKey = this.routeBuckets.get(queued.routeKey) ?? queued.routeKey;
2298
2095
  this.getBucket(bucketKey).pending[queued.priority].push({
2299
2096
  ...queued,
@@ -2310,14 +2107,6 @@ var RestScheduler = class {
2310
2107
  this.queuedByLane[lane] = Math.max(0, this.queuedByLane[lane] - 1);
2311
2108
  }
2312
2109
  }
2313
- buildLaneSchedule(lanes) {
2314
- const schedule = [];
2315
- for (const lane of requestPriorities) {
2316
- const weight = lanes[lane].weight;
2317
- for (let i = 0; i < weight; i += 1) schedule.push(lane);
2318
- }
2319
- return schedule.length > 0 ? schedule : [...requestPriorities];
2320
- }
2321
2110
  getOldestQueuedAge(lane) {
2322
2111
  const now = Date.now();
2323
2112
  let oldest = 0;
@@ -2340,17 +2129,7 @@ const defaultOptions = {
2340
2129
  apiVersion: 10,
2341
2130
  userAgent: "OpenClaw Discord",
2342
2131
  timeout: 15e3,
2343
- queueRequests: true,
2344
- maxQueueSize: 1e3
2345
- };
2346
- const DEFAULT_MAX_CONCURRENT_WORKERS = 4;
2347
- const defaultLaneOptions = {
2348
- critical: { weight: 6 },
2349
- standard: { weight: 3 },
2350
- background: {
2351
- staleAfterMs: 2e4,
2352
- weight: 1
2353
- }
2132
+ queueRequests: true
2354
2133
  };
2355
2134
  const DISCORD_REST_RESPONSE_BODY_MAX_BYTES = 8388608;
2356
2135
  const GZIP_MAGIC = [31, 139];
@@ -2397,12 +2176,7 @@ var RequestClient = class {
2397
2176
  this.token = token.replace(/^Bot\s+/i, "");
2398
2177
  this.customFetch = resolvedOptions?.fetch;
2399
2178
  this.options = normalizeRequestClientOptions(resolvedOptions);
2400
- this.scheduler = new RestScheduler({
2401
- lanes: normalizeSchedulerLanes(this.options.maxQueueSize, this.options.scheduler?.lanes),
2402
- maxConcurrency: resolveIntegerOption(this.options.scheduler?.maxConcurrency, DEFAULT_MAX_CONCURRENT_WORKERS, { min: 1 }),
2403
- maxQueueSize: this.options.maxQueueSize,
2404
- maxRateLimitRetries: resolveIntegerOption(this.options.scheduler?.maxRateLimitRetries, 3, { min: 0 })
2405
- }, async (request) => await this.executeRequest(request.method, request.path, {
2179
+ this.scheduler = new RestScheduler(async (request) => await this.executeRequest(request.method, request.path, {
2406
2180
  data: request.data?.data,
2407
2181
  query: request.query
2408
2182
  }, request.routeKey, request.data?.assertCurrent));
@@ -2489,7 +2263,6 @@ var RequestClient = class {
2489
2263
  if (!response.ok) throw new DiscordError(response, parsed);
2490
2264
  return parsed;
2491
2265
  } catch (error) {
2492
- if (error instanceof DOMException && error.name === "AbortError") throw error;
2493
2266
  if (error instanceof Error) throw error;
2494
2267
  throw new Error(`Discord request failed: ${inspect(error)}`, { cause: error });
2495
2268
  } finally {
@@ -2522,25 +2295,7 @@ function normalizeRequestClientOptions(options) {
2522
2295
  ...merged,
2523
2296
  apiBaseUrl: options?.apiBaseUrl ?? `${options?.baseUrl ?? defaultOptions.baseUrl}/v${apiVersion}`,
2524
2297
  apiVersion,
2525
- timeout: clampTimerTimeoutMs(merged.timeout, 1) ?? resolveTimerTimeoutMs(defaultOptions.timeout, 1),
2526
- maxQueueSize: resolveIntegerOption(merged.maxQueueSize, defaultOptions.maxQueueSize, { min: 1 })
2527
- };
2528
- }
2529
- function normalizeSchedulerLanes(maxQueueSize, lanes) {
2530
- const fallbackMaxQueueSize = resolveIntegerOption(maxQueueSize, defaultOptions.maxQueueSize, { min: 1 });
2531
- return {
2532
- critical: normalizeSchedulerLane("critical", fallbackMaxQueueSize, lanes?.critical),
2533
- standard: normalizeSchedulerLane("standard", fallbackMaxQueueSize, lanes?.standard),
2534
- background: normalizeSchedulerLane("background", fallbackMaxQueueSize, lanes?.background)
2535
- };
2536
- }
2537
- function normalizeSchedulerLane(lane, maxQueueSize, options) {
2538
- const defaults = defaultLaneOptions[lane];
2539
- const staleAfterMs = options?.staleAfterMs !== void 0 ? resolveIntegerOption(options.staleAfterMs, defaults.staleAfterMs ?? 0, { min: 0 }) : defaults.staleAfterMs;
2540
- return {
2541
- maxQueueSize: options?.maxQueueSize !== void 0 ? resolveIntegerOption(options.maxQueueSize, maxQueueSize, { min: 1 }) : maxQueueSize,
2542
- ...staleAfterMs !== void 0 ? { staleAfterMs } : {},
2543
- weight: options?.weight !== void 0 ? resolveIntegerOption(options.weight, defaults.weight, { min: 1 }) : defaults.weight
2298
+ timeout: clampTimerTimeoutMs(merged.timeout, 1) ?? resolveTimerTimeoutMs(defaultOptions.timeout, 1)
2544
2299
  };
2545
2300
  }
2546
2301
  function getRequestPriority(method, path) {
@@ -2572,7 +2327,6 @@ var Client = class {
2572
2327
  this.commandDeployer = new DiscordCommandDeployer({
2573
2328
  clientId: this.options.clientId,
2574
2329
  commands: this.commands,
2575
- devGuilds: this.options.devGuilds,
2576
2330
  hashStore: this.options.commandDeployHashStore,
2577
2331
  rest: () => this.rest
2578
2332
  });
@@ -2587,16 +2341,6 @@ var Client = class {
2587
2341
  getPlugin(id) {
2588
2342
  return this.plugins.find((plugin) => plugin.id === id);
2589
2343
  }
2590
- registerListener(listener) {
2591
- if (!this.listeners.includes(listener)) this.listeners.push(listener);
2592
- return listener;
2593
- }
2594
- unregisterListener(listener) {
2595
- const index = this.listeners.indexOf(listener);
2596
- if (index < 0) return false;
2597
- this.listeners.splice(index, 1);
2598
- return true;
2599
- }
2600
2344
  getRuntimeMetrics() {
2601
2345
  return {
2602
2346
  request: this.rest.getSchedulerMetrics(),
@@ -2618,8 +2362,8 @@ var Client = class {
2618
2362
  async fetchGuildEmojis(guildId, fetcher) {
2619
2363
  return await this.entityCache.fetchGuildEmojis(guildId, fetcher);
2620
2364
  }
2621
- async deployCommands(options = {}) {
2622
- return await this.commandDeployer.deploy(options);
2365
+ async deployCommands() {
2366
+ return await this.commandDeployer.deploy();
2623
2367
  }
2624
2368
  async handleInteraction(rawData) {
2625
2369
  await dispatchInteraction(this, rawData);
@@ -2775,25 +2519,15 @@ var discord_exports = /* @__PURE__ */ __exportAll({
2775
2519
  UserSelectMenu: () => UserSelectMenu,
2776
2520
  UserSelectMenuInteraction: () => UserSelectMenuInteraction,
2777
2521
  VoiceStateUpdateListener: () => VoiceStateUpdateListener,
2778
- addGuildMemberRole: () => addGuildMemberRole,
2779
2522
  channelFactory: () => channelFactory,
2780
- createChannelMessage: () => createChannelMessage,
2781
2523
  createChannelWebhook: () => createChannelWebhook,
2782
- createGuildBan: () => createGuildBan,
2783
- createGuildChannel: () => createGuildChannel,
2784
- createGuildEmoji: () => createGuildEmoji,
2785
- createGuildScheduledEvent: () => createGuildScheduledEvent,
2786
- createGuildSticker: () => createGuildSticker,
2787
2524
  createInteraction: () => createInteraction,
2788
2525
  createOwnMessageReaction: () => createOwnMessageReaction,
2789
2526
  createThread: () => createThread,
2790
2527
  createUserDmChannel: () => createUserDmChannel,
2791
2528
  deferCommandInteractionIfNeeded: () => deferCommandInteractionIfNeeded,
2792
- deleteChannel: () => deleteChannel,
2793
2529
  deleteChannelMessage: () => deleteChannelMessage,
2794
- deleteChannelPermission: () => deleteChannelPermission,
2795
2530
  deleteOwnMessageReaction: () => deleteOwnMessageReaction,
2796
- editChannel: () => editChannel,
2797
2531
  editChannelMessage: () => editChannelMessage,
2798
2532
  getChannel: () => getChannel,
2799
2533
  getChannelMessage: () => getChannelMessage,
@@ -2805,30 +2539,16 @@ var discord_exports = /* @__PURE__ */ __exportAll({
2805
2539
  getUser: () => getUser,
2806
2540
  hasDiscordV2Components: () => hasDiscordV2Components,
2807
2541
  isUnknownDiscordVoiceStateError: () => isUnknownDiscordVoiceStateError,
2808
- listChannelArchivedThreads: () => listChannelArchivedThreads,
2809
- listChannelMessages: () => listChannelMessages,
2810
- listChannelPins: () => listChannelPins,
2811
- listGuildActiveThreads: () => listGuildActiveThreads,
2812
- listGuildChannels: () => listGuildChannels,
2813
2542
  listGuildEmojis: () => listGuildEmojis,
2814
- listGuildRoles: () => listGuildRoles,
2815
- listGuildScheduledEvents: () => listGuildScheduledEvents,
2816
2543
  listMessageReactionUsers: () => listMessageReactionUsers,
2817
- moveGuildChannels: () => moveGuildChannels,
2818
2544
  normalizeDiscordMessageId: () => normalizeDiscordMessageId,
2819
2545
  parseCustomId: () => parseCustomId,
2820
2546
  pinChannelMessage: () => pinChannelMessage,
2821
- putChannelPermission: () => putChannelPermission,
2822
- removeGuildMember: () => removeGuildMember,
2823
- removeGuildMemberRole: () => removeGuildMemberRole,
2824
2547
  resolveFocusedCommandOptionAutocompleteHandler: () => resolveFocusedCommandOptionAutocompleteHandler,
2825
- searchGuildMessages: () => searchGuildMessages,
2826
- sendChannelTyping: () => sendChannelTyping,
2827
2548
  serializePayload: () => serializePayload,
2828
- timeoutGuildMember: () => timeoutGuildMember,
2829
2549
  unpinChannelMessage: () => unpinChannelMessage
2830
2550
  });
2831
2551
  import * as import_discord_api_types_v10 from "discord-api-types/v10";
2832
2552
  __reExport(discord_exports, import_discord_api_types_v10);
2833
2553
  //#endregion
2834
- export { BaseMessageInteractiveComponent as $, serializePayload as A, deleteChannelPermission as At, Container as B, putChannelPermission as Bt, withDiscordRequestAuthority as C, unpinChannelMessage as Ct, Message as D, createGuildEmoji as Dt, Guild as E, createGuildChannel as Et, RadioGroup as F, listGuildChannels as Ft, RoleSelectMenu as G, LinkButton as H, removeGuildMemberRole as Ht, TextInput as I, listGuildEmojis as It, Separator as J, Row as K, AnySelectMenu as L, listGuildRoles as Lt, CheckboxGroup as M, getGuildMember as Mt, Label as N, getGuildVoiceState as Nt, User as O, createGuildScheduledEvent as Ot, Modal as P, listGuildActiveThreads as Pt, UserSelectMenu as Q, Button as R, listGuildScheduledEvents as Rt, readRetryAfter as S, sendChannelTyping as St, CommandWithSubcommands as T, createGuildBan as Tt, MediaGallery as U, timeoutGuildMember as Ut, File as V, removeGuildMember as Vt, MentionableSelectMenu as W, TextDisplay as X, StringSelectMenu as Y, Thumbnail as Z, DiscordError as _, listChannelArchivedThreads as _t, MessageCreateListener as a, createOwnMessageReaction as at, readDiscordCode as b, pinChannelMessage as bt, PresenceUpdateListener as c, createChannelMessage as ct, ThreadDeleteListener as d, deleteChannelMessage as dt, parseCustomId as et, ThreadUpdateListener as f, editChannel as ft, RequestClient as g, getThreadMember as gt, Plugin as h, getChannelMessage as ht, InteractionCreateListener as i, getCurrentUser as it, Embed as j, getGuild as jt, hasDiscordV2Components as k, createGuildSticker as kt, ReadyListener as l, createThread as lt, Client as m, getChannel as mt, GuildCreateListener as n, createChannelWebhook as nt, MessageReactionAddListener as o, deleteOwnMessageReaction as ot, VoiceStateUpdateListener as p, editChannelMessage as pt, Section as q, GuildDeleteListener as r, createUserDmChannel as rt, MessageReactionRemoveListener as s, listMessageReactionUsers as st, discord_exports as t, stripUndefinedFields as tt, ResumedListener as u, deleteChannel as ut, RateLimitError as v, listChannelMessages as vt, Command as w, addGuildMemberRole as wt, readDiscordMessage as x, searchGuildMessages as xt, isUnknownDiscordVoiceStateError as y, listChannelPins as yt, ChannelSelectMenu as z, moveGuildChannels as zt };
2554
+ export { BaseMessageInteractiveComponent as $, serializePayload as A, Container as B, withDiscordRequestAuthority as C, Message as D, Guild as E, RadioGroup as F, RoleSelectMenu as G, LinkButton as H, TextInput as I, Separator as J, Row as K, AnySelectMenu as L, CheckboxGroup as M, Label as N, User as O, Modal as P, UserSelectMenu as Q, Button as R, readRetryAfter as S, CommandWithSubcommands as T, MediaGallery as U, File as V, MentionableSelectMenu as W, TextDisplay as X, StringSelectMenu as Y, Thumbnail as Z, DiscordError as _, getGuildMember as _t, MessageCreateListener as a, createOwnMessageReaction as at, readDiscordCode as b, PresenceUpdateListener as c, createThread as ct, ThreadDeleteListener as d, getChannel as dt, parseCustomId as et, ThreadUpdateListener as f, getChannelMessage as ft, RequestClient as g, getGuild as gt, Plugin as h, unpinChannelMessage as ht, InteractionCreateListener as i, getCurrentUser as it, Embed as j, hasDiscordV2Components as k, ReadyListener as l, deleteChannelMessage as lt, Client as m, pinChannelMessage as mt, GuildCreateListener as n, createChannelWebhook as nt, MessageReactionAddListener as o, deleteOwnMessageReaction as ot, VoiceStateUpdateListener as p, getThreadMember as pt, Section as q, GuildDeleteListener as r, createUserDmChannel as rt, MessageReactionRemoveListener as s, listMessageReactionUsers as st, discord_exports as t, stripUndefinedFields as tt, ResumedListener as u, editChannelMessage as ut, RateLimitError as v, getGuildVoiceState as vt, Command as w, readDiscordMessage as x, isUnknownDiscordVoiceStateError as y, listGuildEmojis as yt, ChannelSelectMenu as z };