@openclaw/discord 2026.8.2 → 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 (57) hide show
  1. package/dist/action-runtime-api.js +1 -1
  2. package/dist/{activities-api-CkKcHUB6.js → activities-api-E-segZn6.js} +20 -8
  3. package/dist/activities-api.js +1 -1
  4. package/dist/api.js +12 -12
  5. package/dist/{approval-handler.runtime-DZM6Kt1Z.js → approval-handler.runtime-CW5k3mSa.js} +16 -10
  6. package/dist/{audit-DIbQA4VT.js → audit-B9rydv5a.js} +4 -4
  7. package/dist/{channel-CarzU3bg.js → channel-D93LnbTE.js} +20 -16
  8. package/dist/{channel-actions.runtime-B2wMqeVK.js → channel-actions.runtime-DMFv4doE.js} +7 -7
  9. package/dist/channel-plugin-api.js +1 -1
  10. package/dist/{channel.setup-z_ewMVa9.js → channel.setup-DTL7kPOM.js} +3 -3
  11. package/dist/{components-gvRA0oaI.js → components-DmXYIQ26.js} +83 -141
  12. package/dist/{conversation-binding-route-DPpBRpYI.js → conversation-binding-route-24afmvEC.js} +1 -1
  13. package/dist/{directory-config-AA8wQx0D.js → directory-config-BD4YL7wT.js} +1 -1
  14. package/dist/directory-contract-api.js +1 -1
  15. package/dist/{directory-live-D_kFz_Fj.js → directory-live-BrFVc1Ds.js} +1 -1
  16. package/dist/{doctor-QQTOkBfW.js → doctor-BUB41_lr.js} +2 -2
  17. package/dist/{handle-action.guild-admin-Cc88ZGon.js → handle-action.guild-admin-B0egstYq.js} +2 -2
  18. package/dist/index.js +1 -1
  19. package/dist/{message-handler-CAeEpqWo.js → message-handler-Qdw9c0j4.js} +5 -5
  20. package/dist/{message-handler.preflight-CoKoE3dY.js → message-handler.preflight-Dxi2yBfR.js} +21 -24
  21. package/dist/{message-handler.process-cdIJ_fDT.js → message-handler.process-BYDjtxZJ.js} +37 -45
  22. package/dist/{message-text-C0K4-fkg.js → message-text-BRVqYm-t.js} +1 -1
  23. package/dist/{outbound-adapter-Ch0At5Ra.js → outbound-adapter-DEhthWTk.js} +25 -52
  24. package/dist/{outbound-components-Bnt_7x7r.js → outbound-components-DehyxvA4.js} +3 -3
  25. package/dist/{outbound-session-route-CzzerX2K.js → outbound-session-route-BFGRF9fE.js} +3 -3
  26. package/dist/{pluralkit-B3cUVI7i.js → pluralkit-XmmAHoV6.js} +1 -1
  27. package/dist/{provider-CjI8BSzS.js → provider-DuDtKbF8.js} +21 -21
  28. package/dist/{provider-session.runtime-DdKRMcE9.js → provider-session.runtime-BA2BPyZ4.js} +3 -3
  29. package/dist/provider.runtime-Db8YwZBv.js +2 -0
  30. package/dist/{realtime-session.runtime-37IC-p5K.js → realtime-session.runtime-DgSbX6ay.js} +66 -122
  31. package/dist/{resolve-channels-BexR2eUn.js → resolve-channels-CYseD5Uw.js} +1 -1
  32. package/dist/{resolve-users-BtXBCH5W.js → resolve-users-DrmhDrqm.js} +1 -1
  33. package/dist/{retry-t5RcEsPk.js → retry-BNCxiyyR.js} +8 -3
  34. package/dist/{runtime-DydyfxST.js → runtime-BbWNtfyq.js} +7 -7
  35. package/dist/{runtime-BNlDfLwS.js → runtime-DB7Fb6AU.js} +1 -1
  36. package/dist/runtime-api.js +15 -15
  37. package/dist/{send-mTKSBdmZ.js → send-BnTEIeLE.js} +60 -56
  38. package/dist/{send.components-nsPnc7kK.js → send.components-BWVEcjRP.js} +4 -4
  39. package/dist/{send.outbound-CaOs9Zy1.js → send.outbound-b5xwHTlL.js} +4 -5
  40. package/dist/{send.shared-BJHt0Vyf.js → send.shared-5vxBTagO.js} +2 -2
  41. package/dist/setup-plugin-api.js +1 -1
  42. package/dist/{shared-BNesVA4P.js → shared-BSJWHEMA.js} +1 -1
  43. package/dist/{subagent-hooks-IeZVPLGj.js → subagent-hooks-IzQKX4RQ.js} +2 -2
  44. package/dist/subagent-hooks-api.js +1 -1
  45. package/dist/{system-events-Be5EJI3b.js → system-events-BOiDS8b3.js} +1 -1
  46. package/dist/{target-resolver-C0MnwEki.js → target-resolver-BVI8xSSC.js} +2 -2
  47. package/dist/targets-DbxVbq8k.js +3 -0
  48. package/dist/{thread-bindings-wECUSIIG.js → thread-bindings-D7mcaXQC.js} +3 -3
  49. package/dist/{thread-bindings.manager-B-3UHCc1.js → thread-bindings.manager-B1oySiVc.js} +12 -6
  50. package/dist/{threading-te5ADPQI.js → threading-OQnL-0Zx.js} +3 -3
  51. package/dist/{transcripts-source-DkUhR7YK.js → transcripts-source-D8lH7AkN.js} +1 -1
  52. package/dist/transcripts-source-api.js +1 -1
  53. package/dist/{typing-DAwJF5VT.js → typing-C9q0AQMb.js} +1 -1
  54. package/dist/{voice-runtime-COyYYTDD.js → voice-runtime-Dfhjh1tV.js} +75 -87
  55. package/package.json +5 -4
  56. package/dist/provider.runtime-Bo1WbLLr.js +0 -2
  57. package/dist/targets-DQSye1Rv.js +0 -3
