@openclaw/discord 2026.9.1-beta.1 → 2026.9.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 (165) hide show
  1. package/dist/account-inspect-BY-ve3yH.js +45 -0
  2. package/dist/account-inspect-api.js +1 -1
  3. package/dist/{accounts-CfQ-vSyf.js → accounts-CwJQoLjM.js} +89 -45
  4. package/dist/action-runtime-api.js +1 -1
  5. package/dist/{activities-api-q-9PaaHH.js → activities-api-CTcGq3Hf.js} +30 -17
  6. package/dist/activities-api.js +1 -1
  7. package/dist/{allow-list-BDMimASD.js → allow-list-DBTtR2dz.js} +13 -35
  8. package/dist/{api-DNVbJyEy.js → api-BfmEP6wp.js} +6 -5
  9. package/dist/api.js +18 -18
  10. package/dist/{approval-handler.runtime-B7qhK3fR.js → approval-handler.runtime-DUSe5fyH.js} +19 -12
  11. package/dist/{audit-CBEv_ERu.js → audit-DpPfwoJM.js} +8 -7
  12. package/dist/{channel-Dx1tMTfx.js → channel-BHajPgwR.js} +29 -23
  13. package/dist/{channel-actions.runtime-CLWWu9nC.js → channel-actions.runtime-DS8pXo0S.js} +38 -38
  14. package/dist/channel-config-api.js +1 -1
  15. package/dist/channel-plugin-api.js +1 -1
  16. package/dist/{channel.setup-DOzXS2Pk.js → channel.setup-BWmMe1tT.js} +18 -18
  17. package/dist/command-owners-D78sAoOz.js +10 -0
  18. package/dist/{components-B9V5o361.js → components-BimX47Mq.js} +111 -149
  19. package/dist/{config-schema-BR13IAx6.js → config-schema-B797-Spt.js} +19 -12
  20. package/dist/{conversation-binding-route-DJYrY2TQ.js → conversation-binding-route-DuR5NGIx.js} +1 -1
  21. package/dist/{directory-config-BK6eqekJ.js → directory-config-CD2v2Szs.js} +2 -2
  22. package/dist/directory-contract-api.js +1 -1
  23. package/dist/{directory-live-DSAJSrJk.js → directory-live-DaJzWJ2N.js} +4 -4
  24. package/dist/{doctor-Cm7Y1pJ2.js → doctor-D4HH1inA.js} +9 -6
  25. package/dist/{doctor-contract-DsWvKIXF.js → doctor-contract-Co5vRCZ6.js} +9 -6
  26. package/dist/doctor-contract-api.js +31 -28
  27. package/dist/{handle-action.guild-admin-BdwCRHmm.js → handle-action.guild-admin-4We6wWQU.js} +6 -3
  28. package/dist/index.js +1 -1
  29. package/dist/ingress-identity-XNmW-mZS.js +60 -0
  30. package/dist/{message-handler-BXpWZyni.js → message-handler-DhgBabyU.js} +61 -70
  31. package/dist/{message-handler.preflight-Ba5LAY_X.js → message-handler.preflight-oZ7dQCd0.js} +41 -101
  32. package/dist/{message-handler.process-3HEzmemS.js → message-handler.process-BzCYf1pa.js} +82 -108
  33. package/dist/{message-text-aiwO5R2F.js → message-text-DK4NnBg-.js} +11 -6
  34. package/dist/{outbound-adapter-BE4jSq2d.js → outbound-adapter-CtggmGh9.js} +52 -67
  35. package/dist/{outbound-components-oLpg8Qzb.js → outbound-components-Dn8SJWMS.js} +5 -4
  36. package/dist/{outbound-session-route-Cg15ZFJd.js → outbound-session-route-Q_HEusBQ.js} +57 -15
  37. package/dist/{owner-access-UlYi9t0M.js → owner-access-Cp8r6Ipf.js} +9 -7
  38. package/dist/{pluralkit-Tiyl70dx.js → pluralkit-BY75YcK0.js} +2 -2
  39. package/dist/{probe-n6ZXxK8V.js → probe-3ovFAp3b.js} +3 -3
  40. package/dist/{probe.runtime-CN4bdPfZ.js → probe.runtime-BckHn3cJ.js} +1 -1
  41. package/dist/{provider-session.runtime-B9xe-Qaf.js → provider-session.runtime-BL2lHBH7.js} +3 -3
  42. package/dist/{provider-B11xwilq.js → provider-uKmmrDM4.js} +299 -136
  43. package/dist/provider.runtime-C-IkWF2w.js +2 -0
  44. package/dist/{realtime-session.runtime-CU8IQUS-.js → realtime-session.runtime-CGYm1t_0.js} +798 -448
  45. package/dist/{resolve-allowlist-common-BLoYaxEG.js → resolve-allowlist-common-sKIKy-cF.js} +3 -3
  46. package/dist/{resolve-channels-C2sT_n67.js → resolve-channels-CoiMlWy0.js} +4 -4
  47. package/dist/{resolve-users-CzpjLwjy.js → resolve-users-DJpiokfW.js} +5 -4
  48. package/dist/{retry-Cv4jCU5Z.js → retry-DQt1zDgH.js} +356 -214
  49. package/dist/{retry-after-DdLPmPoa.js → retry-after-BrLjLUJi.js} +2 -1
  50. package/dist/{runtime-CY4PRMF-.js → runtime-BHsdEdr5.js} +2 -2
  51. package/dist/{runtime-BHrTlFkf.js → runtime-Ghtfh5ZA.js} +151 -109
  52. package/dist/runtime-api.js +20 -20
  53. package/dist/{secret-config-contract-B3i6WxV5.js → secret-config-contract-DFu9hfU8.js} +14 -6
  54. package/dist/secret-contract-api.js +1 -1
  55. package/dist/{security-audit-BfJhAXZp.js → security-audit-DKfK-iPY.js} +10 -11
  56. package/dist/security-audit-contract-api.js +1 -1
  57. package/dist/{security-audit.runtime-BVKF9VtY.js → security-audit.runtime-sKZyKgpx.js} +1 -1
  58. package/dist/{send-C49MFF9j.js → send-CZeWKUiA.js} +132 -100
  59. package/dist/{send.components-DKKAw5VX.js → send.components-BG5IDABj.js} +21 -15
  60. package/dist/{send.outbound-zam0TrZx.js → send.outbound-DHuFUL6W.js} +42 -63
  61. package/dist/{send.shared-JjljcV4O.js → send.shared-B0n_fWzu.js} +77 -149
  62. package/dist/{sender-identity-BJtfyise.js → sender-identity-B8Ncfi63.js} +1 -1
  63. package/dist/setup-plugin-api.js +1 -1
  64. package/dist/{shared-_5EcP4jW.js → shared-C3dKun_X.js} +24 -15
  65. package/dist/{subagent-hooks-DQzvOptn.js → subagent-hooks-ZoQXEI1E.js} +2 -2
  66. package/dist/subagent-hooks-api.js +1 -1
  67. package/dist/{system-events-C7yxaHWP.js → system-events-DFF_awl7.js} +2 -2
  68. package/dist/{target-resolver-vxIh6O3-.js → target-resolver-DLtHDwMK.js} +6 -5
  69. package/dist/targets-BObRyaKX.js +3 -0
  70. package/dist/{thread-bindings-DW5F9vat.js → thread-bindings-DKvsNjQR.js} +7 -6
  71. package/dist/{thread-bindings.manager-ByOtwjo_.js → thread-bindings.manager-pbbRT5gb.js} +38 -29
  72. package/dist/{thread-bindings.session-updates-CJb-BpPL.js → thread-bindings.session-updates-t6jeFB1-.js} +3 -2
  73. package/dist/{thread-bindings.state-D8OMdk4O.js → thread-bindings.state-DtgOqsbX.js} +34 -1
  74. package/dist/{threading-agH1T_6s.js → threading-BCx49X-6.js} +8 -6
  75. package/dist/{timeouts-B9cy6RvQ.js → timeouts-D86uWLt_.js} +1 -1
  76. package/dist/{transcripts-source-BR11iHA4.js → transcripts-source-Dc6Nnli5.js} +55 -7
  77. package/dist/transcripts-source-api.js +1 -1
  78. package/dist/{typing-Dc_YMY2e.js → typing-CuopV-Hi.js} +2 -2
  79. package/dist/{voice-runtime-DIeaa8fJ.js → voice-runtime-BQnILUbG.js} +492 -105
  80. package/node_modules/@discord/embedded-app-sdk/node_modules/@types/lodash/README.md +1 -1
  81. package/node_modules/@discord/embedded-app-sdk/node_modules/@types/lodash/conforms.d.ts +2 -0
  82. package/node_modules/@discord/embedded-app-sdk/node_modules/@types/lodash/package.json +3 -3
  83. package/node_modules/@discord/embedded-app-sdk/node_modules/@types/lodash/stubArray.d.ts +2 -0
  84. package/node_modules/@discord/embedded-app-sdk/node_modules/@types/lodash/stubObject.d.ts +2 -0
  85. package/node_modules/@discord/embedded-app-sdk/node_modules/@types/lodash/stubString.d.ts +2 -0
  86. package/node_modules/@discordjs/voice/node_modules/@types/node/README.md +1 -1
  87. package/node_modules/@discordjs/voice/node_modules/@types/node/buffer.buffer.d.ts +5 -5
  88. package/node_modules/@discordjs/voice/node_modules/@types/node/crypto.d.ts +2 -2
  89. package/node_modules/@discordjs/voice/node_modules/@types/node/http.d.ts +16 -0
  90. package/node_modules/@discordjs/voice/node_modules/@types/node/http2.d.ts +10 -2
  91. package/node_modules/@discordjs/voice/node_modules/@types/node/package.json +2 -2
  92. package/node_modules/@discordjs/voice/node_modules/@types/node/process.d.ts +52 -0
  93. package/node_modules/@discordjs/voice/node_modules/@types/node/quic.d.ts +210 -28
  94. package/node_modules/@discordjs/voice/node_modules/@types/node/sqlite.d.ts +6 -2
  95. package/node_modules/@discordjs/voice/node_modules/@types/node/test.d.ts +36 -0
  96. package/node_modules/typebox/build/format/email.mjs +1 -1
  97. package/node_modules/typebox/build/format/idna/idn-hostname.mjs +19 -1
  98. package/node_modules/typebox/build/format/json_pointer.d.mts +2 -2
  99. package/node_modules/typebox/build/format/json_pointer.mjs +2 -2
  100. package/node_modules/typebox/build/format/json_pointer_uri_fragment.d.mts +2 -2
  101. package/node_modules/typebox/build/format/json_pointer_uri_fragment.mjs +2 -2
  102. package/node_modules/typebox/build/format/relative_json_pointer.d.mts +2 -2
  103. package/node_modules/typebox/build/format/relative_json_pointer.mjs +2 -2
  104. package/node_modules/typebox/build/system/memory/assign.mjs +2 -1
  105. package/node_modules/typebox/build/system/memory/create.mjs +3 -4
  106. package/node_modules/typebox/build/system/memory/discard.mjs +2 -2
  107. package/node_modules/typebox/build/system/memory/freeze.d.mts +4 -0
  108. package/node_modules/typebox/build/system/memory/freeze.mjs +6 -0
  109. package/node_modules/typebox/build/system/memory/update.mjs +3 -2
  110. package/node_modules/typebox/package.json +1 -1
  111. package/node_modules/undici/docs/docs/api/Client.md +4 -0
  112. package/node_modules/undici/docs/docs/api/EnvHttpProxyAgent.md +3 -2
  113. package/node_modules/undici/docs/docs/api/EventSource.md +4 -0
  114. package/node_modules/undici/docs/docs/api/Interceptors.md +7 -3
  115. package/node_modules/undici/docs/docs/api/Socks5ProxyAgent.md +7 -1
  116. package/node_modules/undici/lib/cache/memory-cache-store.js +2 -2
  117. package/node_modules/undici/lib/core/symbols.js +2 -0
  118. package/node_modules/undici/lib/dispatcher/agent.js +7 -2
  119. package/node_modules/undici/lib/dispatcher/balanced-pool.js +7 -4
  120. package/node_modules/undici/lib/dispatcher/client-h1.js +12 -4
  121. package/node_modules/undici/lib/dispatcher/client-h2.js +43 -3
  122. package/node_modules/undici/lib/dispatcher/client.js +3 -2
  123. package/node_modules/undici/lib/dispatcher/dispatcher-base.js +13 -1
  124. package/node_modules/undici/lib/dispatcher/dispatcher.js +15 -1
  125. package/node_modules/undici/lib/dispatcher/dispatcher1-wrapper.js +3 -0
  126. package/node_modules/undici/lib/dispatcher/env-http-proxy-agent.js +10 -3
  127. package/node_modules/undici/lib/dispatcher/proxy-agent.js +18 -1
  128. package/node_modules/undici/lib/dispatcher/retry-agent.js +3 -0
  129. package/node_modules/undici/lib/dispatcher/round-robin-pool.js +1 -1
  130. package/node_modules/undici/lib/dispatcher/socks5-proxy-agent.js +91 -21
  131. package/node_modules/undici/lib/handler/cache-handler.js +29 -5
  132. package/node_modules/undici/lib/handler/decorator-handler.js +7 -1
  133. package/node_modules/undici/lib/handler/deduplication-handler.js +12 -6
  134. package/node_modules/undici/lib/handler/redirect-handler.js +21 -4
  135. package/node_modules/undici/lib/handler/retry-handler.js +148 -30
  136. package/node_modules/undici/lib/interceptor/cache.js +65 -12
  137. package/node_modules/undici/lib/interceptor/decompress.js +115 -13
  138. package/node_modules/undici/lib/interceptor/deduplicate.js +5 -4
  139. package/node_modules/undici/lib/interceptor/dns.js +7 -0
  140. package/node_modules/undici/lib/interceptor/dump.js +10 -23
  141. package/node_modules/undici/lib/mock/mock-agent.js +13 -1
  142. package/node_modules/undici/lib/mock/mock-utils.js +11 -10
  143. package/node_modules/undici/lib/util/cache.js +45 -3
  144. package/node_modules/undici/lib/web/cookies/parse.js +150 -147
  145. package/node_modules/undici/lib/web/eventsource/eventsource-stream.js +28 -1
  146. package/node_modules/undici/lib/web/eventsource/eventsource.js +13 -3
  147. package/node_modules/undici/lib/web/fetch/index.js +6 -0
  148. package/node_modules/undici/lib/web/fetch/request.js +2 -3
  149. package/node_modules/undici/lib/web/fetch/util.js +6 -1
  150. package/node_modules/undici/lib/web/webidl/index.js +3 -3
  151. package/node_modules/undici/lib/web/websocket/connection.js +1 -1
  152. package/node_modules/undici/lib/web/websocket/permessage-deflate.js +5 -0
  153. package/node_modules/undici/lib/web/websocket/stream/websocketstream.js +8 -10
  154. package/node_modules/undici/package.json +3 -3
  155. package/node_modules/undici/types/client.d.ts +10 -0
  156. package/node_modules/undici/types/interceptors.d.ts +2 -0
  157. package/node_modules/undici/types/mock-agent.d.ts +11 -10
  158. package/node_modules/undici/types/socks5-proxy-agent.d.ts +2 -0
  159. package/openclaw.plugin.json +15 -8
  160. package/package.json +7 -6
  161. package/skills/discord/SKILL.md +1 -1
  162. package/dist/account-inspect-BDfKyuvL.js +0 -89
  163. package/dist/provider.runtime-DiYaHvOz.js +0 -2
  164. package/dist/sdk-runtime-4geQHtXc.js +0 -338
  165. package/dist/targets-CtTKvntJ.js +0 -3
