@openclaw/discord 2026.9.1-beta.1 → 2026.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) 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-E-segZn6.js} +30 -17
  6. package/dist/activities-api.js +1 -1
  7. package/dist/{allow-list-BDMimASD.js → allow-list-C2JuH-R0.js} +10 -6
  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-CW5k3mSa.js} +19 -12
  11. package/dist/{audit-CBEv_ERu.js → audit-B9rydv5a.js} +8 -7
  12. package/dist/{channel-Dx1tMTfx.js → channel-D93LnbTE.js} +29 -23
  13. package/dist/{channel-actions.runtime-CLWWu9nC.js → channel-actions.runtime-DMFv4doE.js} +16 -13
  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-DTL7kPOM.js} +18 -18
  17. package/dist/{components-B9V5o361.js → components-DmXYIQ26.js} +111 -149
  18. package/dist/{config-schema-BR13IAx6.js → config-schema-B797-Spt.js} +19 -12
  19. package/dist/{conversation-binding-route-DJYrY2TQ.js → conversation-binding-route-24afmvEC.js} +1 -1
  20. package/dist/{directory-config-BK6eqekJ.js → directory-config-BD4YL7wT.js} +2 -2
  21. package/dist/directory-contract-api.js +1 -1
  22. package/dist/{directory-live-DSAJSrJk.js → directory-live-BrFVc1Ds.js} +4 -4
  23. package/dist/{doctor-Cm7Y1pJ2.js → doctor-BUB41_lr.js} +5 -5
  24. package/dist/{doctor-contract-DsWvKIXF.js → doctor-contract-Co5vRCZ6.js} +9 -6
  25. package/dist/doctor-contract-api.js +3 -2
  26. package/dist/{handle-action.guild-admin-BdwCRHmm.js → handle-action.guild-admin-B0egstYq.js} +2 -2
  27. package/dist/index.js +1 -1
  28. package/dist/ingress-identity-BCzfPPYM.js +60 -0
  29. package/dist/{message-handler-BXpWZyni.js → message-handler-Qdw9c0j4.js} +14 -10
  30. package/dist/{message-handler.preflight-Ba5LAY_X.js → message-handler.preflight-Dxi2yBfR.js} +41 -101
  31. package/dist/{message-handler.process-3HEzmemS.js → message-handler.process-BYDjtxZJ.js} +83 -109
  32. package/dist/{message-text-aiwO5R2F.js → message-text-BRVqYm-t.js} +11 -6
  33. package/dist/{outbound-adapter-BE4jSq2d.js → outbound-adapter-DEhthWTk.js} +52 -67
  34. package/dist/{outbound-components-oLpg8Qzb.js → outbound-components-DehyxvA4.js} +5 -4
  35. package/dist/{outbound-session-route-Cg15ZFJd.js → outbound-session-route-BFGRF9fE.js} +55 -12
  36. package/dist/{owner-access-UlYi9t0M.js → owner-access-yc1sX7Gx.js} +7 -6
  37. package/dist/{pluralkit-Tiyl70dx.js → pluralkit-XmmAHoV6.js} +2 -2
  38. package/dist/{probe-n6ZXxK8V.js → probe-3ovFAp3b.js} +3 -3
  39. package/dist/{probe.runtime-CN4bdPfZ.js → probe.runtime-BckHn3cJ.js} +1 -1
  40. package/dist/{provider-B11xwilq.js → provider-DuDtKbF8.js} +294 -131
  41. package/dist/{provider-session.runtime-B9xe-Qaf.js → provider-session.runtime-BA2BPyZ4.js} +3 -3
  42. package/dist/provider.runtime-Db8YwZBv.js +2 -0
  43. package/dist/{realtime-session.runtime-CU8IQUS-.js → realtime-session.runtime-DgSbX6ay.js} +103 -163
  44. package/dist/{resolve-allowlist-common-BLoYaxEG.js → resolve-allowlist-common-BJ5UZNNT.js} +3 -3
  45. package/dist/{resolve-channels-C2sT_n67.js → resolve-channels-CYseD5Uw.js} +4 -4
  46. package/dist/{resolve-users-CzpjLwjy.js → resolve-users-DrmhDrqm.js} +5 -4
  47. package/dist/{retry-Cv4jCU5Z.js → retry-BNCxiyyR.js} +120 -32
  48. package/dist/{retry-after-DdLPmPoa.js → retry-after-BrLjLUJi.js} +2 -1
  49. package/dist/{runtime-BHrTlFkf.js → runtime-BbWNtfyq.js} +127 -93
  50. package/dist/{runtime-CY4PRMF-.js → runtime-DB7Fb6AU.js} +2 -2
  51. package/dist/runtime-api.js +19 -19
  52. package/dist/{secret-config-contract-B3i6WxV5.js → secret-config-contract-DFu9hfU8.js} +14 -6
  53. package/dist/secret-contract-api.js +1 -1
  54. package/dist/{security-audit-BfJhAXZp.js → security-audit-DKfK-iPY.js} +10 -11
  55. package/dist/security-audit-contract-api.js +1 -1
  56. package/dist/{security-audit.runtime-BVKF9VtY.js → security-audit.runtime-sKZyKgpx.js} +1 -1
  57. package/dist/{send-C49MFF9j.js → send-BnTEIeLE.js} +132 -100
  58. package/dist/{send.components-DKKAw5VX.js → send.components-BWVEcjRP.js} +21 -15
  59. package/dist/{send.outbound-zam0TrZx.js → send.outbound-b5xwHTlL.js} +35 -22
  60. package/dist/{send.shared-JjljcV4O.js → send.shared-5vxBTagO.js} +25 -18
  61. package/dist/{sender-identity-BJtfyise.js → sender-identity-Dt0imZyY.js} +1 -1
  62. package/dist/setup-plugin-api.js +1 -1
  63. package/dist/{shared-_5EcP4jW.js → shared-BSJWHEMA.js} +20 -14
  64. package/dist/{subagent-hooks-DQzvOptn.js → subagent-hooks-IzQKX4RQ.js} +2 -2
  65. package/dist/subagent-hooks-api.js +1 -1
  66. package/dist/{system-events-C7yxaHWP.js → system-events-BOiDS8b3.js} +2 -2
  67. package/dist/{target-resolver-vxIh6O3-.js → target-resolver-BVI8xSSC.js} +6 -5
  68. package/dist/targets-DbxVbq8k.js +3 -0
  69. package/dist/{thread-bindings-DW5F9vat.js → thread-bindings-D7mcaXQC.js} +6 -5
  70. package/dist/{thread-bindings.manager-ByOtwjo_.js → thread-bindings.manager-B1oySiVc.js} +37 -28
  71. package/dist/{thread-bindings.session-updates-CJb-BpPL.js → thread-bindings.session-updates-CC7HoQvt.js} +2 -1
  72. package/dist/{threading-agH1T_6s.js → threading-OQnL-0Zx.js} +8 -6
  73. package/dist/{timeouts-B9cy6RvQ.js → timeouts-D86uWLt_.js} +1 -1
  74. package/dist/{transcripts-source-BR11iHA4.js → transcripts-source-D8lH7AkN.js} +9 -4
  75. package/dist/transcripts-source-api.js +1 -1
  76. package/dist/{typing-Dc_YMY2e.js → typing-C9q0AQMb.js} +2 -2
  77. package/dist/{voice-runtime-DIeaa8fJ.js → voice-runtime-Dfhjh1tV.js} +433 -93
  78. package/node_modules/@discord/embedded-app-sdk/node_modules/@types/lodash/README.md +1 -1
  79. package/node_modules/@discord/embedded-app-sdk/node_modules/@types/lodash/conforms.d.ts +2 -0
  80. package/node_modules/@discord/embedded-app-sdk/node_modules/@types/lodash/package.json +3 -3
  81. package/node_modules/@discord/embedded-app-sdk/node_modules/@types/lodash/stubArray.d.ts +2 -0
  82. package/node_modules/@discord/embedded-app-sdk/node_modules/@types/lodash/stubObject.d.ts +2 -0
  83. package/node_modules/@discord/embedded-app-sdk/node_modules/@types/lodash/stubString.d.ts +2 -0
  84. package/node_modules/typebox/build/format/email.mjs +1 -1
  85. package/node_modules/typebox/build/format/idna/idn-hostname.mjs +19 -1
  86. package/node_modules/typebox/package.json +1 -1
  87. package/openclaw.plugin.json +14 -6
  88. package/package.json +6 -5
  89. package/skills/discord/SKILL.md +1 -1
  90. package/dist/account-inspect-BDfKyuvL.js +0 -89
  91. package/dist/provider.runtime-DiYaHvOz.js +0 -2
  92. package/dist/sdk-runtime-4geQHtXc.js +0 -338
  93. 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";