@@ -1,7 +1,7 @@
1
- import { $t as listGuildRoles, At as getChannel, B as readRetryAfter, Bt as addGuildMemberRole, Ct as listMessageReactionUsers, Dt as deleteChannelMessage, Et as deleteChannel, F as DiscordError, Ft as listChannelPins, Gt as createGuildSticker, Ht as createGuildChannel, I as RateLimitError, It as pinChannelMessage, Jt as getGuildMember, Kt as deleteChannelPermission, L as isUnknownDiscordVoiceStateError, Lt as searchGuildMessages, Nt as listChannelArchivedThreads, Ot as editChannel, Pt as listChannelMessages, Qt as listGuildEmojis, R as readDiscordCode, Rt as sendChannelTyping, St as deleteOwnMessageReaction, Tt as createThread, Ut as createGuildEmoji, Vt as createGuildBan, Wt as createGuildScheduledEvent, Xt as listGuildActiveThreads, Yt as getGuildVoiceState, Zt as listGuildChannels, an as timeoutGuildMember, c as createDiscordSendResult, en as listGuildScheduledEvents, i as recordDiscordMessageCreateAmbiguity, in as removeGuildMemberRole, jt as getChannelMessage, kt as editChannelMessage, n as createDiscordRetryRunner, nn as putChannelPermission, on as __exportAll, qt as getGuild, rn as removeGuildMember, t as classifyDiscordDeliveryFailure, tn as moveGuildChannels, xt as createOwnMessageReaction, z as readDiscordMessage, zt as unpinChannelMessage } from "./retry-t5RcEsPk.js";
1
+ import { $t as listGuildEmojis, At as editChannelMessage, B as readDiscordMessage, Bt as unpinChannelMessage, Ct as deleteOwnMessageReaction, Dt as deleteChannel, Et as createThread, Ft as listChannelMessages, Gt as createGuildScheduledEvent, Ht as createGuildBan, I as DiscordError, It as listChannelPins, Jt as getGuild, Kt as createGuildSticker, L as RateLimitError, Lt as pinChannelMessage, Mt as getChannelMessage, Ot as deleteChannelMessage, Pt as listChannelArchivedThreads, Qt as listGuildChannels, R as isUnknownDiscordVoiceStateError, Rt as searchGuildMessages, St as createOwnMessageReaction, Ut as createGuildChannel, V as readRetryAfter, Vt as addGuildMemberRole, Wt as createGuildEmoji, Xt as getGuildVoiceState, Yt as getGuildMember, Zt as listGuildActiveThreads, a as recordDiscordMessageCreateAmbiguity, an as removeGuildMemberRole, c as createDiscordSendReceiptFromResults, en as listGuildRoles, in as removeGuildMember, jt as getChannel, kt as editChannel, l as createDiscordSendResult, n as classifyDiscordDeliveryFailure, nn as moveGuildChannels, o as chunkDiscordTextWithMode, on as timeoutGuildMember, qt as deleteChannelPermission, r as createDiscordRetryRunner, rn as putChannelPermission, sn as __exportAll, tn as listGuildScheduledEvents, wt as listMessageReactionUsers, z as readDiscordCode, zt as sendChannelTyping } from "./retry-BNCxiyyR.js";
2
2
  import { t as parseDiscordRetryAfterBodySeconds } from "./retry-after-BrLjLUJi.js";
3
- import { C as hasAllGuildPermissionsDiscord, I as resolveDiscordClientAccountContext, K as parseAndResolveChannelRecipient, L as resolveDiscordRest, M as resolveDiscordSuppressEmbeds, N as createDiscordClient, O as createDiscordMessageNonce, R as DISCORD_REST_TIMEOUT_MS, S as fetchMemberGuildPermissionsDiscord, T as hasAnyGuildPermissionDiscord, _ as DiscordSendError, b as canViewDiscordGuildChannel, g as DISCORD_MAX_STICKER_BYTES, h as DISCORD_MAX_EVENT_COVER_BYTES, i as formatReactionEmoji, k as resolveDiscordMessageFlags, l as resolveChannelId, m as DISCORD_MAX_EMOJI_BYTES, n as buildDiscordTextChunks, o as normalizeEmojiName, p as sendDiscordText, r as buildReactionIdentifier, s as normalizeReactionEmoji, t as buildDiscordSendError, v as canManageGuildMemberRoleDiscord, w as hasAnyChannelPermissionDiscord, x as fetchChannelPermissionsDiscord, y as canManageGuildRoleDiscord } from "./send.shared-BJHt0Vyf.js";
4
- import { n as sendPollDiscord, o as rewriteDiscordKnownMentions, r as sendStickerDiscord, t as sendMessageDiscord } from "./send.outbound-CaOs9Zy1.js";
3
+ import { C as hasAllGuildPermissionsDiscord, I as resolveDiscordClientAccountContext, K as parseAndResolveChannelRecipient, L as resolveDiscordRest, M as resolveDiscordSuppressEmbeds, N as createDiscordClient, O as createDiscordMessageNonce, R as DISCORD_REST_TIMEOUT_MS, S as fetchMemberGuildPermissionsDiscord, T as hasAnyGuildPermissionDiscord, _ as DiscordSendError, b as canViewDiscordGuildChannel, g as DISCORD_MAX_STICKER_BYTES, h as DISCORD_MAX_EVENT_COVER_BYTES, i as formatReactionEmoji, k as resolveDiscordMessageFlags, l as resolveChannelId, m as DISCORD_MAX_EMOJI_BYTES, n as buildDiscordTextChunks, o as normalizeEmojiName, p as sendDiscordText, r as buildReactionIdentifier, s as normalizeReactionEmoji, t as buildDiscordSendError, v as canManageGuildMemberRoleDiscord, w as hasAnyChannelPermissionDiscord, x as fetchChannelPermissionsDiscord, y as canManageGuildRoleDiscord } from "./send.shared-5vxBTagO.js";
4
+ import { n as sendPollDiscord, o as rewriteDiscordKnownMentions, r as sendStickerDiscord, t as sendMessageDiscord } from "./send.outbound-b5xwHTlL.js";
5
5
  import { n as DISCORD_ATTACHMENT_TOTAL_TIMEOUT_MS } from "./timeouts-D86uWLt_.js";
6
6
  import fs from "node:fs/promises";
7
7
  import { ChannelType } from "discord-api-types/v10";