@@ -1,4 +1,4 @@
1
- import { t as parseDiscordRetryAfterBodySeconds } from "./retry-after-DdLPmPoa.js";
1
+ import { t as parseDiscordRetryAfterBodySeconds } from "./retry-after-BrLjLUJi.js";
2
2
  import "node:module";
3
3
  import { redactIdentifier, redactSensitiveFieldValue } from "openclaw/plugin-sdk/logging-core";
4
4
  import { ApplicationCommandOptionType, ApplicationCommandType, ButtonStyle, ComponentType, GatewayDispatchEvents, InteractionContextType, InteractionResponseType, InteractionType, MessageFlags, Routes, TextInputStyle } from "discord-api-types/v10";
@@ -15,8 +15,8 @@ import { classifyTransientNetworkErrorCode, createChannelApiRetryRunner, parseRe
15
15
  import { buildMessagingTarget, parseMentionPrefixOrAtUserTarget, requireTargetKind } from "openclaw/plugin-sdk/channel-targets";
16
16
  import { sleepWithAbort } from "openclaw/plugin-sdk/runtime-env";
17
17
  import { resolveAllowlistMatchByCandidates } from "openclaw/plugin-sdk/allow-from";
18
- import { chunkMarkdownTextWithMode } from "openclaw/plugin-sdk/reply-chunking";
19
- import { chunkTextForOutbound } from "openclaw/plugin-sdk/text-chunking";
18
+ import { chunkByParagraph } from "openclaw/plugin-sdk/reply-chunking";
19
+ import { avoidTrailingHighSurrogateBreak, chunkTextForOutbound, findCodeRegions } from "openclaw/plugin-sdk/text-chunking";
20
20
  import { isSingleUseReplyToMode } from "openclaw/plugin-sdk/reply-reference";
21
21
  import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-outbound";
22
22
  import { attachChannelToResults } from "openclaw/plugin-sdk/channel-send-result";
@@ -1676,6 +1676,7 @@ var BaseInteraction = class {
1676
1676
  this.message = null;
1677
1677
  this.response = new InteractionResponseController();
1678
1678
  this.pendingResponse = Promise.resolve();
1679
+ this.sentFollowUp = false;
1679
1680
  this.id = rawData.id;
1680
1681
  this.token = rawData.token;
1681
1682
  this.user = readInteractionUser(rawData, client);
@@ -1692,6 +1693,14 @@ var BaseInteraction = class {
1692
1693
  set responseState(nextState) {
1693
1694
  this.response.state = nextState;
1694
1695
  }
1696
+ /**
1697
+ * True once a follow-up message has been delivered. Follow-ups are visible to
1698
+ * the user but never advance `responseState`, so this is the only record that
1699
+ * the interaction has already produced output.
1700
+ */
1701
+ get hasSentFollowUp() {
1702
+ return this.sentFollowUp;
1703
+ }
1695
1704
  enqueueResponse(operation) {
1696
1705
  const result = this.pendingResponse.then(operation);
1697
1706
  this.pendingResponse = result.then(() => void 0, () => void 0);
@@ -1726,6 +1735,24 @@ var BaseInteraction = class {
1726
1735
  async editReply(payload) {
1727
1736
  return await this.enqueueResponse(() => this.performReplyEdit(payload));
1728
1737
  }
1738
+ /**
1739
+ * Edits the deferred placeholder only if this interaction is still an
1740
+ * unanswered spinner when the queue reaches this operation.
1741
+ *
1742
+ * Both conditions are re-read inside the queue. A follow-up that was still in
1743
+ * flight when the caller decided to report will have settled — and recorded
1744
+ * itself in `sentFollowUp` — by the time this runs, so the decision cannot be
1745
+ * made against state that is about to change.
1746
+ *
1747
+ * Resolves true when the edit was sent.
1748
+ */
1749
+ async editDeferredPlaceholderIfUnanswered(payload) {
1750
+ return await this.enqueueResponse(async () => {
1751
+ if (this.responseState !== "deferred" || this.sentFollowUp) return false;
1752
+ await this.performReplyEdit(payload);
1753
+ return true;
1754
+ });
1755
+ }
1729
1756
  async performReplyEdit(payload) {
1730
1757
  const body = serializePayload(payload);
1731
1758
  const query = needsComponentsV2Query(body) ? { with_components: true } : void 0;
@@ -1755,7 +1782,9 @@ var BaseInteraction = class {
1755
1782
  }
1756
1783
  async performFollowUp(payload) {
1757
1784
  const body = serializePayload(payload);
1758
- return await createWebhookMessage(this.client.rest, this.client.options.clientId, this.token, { body }, needsComponentsV2Query(body) ? { with_components: true } : void 0);
1785
+ const result = await createWebhookMessage(this.client.rest, this.client.options.clientId, this.token, { body }, needsComponentsV2Query(body) ? { with_components: true } : void 0);
1786
+ this.sentFollowUp = true;
1787
+ return result;
1759
1788
  }
1760
1789
  };
1761
1790
  var CommandInteraction = class extends BaseInteraction {
@@ -1844,6 +1873,14 @@ async function dispatchInteraction(client, rawData) {
1844
1873
  if (command.commandKind === "leaf") await command.autocomplete(autocompleteInteraction);
1845
1874
  return;
1846
1875
  }
1876
+ try {
1877
+ await dispatchAcknowledgeableInteraction(client, rawData, interaction);
1878
+ } catch (error) {
1879
+ await reportInteractionFailure(interaction);
1880
+ throw error;
1881
+ }
1882
+ }
1883
+ async function dispatchAcknowledgeableInteraction(client, rawData, interaction) {
1847
1884
  if (rawData.type === InteractionType.ApplicationCommand) {
1848
1885
  const command = client.commands.find((entry) => entry.name === readInteractionName(rawData));
1849
1886
  if (command) {
@@ -1879,6 +1916,44 @@ async function dispatchInteraction(client, rawData) {
1879
1916
  if (modal) await modal.run(interaction, modal.customIdParser(customId).data);
1880
1917
  }
1881
1918
  }
1919
+ /**
1920
+ * Fixed text. The thrown error is deliberately not echoed here: an interaction
1921
+ * response is visible to the whole channel, and handler exceptions routinely
1922
+ * carry absolute paths, config keys, and provider responses. The rethrow keeps
1923
+ * the detail in the Gateway log where operators already look for it.
1924
+ */
1925
+ const INTERACTION_FAILURE_NOTICE = "Command failed. Check the Gateway logs for details.";
1926
+ /**
1927
+ * Best-effort user-visible notice for a failed interaction. Never throws: a
1928
+ * reporting failure must not mask the original error.
1929
+ *
1930
+ * Deliberately narrow. It reports only for `deferred`, where a spinner is known
1931
+ * to exist and the original response is a placeholder this dispatch created:
1932
+ *
1933
+ * - `deferred` the deferring callback succeeded (state advances only
1934
+ * after a REST success), so editing the original response
1935
+ * resolves a spinner that would otherwise hang forever.
1936
+ * - `deferred-update` a component acknowledgement. Discord leaves no spinner,
1937
+ * and the original response is the message the component is
1938
+ * attached to, so editing it would overwrite content the
1939
+ * user is still reading.
1940
+ * - `unacknowledged` nothing is known to have reached Discord. A second
1941
+ * initial callback risks "already acknowledged" if the
1942
+ * first one landed after all, and Discord already shows its
1943
+ * own "did not respond" notice.
1944
+ * - `replied` the user has seen a message, and nextReplyAction() would
1945
+ * turn this into a contradictory follow-up beside it.
1946
+ */
1947
+ async function reportInteractionFailure(interaction) {
1948
+ if (interaction.responseState !== "deferred") return;
1949
+ if (interaction.hasSentFollowUp) return;
1950
+ try {
1951
+ await interaction.editDeferredPlaceholderIfUnanswered({
1952
+ content: INTERACTION_FAILURE_NOTICE,
1953
+ allowed_mentions: { parse: [] }
1954
+ });
1955
+ } catch {}
1956
+ }
1882
1957
  function resolveConditionalComponentOption(value, interaction) {
1883
1958
  return typeof value === "function" ? value(interaction) : value;
1884
1959
  }
@@ -2054,7 +2129,8 @@ function redactDiscordErrorBody(body, fieldKey = "", sensitiveAncestorKey, state
2054
2129
  return redacted;
2055
2130
  }
2056
2131
  function readDiscordCode(body) {
2057
- return parseStrictNonNegativeInteger(body && typeof body === "object" && "code" in body ? body.code : void 0);
2132
+ const value = body && typeof body === "object" && "code" in body ? body.code : void 0;
2133
+ return parseStrictNonNegativeInteger(value);
2058
2134
  }
2059
2135
  function readDiscordMessage(body, fallback) {
2060
2136
  const value = body && typeof body === "object" && "message" in body ? body.message : void 0;
@@ -2064,7 +2140,8 @@ function isUnknownDiscordVoiceStateError(err) {
2064
2140
  return (err && typeof err === "object" && "discordCode" in err ? parseStrictNonNegativeInteger(err.discordCode) : void 0) === DISCORD_UNKNOWN_VOICE_STATE || /unknown voice state/i.test(formatErrorMessage(err));
2065
2141
  }
2066
2142
  function readRetryAfter(body, response, fallbackSeconds = 0) {
2067
- return parseDiscordRetryAfterBodySeconds(body && typeof body === "object" && "retry_after" in body ? body.retry_after : void 0) ?? parseRetryAfterHeaderSeconds(response.headers.get("Retry-After")) ?? fallbackSeconds;
2143
+ const bodyValue = body && typeof body === "object" && "retry_after" in body ? body.retry_after : void 0;
2144
+ return parseDiscordRetryAfterBodySeconds(bodyValue) ?? parseRetryAfterHeaderSeconds(response.headers.get("Retry-After")) ?? fallbackSeconds;
2068
2145
  }
2069
2146
  function readDiscordRateLimitBucket(response) {
2070
2147
  const value = response.headers.get("X-RateLimit-Bucket")?.trim();
@@ -2076,7 +2153,8 @@ function readDiscordRateLimitScope(response) {
2076
2153
  }
2077
2154
  var DiscordError = class extends Error {
2078
2155
  constructor(response, body) {
2079
- const redactedMessage = redactSensitiveFieldValue("message", readDiscordMessage(body, `Discord API request failed (${response.status})`));
2156
+ const fallbackMessage = `Discord API request failed (${response.status})`;
2157
+ const redactedMessage = redactSensitiveFieldValue("message", readDiscordMessage(body, fallbackMessage));
2080
2158
  const redactedBody = redactDiscordErrorBody(body);
2081
2159
  super(redactedMessage);
2082
2160
  this.name = "DiscordError";
@@ -2149,7 +2227,7 @@ function appendQuery(path, query) {
2149
2227
  }
2150
2228
  //#endregion
2151
2229
  //#region extensions/discord/src/internal/rest-scheduler.ts
2152
- const INVALID_REQUEST_WINDOW_MS = 10 * 6e4;
2230
+ const INVALID_REQUEST_WINDOW_MS = 6e5;
2153
2231
  const requestPriorities = [
2154
2232
  "critical",
2155
2233
  "standard",
@@ -2538,7 +2616,7 @@ const defaultLaneOptions = {
2538
2616
  weight: 1
2539
2617
  }
2540
2618
  };
2541
- const DISCORD_REST_RESPONSE_BODY_MAX_BYTES = 8 * 1024 * 1024;
2619
+ const DISCORD_REST_RESPONSE_BODY_MAX_BYTES = 8388608;
2542
2620
  const GZIP_MAGIC = [31, 139];
2543
2621
  function createResponseBodyOverflowError(size) {
2544
2622
  return /* @__PURE__ */ new Error(`Discord REST response body exceeds ${DISCORD_REST_RESPONSE_BODY_MAX_BYTES} bytes (received ${size})`);
@@ -3057,9 +3135,10 @@ function parseDiscordProviderPrefixedTarget(raw) {
3057
3135
  return buildMessagingTarget(kind, id, `${kind}:${id}`);
3058
3136
  }
3059
3137
  function resolveDiscordChannelId(raw) {
3138
+ const target = parseDiscordTarget(raw, { defaultKind: "channel" });
3060
3139
  return requireTargetKind({
3061
3140
  platform: "Discord",
3062
- target: parseDiscordTarget(raw, { defaultKind: "channel" }),
3141
+ target,
3063
3142
  kind: "channel"
3064
3143
  });
3065
3144
  }
@@ -3098,8 +3177,9 @@ function normalizeDiscordOutboundTarget(to, allowFrom) {
3098
3177
  function allowFromContainsDiscordUserId(allowFrom, userId) {
3099
3178
  const normalizedUserId = userId.trim();
3100
3179
  if (!normalizedUserId) return false;
3180
+ const normalizedAllowFrom = (allowFrom ?? []).map(normalizeAllowFromDiscordUserId).filter((entry) => Boolean(entry));
3101
3181
  return resolveAllowlistMatchByCandidates({
3102
- allowList: (allowFrom ?? []).map(normalizeAllowFromDiscordUserId).filter((entry) => Boolean(entry)),
3182
+ allowList: normalizedAllowFrom,
3103
3183
  candidates: [{
3104
3184
  value: normalizedUserId,
3105
3185
  source: "id"
@@ -3174,35 +3254,36 @@ function createDiscordSendReceiptFromResults(params) {
3174
3254
  };
3175
3255
  }
3176
3256
  function createDiscordSendReceipt(params) {
3177
- return createMessageReceiptFromOutboundResults({
3178
- results: params.platformMessageIds.map((messageId) => messageId.trim()).filter((messageId) => messageId && messageId !== "unknown").map((messageId, index) => {
3179
- const result = {
3257
+ const results = params.platformMessageIds.map((messageId) => messageId.trim()).filter(Boolean).map((messageId, index) => {
3258
+ const result = {
3259
+ channel: "discord",
3260
+ messageId
3261
+ };
3262
+ if (params.channelId) result.channelId = params.channelId;
3263
+ if (params.reply?.scope === "first" && index === 0) {
3264
+ const rawResult = {
3180
3265
  channel: "discord",
3181
3266
  messageId
3182
3267
  };
3183
- if (params.channelId) result.channelId = params.channelId;
3184
- if (params.reply?.scope === "first" && index === 0) {
3185
- const rawResult = {
3186
- channel: "discord",
3187
- messageId
3188
- };
3189
- if (params.channelId) rawResult.channelId = params.channelId;
3190
- result.receipt = createMessageReceiptFromOutboundResults({
3191
- results: [rawResult],
3192
- kind: params.kind,
3193
- threadId: params.threadId,
3194
- replyToId: params.reply.messageId
3195
- });
3196
- }
3197
- return result;
3198
- }),
3268
+ if (params.channelId) rawResult.channelId = params.channelId;
3269
+ result.receipt = createMessageReceiptFromOutboundResults({
3270
+ results: [rawResult],
3271
+ kind: params.kind,
3272
+ threadId: params.threadId,
3273
+ replyToId: params.reply.messageId
3274
+ });
3275
+ }
3276
+ return result;
3277
+ });
3278
+ return createMessageReceiptFromOutboundResults({
3279
+ results,
3199
3280
  kind: params.kind,
3200
3281
  threadId: params.threadId,
3201
3282
  replyToId: params.reply?.scope === "all" ? params.reply.messageId : void 0
3202
3283
  });
3203
3284
  }
3204
3285
  function createDiscordSendResult(params) {
3205
- const messageId = params.result.id || "unknown";
3286
+ const messageId = params.result.id ?? "";
3206
3287
  const channelId = params.result.channel_id ?? params.fallbackChannelId;
3207
3288
  const receiptParams = {
3208
3289
  platformMessageIds: params.result.platformMessageIds?.length ? params.result.platformMessageIds : [messageId],
@@ -3234,213 +3315,268 @@ function countLines(text) {
3234
3315
  if (!text) return 0;
3235
3316
  return text.split("\n").length;
3236
3317
  }
3237
- function parseFenceLine(line) {
3318
+ function parseFenceLine(line, maxChars = Number.POSITIVE_INFINITY) {
3238
3319
  const match = line.match(FENCE_RE);
3239
3320
  if (!match) return null;
3240
- const indent = match[1] ?? "";
3241
3321
  const marker = match[2] ?? "";
3322
+ const closeLine = (match[1] ?? "") + marker;
3323
+ const canBalance = closeLine.length * 2 + 3 <= maxChars;
3324
+ const reopenLine = line.length + closeLine.length + 3 <= maxChars ? line : closeLine;
3242
3325
  return {
3243
- indent,
3244
- markerChar: marker[0] ?? "`",
3245
- markerLen: marker.length,
3246
- openLine: line
3326
+ marker,
3327
+ closeLine,
3328
+ reopenLine: canBalance ? reopenLine : null
3247
3329
  };
3248
3330
  }
3249
- function closeFenceLine(openFence) {
3250
- return `${openFence.indent}${openFence.markerChar.repeat(openFence.markerLen)}`;
3251
- }
3252
- function canBalanceFence(openFence, maxChars) {
3253
- return closeFenceLine(openFence).length * 2 + 3 <= maxChars;
3254
- }
3255
- function reopenFenceLine(openFence, maxChars) {
3256
- const bareMarker = closeFenceLine(openFence);
3257
- if (!canBalanceFence(openFence, maxChars)) return null;
3258
- if (openFence.openLine.length + bareMarker.length + 3 <= maxChars) return openFence.openLine;
3259
- return bareMarker;
3260
- }
3261
- function closeFenceIfNeeded(text, openFence, maxChars) {
3262
- if (!openFence || !canBalanceFence(openFence, maxChars)) return text;
3263
- const closeLine = closeFenceLine(openFence);
3264
- if (!text) return closeLine;
3265
- if (!text.endsWith("\n")) return `${text}\n${closeLine}`;
3266
- return `${text}${closeLine}`;
3331
+ function closesFence(open, close) {
3332
+ return open.marker[0] === close.marker[0] && close.marker.length >= open.marker.length;
3267
3333
  }
3268
- /**
3269
- * Chunks outbound Discord text by both character count and (soft) line count,
3270
- * while keeping fenced code blocks balanced across chunks.
3271
- */
3272
3334
  function chunkDiscordText(text, opts = {}) {
3273
3335
  const hardMaxChars = resolveDiscordChunkLimit(opts.maxChars, DEFAULT_MAX_CHARS);
3274
3336
  const maxLines = resolveDiscordChunkLimit(opts.maxLines, DEFAULT_MAX_LINES);
3275
- const body = text ?? "";
3276
- if (!body) return [];
3277
- if (body.length <= hardMaxChars && countLines(body) <= maxLines) return [body];
3278
- const maxChars = hardMaxChars >= MIN_REASONING_ITALICS_CHUNK_CHARS && hasReasoningItalics(body) ? hardMaxChars - REASONING_ITALICS_MARKER_CHARS : hardMaxChars;
3279
- const lines = body.split("\n");
3337
+ if (!text) return [];
3338
+ if (text.length <= hardMaxChars && countLines(text) <= maxLines) return [text];
3339
+ const maxChars = hardMaxChars >= MIN_REASONING_ITALICS_CHUNK_CHARS && hasReasoningItalics(text) ? hardMaxChars - REASONING_ITALICS_MARKER_CHARS : hardMaxChars;
3340
+ const ranges = createDiscordRanges(text, maxChars, maxLines);
3280
3341
  const chunks = [];
3281
- let current = "";
3282
- let currentLines = 0;
3283
- let openFence = null;
3284
- const flush = () => {
3285
- if (!current) return;
3286
- const payload = closeFenceIfNeeded(current, openFence, maxChars);
3287
- if (payload.trim().length) chunks.push(payload);
3288
- current = "";
3289
- currentLines = 0;
3290
- if (openFence) {
3291
- const reopenLine = reopenFenceLine(openFence, maxChars);
3292
- if (reopenLine) {
3293
- current = reopenLine;
3294
- currentLines = 1;
3295
- }
3296
- }
3342
+ let current;
3343
+ let consumed = 0;
3344
+ let lineStart = 0;
3345
+ const raw = (frame) => {
3346
+ const prefix = ranges.fenceAt(frame.start)?.reopenLine ?? "";
3347
+ const body = text.slice(frame.start, frame.end);
3348
+ return prefix + (prefix ? "\n" : "") + body;
3297
3349
  };
3298
- for (const originalLine of lines) {
3299
- const fenceInfo = parseFenceLine(originalLine);
3300
- const wasInsideFence = openFence !== null;
3301
- let nextOpenFence = openFence;
3302
- if (fenceInfo) {
3303
- if (!openFence) nextOpenFence = fenceInfo;
3304
- else if (openFence.markerChar === fenceInfo.markerChar && fenceInfo.markerLen >= openFence.markerLen) nextOpenFence = null;
3350
+ const render = (frame) => {
3351
+ const body = ranges.render(frame.start, frame.end);
3352
+ if (body === void 0) return;
3353
+ const prefix = ranges.fenceAt(frame.start)?.reopenLine ?? "";
3354
+ const result = prefix + (prefix ? "\n" : "") + body;
3355
+ const close = ranges.fenceAt(frame.end);
3356
+ return close?.reopenLine ? result + (result.endsWith("\n") ? "" : "\n") + close.closeLine : result;
3357
+ };
3358
+ const fits = (frame) => {
3359
+ const payload = render(frame);
3360
+ return payload !== void 0 && payload.length <= maxChars && countLines(payload) <= Math.max(maxLines, ranges.fenceAt(frame.start)?.reopenLine || ranges.fenceAt(frame.end)?.reopenLine ? 3 : 1);
3361
+ };
3362
+ const flush = (frame) => {
3363
+ let end = ranges.overlaps(frame.start, frame.end) ? ranges.cutBoundary(frame.start, frame.end) : ranges.boundary(frame.start, frame.end);
3364
+ if (frame.end > frame.start && end <= frame.start) return frame;
3365
+ const minimum = ranges.boundary(frame.start, frame.start + 1);
3366
+ while (end > minimum && !fits({
3367
+ ...frame,
3368
+ end
3369
+ })) {
3370
+ const cut = ranges.cutBoundary(frame.start, end - 1);
3371
+ end = cut > frame.start ? cut : minimum;
3305
3372
  }
3306
- const candidateFence = nextOpenFence ?? openFence;
3307
- const fenceToReserve = candidateFence && canBalanceFence(candidateFence, maxChars) ? candidateFence : null;
3308
- const reserveChars = fenceToReserve ? closeFenceLine(fenceToReserve).length + 1 : 0;
3309
- const reserveLines = fenceToReserve ? 1 : 0;
3310
- const effectiveMaxChars = maxChars - reserveChars;
3311
- const effectiveMaxLines = maxLines - reserveLines;
3312
- const charLimit = effectiveMaxChars > 0 ? effectiveMaxChars : maxChars;
3313
- const lineLimit = effectiveMaxLines > 0 ? effectiveMaxLines : maxLines;
3314
- const reopenPrefixLen = fenceToReserve ? reopenFenceLine(fenceToReserve, maxChars)?.length ?? 0 : 0;
3315
- const prefixLen = current.length > 0 ? current.length + 1 : 0;
3316
- const reopenBudget = reopenPrefixLen > 0 ? reopenPrefixLen + 1 : 0;
3317
- const segments = chunkTextForOutbound(originalLine, Math.max(1, charLimit - Math.max(prefixLen, reopenBudget)), { preserveWhitespace: wasInsideFence });
3318
- for (let segIndex = 0; segIndex < segments.length; segIndex++) {
3319
- const segment = segments[segIndex];
3320
- const isLineContinuation = segIndex > 0;
3321
- let delimiter = isLineContinuation ? "" : current.length > 0 ? "\n" : "";
3322
- let addition = `${delimiter}${segment}`;
3323
- const nextLen = current.length + addition.length;
3324
- const nextLines = currentLines + (isLineContinuation ? 0 : 1);
3325
- if ((nextLen > charLimit || nextLines > lineLimit) && current.length > 0) {
3326
- flush();
3327
- delimiter = current.length > 0 ? "\n" : "";
3328
- addition = `${delimiter}${segment}`;
3329
- }
3330
- if (current.length > 0) {
3331
- current += addition;
3332
- if (!isLineContinuation || delimiter) currentLines += 1;
3333
- } else {
3334
- current = expectDefined(segment, "current Discord chunk segment");
3335
- currentLines = 1;
3373
+ const payload = expectDefined(render({
3374
+ ...frame,
3375
+ end
3376
+ }), "renderable Discord source range");
3377
+ if (payload.trim()) chunks.push(payload);
3378
+ consumed = end;
3379
+ return end < frame.end ? {
3380
+ start: end,
3381
+ end: frame.end
3382
+ } : void 0;
3383
+ };
3384
+ for (const line of text.split("\n")) {
3385
+ const openFence = ranges.fenceAt(lineStart - 1);
3386
+ const candidateFence = ranges.fenceAt(lineStart + line.length) ?? openFence;
3387
+ const fence = candidateFence?.reopenLine ? candidateFence : null;
3388
+ const charLimit = maxChars - (fence ? fence.closeLine.length + 1 : 0);
3389
+ const lineLimit = Math.max(1, maxLines - (fence ? 1 : 0));
3390
+ const content = current ? raw(current) : ranges.fenceAt(consumed)?.reopenLine ?? "";
3391
+ const segmentLimit = openFence?.reopenLine && openFence.closeStart === lineStart && fits({
3392
+ start: lineStart,
3393
+ end: lineStart + line.length
3394
+ }) ? maxChars : Math.max(1, charLimit - Math.max(content ? content.length + 1 : 0, fence?.reopenLine ? fence.reopenLine.length + 1 : 0));
3395
+ let segmentStart = lineStart;
3396
+ for (const segment of chunkTextForOutbound(line, segmentLimit, { preserveWhitespace: Boolean(openFence) })) {
3397
+ const end = segmentStart + segment.length;
3398
+ const start = current?.start ?? (ranges.joins(consumed, segmentStart) ? consumed : segmentStart);
3399
+ const candidate = {
3400
+ start,
3401
+ end
3402
+ };
3403
+ const exceeds = openFence && !ranges.fenceAt(end) ? !fits(candidate) : raw(candidate).length > charLimit || countLines(raw(candidate)) > lineLimit || ranges.overlaps(start, end) && !fits(candidate);
3404
+ if (current && exceeds) {
3405
+ current = flush(current);
3406
+ candidate.start = current?.start ?? (ranges.joins(consumed, segmentStart) ? consumed : segmentStart);
3336
3407
  }
3408
+ current = raw(candidate) ? candidate : void 0;
3409
+ segmentStart = end;
3337
3410
  }
3338
- openFence = nextOpenFence;
3339
- }
3340
- if (current.length) {
3341
- const payload = closeFenceIfNeeded(current, openFence, maxChars);
3342
- if (payload.trim().length) chunks.push(payload);
3411
+ lineStart += line.length + 1;
3343
3412
  }
3413
+ while (current) current = flush(current);
3344
3414
  return rebalanceReasoningItalics(text, chunks, hardMaxChars);
3345
3415
  }
3346
3416
  function chunkDiscordTextWithMode(text, opts) {
3347
3417
  if ((opts.chunkMode ?? "length") !== "newline") return chunkDiscordText(text, opts);
3348
- const lineChunks = chunkMarkdownTextWithMode(text, resolveDiscordChunkLimit(opts.maxChars, DEFAULT_MAX_CHARS), "newline");
3349
- const chunks = [];
3350
- for (const line of lineChunks) {
3351
- const nested = chunkDiscordText(line, opts);
3352
- if (!nested.length && line) {
3353
- chunks.push(line);
3354
- continue;
3355
- }
3356
- chunks.push(...nested);
3357
- }
3358
- return chunks;
3359
- }
3360
- function leadingCodeSpanEnd(body) {
3361
- if (!body) return -1;
3362
- const firstNewline = body.indexOf("\n");
3363
- const openFence = parseFenceLine(firstNewline === -1 ? body : body.slice(0, firstNewline));
3364
- if (openFence) {
3365
- if (firstNewline === -1) return body.length;
3366
- let lineStart = firstNewline + 1;
3367
- while (lineStart <= body.length) {
3368
- const lineEnd = body.indexOf("\n", lineStart);
3369
- const line = lineEnd === -1 ? body.slice(lineStart) : body.slice(lineStart, lineEnd);
3370
- const closeFence = parseFenceLine(line);
3371
- const closeSuffix = closeFence ? line.slice(closeFence.indent.length + closeFence.markerLen) : "";
3372
- if (closeFence?.markerChar === openFence.markerChar && closeFence.markerLen >= openFence.markerLen && /^[ \t]*_?[ \t]*$/u.test(closeSuffix)) {
3373
- const markerEnd = closeFence.indent.length + closeFence.markerLen;
3374
- const trailingSpaces = /^ */.exec(line.slice(markerEnd))?.[0].length ?? 0;
3375
- return lineStart + markerEnd + trailingSpaces;
3376
- }
3377
- if (lineEnd === -1) return body.length;
3378
- lineStart = lineEnd + 1;
3379
- }
3380
- return body.length;
3381
- }
3382
- if (!body.startsWith("`")) return -1;
3383
- const ticks = /^(?<ticks>`+)/.exec(body)?.groups?.ticks;
3384
- if (!ticks) return -1;
3385
- for (let index = ticks.length; index < body.length;) {
3386
- if (body[index] !== "`") {
3387
- index += 1;
3388
- continue;
3389
- }
3390
- let runEnd = index + 1;
3391
- while (body[runEnd] === "`") runEnd += 1;
3392
- if (runEnd - index === ticks.length) return runEnd;
3393
- index = runEnd;
3394
- }
3395
- return -1;
3418
+ return chunkByParagraph(text, resolveDiscordChunkLimit(opts.maxChars, DEFAULT_MAX_CHARS), { splitLongParagraphs: false }).flatMap((line) => {
3419
+ const chunks = chunkDiscordText(line, opts);
3420
+ return chunks.length || !line ? chunks : [line];
3421
+ });
3396
3422
  }
3397
3423
  function leadingCodePrefixEnd(body) {
3398
- let prefixEnd = leadingCodeSpanEnd(body);
3399
- if (prefixEnd < 0) return -1;
3400
- while (prefixEnd < body.length) {
3401
- const separator = /^\s+/u.exec(body.slice(prefixEnd))?.[0] ?? "";
3402
- if (!separator) break;
3403
- const nextStart = prefixEnd + separator.length;
3404
- const nextEnd = leadingCodeSpanEnd(body.slice(nextStart));
3405
- if (nextEnd < 0) break;
3406
- prefixEnd = nextStart + nextEnd;
3424
+ let offset = 0;
3425
+ let prefixEnd = -1;
3426
+ while (offset < body.length) {
3427
+ const rest = body.slice(offset);
3428
+ const fence = parseFenceLine(rest.split("\n", 1)[0] ?? "");
3429
+ const marker = fence?.marker ?? /^`+/.exec(rest)?.[0];
3430
+ if (!marker) return prefixEnd;
3431
+ const pattern = fence ? `\\n( {0,3}${marker[0]}{${marker.length},} *)(?=[\\t ]*_?[\\t ]*(?:\\n|$))` : "(?<!`)`{" + marker.length + "}(?!`)";
3432
+ const delimiter = new RegExp(pattern, "g");
3433
+ delimiter.lastIndex = fence ? 0 : marker.length;
3434
+ const match = delimiter.exec(rest);
3435
+ if (!match) return fence ? body.length : prefixEnd;
3436
+ prefixEnd = offset + match.index + match[0].length;
3437
+ const separator = /^\s+/u.exec(body.slice(prefixEnd))?.[0];
3438
+ if (!separator) return prefixEnd;
3439
+ offset = prefixEnd + separator.length;
3407
3440
  }
3408
3441
  return prefixEnd;
3409
3442
  }
3410
- function hasReasoningItalicsOpen(chunk) {
3411
- const trimmed = chunk.trimStart();
3412
- if (trimmed.startsWith("_") || /^(?:Reasoning:|Thinking\.{0,3})\n+_/u.test(trimmed)) return true;
3413
- const codeEnd = leadingCodePrefixEnd(trimmed);
3414
- return codeEnd >= 0 && trimmed.slice(codeEnd).trimStart().startsWith("_");
3415
- }
3416
- function reopenReasoningItalicsAfterLeadingCode(body, codeEnd) {
3417
- const code = body.slice(0, codeEnd);
3418
- const rest = body.slice(codeEnd);
3419
- if (!rest.trim()) return code + rest;
3420
- if (/^\s*_\s*$/.test(rest)) return code;
3421
- const whitespaceLength = rest.length - rest.trimStart().length;
3422
- const whitespace = rest.slice(0, whitespaceLength);
3423
- const restBody = rest.slice(whitespaceLength);
3424
- return restBody.startsWith("_") ? code + rest : `${code}${whitespace}_${restBody}`;
3425
- }
3426
3443
  function rebalanceReasoningItalics(source, chunks, maxChars) {
3427
- if (chunks.length <= 1 || maxChars < MIN_REASONING_ITALICS_CHUNK_CHARS) return chunks;
3428
- if (!hasReasoningItalics(source)) return chunks;
3429
- const adjusted = [...chunks];
3430
- for (let i = 0; i < adjusted.length; i++) {
3431
- const isLast = i === adjusted.length - 1;
3432
- const current = expectDefined(adjusted[i], "Discord chunk adjustment index");
3433
- if (!current.trimEnd().endsWith("_") && hasReasoningItalicsOpen(current)) adjusted[i] = `${current}_`;
3434
- if (isLast) break;
3435
- const next = expectDefined(adjusted[i + 1], "non-final Discord chunk successor");
3436
- const leadingWhitespaceLen = next.length - next.trimStart().length;
3437
- const leadingWhitespace = next.slice(0, leadingWhitespaceLen);
3438
- const nextBody = next.slice(leadingWhitespaceLen);
3439
- if (nextBody.startsWith("_")) continue;
3440
- const codeEnd = leadingCodePrefixEnd(nextBody);
3441
- adjusted[i + 1] = codeEnd >= 0 ? `${leadingWhitespace}${reopenReasoningItalicsAfterLeadingCode(nextBody, codeEnd)}` : `${leadingWhitespace}_${nextBody}`;
3442
- }
3443
- return adjusted;
3444
+ if (chunks.length <= 1 || maxChars < MIN_REASONING_ITALICS_CHUNK_CHARS || !hasReasoningItalics(source)) return chunks;
3445
+ return chunks.map((chunk, index) => {
3446
+ const leadingWhitespace = chunk.length - chunk.trimStart().length;
3447
+ const codeEnd = leadingCodePrefixEnd(chunk.slice(leadingWhitespace));
3448
+ const prefixEnd = leadingWhitespace + Math.max(0, codeEnd);
3449
+ const prefix = chunk.slice(0, prefixEnd);
3450
+ let body = chunk.slice(prefixEnd);
3451
+ if (index > 0) {
3452
+ if (codeEnd >= 0 && /^\s*_\s*$/.test(body)) return prefix;
3453
+ const content = body.trimStart();
3454
+ if (content && !content.startsWith("_")) body = `${body.slice(0, body.length - content.length)}_${content}`;
3455
+ }
3456
+ if (!body.trimEnd().endsWith("_") && /^(?:_|(?:Reasoning:|Thinking\.{0,3})\n+_)/u.test(body.trimStart())) body += "_";
3457
+ return prefix + body;
3458
+ });
3459
+ }
3460
+ function renderInlineCode(body, delimiter) {
3461
+ const runs = new Set(Array.from(body.matchAll(/`+/g), (match) => match[0].length));
3462
+ let marker = delimiter;
3463
+ if (runs.has(marker.length) || marker.length >= 3 && /[\r\n]/.test(body)) {
3464
+ marker = "`";
3465
+ while (runs.has(marker.length)) marker += "`";
3466
+ }
3467
+ if (marker.length >= 3 && /[\r\n]/.test(body) && !body.split(/\r\n|[\r\n]/, 1)[0]?.includes("`")) return;
3468
+ const normalized = body.replace(/\r\n|[\r\n]/g, " ");
3469
+ const padding = body.startsWith("`") || body.endsWith("`") || normalized.startsWith(" ") && normalized.endsWith(" ") && /[^ ]/.test(normalized) ? " " : "";
3470
+ return marker + padding + body + padding + marker;
3471
+ }
3472
+ function createDiscordRanges(source, maxChars, maxLines) {
3473
+ const spans = [];
3474
+ const fences = [];
3475
+ let offset = 0;
3476
+ let plainStart = 0;
3477
+ let fence;
3478
+ const collect = (end) => {
3479
+ for (const span of findCodeRegions(source.slice(plainStart, end), {
3480
+ includeSource: true,
3481
+ syntax: "commonmark"
3482
+ })) {
3483
+ if (span.block) continue;
3484
+ const start = plainStart + span.start;
3485
+ const finish = plainStart + span.end;
3486
+ const marker = /^`+/.exec(source.slice(start, finish))?.[0];
3487
+ if (!marker) continue;
3488
+ const code = expectDefined(span.source, "inline code source map");
3489
+ const atomicTicks = (renderInlineCode("`", marker)?.length ?? Infinity) + code.prefix.text.length > maxChars;
3490
+ const pattern = atomicTicks ? /`+|\r\n|[\s\S]/gu : /\r\n|[\s\S]/gu;
3491
+ if (Array.from(source.slice(start, finish).matchAll(pattern)).every(({ index, 0: raw }) => {
3492
+ const value = code.value.slice(code.offsets[index], code.offsets[index + raw.length]);
3493
+ return !value || (renderInlineCode(value, marker)?.length ?? Infinity) + code.prefix.text.length <= maxChars;
3494
+ }) && (maxLines > 1 || !code.value.includes("\n"))) spans.push({
3495
+ start,
3496
+ end: finish,
3497
+ code,
3498
+ base: plainStart,
3499
+ marker,
3500
+ atomicTicks
3501
+ });
3502
+ }
3503
+ };
3504
+ for (const line of source.split("\n")) {
3505
+ const info = parseFenceLine(line, maxChars);
3506
+ if (info && !fence) {
3507
+ collect(offset);
3508
+ fence = {
3509
+ start: offset,
3510
+ bodyStart: offset + line.length + 1,
3511
+ closeStart: source.length,
3512
+ end: source.length,
3513
+ ...info
3514
+ };
3515
+ fences.push(fence);
3516
+ } else if (info && fence && closesFence(fence, info)) {
3517
+ fence.closeStart = offset;
3518
+ fence.end = offset + line.length;
3519
+ fence = void 0;
3520
+ plainStart = offset + line.length + 1;
3521
+ }
3522
+ offset += line.length + 1;
3523
+ }
3524
+ if (!fence) collect(source.length);
3525
+ const overlaps = (start, end) => spans.some((span) => span.start < end && span.end > start);
3526
+ const joins = (end, start) => end <= start && spans.some((span) => span.start < end && end < span.end && start < span.end);
3527
+ const boundary = (start, end) => {
3528
+ let safe = avoidTrailingHighSurrogateBreak(source, start, end);
3529
+ for (const span of spans) {
3530
+ const prefix = span.code.prefix;
3531
+ if (span.base + prefix.start < safe && safe < span.base + prefix.end) return span.base + prefix.start;
3532
+ if (span.start < safe && safe < span.end) {
3533
+ if (source[safe - 1] === "\r" && source[safe] === "\n") safe -= 1;
3534
+ if (span.atomicTicks) while (source[safe - 1] === "`" && source[safe] === "`") safe -= 1;
3535
+ }
3536
+ }
3537
+ return safe;
3538
+ };
3539
+ const render = (start, end) => {
3540
+ let cursor = start, text = "";
3541
+ for (const span of spans) {
3542
+ if (span.end <= start || span.start >= end) continue;
3543
+ const prefix = span.code.prefix;
3544
+ const prefixStart = span.base + prefix.start;
3545
+ if (start > span.base + prefix.ownerStart && cursor <= prefixStart) {
3546
+ text += source.slice(cursor, prefixStart) + prefix.text;
3547
+ cursor = span.base + prefix.end;
3548
+ }
3549
+ text += source.slice(cursor, Math.max(cursor, span.start));
3550
+ if (span.start >= start && span.end <= end) text += source.slice(span.start, span.end);
3551
+ else {
3552
+ const body = span.code.value.slice(span.code.offsets[Math.max(start, span.start) - span.start], span.code.offsets[Math.min(end, span.end) - span.start]);
3553
+ if (body) {
3554
+ const value = renderInlineCode(body, span.marker);
3555
+ if (value === void 0) return;
3556
+ text += (span.start < start ? span.code.prefix.text : "") + value;
3557
+ }
3558
+ }
3559
+ cursor = Math.min(end, span.end);
3560
+ }
3561
+ return text + source.slice(cursor, end);
3562
+ };
3563
+ const fenceAt = (position) => fences.find((range) => range.bodyStart - 1 <= position && (position < range.end || position === range.end && range.closeStart === range.end));
3564
+ const cutBoundary = (start, end) => {
3565
+ const safe = boundary(start, end);
3566
+ for (const range of fences) {
3567
+ if (start < range.start && range.start < safe && safe <= range.bodyStart) return range.start;
3568
+ if (range.closeStart < safe && safe < range.end) return range.closeStart;
3569
+ }
3570
+ return safe;
3571
+ };
3572
+ return {
3573
+ render,
3574
+ overlaps,
3575
+ joins,
3576
+ boundary,
3577
+ fenceAt,
3578
+ cutBoundary
3579
+ };
3444
3580
  }
3445
3581
  //#endregion
3446
3582
  //#region extensions/discord/src/retry.ts
@@ -3455,7 +3591,8 @@ const DISCORD_TRANSIENT_MESSAGE_RE = /\b(?:bad gateway|fetch failed|network erro
3455
3591
  const ambiguousDiscordMessageCreates = /* @__PURE__ */ new WeakSet();
3456
3592
  function readDiscordErrorStatus(err) {
3457
3593
  if (!err || typeof err !== "object") return;
3458
- return parseStrictNonNegativeInteger("status" in err && err.status !== void 0 ? err.status : "statusCode" in err && err.statusCode !== void 0 ? err.statusCode : void 0);
3594
+ const raw = "status" in err && err.status !== void 0 ? err.status : "statusCode" in err && err.statusCode !== void 0 ? err.statusCode : void 0;
3595
+ return parseStrictNonNegativeInteger(raw);
3459
3596
  }
3460
3597
  function classifyDiscordDeliveryFailure(error) {
3461
3598
  const candidates = collectErrorGraphCandidates(error, (current) => [current.cause, current.error]);
@@ -3476,6 +3613,11 @@ function recordDiscordMessageCreateAmbiguity(error) {
3476
3613
  function hasDiscordMessageCreateAmbiguity(error) {
3477
3614
  return collectErrorGraphCandidates(error, (current) => [current.cause, current.error]).some((candidate) => candidate !== null && typeof candidate === "object" && ambiguousDiscordMessageCreates.has(candidate));
3478
3615
  }
3616
+ function canFallbackDiscordWebhookSend(error) {
3617
+ if (hasDiscordMessageCreateAmbiguity(error)) return false;
3618
+ const failure = classifyDiscordDeliveryFailure(error);
3619
+ return failure === "rejected" || failure === "pre-connect";
3620
+ }
3479
3621
  function hasDiscordRateLimitRejection(error) {
3480
3622
  return error instanceof RateLimitError || collectErrorGraphCandidates(error, (current) => [current.cause, current.error]).some((candidate) => readDiscordErrorStatus(candidate) === 429);
3481
3623
  }
@@ -3540,4 +3682,4 @@ function createDiscordRetryRunner(params) {
3540
3682
  };
3541
3683
  }
3542
3684
  //#endregion
3543
- export { TextInput as $, listGuildRoles as $t, ThreadUpdateListener as A, getChannel as At, readRetryAfter as B, addGuildMemberRole as Bt, MessageCreateListener as C, listMessageReactionUsers as Ct, ReadyListener as D, deleteChannelMessage as Dt, PresenceUpdateListener as E, deleteChannel as Et, DiscordError as F, listChannelPins as Ft, User as G, createGuildSticker as Gt, CommandWithSubcommands as H, createGuildChannel as Ht, RateLimitError as I, pinChannelMessage as It, Embed as J, getGuildMember as Jt, hasDiscordV2Components as K, deleteChannelPermission as Kt, isUnknownDiscordVoiceStateError as L, searchGuildMessages as Lt, Client as M, getThreadMember as Mt, Plugin as N, listChannelArchivedThreads as Nt, ResumedListener as O, editChannel as Ot, RequestClient as P, listChannelMessages as Pt, RadioGroup as Q, listGuildEmojis as Qt, readDiscordCode as R, sendChannelTyping as Rt, InteractionCreateListener as S, deleteOwnMessageReaction as St, MessageReactionRemoveListener as T, createThread as Tt, Guild as U, createGuildEmoji as Ut, Command as V, createGuildBan as Vt, Message as W, createGuildScheduledEvent as Wt, Label as X, listGuildActiveThreads as Xt, CheckboxGroup as Y, getGuildVoiceState as Yt, Modal as Z, listGuildChannels as Zt, parseDiscordTarget as _, stripUndefinedFields as _t, chunkDiscordTextWithMode as a, timeoutGuildMember as an, MediaGallery as at, GuildCreateListener as b, getCurrentUser as bt, createDiscordSendResult as c, Row as ct, resolveDiscordReplyMessageId as d, StringSelectMenu as dt, listGuildScheduledEvents as en, Button as et, resolveDiscordReplyReference as f, TextDisplay as ft, normalizeDiscordOutboundTarget as g, parseCustomId as gt, normalizeDiscordMessagingTarget as h, BaseMessageInteractiveComponent as ht, recordDiscordMessageCreateAmbiguity as i, removeGuildMemberRole as in, LinkButton as it, VoiceStateUpdateListener as j, getChannelMessage as jt, ThreadDeleteListener as k, editChannelMessage as kt, toDiscordOutboundDeliveryResult as l, Section as lt, looksLikeDiscordTargetId as m, UserSelectMenu as mt, createDiscordRetryRunner as n, putChannelPermission as nn, Container as nt, createDiscordSendReceipt as o, __exportAll as on, MentionableSelectMenu as ot, allowFromContainsDiscordUserId as p, Thumbnail as pt, serializePayload as q, getGuild as qt, hasDiscordMessageCreateAmbiguity as r, removeGuildMember as rn, File as rt, createDiscordSendReceiptFromResults as s, RoleSelectMenu as st, classifyDiscordDeliveryFailure as t, moveGuildChannels as tn, ChannelSelectMenu as tt, createReusableDiscordReplyReference as u, Separator as ut, resolveDiscordChannelId as v, createChannelWebhook as vt, MessageReactionAddListener as w, createChannelMessage as wt, GuildDeleteListener as x, createOwnMessageReaction as xt, discord_exports as y, createUserDmChannel as yt, readDiscordMessage as z, unpinChannelMessage as zt };
3685
+ export { RadioGroup as $, listGuildEmojis as $t, ThreadDeleteListener as A, editChannelMessage as At, readDiscordMessage as B, unpinChannelMessage as Bt, InteractionCreateListener as C, deleteOwnMessageReaction as Ct, PresenceUpdateListener as D, deleteChannel as Dt, MessageReactionRemoveListener as E, createThread as Et, RequestClient as F, listChannelMessages as Ft, Message as G, createGuildScheduledEvent as Gt, Command as H, createGuildBan as Ht, DiscordError as I, listChannelPins as It, serializePayload as J, getGuild as Jt, User as K, createGuildSticker as Kt, RateLimitError as L, pinChannelMessage as Lt, VoiceStateUpdateListener as M, getChannelMessage as Mt, Client as N, getThreadMember as Nt, ReadyListener as O, deleteChannelMessage as Ot, Plugin as P, listChannelArchivedThreads as Pt, Modal as Q, listGuildChannels as Qt, isUnknownDiscordVoiceStateError as R, searchGuildMessages as Rt, GuildDeleteListener as S, createOwnMessageReaction as St, MessageReactionAddListener as T, createChannelMessage as Tt, CommandWithSubcommands as U, createGuildChannel as Ut, readRetryAfter as V, addGuildMemberRole as Vt, Guild as W, createGuildEmoji as Wt, CheckboxGroup as X, getGuildVoiceState as Xt, Embed as Y, getGuildMember as Yt, Label as Z, listGuildActiveThreads as Zt, normalizeDiscordOutboundTarget as _, parseCustomId as _t, recordDiscordMessageCreateAmbiguity as a, removeGuildMemberRole as an, LinkButton as at, discord_exports as b, createUserDmChannel as bt, createDiscordSendReceiptFromResults as c, RoleSelectMenu as ct, createReusableDiscordReplyReference as d, Separator as dt, listGuildRoles as en, TextInput as et, resolveDiscordReplyMessageId as f, StringSelectMenu as ft, normalizeDiscordMessagingTarget as g, BaseMessageInteractiveComponent as gt, looksLikeDiscordTargetId as h, UserSelectMenu as ht, hasDiscordMessageCreateAmbiguity as i, removeGuildMember as in, File as it, ThreadUpdateListener as j, getChannel as jt, ResumedListener as k, editChannel as kt, createDiscordSendResult as l, Row as lt, allowFromContainsDiscordUserId as m, Thumbnail as mt, classifyDiscordDeliveryFailure as n, moveGuildChannels as nn, ChannelSelectMenu as nt, chunkDiscordTextWithMode as o, timeoutGuildMember as on, MediaGallery as ot, resolveDiscordReplyReference as p, TextDisplay as pt, hasDiscordV2Components as q, deleteChannelPermission as qt, createDiscordRetryRunner as r, putChannelPermission as rn, Container as rt, createDiscordSendReceipt as s, __exportAll as sn, MentionableSelectMenu as st, canFallbackDiscordWebhookSend as t, listGuildScheduledEvents as tn, Button as tt, toDiscordOutboundDeliveryResult as u, Section as ut, parseDiscordTarget as v, stripUndefinedFields as vt, MessageCreateListener as w, listMessageReactionUsers as wt, GuildCreateListener as x, getCurrentUser as xt, resolveDiscordChannelId as y, createChannelWebhook as yt, readDiscordCode as z, sendChannelTyping as zt };