@@ -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],
@@ -3314,7 +3395,8 @@ function chunkDiscordText(text, opts = {}) {
3314
3395
  const reopenPrefixLen = fenceToReserve ? reopenFenceLine(fenceToReserve, maxChars)?.length ?? 0 : 0;
3315
3396
  const prefixLen = current.length > 0 ? current.length + 1 : 0;
3316
3397
  const reopenBudget = reopenPrefixLen > 0 ? reopenPrefixLen + 1 : 0;
3317
- const segments = chunkTextForOutbound(originalLine, Math.max(1, charLimit - Math.max(prefixLen, reopenBudget)), { preserveWhitespace: wasInsideFence });
3398
+ const segmentLimit = Math.max(1, charLimit - Math.max(prefixLen, reopenBudget));
3399
+ const segments = chunkTextForOutbound(originalLine, segmentLimit, { preserveWhitespace: wasInsideFence });
3318
3400
  for (let segIndex = 0; segIndex < segments.length; segIndex++) {
3319
3401
  const segment = segments[segIndex];
3320
3402
  const isLineContinuation = segIndex > 0;
@@ -3455,7 +3537,8 @@ const DISCORD_TRANSIENT_MESSAGE_RE = /\b(?:bad gateway|fetch failed|network erro
3455
3537
  const ambiguousDiscordMessageCreates = /* @__PURE__ */ new WeakSet();
3456
3538
  function readDiscordErrorStatus(err) {
3457
3539
  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);
3540
+ const raw = "status" in err && err.status !== void 0 ? err.status : "statusCode" in err && err.statusCode !== void 0 ? err.statusCode : void 0;
3541
+ return parseStrictNonNegativeInteger(raw);
3459
3542
  }
3460
3543
  function classifyDiscordDeliveryFailure(error) {
3461
3544
  const candidates = collectErrorGraphCandidates(error, (current) => [current.cause, current.error]);
@@ -3476,6 +3559,11 @@ function recordDiscordMessageCreateAmbiguity(error) {
3476
3559
  function hasDiscordMessageCreateAmbiguity(error) {
3477
3560
  return collectErrorGraphCandidates(error, (current) => [current.cause, current.error]).some((candidate) => candidate !== null && typeof candidate === "object" && ambiguousDiscordMessageCreates.has(candidate));
3478
3561
  }
3562
+ function canFallbackDiscordWebhookSend(error) {
3563
+ if (hasDiscordMessageCreateAmbiguity(error)) return false;
3564
+ const failure = classifyDiscordDeliveryFailure(error);
3565
+ return failure === "rejected" || failure === "pre-connect";
3566
+ }
3479
3567
  function hasDiscordRateLimitRejection(error) {
3480
3568
  return error instanceof RateLimitError || collectErrorGraphCandidates(error, (current) => [current.cause, current.error]).some((candidate) => readDiscordErrorStatus(candidate) === 429);
3481
3569
  }
@@ -3540,4 +3628,4 @@ function createDiscordRetryRunner(params) {
3540
3628
  };
3541
3629
  }
3542
3630
  //#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 };
3631
+ 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 };
@@ -3,7 +3,8 @@ import { asFiniteNumberInRange, parseStrictFiniteNumber } from "openclaw/plugin-
3
3
  const RETRY_AFTER_BODY_SECONDS_RE = /^(?:\d+\.?\d*|\.\d+)$/;
4
4
  const MAX_SAFE_RETRY_AFTER_SECONDS = Number.MAX_SAFE_INTEGER / 1e3;
5
5
  function parseDiscordRetryAfterBodySeconds(value) {
6
- return asFiniteNumberInRange(typeof value === "number" ? value : typeof value === "string" && RETRY_AFTER_BODY_SECONDS_RE.test(value.trim()) ? parseStrictFiniteNumber(value.trim()) : void 0, {
6
+ const seconds = typeof value === "number" ? value : typeof value === "string" && RETRY_AFTER_BODY_SECONDS_RE.test(value.trim()) ? parseStrictFiniteNumber(value.trim()) : void 0;
7
+ return asFiniteNumberInRange(seconds, {
7
8
  min: 0,
8
9
  max: MAX_SAFE_RETRY_AFTER_SECONDS
9
10
  });