@@ -404,12 +404,6 @@ async function searchMessagesDiscord(query, opts) {
404
404
  //#region extensions/discord/src/send.webhook.ts
405
405
  const DISCORD_WEBHOOK_ERROR_BODY_LIMIT_BYTES = 8192;
406
406
  const DISCORD_WEBHOOK_TIMEOUT_MS = DISCORD_REST_TIMEOUT_MS;
407
- function resolveWebhookExecutionUrl(params) {
408
- const baseUrl = new URL(`https://discord.com/api/v10/webhooks/${encodeURIComponent(params.webhookId)}/${encodeURIComponent(params.webhookToken)}`);
409
- baseUrl.searchParams.set("wait", params.wait === false ? "false" : "true");
410
- if (params.threadId !== void 0 && params.threadId !== null && params.threadId !== "") baseUrl.searchParams.set("thread_id", String(params.threadId));
411
- return baseUrl.toString();
412
- }
413
407
  function coerceWebhookErrorBody(raw) {
414
408
  if (!raw) return;
415
409
  try {
@@ -460,63 +454,73 @@ async function sendWebhookMessageDiscord(text, opts) {
460
454
  conversationId: threadConversationId,
461
455
  sourceId: webhookId
462
456
  });
463
- const url = resolveWebhookExecutionUrl({
464
- webhookId,
465
- webhookToken,
466
- threadId: opts.threadId,
467
- wait: opts.wait
468
- });
457
+ const url = new URL(`https://discord.com/api/v10/webhooks/${encodeURIComponent(webhookId)}/${encodeURIComponent(webhookToken)}`);
458
+ url.searchParams.set("wait", opts.wait === false ? "false" : "true");
459
+ if (opts.threadId != null && opts.threadId !== "") url.searchParams.set("thread_id", String(opts.threadId));
469
460
  const deadline = buildTimeoutAbortSignal({
470
461
  timeoutMs: DISCORD_WEBHOOK_TIMEOUT_MS,
471
462
  operation: "discord.webhook.send"
472
463
  });
473
464
  const request = createDiscordRetryRunner({ signal: deadline.signal });
465
+ const chunks = chunkDiscordTextWithMode(rewrittenText, { maxLines: Number.MAX_SAFE_INTEGER });
466
+ const results = [];
474
467
  try {
475
- const response = await request(async () => {
476
- await opts.onPlatformSendDispatch?.();
477
- opts.assertPlatformSendAuthorized?.();
478
- const attemptResponse = await (proxyFetch ?? fetch)(url, {
479
- method: "POST",
480
- headers: { "content-type": "application/json" },
481
- body: JSON.stringify({
482
- content: rewrittenText,
483
- username: normalizeOptionalString(opts.username),
484
- avatar_url: normalizeOptionalString(opts.avatarUrl),
485
- ...flags ? { flags } : {},
486
- ...messageReference ? { message_reference: messageReference } : {}
487
- }),
488
- signal: deadline.signal
468
+ for (const content of chunks.length ? chunks : [""]) {
469
+ const response = await request(async () => {
470
+ await opts.onPlatformSendDispatch?.();
471
+ opts.assertPlatformSendAuthorized?.();
472
+ const attemptResponse = await (proxyFetch ?? fetch)(url.toString(), {
473
+ method: "POST",
474
+ headers: { "content-type": "application/json" },
475
+ body: JSON.stringify({
476
+ content,
477
+ username: normalizeOptionalString(opts.username),
478
+ avatar_url: normalizeOptionalString(opts.avatarUrl),
479
+ ...flags ? { flags } : {},
480
+ ...messageReference ? { message_reference: messageReference } : {}
481
+ }),
482
+ signal: deadline.signal
483
+ });
484
+ if (!attemptResponse.ok) await throwWebhookResponseError(attemptResponse, deadline.signal);
485
+ return attemptResponse;
486
+ }, "webhook", { safety: "non-idempotent-create" });
487
+ const payload = response.status === 204 ? {} : await readProviderJsonResponse(response, "Discord webhook send").catch(() => {
488
+ throwIfWebhookDeadlineExpired(deadline.signal);
489
+ return {};
489
490
  });
490
- if (!attemptResponse.ok) await throwWebhookResponseError(attemptResponse, deadline.signal);
491
- return attemptResponse;
492
- }, "webhook", { safety: "non-idempotent-create" });
493
- const payload = response.status === 204 ? {} : await readProviderJsonResponse(response, "Discord webhook send").catch(() => {
494
- throwIfWebhookDeadlineExpired(deadline.signal);
495
- return {};
496
- });
497
- try {
498
- recordChannelActivity({
491
+ try {
492
+ recordChannelActivity({
493
+ channel: "discord",
494
+ accountId: account.accountId,
495
+ direction: "outbound"
496
+ });
497
+ } catch {}
498
+ const result = createDiscordSendResult({
499
+ result: payload,
500
+ fallbackChannelId: opts.threadId ? String(opts.threadId) : "",
501
+ kind: "text",
502
+ ...opts.threadId != null ? { threadId: opts.threadId } : {},
503
+ ...replyTo ? { replyToId: replyTo } : {}
504
+ });
505
+ const resultConversationId = result.channelId.trim();
506
+ if (result.messageId && resultConversationId) recordOutboundMessageIdentity({
499
507
  channel: "discord",
500
508
  accountId: account.accountId,
501
- direction: "outbound"
509
+ conversationId: resultConversationId,
510
+ messageId: result.messageId,
511
+ sourceId: webhookId
502
512
  });
503
- } catch {}
504
- const result = createDiscordSendResult({
505
- result: payload,
506
- fallbackChannelId: opts.threadId ? String(opts.threadId) : "",
507
- kind: "text",
508
- ...opts.threadId != null ? { threadId: opts.threadId } : {},
509
- ...replyTo ? { replyToId: replyTo } : {}
510
- });
511
- const resultConversationId = result.channelId.trim();
512
- if (result.messageId !== "unknown" && resultConversationId) recordOutboundMessageIdentity({
513
- channel: "discord",
514
- accountId: account.accountId,
515
- conversationId: resultConversationId,
516
- messageId: result.messageId,
517
- sourceId: webhookId
518
- });
519
- return result;
513
+ results.push(result);
514
+ await opts.onDeliveryResult?.(result);
515
+ }
516
+ const last = expectDefined(results.at(-1), "Discord webhook delivery result");
517
+ return results.length === 1 ? last : {
518
+ ...last,
519
+ receipt: createDiscordSendReceiptFromResults({ results })
520
+ };
521
+ } catch (error) {
522
+ if (results.length) recordDiscordMessageCreateAmbiguity(error);
523
+ throw error;
520
524
  } finally {
521
525
  deadline.cleanup();
522
526
  }
@@ -1,8 +1,8 @@
1
- import { c as createDiscordSendResult, kt as editChannelMessage, on as __exportAll, q as serializePayload, wt as createChannelMessage } from "./retry-t5RcEsPk.js";
2
- import { d as buildDiscordComponentMessage, f as buildDiscordComponentMessageFlags, g as resolveDiscordComponentAttachmentName } from "./components-gvRA0oaI.js";
1
+ import { At as editChannelMessage, J as serializePayload, Tt as createChannelMessage, l as createDiscordSendResult, sn as __exportAll } from "./retry-BNCxiyyR.js";
2
+ import { d as buildDiscordComponentMessage, f as buildDiscordComponentMessageFlags, g as resolveDiscordComponentAttachmentName } from "./components-DmXYIQ26.js";
3
3
  import { n as getOptionalDiscordRuntime } from "./runtime-DgnVQ7zW.js";
4
- import { E as SUPPRESS_NOTIFICATIONS_FLAG, K as parseAndResolveChannelRecipient, N as createDiscordClient, O as createDiscordMessageNonce, l as resolveChannelId, t as buildDiscordSendError, u as resolveDiscordChannel } from "./send.shared-BJHt0Vyf.js";
5
- import { t as sendMessageDiscord } from "./send.outbound-CaOs9Zy1.js";
4
+ import { E as SUPPRESS_NOTIFICATIONS_FLAG, K as parseAndResolveChannelRecipient, N as createDiscordClient, O as createDiscordMessageNonce, l as resolveChannelId, t as buildDiscordSendError, u as resolveDiscordChannel } from "./send.shared-5vxBTagO.js";
5
+ import { t as sendMessageDiscord } from "./send.outbound-b5xwHTlL.js";
6
6
  import { ChannelType } from "discord-api-types/v10";
7
7
  import { asDateTimestampMs, isFutureDateTimestampMs, resolveDateTimestampMs, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
8
8
  import { uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
@@ -1,6 +1,6 @@
1
- import { Tt as createThread, c as createDiscordSendResult, s as createDiscordSendReceiptFromResults, u as createReusableDiscordReplyReference, wt as createChannelMessage } from "./retry-t5RcEsPk.js";
2
- import { i as normalizeDiscordHandleKey, o as resolveDiscordDirectoryUserId } from "./directory-live-D_kFz_Fj.js";
3
- import { A as resolveDiscordSendComponents, D as buildDiscordMessageRequest, K as parseAndResolveChannelRecipient, M as resolveDiscordSuppressEmbeds, N as createDiscordClient, O as createDiscordMessageNonce, a as normalizeDiscordPollInput, c as normalizeStickerIds, f as sendDiscordMedia, j as resolveDiscordSendEmbeds, k as resolveDiscordMessageFlags, l as resolveChannelId, n as buildDiscordTextChunks, p as sendDiscordText, t as buildDiscordSendError, u as resolveDiscordChannel } from "./send.shared-BJHt0Vyf.js";
1
+ import { Et as createThread, Tt as createChannelMessage, c as createDiscordSendReceiptFromResults, d as createReusableDiscordReplyReference, l as createDiscordSendResult } from "./retry-BNCxiyyR.js";
2
+ import { i as normalizeDiscordHandleKey, o as resolveDiscordDirectoryUserId } from "./directory-live-BrFVc1Ds.js";
3
+ import { A as resolveDiscordSendComponents, D as buildDiscordMessageRequest, K as parseAndResolveChannelRecipient, M as resolveDiscordSuppressEmbeds, N as createDiscordClient, O as createDiscordMessageNonce, a as normalizeDiscordPollInput, c as normalizeStickerIds, f as sendDiscordMedia, j as resolveDiscordSendEmbeds, k as resolveDiscordMessageFlags, l as resolveChannelId, n as buildDiscordTextChunks, p as sendDiscordText, t as buildDiscordSendError, u as resolveDiscordChannel } from "./send.shared-5vxBTagO.js";
4
4
  import { ChannelType } from "discord-api-types/v10";
5
5
  import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
6
6
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalString, normalizeOptionalStringifiedId } from "openclaw/plugin-sdk/string-coerce-runtime";
@@ -700,8 +700,7 @@ async function sendMessageDiscord(to, text, opts) {
700
700
  direction: "outbound"
701
701
  });
702
702
  return {
703
- messageId: result.id || "unknown",
704
- channelId: result.channel_id ?? channelId,
703
+ ...toDiscordSendResult(result, channelId),
705
704
  receipt: createDiscordSendReceiptFromResults({ results: deliveredResults })
706
705
  };
707
706
  }
@@ -1,6 +1,6 @@
1
- import { At as getChannel, J as Embed, Jt as getGuildMember, K as hasDiscordV2Components, Mt as getThreadMember, P as RequestClient, a as chunkDiscordTextWithMode, bt as getCurrentUser, d as resolveDiscordReplyMessageId, n as createDiscordRetryRunner, q as serializePayload, qt as getGuild, wt as createChannelMessage, yt as createUserDmChannel } from "./retry-t5RcEsPk.js";
1
+ import { F as RequestClient, J as serializePayload, Jt as getGuild, Nt as getThreadMember, Tt as createChannelMessage, Y as Embed, Yt as getGuildMember, bt as createUserDmChannel, f as resolveDiscordReplyMessageId, jt as getChannel, o as chunkDiscordTextWithMode, q as hasDiscordV2Components, r as createDiscordRetryRunner, xt as getCurrentUser } from "./retry-BNCxiyyR.js";
2
2
  import { c as resolveDiscordAccount, m as normalizeDiscordToken, o as mergeDiscordAccountConfig } from "./accounts-CwJQoLjM.js";
3
- import { t as parseAndResolveDiscordTarget } from "./target-resolver-C0MnwEki.js";
3
+ import { t as parseAndResolveDiscordTarget } from "./target-resolver-BVI8xSSC.js";
4
4
  import { t as isDiscordThreadChannelType } from "./channel-type-CVLZyGYS.js";
5
5
  import { ChannelType, MessageFlags, PermissionFlagsBits } from "discord-api-types/v10";
6
6
  import { randomBytes } from "node:crypto";
@@ -1,2 +1,2 @@
1
- import { t as discordSetupPlugin } from "./channel.setup-z_ewMVa9.js";
1
+ import { t as discordSetupPlugin } from "./channel.setup-DTL7kPOM.js";
2
2
  export { discordSetupPlugin };
@@ -117,7 +117,7 @@ const DISCORD_LEGACY_CONFIG_RULES = [];
117
117
  //#endregion
118
118
  //#region extensions/discord/src/shared.ts
119
119
  const DISCORD_CHANNEL = "discord";
120
- const loadDiscordDoctorModule = createLazyRuntimeModule(() => import("./doctor-QQTOkBfW.js"));
120
+ const loadDiscordDoctorModule = createLazyRuntimeModule(() => import("./doctor-BUB41_lr.js"));
121
121
  const discordDoctor = {
122
122
  dmAllowFromMode: "topOnly",
123
123
  groupModel: "route",
@@ -1,5 +1,5 @@
1
- import { on as __exportAll } from "./retry-t5RcEsPk.js";
2
- import { o as unbindThreadBindingsBySessionKey, r as listThreadBindingsBySessionKey } from "./thread-bindings-wECUSIIG.js";
1
+ import { sn as __exportAll } from "./retry-BNCxiyyR.js";
2
+ import { o as unbindThreadBindingsBySessionKey, r as listThreadBindingsBySessionKey } from "./thread-bindings-D7mcaXQC.js";
3
3
  import { normalizeOptionalLowercaseString, normalizeOptionalStringifiedId } from "openclaw/plugin-sdk/string-coerce-runtime";
4
4
  //#region extensions/discord/src/subagent-hooks.ts
5
5
  var subagent_hooks_exports = /* @__PURE__ */ __exportAll({
@@ -1,6 +1,6 @@
1
1
  import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
2
2
  //#region extensions/discord/subagent-hooks-api.ts
3
- const loadDiscordSubagentHooksModule = createLazyRuntimeModule(() => import("./subagent-hooks-IeZVPLGj.js").then((n) => n.r));
3
+ const loadDiscordSubagentHooksModule = createLazyRuntimeModule(() => import("./subagent-hooks-IzQKX4RQ.js").then((n) => n.r));
4
4
  function registerDiscordSubagentHooks(api) {
5
5
  api.on("subagent_ended", async (event) => {
6
6
  const { handleDiscordSubagentEnded } = await loadDiscordSubagentHooksModule();
@@ -1,4 +1,4 @@
1
- import { y as discord_exports } from "./retry-t5RcEsPk.js";
1
+ import { b as discord_exports } from "./retry-BNCxiyyR.js";
2
2
  import { x as formatDiscordUserTag } from "./allow-list-C2JuH-R0.js";
3
3
  //#region extensions/discord/src/monitor/system-events.ts
4
4
  function resolveDiscordSystemEvent(message, location) {
@@ -1,6 +1,6 @@
1
- import { _ as parseDiscordTarget, on as __exportAll, p as allowFromContainsDiscordUserId } from "./retry-t5RcEsPk.js";
1
+ import { m as allowFromContainsDiscordUserId, sn as __exportAll, v as parseDiscordTarget } from "./retry-BNCxiyyR.js";
2
2
  import { c as resolveDiscordAccount, l as resolveDiscordAccountAllowFrom } from "./accounts-CwJQoLjM.js";
3
- import { a as rememberDiscordDirectoryUser, r as listDiscordDirectoryPeersLive } from "./directory-live-D_kFz_Fj.js";
3
+ import { a as rememberDiscordDirectoryUser, r as listDiscordDirectoryPeersLive } from "./directory-live-BrFVc1Ds.js";
4
4
  import { buildMessagingTarget } from "openclaw/plugin-sdk/channel-targets";
5
5
  //#region extensions/discord/src/send-target-parsing.ts
6
6
  const parseDiscordSendTarget = (raw, options = {}) => parseDiscordTarget(raw, options);
@@ -0,0 +1,3 @@
1
+ import "./retry-BNCxiyyR.js";
2
+ import "./target-resolver-BVI8xSSC.js";
3
+ export {};
@@ -1,8 +1,8 @@
1
- import { _ as parseDiscordTarget, on as __exportAll } from "./retry-t5RcEsPk.js";
2
- import "./targets-DQSye1Rv.js";
1
+ import { sn as __exportAll, v as parseDiscordTarget } from "./retry-BNCxiyyR.js";
2
+ import "./targets-DbxVbq8k.js";
3
3
  import { C as resolveThreadBindingMaxAgeExpiresAt, O as shouldPersistBindingMutations, S as resolveThreadBindingInactivityExpiresAt, T as saveBindingsToDisk, h as refreshUnboundThreadWebhookIdentity, m as normalizeThreadId, n as MANAGERS_BY_ACCOUNT_ID, t as BINDINGS_BY_THREAD_ID, u as getThreadBindingToken, v as removeBindingRecord, w as resolveThreadBindingMaxAgeMs$1, x as resolveThreadBindingIdleTimeoutMs$1 } from "./thread-bindings.state-D8OMdk4O.js";
4
4
  import { n as setThreadBindingMaxAgeBySessionKey, r as resolveBindingIdsForTargetSession, t as setThreadBindingIdleTimeoutBySessionKey } from "./thread-bindings.session-updates-CC7HoQvt.js";
5
- import { _ as resolveThreadBindingThreadName, g as resolveThreadBindingIntroText, h as formatThreadBindingDurationLabel, m as resolveThreadBindingPersonaFromRecord, n as createThreadBindingManager, o as resolveChannelIdForBinding, p as resolveThreadBindingPersona, r as getThreadBindingManager, t as createNoopThreadBindingManager } from "./thread-bindings.manager-B-3UHCc1.js";
5
+ import { _ as resolveThreadBindingThreadName, g as resolveThreadBindingIntroText, h as formatThreadBindingDurationLabel, m as resolveThreadBindingPersonaFromRecord, n as createThreadBindingManager, o as resolveChannelIdForBinding, p as resolveThreadBindingPersona, r as getThreadBindingManager, t as createNoopThreadBindingManager } from "./thread-bindings.manager-B1oySiVc.js";
6
6
  import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
7
7
  import { normalizeOptionalLowercaseString, normalizeOptionalString, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
8
8
  import { resolveThreadBindingIdleTimeoutMs, resolveThreadBindingMaxAgeMs, resolveThreadBindingsEnabled } from "openclaw/plugin-sdk/conversation-runtime";
@@ -1,14 +1,14 @@
1
- import { At as getChannel, on as __exportAll, v as resolveDiscordChannelId, vt as createChannelWebhook } from "./retry-t5RcEsPk.js";
2
- import { P as createDiscordRestClient } from "./send.shared-BJHt0Vyf.js";
3
- import { t as sendMessageDiscord } from "./send.outbound-CaOs9Zy1.js";
1
+ import { jt as getChannel, sn as __exportAll, t as canFallbackDiscordWebhookSend, y as resolveDiscordChannelId, yt as createChannelWebhook } from "./retry-BNCxiyyR.js";
2
+ import { P as createDiscordRestClient } from "./send.shared-5vxBTagO.js";
3
+ import { t as sendMessageDiscord } from "./send.outbound-b5xwHTlL.js";
4
4
  import { t as isDiscordThreadChannelType } from "./channel-type-CVLZyGYS.js";
5
- import { c as sendWebhookMessageDiscord, u as createThreadDiscord } from "./send-mTKSBdmZ.js";
5
+ import { c as sendWebhookMessageDiscord, u as createThreadDiscord } from "./send-BnTEIeLE.js";
6
6
  import { A as toReusableWebhookKey, C as resolveThreadBindingMaxAgeExpiresAt, D as shouldDefaultPersist, E as setBindingRecord, S as resolveThreadBindingInactivityExpiresAt, T as saveBindingsToDisk, _ as rememberThreadBindingToken, b as resolveBindingRecordKey, c as ensureBindingsLoaded, f as normalizeTargetKind, g as rememberReusableWebhook, h as refreshUnboundThreadWebhookIdentity, i as REUSABLE_WEBHOOKS_BY_ACCOUNT_CHANNEL, l as forgetThreadBindingToken, m as normalizeThreadId, n as MANAGERS_BY_ACCOUNT_ID, p as normalizeThreadBindingDurationMs, r as PERSIST_BY_ACCOUNT_ID, s as THREAD_BINDING_TOUCH_PERSIST_MIN_INTERVAL_MS, t as BINDINGS_BY_THREAD_ID, u as getThreadBindingToken, v as removeBindingRecord, w as resolveThreadBindingMaxAgeMs$1, x as resolveThreadBindingIdleTimeoutMs$1, y as resolveBindingIdsForSession } from "./thread-bindings.state-D8OMdk4O.js";
7
7
  import { parseStrictNonNegativeInteger } from "openclaw/plugin-sdk/number-runtime";
8
8
  import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
9
9
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
10
10
  import { getRuntimeConfigSnapshot } from "openclaw/plugin-sdk/runtime-config-snapshot";
11
- import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
11
+ import { createSubsystemLogger, logVerbose } from "openclaw/plugin-sdk/runtime-env";
12
12
  import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
13
13
  import { SYSTEM_MARK } from "openclaw/plugin-sdk/text-chunking";
14
14
  import { formatThreadBindingDurationLabel, registerSessionBindingAdapter, resolveThreadBindingConversationIdFromBindingId, resolveThreadBindingFarewellText, resolveThreadBindingIntroText, resolveThreadBindingThreadName, unregisterSessionBindingAdapter } from "openclaw/plugin-sdk/conversation-runtime";
@@ -96,6 +96,7 @@ const THREAD_BINDINGS_SWEEP_INTERVAL_MS = 12e4;
96
96
  const DEFAULT_THREAD_BINDING_IDLE_TIMEOUT_MS = 864e5;
97
97
  //#endregion
98
98
  //#region extensions/discord/src/monitor/thread-bindings.discord-api.ts
99
+ const log = createSubsystemLogger("discord/thread-bindings");
99
100
  function buildThreadTarget(threadId) {
100
101
  return /^(channel:|user:)/i.test(threadId) ? threadId : `channel:${threadId}`;
101
102
  }
@@ -155,7 +156,12 @@ async function maybeSendBindingMessage(params) {
155
156
  });
156
157
  return;
157
158
  } catch (err) {
158
- logVerbose(`discord thread binding webhook send failed: ${summarizeDiscordError(err)}`);
159
+ const fallbackToBot = canFallbackDiscordWebhookSend(err);
160
+ log.warn("discord thread binding webhook send failed", {
161
+ error: summarizeDiscordError(err),
162
+ fallbackToBot
163
+ });
164
+ if (!fallbackToBot) return;
159
165
  }
160
166
  try {
161
167
  await sendMessageDiscord(buildThreadTarget(record.threadId), text, {
@@ -1,7 +1,7 @@
1
- import { F as DiscordError, Ot as editChannel, Tt as createThread, jt as getChannelMessage, on as __exportAll, y as discord_exports } from "./retry-t5RcEsPk.js";
1
+ import { Et as createThread, I as DiscordError, Mt as getChannelMessage, b as discord_exports, kt as editChannel, sn as __exportAll } from "./retry-BNCxiyyR.js";
2
2
  import { t as isDiscordThreadChannelType } from "./channel-type-CVLZyGYS.js";
3
- import { d as resolveDiscordChannelParentSafe, l as resolveDiscordChannelNameSafe, s as resolveDiscordChannelIdSafe, u as resolveDiscordChannelParentIdSafe } from "./thread-bindings.manager-B-3UHCc1.js";
4
- import { a as formatDiscordMediaText, h as resolveDiscordMessageChannelId, m as resolveDiscordChannelInfo, n as resolveDiscordForwardedMessagesTextFromSnapshots, t as resolveDiscordEmbedText } from "./message-text-C0K4-fkg.js";
3
+ import { d as resolveDiscordChannelParentSafe, l as resolveDiscordChannelNameSafe, s as resolveDiscordChannelIdSafe, u as resolveDiscordChannelParentIdSafe } from "./thread-bindings.manager-B1oySiVc.js";
4
+ import { a as formatDiscordMediaText, h as resolveDiscordMessageChannelId, m as resolveDiscordChannelInfo, n as resolveDiscordForwardedMessagesTextFromSnapshots, t as resolveDiscordEmbedText } from "./message-text-BRVqYm-t.js";
5
5
  import { buildAgentSessionKey } from "openclaw/plugin-sdk/routing";
6
6
  import { normalizeOptionalString, normalizeOptionalStringifiedId } from "openclaw/plugin-sdk/string-coerce-runtime";
7
7
  import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
@@ -1,4 +1,4 @@
1
- import { on as __exportAll } from "./retry-t5RcEsPk.js";
1
+ import { sn as __exportAll } from "./retry-BNCxiyyR.js";
2
2
  import { a as listEnabledDiscordAccounts, c as resolveDiscordAccount } from "./accounts-CwJQoLjM.js";
3
3
  import { n as resolveDiscordVoiceEnabled, r as authorizeDiscordVoiceIngress, t as resolveDiscordVoiceAccess } from "./owner-access-yc1sX7Gx.js";
4
4
  import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-id";
@@ -1,4 +1,4 @@
1
- import { t as discordVoiceTranscriptsSourceProvider } from "./transcripts-source-DkUhR7YK.js";
1
+ import { t as discordVoiceTranscriptsSourceProvider } from "./transcripts-source-D8lH7AkN.js";
2
2
  //#region extensions/discord/transcripts-source-api.ts
3
3
  function registerDiscordTranscriptSourceProvider(api) {
4
4
  api.registerTranscriptSourceProvider(discordVoiceTranscriptsSourceProvider);
@@ -1,4 +1,4 @@
1
- import { Rt as sendChannelTyping, on as __exportAll } from "./retry-t5RcEsPk.js";
1
+ import { sn as __exportAll, zt as sendChannelTyping } from "./retry-BNCxiyyR.js";
2
2
  import { c as raceWithTimeout } from "./timeouts-D86uWLt_.js";
3
3
  //#region extensions/discord/src/monitor/typing.ts
4
4
  var typing_exports = /* @__PURE__ */ __exportAll({ sendTyping: () => sendTyping });
@@ -1,13 +1,14 @@
1
- import { D as ReadyListener, L as isUnknownDiscordVoiceStateError, O as ResumedListener, Yt as getGuildVoiceState, _ as parseDiscordTarget, j as VoiceStateUpdateListener, on as __exportAll, y as discord_exports } from "./retry-t5RcEsPk.js";
1
+ import { M as VoiceStateUpdateListener, O as ReadyListener, R as isUnknownDiscordVoiceStateError, Xt as getGuildVoiceState, b as discord_exports, k as ResumedListener, sn as __exportAll, v as parseDiscordTarget } from "./retry-BNCxiyyR.js";
2
2
  import { t as getDiscordRuntime } from "./runtime-DgnVQ7zW.js";
3
3
  import { a as normalizeDiscordSlug, h as resolveDiscordOwnerAccess, x as formatDiscordUserTag } from "./allow-list-C2JuH-R0.js";
4
- import { a as formatMention } from "./send.outbound-CaOs9Zy1.js";
4
+ import { a as formatMention } from "./send.outbound-b5xwHTlL.js";
5
5
  import { n as resolveDiscordVoiceEnabled, r as authorizeDiscordVoiceIngress, t as resolveDiscordVoiceAccess } from "./owner-access-yc1sX7Gx.js";
6
- import { b as resolveFetchedDiscordThreadLikeChannelContext, m as buildDiscordGroupSystemPrompt } from "./provider-CjI8BSzS.js";
6
+ import { b as resolveFetchedDiscordThreadLikeChannelContext, m as buildDiscordGroupSystemPrompt } from "./provider-DuDtKbF8.js";
7
7
  import { createRequire } from "node:module";
8
8
  import fs from "node:fs/promises";
9
9
  import { asDateTimestampMs, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
10
10
  import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
11
+ import { readByteStreamWithLimit } from "openclaw/plugin-sdk/response-limit-runtime";
11
12
  import { formatErrorMessage } from "openclaw/plugin-sdk/ssrf-runtime";
12
13
  import { resolveAgentRoute } from "openclaw/plugin-sdk/routing";
13
14
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
@@ -228,14 +229,19 @@ function pcmInt16ToBuffer(pcm) {
228
229
  return Buffer.from(pcm.buffer, pcm.byteOffset, pcm.byteLength);
229
230
  }
230
231
  async function decodeOpusStream(stream, params) {
231
- const chunks = [];
232
- await decodeOpusStreamChunks(stream, {
233
- ...params,
234
- onChunk: (chunk) => chunks.push(chunk)
232
+ return await readByteStreamWithLimit(decodeOpusFrames(stream, params), {
233
+ maxBytes: params.maxBytes,
234
+ onOverflow: () => /* @__PURE__ */ new Error(`Discord voice capture exceeds the transcription PCM limit (${params.maxBytes} bytes); speak a shorter segment.`)
235
235
  });
236
- return Buffer.concat(chunks);
237
236
  }
238
237
  async function decodeOpusStreamChunks(stream, params) {
238
+ try {
239
+ for await (const pcm of decodeOpusFrames(stream, params)) params.onChunk(pcm);
240
+ } catch (err) {
241
+ params.onError?.(err);
242
+ }
243
+ }
244
+ async function* decodeOpusFrames(stream, params) {
239
245
  let decoder;
240
246
  try {
241
247
  decoder = await createDecoder({
@@ -254,7 +260,7 @@ async function decodeOpusStreamChunks(stream, params) {
254
260
  for await (const chunk of stream) {
255
261
  if (!chunk || !(chunk instanceof Buffer) || chunk.length === 0) continue;
256
262
  const decoded = decoder.decode(chunk, { maxFrameSize: DISCORD_OPUS_FRAME_SIZE });
257
- if (decoded.length > 0) params.onChunk(pcmInt16ToBuffer(decoded));
263
+ if (decoded.length > 0) yield pcmInt16ToBuffer(decoded);
258
264
  }
259
265
  } catch (err) {
260
266
  params.onError?.(err);
@@ -1356,70 +1362,43 @@ var DiscordVoiceFollowing = class {
1356
1362
  //#endregion
1357
1363
  //#region extensions/discord/src/voice/capture-state.ts
1358
1364
  function createVoiceCaptureState() {
1359
- return {
1360
- activeSpeakers: /* @__PURE__ */ new Set(),
1361
- activeCaptureStreams: /* @__PURE__ */ new Map(),
1362
- captureFinalizeTimers: /* @__PURE__ */ new Map(),
1363
- captureGenerations: /* @__PURE__ */ new Map()
1364
- };
1365
+ return /* @__PURE__ */ new Map();
1365
1366
  }
1366
1367
  function stopVoiceCaptureState(state) {
1367
- for (const { timer } of state.captureFinalizeTimers.values()) clearTimeout(timer);
1368
- state.captureFinalizeTimers.clear();
1369
- for (const { stream } of state.activeCaptureStreams.values()) stream.destroy();
1370
- state.activeCaptureStreams.clear();
1371
- state.captureGenerations.clear();
1372
- state.activeSpeakers.clear();
1373
- }
1374
- function getActiveVoiceCapture(state, userId) {
1375
- return state.activeCaptureStreams.get(userId);
1376
- }
1377
- function isVoiceCaptureActive(state, userId) {
1378
- return state.activeSpeakers.has(userId);
1379
- }
1380
- function clearVoiceCaptureFinalizeTimer(state, userId, generation) {
1381
- const scheduled = state.captureFinalizeTimers.get(userId);
1382
- if (!scheduled || generation !== void 0 && scheduled.generation !== generation) return false;
1383
- clearTimeout(scheduled.timer);
1384
- state.captureFinalizeTimers.delete(userId);
1368
+ const captures = [...state.values()];
1369
+ state.clear();
1370
+ for (const capture of captures) {
1371
+ clearVoiceCaptureFinalizeTimer(capture);
1372
+ capture.stream?.destroy();
1373
+ }
1374
+ }
1375
+ function clearVoiceCaptureFinalizeTimer(capture) {
1376
+ if (!capture.finalizeTimer) return false;
1377
+ clearTimeout(capture.finalizeTimer);
1378
+ delete capture.finalizeTimer;
1385
1379
  return true;
1386
1380
  }
1387
1381
  function beginVoiceCapture(state, userId, stream) {
1388
- const generation = (state.captureGenerations.get(userId) ?? 0) + 1;
1389
- state.captureGenerations.set(userId, generation);
1390
- state.activeSpeakers.add(userId);
1391
- state.activeCaptureStreams.set(userId, {
1392
- generation,
1393
- stream
1394
- });
1395
- clearVoiceCaptureFinalizeTimer(state, userId, generation);
1396
- return generation;
1397
- }
1398
- function finishVoiceCapture(state, userId, generation) {
1399
- clearVoiceCaptureFinalizeTimer(state, userId, generation);
1400
- if (state.activeCaptureStreams.get(userId)?.generation !== generation) return false;
1401
- state.activeCaptureStreams.delete(userId);
1402
- state.activeSpeakers.delete(userId);
1382
+ const capture = { stream };
1383
+ state.set(userId, capture);
1384
+ return capture;
1385
+ }
1386
+ function finishVoiceCapture(state, userId, capture) {
1387
+ clearVoiceCaptureFinalizeTimer(capture);
1388
+ if (state.get(userId) !== capture) return false;
1389
+ state.delete(userId);
1403
1390
  return true;
1404
1391
  }
1405
1392
  function scheduleVoiceCaptureFinalize(params) {
1406
1393
  const { state, userId, delayMs, onFinalize } = params;
1407
- const capture = state.activeCaptureStreams.get(userId);
1394
+ const capture = state.get(userId);
1408
1395
  if (!capture) return false;
1409
- clearVoiceCaptureFinalizeTimer(state, userId, capture.generation);
1410
- const timer = setTimeout(() => {
1411
- const activeCapture = state.activeCaptureStreams.get(userId);
1412
- if (!activeCapture || activeCapture.generation !== capture.generation) return;
1413
- state.captureFinalizeTimers.delete(userId);
1414
- state.activeCaptureStreams.delete(userId);
1415
- state.activeSpeakers.delete(userId);
1416
- onFinalize?.(activeCapture);
1417
- activeCapture.stream.destroy();
1396
+ clearVoiceCaptureFinalizeTimer(capture);
1397
+ capture.finalizeTimer = setTimeout(() => {
1398
+ if (!finishVoiceCapture(state, userId, capture)) return;
1399
+ onFinalize?.(capture);
1400
+ capture.stream?.destroy();
1418
1401
  }, delayMs);
1419
- state.captureFinalizeTimers.set(userId, {
1420
- generation: capture.generation,
1421
- timer
1422
- });
1423
1402
  return true;
1424
1403
  }
1425
1404
  //#endregion
@@ -1663,9 +1642,9 @@ var DiscordVoiceReceive = class {
1663
1642
  const botUserId = this.params.botUserId();
1664
1643
  if (botUserId && userId === botUserId) return;
1665
1644
  this.params.membership.notePresent(entry, userId);
1666
- if (isVoiceCaptureActive(entry.capture, userId)) {
1667
- const activeCapture = getActiveVoiceCapture(entry.capture, userId);
1668
- const extended = activeCapture ? clearVoiceCaptureFinalizeTimer(entry.capture, userId, activeCapture.generation) : false;
1645
+ const activeCapture = entry.capture.get(userId);
1646
+ if (activeCapture) {
1647
+ const extended = clearVoiceCaptureFinalizeTimer(activeCapture);
1669
1648
  logVoiceVerbose(`capture start ignored (already active): guild ${entry.guildId} channel ${entry.channelId} user ${userId}${extended ? " (finalize canceled)" : ""}`);
1670
1649
  return;
1671
1650
  }
@@ -1678,24 +1657,7 @@ var DiscordVoiceReceive = class {
1678
1657
  logVoiceVerbose(`capture ignored during playback: guild ${entry.guildId} channel ${entry.channelId} user ${userId}`);
1679
1658
  return;
1680
1659
  }
1681
- const realtimeIngress = realtime ? await this.resolveDiscordVoiceIngressContext(entry, userId) : void 0;
1682
- if (realtime && !realtimeIngress) {
1683
- logVoiceVerbose(`realtime capture unauthorized: guild ${entry.guildId} channel ${entry.channelId} user ${userId}`);
1684
- return;
1685
- }
1686
- if (!this.params.isEntryCurrent(entry)) return;
1687
- if (entry.player.state.status === voiceSdk.AudioPlayerStatus.Playing && realtime) {
1688
- if (!realtime.isBargeInEnabled()) {
1689
- logger$3.info(`discord voice: realtime capture ignored during playback (barge-in disabled): guild ${entry.guildId} channel ${entry.channelId} user ${userId}`);
1690
- return;
1691
- }
1692
- logVoiceVerbose(`realtime barge-in: guild ${entry.guildId} channel ${entry.channelId} user ${userId}`);
1693
- logger$3.info(`discord voice: realtime barge-in detected source=speaker-start guild=${entry.guildId} channel=${entry.channelId} user=${userId} playerStatus=${entry.player.state.status}`);
1694
- realtime.handleBargeIn("speaker-start");
1695
- }
1696
- this.enableDaveReceivePassthrough(entry, `speaker ${userId} start`, 15);
1697
- const stream = entry.connection.receiver.subscribe(userId, { end: { behavior: voiceSdk.EndBehaviorType.Manual } });
1698
- const generation = beginVoiceCapture(entry.capture, userId, stream);
1660
+ const capture = beginVoiceCapture(entry.capture, userId);
1699
1661
  let streamAborted = false;
1700
1662
  let receiveFailureHandled = false;
1701
1663
  let receiveStreamEndHandled = false;
@@ -1712,8 +1674,25 @@ var DiscordVoiceReceive = class {
1712
1674
  receiveFailureHandled = true;
1713
1675
  this.handleReceiveError(entry, err);
1714
1676
  };
1715
- stream.on("error", handleStreamError);
1716
1677
  try {
1678
+ const realtimeIngress = realtime ? await this.resolveDiscordVoiceIngressContext(entry, userId) : void 0;
1679
+ if (realtime && !realtimeIngress) {
1680
+ logVoiceVerbose(`realtime capture unauthorized: guild ${entry.guildId} channel ${entry.channelId} user ${userId}`);
1681
+ return;
1682
+ }
1683
+ if (!this.params.isEntryCurrent(entry) || entry.capture.get(userId) !== capture) return;
1684
+ if (entry.player.state.status === voiceSdk.AudioPlayerStatus.Playing && realtime) {
1685
+ if (!realtime.isBargeInEnabled()) {
1686
+ logger$3.info(`discord voice: realtime capture ignored during playback (barge-in disabled): guild ${entry.guildId} channel ${entry.channelId} user ${userId}`);
1687
+ return;
1688
+ }
1689
+ logVoiceVerbose(`realtime barge-in: guild ${entry.guildId} channel ${entry.channelId} user ${userId}`);
1690
+ logger$3.info(`discord voice: realtime barge-in detected source=speaker-start guild=${entry.guildId} channel=${entry.channelId} user=${userId} playerStatus=${entry.player.state.status}`);
1691
+ realtime.handleBargeIn("speaker-start");
1692
+ }
1693
+ this.enableDaveReceivePassthrough(entry, `speaker ${userId} start`, 15);
1694
+ const stream = capture.stream = entry.connection.receiver.subscribe(userId, { end: { behavior: voiceSdk.EndBehaviorType.Manual } });
1695
+ stream.on("error", handleStreamError);
1717
1696
  if (realtime && realtimeIngress) {
1718
1697
  const turn = realtime.beginSpeakerTurn(realtimeIngress, userId);
1719
1698
  try {
@@ -1728,7 +1707,12 @@ var DiscordVoiceReceive = class {
1728
1707
  }
1729
1708
  return;
1730
1709
  }
1710
+ if (!entry.audioInputBudget.enabled) {
1711
+ logger$3.warn("discord voice: capture skipped: audio understanding is disabled; enable tools.media.audio.enabled to transcribe voice.");
1712
+ return;
1713
+ }
1731
1714
  const pcm = await decodeOpusStream(stream, {
1715
+ maxBytes: Math.max(0, entry.audioInputBudget.maxBytes - 44),
1732
1716
  onError: handleStreamError,
1733
1717
  onVerbose: logVoiceVerbose,
1734
1718
  onWarn: (message) => logger$3.warn(message)
@@ -1761,8 +1745,9 @@ var DiscordVoiceReceive = class {
1761
1745
  if (!receiveFailureHandled) this.handleReceiveError(entry, err);
1762
1746
  throw err;
1763
1747
  } finally {
1764
- stream.off?.("error", handleStreamError);
1765
- if (finishVoiceCapture(entry.capture, userId, generation) && !stream.destroyed) stream.destroy();
1748
+ const stream = capture.stream;
1749
+ stream?.off?.("error", handleStreamError);
1750
+ if (finishVoiceCapture(entry.capture, userId, capture) && stream && !stream.destroyed) stream.destroy();
1766
1751
  }
1767
1752
  }
1768
1753
  async processSegment(params) {
@@ -2095,6 +2080,8 @@ var DiscordVoiceSessions = class {
2095
2080
  ok: false,
2096
2081
  message: "Discord voice plugin is not available."
2097
2082
  };
2083
+ const audioInputBudget = await getDiscordRuntime().mediaUnderstanding.resolveAudioInputBudget({ cfg: this.params.cfg });
2084
+ if (authority && !authority.isCurrent()) return cancelledJoinResult();
2098
2085
  const adapterCreator = voicePlugin.getGatewayAdapterCreator(guildId);
2099
2086
  const daveEncryption = voiceConfig?.daveEncryption;
2100
2087
  const decryptionFailureTolerance = voiceConfig?.decryptionFailureTolerance;
@@ -2245,6 +2232,7 @@ var DiscordVoiceSessions = class {
2245
2232
  player,
2246
2233
  playbackQueue: Promise.resolve(),
2247
2234
  processingQueue: Promise.resolve(),
2235
+ audioInputBudget,
2248
2236
  ttsStreamFallbackWarned: false,
2249
2237
  capture: createVoiceCaptureState(),
2250
2238
  transcripts: options?.transcripts,
@@ -2379,7 +2367,7 @@ var DiscordVoiceSessions = class {
2379
2367
  ok: false,
2380
2368
  message: "Discord realtime voice session stopped before startup completed."
2381
2369
  };
2382
- const { DiscordRealtimeVoiceSession } = await import("./realtime-session.runtime-37IC-p5K.js");
2370
+ const { DiscordRealtimeVoiceSession } = await import("./realtime-session.runtime-DgSbX6ay.js");
2383
2371
  const realtime = new DiscordRealtimeVoiceSession({
2384
2372
  accountId: this.params.accountId,
2385
2373
  bootstrapContextInstructions,