@openclaw/discord 2026.5.7 → 2026.5.9-beta.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 (110) hide show
  1. package/dist/{access-CHY9FK3X.js → access-Lk7H_e7y.js} +1 -1
  2. package/dist/action-runtime-api.js +1 -1
  3. package/dist/{allow-list-ek-1hMKN.js → allow-list-Dtho5Hww.js} +1 -1
  4. package/dist/api.js +19 -17
  5. package/dist/{approval-handler.runtime-BBZRYAGs.js → approval-handler.runtime-CqvKEAqO.js} +3 -3
  6. package/dist/{approval-native-CBdZsAR7.js → approval-native-W5mtrjYy.js} +2 -2
  7. package/dist/{approval-shared-Ck6TxKgo.js → approval-shared-D0FVj8b_.js} +1 -1
  8. package/dist/{audit-CCJ0h49k.js → audit-CrCPCVFG.js} +3 -3
  9. package/dist/{channel-UXGa9PGc.js → channel-CRTWY5R-.js} +53 -31
  10. package/dist/{channel-actions-Br29_1nE.js → channel-actions-BRgtLo8F.js} +27 -1
  11. package/dist/{channel-actions.runtime-ChmNUig1.js → channel-actions.runtime-gosyu06g.js} +5 -5
  12. package/dist/channel-config-api.js +1 -1
  13. package/dist/channel-plugin-api.js +1 -1
  14. package/dist/{channel.setup-D_xyQu_h.js → channel.setup-BQlXR1Gt.js} +3 -3
  15. package/dist/chunk-BDgKaWaV.js +179 -0
  16. package/dist/{components-D5LnN7ZQ.js → components-BWdIitIb.js} +2 -2
  17. package/dist/{config-schema-Cc953rAs.js → config-schema-D1DUqXws.js} +46 -1
  18. package/dist/contract-api.js +7 -7
  19. package/dist/{conversation-identity-DHhS0ez3.js → conversation-identity-6hcTVj3L.js} +1 -1
  20. package/dist/directory-contract-api.js +1 -1
  21. package/dist/{directory-live-DJ0V5asB.js → directory-live-D3kbmVAu.js} +3 -3
  22. package/dist/{discord-eZlimVfW.js → discord-Du6FnKAq.js} +30 -13
  23. package/dist/{doctor-Bo-yifB3.js → doctor-Ys2-q5bc.js} +3 -3
  24. package/dist/{doctor-contract-Bso46EOQ.js → doctor-contract-DSB2zzJA.js} +1 -1
  25. package/dist/doctor-contract-api.js +1 -1
  26. package/dist/{handle-action.guild-admin-sJiQymg8.js → handle-action.guild-admin-LM6kZ6zE.js} +6 -3
  27. package/dist/{inbound-context-CRylwjg0.js → inbound-context-BobVUBqo.js} +1 -1
  28. package/dist/{manager.runtime-Cug1PoeZ.js → manager.runtime-C_cPd048.js} +802 -134
  29. package/dist/{mentions-BPZUaFk7.js → mentions-CiPUID82.js} +1 -1
  30. package/dist/{message-handler-C9Ohf-ea.js → message-handler-C2ZQV7ZQ.js} +7 -7
  31. package/dist/{message-handler.preflight-BrvazsYn.js → message-handler.preflight-B5hN7RpX.js} +15 -15
  32. package/dist/{message-handler.process-CEnzuLiN.js → message-handler.process-Dns8D7t2.js} +82 -65
  33. package/dist/{message-utils-9kaGF59d.js → message-utils-B3uf0_3D.js} +2 -2
  34. package/dist/normalize-DBcng6RL.js +58 -0
  35. package/dist/{outbound-adapter-DNsTVJfH.js → outbound-adapter-jP0OgIyW.js} +78 -17
  36. package/dist/{outbound-session-route-DK9qkPgP.js → outbound-session-route-BaJRt05p.js} +1 -1
  37. package/dist/{preflight-audio-CRmUxxuM.js → preflight-audio-6J0vFNtu.js} +1 -1
  38. package/dist/{preview-streaming-Cc_oeIPP.js → preview-streaming-CXrFDP2T.js} +1 -0
  39. package/dist/{probe-E80IMT1X.js → probe-91lU5eh8.js} +1 -1
  40. package/dist/{probe.runtime-CMgUDax3.js → probe.runtime-DV37RDCU.js} +1 -1
  41. package/dist/{provider-CuOh6z_b.js → provider-D_QVXvp8.js} +53 -50
  42. package/dist/{provider-session.runtime-CCESIHVo.js → provider-session.runtime-CcPDguh6.js} +3 -3
  43. package/dist/provider.runtime-O7G03kik.js +2 -0
  44. package/dist/{reply-delivery-D9aKHtDH.js → reply-delivery-DKTZ6HkK.js} +10 -7
  45. package/dist/{resolve-allowlist-common-_e1cWOb3.js → resolve-allowlist-common-LhuVITjh.js} +2 -2
  46. package/dist/{resolve-channels-kyuvrXJg.js → resolve-channels-DjpVRJdT.js} +3 -3
  47. package/dist/{resolve-users-CAwh4EBq.js → resolve-users-DrZYxZSX.js} +2 -2
  48. package/dist/{route-resolution-BWErj5Cn.js → route-resolution-CYRPDKY4.js} +3 -3
  49. package/dist/{runtime-D8alY00g.js → runtime-BHAwVXEa.js} +7 -7
  50. package/dist/runtime-api.actions.js +2 -2
  51. package/dist/runtime-api.js +25 -25
  52. package/dist/runtime-api.lookup.js +6 -6
  53. package/dist/runtime-api.monitor--iuvLjPX.js +6 -0
  54. package/dist/runtime-api.monitor.js +7 -7
  55. package/dist/runtime-api.send.js +5 -5
  56. package/dist/runtime-api.threads.js +5 -5
  57. package/dist/runtime-setter-api.js +1 -1
  58. package/dist/secret-contract-api.js +1 -1
  59. package/dist/{security-audit-BtRd_VhN.js → security-audit-D8IaFuCm.js} +1 -1
  60. package/dist/security-audit-contract-api.js +1 -1
  61. package/dist/{security-audit.runtime-Dm1LW9KX.js → security-audit.runtime-DO1398sV.js} +1 -1
  62. package/dist/security-contract-api.js +1 -1
  63. package/dist/{send-8S_HKJpQ.js → send-C3peGbWO.js} +83 -56
  64. package/dist/{send.components-A42c_5tQ.js → send.components-Dsk3IzS_.js} +22 -14
  65. package/dist/{send.outbound-D3tonSz8.js → send.outbound-CXyInQ3c.js} +22 -11
  66. package/dist/send.receipt-DXimpUGs.js +35 -0
  67. package/dist/{send.shared-BQGiUPvZ.js → send.shared-BydEWvYg.js} +26 -7
  68. package/dist/{sender-identity-BGUfyvOC.js → sender-identity-DVJCrDxs.js} +1 -1
  69. package/dist/session-key-api.js +1 -1
  70. package/dist/setup-plugin-api.js +1 -1
  71. package/dist/{shared-BEW4H3bj.js → shared-BWD6uc0p.js} +8 -8
  72. package/dist/{shared-interactive-KgJjCqnB.js → shared-interactive-BZCU0ZJ8.js} +2 -2
  73. package/dist/{subagent-hooks-T0LPLh4H.js → subagent-hooks-DtbWOdAK.js} +1 -1
  74. package/dist/subagent-hooks-api.js +1 -1
  75. package/dist/{system-events-_fzSG--3.js → system-events-Dsc8MFYs.js} +2 -2
  76. package/dist/target-parsing-D-H7nnh2.js +51 -0
  77. package/dist/target-resolver-D7t8FMhO.js +85 -0
  78. package/dist/targets-DzAZIwg4.js +3 -0
  79. package/dist/test-api.js +4 -4
  80. package/dist/{thread-bindings-CMpZjP50.js → thread-bindings-B90pBWJg.js} +6 -6
  81. package/dist/{thread-bindings.discord-api-CwWGoyei.js → thread-bindings.discord-api-Dvf789Je.js} +7 -7
  82. package/dist/{thread-bindings.manager-BtxfLfWf.js → thread-bindings.manager-AwZ5Vble.js} +5 -5
  83. package/dist/{thread-bindings.session-updates-jcZSiRPI.js → thread-bindings.session-updates-B_AcsXSf.js} +1 -1
  84. package/dist/{threading-BMmpA2JR.js → threading-Dku_cGS8.js} +4 -4
  85. package/dist/timeouts.js +1 -1
  86. package/dist/{typing-Bw6NKWLZ.js → typing-BIjMmOZB.js} +2 -2
  87. package/openclaw.plugin.json +222 -1
  88. package/package.json +5 -5
  89. package/dist/provider.runtime-B68g3qLv.js +0 -2
  90. package/dist/runtime-api.monitor-DzkCxeBL.js +0 -6
  91. package/dist/target-resolver-DA84_xbt.js +0 -365
  92. package/dist/targets-FwL1BPTU.js +0 -2
  93. /package/dist/{agent-components.runtime-Dof1YMSz.js → agent-components.runtime-caj0h9y4.js} +0 -0
  94. /package/dist/{api-DzNBVTto.js → api-DaTujGTe.js} +0 -0
  95. /package/dist/{audit-core-CejGc3hO.js → audit-core-CIvZE94W.js} +0 -0
  96. /package/dist/{channel-access-DFIQqbYm.js → channel-access-CXAdcM95.js} +0 -0
  97. /package/dist/{directory-cache-D93eSrpB.js → directory-cache-D3l2v2_L.js} +0 -0
  98. /package/dist/{directory-config-DoETeOOx.js → directory-config-S2852QcC.js} +0 -0
  99. /package/dist/{doctor-shared-Cqvfgv9m.js → doctor-shared-DtOaqWzy.js} +0 -0
  100. /package/dist/{format-D8TsaXxW.js → format-XDPCvGK4.js} +0 -0
  101. /package/dist/{pluralkit-OFss_pIy.js → pluralkit-EXKKni07.js} +0 -0
  102. /package/dist/{preflight-audio.runtime-DPVbpZid.js → preflight-audio.runtime-3hiRefuj.js} +0 -0
  103. /package/dist/{runtime-K9RT6Egn.js → runtime-EoVRXYxX.js} +0 -0
  104. /package/dist/{secret-config-contract-5S9U9pjx.js → secret-config-contract-BA9jVaKx.js} +0 -0
  105. /package/dist/{security-contract-BE8rsdPq.js → security-contract-B7i5uqn6.js} +0 -0
  106. /package/dist/{security-doctor-DiilN216.js → security-doctor-2SGSPibT.js} +0 -0
  107. /package/dist/{session-contract-CuW9Nlxg.js → session-contract-DwjfF970.js} +0 -0
  108. /package/dist/{session-key-normalization-B5La-jFM.js → session-key-normalization-DvI2OlyS.js} +0 -0
  109. /package/dist/{thread-bindings.state-WU4duXKY.js → thread-bindings.state-CBwtFsbB.js} +0 -0
  110. /package/dist/{timeouts-CdsmBWWs.js → timeouts-BxAzVpSG.js} +0 -0
@@ -1,20 +1,22 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-C3SqQTfK.js";
2
2
  import { s as resolveDiscordAccount } from "./accounts-CaHGiVB4.js";
3
- import { $ as createChannelMessage, At as putChannelPermission, Ct as getGuildVoiceState, Dt as listGuildRoles, Et as listGuildEmojis, Mt as removeGuildMemberRole, Nt as timeoutGuildMember, Ot as listGuildScheduledEvents, Q as listMessageReactionUsers, St as getGuildMember, Tt as listGuildChannels, X as createOwnMessageReaction, Z as deleteOwnMessageReaction, _ as readDiscordMessage, _t as createGuildEmoji, at as getChannel, bt as deleteChannelPermission, ct as listChannelMessages, dt as searchGuildMessages, et as createThread, ft as sendChannelTyping, g as readDiscordCode, gt as createGuildChannel, h as RateLimitError, ht as createGuildBan, it as editChannelMessage, jt as removeGuildMember, kt as moveGuildChannels, lt as listChannelPins, m as DiscordError, mt as addGuildMemberRole, nt as deleteChannelMessage, ot as getChannelMessage, pt as unpinChannelMessage, rt as editChannel, st as listChannelArchivedThreads, tt as deleteChannel, ut as pinChannelMessage, v as readRetryAfter, vt as createGuildScheduledEvent, wt as listGuildActiveThreads, yt as createGuildSticker } from "./discord-eZlimVfW.js";
4
- import { A as createDiscordClient, C as DiscordSendError, D as hasAllGuildPermissionsDiscord, E as fetchMemberGuildPermissionsDiscord, N as resolveDiscordClientAccountContext, O as hasAnyGuildPermissionDiscord, P as resolveDiscordRest, S as DISCORD_MAX_STICKER_BYTES, T as fetchChannelPermissionsDiscord, b as DISCORD_MAX_EMOJI_BYTES, i as formatReactionEmoji, k as parseAndResolveRecipient, l as resolveChannelId, o as normalizeEmojiName, r as buildReactionIdentifier, s as normalizeReactionEmoji, t as buildDiscordSendError, w as canViewDiscordGuildChannel, x as DISCORD_MAX_EVENT_COVER_BYTES } from "./send.shared-BQGiUPvZ.js";
5
- import { n as rewriteDiscordKnownMentions } from "./mentions-BPZUaFk7.js";
6
- import { n as sendPollDiscord, r as sendStickerDiscord, t as sendMessageDiscord } from "./send.outbound-D3tonSz8.js";
3
+ import { $ as createChannelMessage, At as putChannelPermission, Ct as getGuildVoiceState, Dt as listGuildRoles, Et as listGuildEmojis, Mt as removeGuildMemberRole, Nt as timeoutGuildMember, Ot as listGuildScheduledEvents, Q as listMessageReactionUsers, St as getGuildMember, Tt as listGuildChannels, X as createOwnMessageReaction, Z as deleteOwnMessageReaction, _ as readDiscordMessage, _t as createGuildEmoji, at as getChannel, bt as deleteChannelPermission, ct as listChannelMessages, dt as searchGuildMessages, et as createThread, ft as sendChannelTyping, g as readDiscordCode, gt as createGuildChannel, h as RateLimitError, ht as createGuildBan, it as editChannelMessage, jt as removeGuildMember, kt as moveGuildChannels, lt as listChannelPins, m as DiscordError, mt as addGuildMemberRole, nt as deleteChannelMessage, ot as getChannelMessage, pt as unpinChannelMessage, rt as editChannel, st as listChannelArchivedThreads, tt as deleteChannel, ut as pinChannelMessage, v as readRetryAfter, vt as createGuildScheduledEvent, wt as listGuildActiveThreads, yt as createGuildSticker } from "./discord-Du6FnKAq.js";
4
+ import { A as createDiscordClient, C as DiscordSendError, D as hasAllGuildPermissionsDiscord, E as fetchMemberGuildPermissionsDiscord, N as resolveDiscordClientAccountContext, O as hasAnyGuildPermissionDiscord, P as resolveDiscordRest, S as DISCORD_MAX_STICKER_BYTES, T as fetchChannelPermissionsDiscord, b as DISCORD_MAX_EMOJI_BYTES, i as formatReactionEmoji, k as parseAndResolveRecipient, l as resolveChannelId, o as normalizeEmojiName, r as buildReactionIdentifier, s as normalizeReactionEmoji, t as buildDiscordSendError, w as canViewDiscordGuildChannel, x as DISCORD_MAX_EVENT_COVER_BYTES } from "./send.shared-BydEWvYg.js";
5
+ import { n as rewriteDiscordKnownMentions } from "./mentions-CiPUID82.js";
6
+ import { n as createDiscordSendResult } from "./send.receipt-DXimpUGs.js";
7
+ import { n as sendPollDiscord, r as sendStickerDiscord, t as sendMessageDiscord } from "./send.outbound-CXyInQ3c.js";
7
8
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
8
9
  import { ChannelType } from "discord-api-types/v10";
9
10
  import crypto from "node:crypto";
10
- import fs from "node:fs/promises";
11
11
  import path from "node:path";
12
+ import { writeExternalFileWithinRoot } from "openclaw/plugin-sdk/security-runtime";
12
13
  import { MEDIA_FFMPEG_MAX_AUDIO_DURATION_SECS, extensionForMime, maxBytesForKind, parseFfprobeCodecAndSampleRate, runFfmpeg, runFfprobe, unlinkIfExists } from "openclaw/plugin-sdk/media-runtime";
13
14
  import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
14
15
  import { loadWebMediaRaw } from "openclaw/plugin-sdk/web-media";
15
16
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
16
17
  import { recordChannelActivity } from "openclaw/plugin-sdk/channel-activity-runtime";
17
- import { resolvePreferredOpenClawTmpDir } from "openclaw/plugin-sdk/temp-path";
18
+ import fs from "node:fs/promises";
19
+ import { resolvePreferredOpenClawTmpDir, tempWorkspace } from "openclaw/plugin-sdk/temp-path";
18
20
  import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
19
21
  //#region extensions/discord/src/send.channels.ts
20
22
  async function createChannelDiscord(payload, opts) {
@@ -352,10 +354,13 @@ async function sendWebhookMessageDiscord(text, opts) {
352
354
  direction: "outbound"
353
355
  });
354
356
  } catch {}
355
- return {
356
- messageId: payload.id || "unknown",
357
- channelId: payload.channel_id ? payload.channel_id : opts.threadId ? String(opts.threadId) : ""
358
- };
357
+ return createDiscordSendResult({
358
+ result: payload,
359
+ fallbackChannelId: opts.threadId ? String(opts.threadId) : "",
360
+ kind: "text",
361
+ ...opts.threadId != null ? { threadId: opts.threadId } : {},
362
+ ...replyTo ? { replyToId: replyTo } : {}
363
+ });
359
364
  }
360
365
  //#endregion
361
366
  //#region extensions/discord/src/voice-message.ts
@@ -374,6 +379,17 @@ const DISCORD_VOICE_MESSAGE_FLAG = 8192;
374
379
  const SUPPRESS_NOTIFICATIONS_FLAG = 4096;
375
380
  const WAVEFORM_SAMPLES = 256;
376
381
  const DISCORD_OPUS_SAMPLE_RATE_HZ = 48e3;
382
+ async function runFfmpegToOutput(params) {
383
+ const rootDir = path.dirname(params.outputPath);
384
+ await fs.mkdir(rootDir, { recursive: true });
385
+ await writeExternalFileWithinRoot({
386
+ rootDir,
387
+ path: path.basename(params.outputPath),
388
+ write: async (tempPath) => {
389
+ await runFfmpeg(params.buildArgs(tempPath));
390
+ }
391
+ });
392
+ }
377
393
  function createRateLimitError(response, body, request) {
378
394
  return new RateLimitError(response, body, request ?? new Request("https://discord.com/api/v10/channels/voice/messages", { method: "POST" }));
379
395
  }
@@ -417,25 +433,28 @@ async function generateWaveformFromPcm(filePath) {
417
433
  const tempDir = resolvePreferredOpenClawTmpDir();
418
434
  const tempPcm = path.join(tempDir, `waveform-${crypto.randomUUID()}.raw`);
419
435
  try {
420
- await runFfmpeg([
421
- "-y",
422
- "-i",
423
- filePath,
424
- "-vn",
425
- "-sn",
426
- "-dn",
427
- "-t",
428
- String(MEDIA_FFMPEG_MAX_AUDIO_DURATION_SECS),
429
- "-f",
430
- "s16le",
431
- "-acodec",
432
- "pcm_s16le",
433
- "-ac",
434
- "1",
435
- "-ar",
436
- "8000",
437
- tempPcm
438
- ]);
436
+ await runFfmpegToOutput({
437
+ outputPath: tempPcm,
438
+ buildArgs: (outputPath) => [
439
+ "-y",
440
+ "-i",
441
+ filePath,
442
+ "-vn",
443
+ "-sn",
444
+ "-dn",
445
+ "-t",
446
+ String(MEDIA_FFMPEG_MAX_AUDIO_DURATION_SECS),
447
+ "-f",
448
+ "s16le",
449
+ "-acodec",
450
+ "pcm_s16le",
451
+ "-ac",
452
+ "1",
453
+ "-ar",
454
+ "8000",
455
+ outputPath
456
+ ]
457
+ });
439
458
  const pcmData = await fs.readFile(tempPcm);
440
459
  const samples = new Int16Array(pcmData.buffer, pcmData.byteOffset, pcmData.byteLength / 2);
441
460
  const step = Math.max(1, Math.floor(samples.length / WAVEFORM_SAMPLES));
@@ -494,23 +513,26 @@ async function ensureOggOpus(filePath) {
494
513
  } catch {}
495
514
  const tempDir = resolvePreferredOpenClawTmpDir();
496
515
  const outputPath = path.join(tempDir, `voice-${crypto.randomUUID()}.ogg`);
497
- await runFfmpeg([
498
- "-y",
499
- "-i",
500
- filePath,
501
- "-vn",
502
- "-sn",
503
- "-dn",
504
- "-t",
505
- String(MEDIA_FFMPEG_MAX_AUDIO_DURATION_SECS),
506
- "-ar",
507
- String(DISCORD_OPUS_SAMPLE_RATE_HZ),
508
- "-c:a",
509
- "libopus",
510
- "-b:a",
511
- "64k",
512
- outputPath
513
- ]);
516
+ await runFfmpegToOutput({
517
+ outputPath,
518
+ buildArgs: (tempPath) => [
519
+ "-y",
520
+ "-i",
521
+ filePath,
522
+ "-vn",
523
+ "-sn",
524
+ "-dn",
525
+ "-t",
526
+ String(MEDIA_FFMPEG_MAX_AUDIO_DURATION_SECS),
527
+ "-ar",
528
+ String(DISCORD_OPUS_SAMPLE_RATE_HZ),
529
+ "-c:a",
530
+ "libopus",
531
+ "-b:a",
532
+ "64k",
533
+ tempPath
534
+ ]
535
+ });
514
536
  return {
515
537
  path: outputPath,
516
538
  cleanup: true
@@ -631,20 +653,25 @@ async function sendDiscordVoiceMessage(rest, channelId, audioBuffer, metadata, r
631
653
  //#endregion
632
654
  //#region extensions/discord/src/send.voice.ts
633
655
  function toDiscordSendResult(result, fallbackChannelId) {
634
- return {
635
- messageId: result.id || "unknown",
636
- channelId: result.channel_id ?? fallbackChannelId
637
- };
656
+ return createDiscordSendResult({
657
+ result,
658
+ fallbackChannelId,
659
+ kind: "voice"
660
+ });
638
661
  }
639
662
  async function materializeVoiceMessageInput(mediaUrl) {
640
663
  const media = await loadWebMediaRaw(mediaUrl, maxBytesForKind("audio"));
641
664
  const extFromName = media.fileName ? path.extname(media.fileName) : "";
642
665
  const extFromMime = media.contentType ? extensionForMime(media.contentType) : "";
643
666
  const ext = extFromName || extFromMime || ".bin";
644
- const tempDir = resolvePreferredOpenClawTmpDir();
645
- const filePath = path.join(tempDir, `voice-src-${crypto.randomUUID()}${ext}`);
646
- await fs.writeFile(filePath, media.buffer, { mode: 384 });
647
- return { filePath };
667
+ const workspace = await tempWorkspace({
668
+ rootDir: resolvePreferredOpenClawTmpDir(),
669
+ prefix: "voice-src-"
670
+ });
671
+ return {
672
+ filePath: await workspace.write(`input${ext}`, media.buffer),
673
+ cleanup: async () => await workspace.cleanup()
674
+ };
648
675
  }
649
676
  /**
650
677
  * Send a voice message to Discord.
@@ -657,7 +684,7 @@ async function materializeVoiceMessageInput(mediaUrl) {
657
684
  * @param opts - Send options
658
685
  */
659
686
  async function sendVoiceMessageDiscord(to, audioPath, opts) {
660
- const { filePath: localInputPath } = await materializeVoiceMessageInput(audioPath);
687
+ const { filePath: localInputPath, cleanup: cleanupLocalInput } = await materializeVoiceMessageInput(audioPath);
661
688
  let oggPath = null;
662
689
  let oggCleanup = false;
663
690
  let token;
@@ -701,7 +728,7 @@ async function sendVoiceMessageDiscord(to, audioPath, opts) {
701
728
  throw err;
702
729
  } finally {
703
730
  await unlinkIfExists(oggCleanup ? oggPath : null);
704
- await unlinkIfExists(localInputPath);
731
+ await cleanupLocalInput();
705
732
  }
706
733
  }
707
734
  //#endregion
@@ -2,12 +2,13 @@ import { t as __exportAll } from "./rolldown-runtime-C3SqQTfK.js";
2
2
  import { s as resolveDiscordAccount } from "./accounts-CaHGiVB4.js";
3
3
  import "./config-api-CFZtoMaS.js";
4
4
  import "./channel-api-CTSWMrnD.js";
5
- import "./outbound-session-route-DK9qkPgP.js";
6
- import { $ as createChannelMessage, it as editChannelMessage, w as serializePayload } from "./discord-eZlimVfW.js";
7
- import { A as createDiscordClient, h as SUPPRESS_NOTIFICATIONS_FLAG, k as parseAndResolveRecipient, l as resolveChannelId, m as toDiscordFileBlob, t as buildDiscordSendError, u as resolveDiscordChannelType, y as stripUndefinedFields } from "./send.shared-BQGiUPvZ.js";
8
- import { t as sendMessageDiscord } from "./send.outbound-D3tonSz8.js";
9
- import { a as buildDiscordComponentMessage, l as resolveDiscordComponentAttachmentName, o as buildDiscordComponentMessageFlags } from "./components-D5LnN7ZQ.js";
10
- import { n as getOptionalDiscordRuntime } from "./runtime-K9RT6Egn.js";
5
+ import "./outbound-session-route-BaJRt05p.js";
6
+ import { $ as createChannelMessage, it as editChannelMessage, w as serializePayload } from "./discord-Du6FnKAq.js";
7
+ import { A as createDiscordClient, h as SUPPRESS_NOTIFICATIONS_FLAG, k as parseAndResolveRecipient, l as resolveChannelId, m as toDiscordFileBlob, t as buildDiscordSendError, u as resolveDiscordChannelType, y as stripUndefinedFields } from "./send.shared-BydEWvYg.js";
8
+ import { n as createDiscordSendResult } from "./send.receipt-DXimpUGs.js";
9
+ import { t as sendMessageDiscord } from "./send.outbound-CXyInQ3c.js";
10
+ import { a as buildDiscordComponentMessage, l as resolveDiscordComponentAttachmentName, o as buildDiscordComponentMessageFlags } from "./components-BWdIitIb.js";
11
+ import { n as getOptionalDiscordRuntime } from "./runtime-EoVRXYxX.js";
11
12
  import "openclaw/plugin-sdk/account-id";
12
13
  import "openclaw/plugin-sdk/secret-input";
13
14
  import "openclaw/plugin-sdk/account-helpers";
@@ -417,10 +418,12 @@ async function sendDiscordComponentMessage(to, spec, opts) {
417
418
  accountId: accountInfo.accountId,
418
419
  direction: "outbound"
419
420
  });
420
- return {
421
- messageId: result.id ?? "unknown",
422
- channelId: result.channel_id ?? channelId
423
- };
421
+ return createDiscordSendResult({
422
+ result,
423
+ fallbackChannelId: channelId,
424
+ kind: "card",
425
+ ...opts.replyTo ? { replyToId: opts.replyTo } : {}
426
+ });
424
427
  }
425
428
  async function editDiscordComponentMessage(to, messageId, spec, opts) {
426
429
  const cfg = requireRuntimeConfig(opts.cfg, "Discord component edit");
@@ -459,10 +462,15 @@ async function editDiscordComponentMessage(to, messageId, spec, opts) {
459
462
  accountId: accountInfo.accountId,
460
463
  direction: "outbound"
461
464
  });
462
- return {
463
- messageId: result.id ?? messageId,
464
- channelId: result.channel_id ?? channelId
465
- };
465
+ return createDiscordSendResult({
466
+ result: {
467
+ id: result.id ?? messageId,
468
+ channel_id: result.channel_id
469
+ },
470
+ fallbackChannelId: channelId,
471
+ kind: "card",
472
+ ...opts.replyTo ? { replyToId: opts.replyTo } : {}
473
+ });
466
474
  }
467
475
  //#endregion
468
476
  export { resolveDiscordComponentEntryWithPersistence as a, jsonResult as c, readNumberParam as d, readReactionParams as f, withNormalizedTimestamp as g, resolvePollMaxSelections as h, send_components_exports as i, parseAvailableTags as l, readStringParam as m, registerBuiltDiscordComponentMessage as n, resolveDiscordModalEntryWithPersistence as o, readStringArrayParam as p, sendDiscordComponentMessage as r, assertMediaNotDataUrl as s, editDiscordComponentMessage as t, readBooleanParam$1 as u };
@@ -1,7 +1,8 @@
1
1
  import { s as resolveDiscordAccount } from "./accounts-CaHGiVB4.js";
2
- import { $ as createChannelMessage, et as createThread } from "./discord-eZlimVfW.js";
3
- import { A as createDiscordClient, _ as resolveDiscordSendComponents, a as normalizeDiscordPollInput, c as normalizeStickerIds, f as sendDiscordMedia, g as buildDiscordMessageRequest, h as SUPPRESS_NOTIFICATIONS_FLAG, k as parseAndResolveRecipient, l as resolveChannelId, n as buildDiscordTextChunks, p as sendDiscordText, t as buildDiscordSendError, u as resolveDiscordChannelType, v as resolveDiscordSendEmbeds } from "./send.shared-BQGiUPvZ.js";
4
- import { n as rewriteDiscordKnownMentions } from "./mentions-BPZUaFk7.js";
2
+ import { $ as createChannelMessage, et as createThread } from "./discord-Du6FnKAq.js";
3
+ import { A as createDiscordClient, _ as resolveDiscordSendComponents, a as normalizeDiscordPollInput, c as normalizeStickerIds, f as sendDiscordMedia, g as buildDiscordMessageRequest, h as SUPPRESS_NOTIFICATIONS_FLAG, k as parseAndResolveRecipient, l as resolveChannelId, n as buildDiscordTextChunks, p as sendDiscordText, t as buildDiscordSendError, u as resolveDiscordChannelType, v as resolveDiscordSendEmbeds } from "./send.shared-BydEWvYg.js";
4
+ import { n as rewriteDiscordKnownMentions } from "./mentions-CiPUID82.js";
5
+ import { n as createDiscordSendResult } from "./send.receipt-DXimpUGs.js";
5
6
  import { convertMarkdownTables, normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
6
7
  import { ChannelType } from "discord-api-types/v10";
7
8
  import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
@@ -23,11 +24,15 @@ function deriveForumThreadName(text) {
23
24
  function isForumLikeType(channelType) {
24
25
  return channelType === ChannelType.GuildForum || channelType === ChannelType.GuildMedia;
25
26
  }
26
- function toDiscordSendResult(result, fallbackChannelId) {
27
- return {
28
- messageId: result.id || "unknown",
29
- channelId: result.channel_id ?? fallbackChannelId
27
+ function toDiscordSendResult(result, fallbackChannelId, params = {}) {
28
+ const resultParams = {
29
+ result,
30
+ fallbackChannelId,
31
+ kind: params.kind ?? "text"
30
32
  };
33
+ if (params.threadId != null) resultParams.threadId = params.threadId;
34
+ if (params.replyToId) resultParams.replyToId = params.replyToId;
35
+ return createDiscordSendResult(resultParams);
31
36
  }
32
37
  async function resolveDiscordSendTarget(to, opts) {
33
38
  const cfg = requireRuntimeConfig(opts.cfg, "Discord send target resolution");
@@ -149,7 +154,10 @@ async function sendMessageDiscord(to, text, opts) {
149
154
  return toDiscordSendResult({
150
155
  id: messageId,
151
156
  channel_id: resultChannelId
152
- }, channelId);
157
+ }, channelId, {
158
+ kind: opts.mediaUrl ? "media" : "text",
159
+ threadId
160
+ });
153
161
  }
154
162
  let result;
155
163
  try {
@@ -169,7 +177,10 @@ async function sendMessageDiscord(to, text, opts) {
169
177
  accountId: accountInfo.accountId,
170
178
  direction: "outbound"
171
179
  });
172
- return toDiscordSendResult(result, channelId);
180
+ return toDiscordSendResult(result, channelId, {
181
+ kind: opts.mediaUrl ? "media" : opts.components || opts.embeds ? "card" : "text",
182
+ replyToId: opts.replyTo
183
+ });
173
184
  }
174
185
  async function sendStickerDiscord(to, stickerIds, opts) {
175
186
  const { rest, request, channelId, rewrittenContent } = await resolveDiscordStructuredSendContext(to, opts);
@@ -177,7 +188,7 @@ async function sendStickerDiscord(to, stickerIds, opts) {
177
188
  return toDiscordSendResult(await request(() => createChannelMessage(rest, channelId, { body: {
178
189
  content: rewrittenContent || void 0,
179
190
  sticker_ids: stickers
180
- } }), "sticker"), channelId);
191
+ } }), "sticker"), channelId, { kind: "card" });
181
192
  }
182
193
  async function sendPollDiscord(to, poll, opts) {
183
194
  const { rest, request, channelId, rewrittenContent } = await resolveDiscordStructuredSendContext(to, opts);
@@ -188,7 +199,7 @@ async function sendPollDiscord(to, poll, opts) {
188
199
  content: rewrittenContent || void 0,
189
200
  poll: payload,
190
201
  ...flags ? { flags } : {}
191
- } }), "poll"), channelId);
202
+ } }), "poll"), channelId, { kind: "card" });
192
203
  }
193
204
  async function resolveDiscordStructuredSendContext(to, opts) {
194
205
  const accountInfo = resolveDiscordAccount({
@@ -0,0 +1,35 @@
1
+ import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-message";
2
+ //#region extensions/discord/src/send.receipt.ts
3
+ function createDiscordSendReceipt(params) {
4
+ return createMessageReceiptFromOutboundResults({
5
+ results: params.platformMessageIds.map((messageId) => messageId.trim()).filter((messageId) => messageId && messageId !== "unknown").map((messageId) => {
6
+ const result = {
7
+ channel: "discord",
8
+ messageId
9
+ };
10
+ if (params.channelId) result.channelId = params.channelId;
11
+ return result;
12
+ }),
13
+ kind: params.kind,
14
+ threadId: params.threadId,
15
+ replyToId: params.replyToId
16
+ });
17
+ }
18
+ function createDiscordSendResult(params) {
19
+ const messageId = params.result.id || "unknown";
20
+ const channelId = params.result.channel_id ?? params.fallbackChannelId;
21
+ const receiptParams = {
22
+ platformMessageIds: params.result.platformMessageIds?.length ? params.result.platformMessageIds : [messageId],
23
+ channelId,
24
+ kind: params.kind
25
+ };
26
+ if (params.threadId != null) receiptParams.threadId = String(params.threadId);
27
+ if (params.replyToId) receiptParams.replyToId = params.replyToId;
28
+ return {
29
+ messageId,
30
+ channelId,
31
+ receipt: createDiscordSendReceipt(receiptParams)
32
+ };
33
+ }
34
+ //#endregion
35
+ export { createDiscordSendResult as n, createDiscordSendReceipt as t };
@@ -1,7 +1,8 @@
1
1
  import { t as normalizeDiscordToken } from "./token-BZtonk7d.js";
2
2
  import { a as mergeDiscordAccountConfig, s as resolveDiscordAccount } from "./accounts-CaHGiVB4.js";
3
- import { s as chunkDiscordTextWithMode, t as parseAndResolveDiscordTarget } from "./target-resolver-DA84_xbt.js";
4
- import { $ as createChannelMessage, J as createUserDmChannel, St as getGuildMember, Y as getCurrentUser, at as getChannel, h as RateLimitError, p as RequestClient, u as Embed, w as serializePayload, xt as getGuild } from "./discord-eZlimVfW.js";
3
+ import { $ as createChannelMessage, J as createUserDmChannel, St as getGuildMember, Y as getCurrentUser, at as getChannel, h as RateLimitError, p as RequestClient, u as Embed, w as serializePayload, xt as getGuild } from "./discord-Du6FnKAq.js";
4
+ import { t as chunkDiscordTextWithMode } from "./chunk-BDgKaWaV.js";
5
+ import { t as parseAndResolveDiscordTarget } from "./target-resolver-D7t8FMhO.js";
5
6
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
6
7
  import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
7
8
  import { ChannelType, PermissionFlagsBits } from "discord-api-types/v10";
@@ -579,11 +580,24 @@ async function sendDiscordText(rest, channelId, text, replyTo, request, maxLines
579
580
  });
580
581
  return await request(() => createChannelMessage(rest, channelId, { body }), "text");
581
582
  };
582
- if (chunks.length === 1) return await sendChunk(chunks[0], true);
583
+ if (chunks.length === 1) {
584
+ const result = await sendChunk(chunks[0], true);
585
+ return {
586
+ ...result,
587
+ platformMessageIds: result.id ? [result.id] : []
588
+ };
589
+ }
590
+ const platformMessageIds = [];
583
591
  let last = null;
584
- for (const [index, chunk] of chunks.entries()) last = await sendChunk(chunk, index === 0);
592
+ for (const [index, chunk] of chunks.entries()) {
593
+ last = await sendChunk(chunk, index === 0);
594
+ if (last.id) platformMessageIds.push(last.id);
595
+ }
585
596
  if (!last) throw new Error("Discord send failed (empty chunk result)");
586
- return last;
597
+ return {
598
+ ...last,
599
+ platformMessageIds
600
+ };
587
601
  }
588
602
  async function sendDiscordMedia(rest, channelId, text, mediaUrl, filename, mediaAccess, mediaLocalRoots, mediaReadFile, maxBytes, replyTo, request, maxLinesPerMessage, components, embeds, chunkMode, silent, maxChars) {
589
603
  const media = await loadWebMedia(mediaUrl, buildOutboundMediaLoadOptions({
@@ -620,11 +634,16 @@ async function sendDiscordMedia(rest, channelId, text, mediaUrl, filename, media
620
634
  }]
621
635
  });
622
636
  const res = await request(() => createChannelMessage(rest, channelId, { body }), "media");
637
+ const platformMessageIds = res.id ? [res.id] : [];
623
638
  for (const chunk of chunks.slice(1)) {
624
639
  if (!chunk.trim()) continue;
625
- await sendDiscordText(rest, channelId, chunk, replyTo, request, maxLinesPerMessage, void 0, void 0, chunkMode, silent, maxChars);
640
+ const followup = await sendDiscordText(rest, channelId, chunk, replyTo, request, maxLinesPerMessage, void 0, void 0, chunkMode, silent, maxChars);
641
+ for (const id of followup.platformMessageIds) if (id) platformMessageIds.push(id);
626
642
  }
627
- return res;
643
+ return {
644
+ ...res,
645
+ platformMessageIds
646
+ };
628
647
  }
629
648
  function buildReactionIdentifier(emoji) {
630
649
  if (emoji.id && emoji.name) return `${emoji.name}:${emoji.id}`;
@@ -1,4 +1,4 @@
1
- import { n as formatDiscordUserTag } from "./format-D8TsaXxW.js";
1
+ import { n as formatDiscordUserTag } from "./format-XDPCvGK4.js";
2
2
  import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
3
3
  //#region extensions/discord/src/monitor/sender-identity.ts
4
4
  function resolveDiscordWebhookId(message) {
@@ -1,2 +1,2 @@
1
- import { t as normalizeExplicitDiscordSessionKey } from "./session-key-normalization-B5La-jFM.js";
1
+ import { t as normalizeExplicitDiscordSessionKey } from "./session-key-normalization-DvI2OlyS.js";
2
2
  export { normalizeExplicitDiscordSessionKey };
@@ -1,2 +1,2 @@
1
- import { t as discordSetupPlugin } from "./channel.setup-D_xyQu_h.js";
1
+ import { t as discordSetupPlugin } from "./channel.setup-BQlXR1Gt.js";
2
2
  export { discordSetupPlugin };
@@ -1,12 +1,12 @@
1
1
  import { a as mergeDiscordAccountConfig, c as resolveDiscordAccountAllowFrom, d as resolveDiscordAccountDmPolicy, n as isDiscordAccountEnabledForRuntime, o as resolveDefaultDiscordAccountId, r as listDiscordAccountIds, s as resolveDiscordAccount, u as resolveDiscordAccountDisabledReason } from "./accounts-CaHGiVB4.js";
2
2
  import { t as inspectDiscordAccount } from "./account-inspect-BcQAxhKY.js";
3
3
  import { i as getChatChannelMeta } from "./channel-api-CTSWMrnD.js";
4
- import { t as DiscordChannelConfigSchema } from "./config-schema-Cc953rAs.js";
5
- import { n as normalizeCompatibilityConfig } from "./doctor-contract-Bso46EOQ.js";
6
- import { t as DISCORD_LEGACY_CONFIG_RULES } from "./doctor-shared-Cqvfgv9m.js";
7
- import { n as secretTargetRegistryEntries, t as collectRuntimeConfigAssignments } from "./secret-config-contract-5S9U9pjx.js";
8
- import { n as unsupportedSecretRefSurfacePatterns, t as collectUnsupportedSecretRefConfigCandidates } from "./security-contract-BE8rsdPq.js";
9
- import { t as deriveLegacySessionChatType } from "./session-contract-CuW9Nlxg.js";
4
+ import { t as DiscordChannelConfigSchema } from "./config-schema-D1DUqXws.js";
5
+ import { n as normalizeCompatibilityConfig } from "./doctor-contract-DSB2zzJA.js";
6
+ import { t as DISCORD_LEGACY_CONFIG_RULES } from "./doctor-shared-DtOaqWzy.js";
7
+ import { n as secretTargetRegistryEntries, t as collectRuntimeConfigAssignments } from "./secret-config-contract-BA9jVaKx.js";
8
+ import { n as unsupportedSecretRefSurfacePatterns, t as collectUnsupportedSecretRefConfigCandidates } from "./security-contract-B7i5uqn6.js";
9
+ import { t as deriveLegacySessionChatType } from "./session-contract-DwjfF970.js";
10
10
  import { normalizeAccountId } from "openclaw/plugin-sdk/account-id";
11
11
  import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
12
12
  import { adaptScopedAccountAccessor, createScopedChannelConfigAdapter, createScopedDmSecurityResolver } from "openclaw/plugin-sdk/channel-config-helpers";
@@ -49,7 +49,7 @@ const collectDiscordSecurityWarnings = createOpenProviderConfiguredRouteWarningC
49
49
  });
50
50
  let discordSecurityAuditModulePromise;
51
51
  async function loadDiscordSecurityAuditModule() {
52
- discordSecurityAuditModulePromise ??= import("./security-audit.runtime-Dm1LW9KX.js");
52
+ discordSecurityAuditModulePromise ??= import("./security-audit.runtime-DO1398sV.js");
53
53
  return await discordSecurityAuditModulePromise;
54
54
  }
55
55
  const discordSecurityAdapter = {
@@ -69,7 +69,7 @@ const discordSetupAdapter = createEnvPatchedAccountSetupAdapter({
69
69
  const DISCORD_CHANNEL = "discord";
70
70
  let discordDoctorModulePromise;
71
71
  async function loadDiscordDoctorModule() {
72
- discordDoctorModulePromise ??= import("./doctor-Bo-yifB3.js");
72
+ discordDoctorModulePromise ??= import("./doctor-Ys2-q5bc.js");
73
73
  return await discordDoctorModulePromise;
74
74
  }
75
75
  const discordDoctor = {
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-C3SqQTfK.js";
2
- import { presentationToInteractiveReply, reduceInteractiveReply } from "openclaw/plugin-sdk/interactive-runtime";
2
+ import { presentationToInteractiveControlsReply, reduceInteractiveReply } from "openclaw/plugin-sdk/interactive-runtime";
3
3
  //#region extensions/discord/src/shared-interactive.ts
4
4
  var shared_interactive_exports = /* @__PURE__ */ __exportAll({
5
5
  buildDiscordInteractiveComponents: () => buildDiscordInteractiveComponents,
@@ -71,7 +71,7 @@ function buildDiscordPresentationComponents(presentation) {
71
71
  continue;
72
72
  }
73
73
  }
74
- const interactiveSpec = buildDiscordInteractiveComponents(presentationToInteractiveReply({ blocks: presentation.blocks.filter((block) => block.type === "buttons" || block.type === "select") }));
74
+ const interactiveSpec = buildDiscordInteractiveComponents(presentationToInteractiveControlsReply(presentation));
75
75
  if (interactiveSpec?.blocks?.length) spec.blocks?.push(...interactiveSpec.blocks);
76
76
  return spec.blocks?.length ? spec : void 0;
77
77
  }
@@ -1,6 +1,6 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-C3SqQTfK.js";
2
2
  import { s as resolveDiscordAccount } from "./accounts-CaHGiVB4.js";
3
- import { n as autoBindSpawnedDiscordSubagent, o as unbindThreadBindingsBySessionKey, r as listThreadBindingsBySessionKey } from "./thread-bindings-CMpZjP50.js";
3
+ import { n as autoBindSpawnedDiscordSubagent, o as unbindThreadBindingsBySessionKey, r as listThreadBindingsBySessionKey } from "./thread-bindings-B90pBWJg.js";
4
4
  import { normalizeOptionalLowercaseString, normalizeOptionalStringifiedId } from "openclaw/plugin-sdk/text-runtime";
5
5
  import { formatThreadBindingDisabledError, formatThreadBindingSpawnDisabledError, resolveThreadBindingSpawnPolicy } from "openclaw/plugin-sdk/conversation-runtime";
6
6
  //#region extensions/discord/src/subagent-hooks.ts
@@ -1,7 +1,7 @@
1
1
  //#region extensions/discord/subagent-hooks-api.ts
2
2
  let discordSubagentHooksPromise = null;
3
3
  function loadDiscordSubagentHooksModule() {
4
- discordSubagentHooksPromise ??= import("./subagent-hooks-T0LPLh4H.js").then((n) => n.i);
4
+ discordSubagentHooksPromise ??= import("./subagent-hooks-DtbWOdAK.js").then((n) => n.i);
5
5
  return discordSubagentHooksPromise;
6
6
  }
7
7
  function registerDiscordSubagentHooks(api) {
@@ -1,5 +1,5 @@
1
- import { t as discord_exports } from "./discord-eZlimVfW.js";
2
- import { n as formatDiscordUserTag } from "./format-D8TsaXxW.js";
1
+ import { t as discord_exports } from "./discord-Du6FnKAq.js";
2
+ import { n as formatDiscordUserTag } from "./format-XDPCvGK4.js";
3
3
  //#region extensions/discord/src/monitor/system-events.ts
4
4
  function resolveDiscordSystemEvent(message, location) {
5
5
  switch (message.type) {
@@ -0,0 +1,51 @@
1
+ import { buildMessagingTarget, parseMentionPrefixOrAtUserTarget, requireTargetKind } from "openclaw/plugin-sdk/messaging-targets";
2
+ //#region extensions/discord/src/target-parsing.ts
3
+ function parseDiscordTarget(raw, options = {}) {
4
+ const trimmed = raw.trim();
5
+ if (!trimmed) return;
6
+ const providerPrefixedTarget = parseDiscordProviderPrefixedTarget(trimmed);
7
+ if (providerPrefixedTarget) return providerPrefixedTarget;
8
+ const userTarget = parseMentionPrefixOrAtUserTarget({
9
+ raw: trimmed,
10
+ mentionPattern: /^<@!?(\d+)>$/,
11
+ prefixes: [
12
+ {
13
+ prefix: "user:",
14
+ kind: "user"
15
+ },
16
+ {
17
+ prefix: "channel:",
18
+ kind: "channel"
19
+ },
20
+ {
21
+ prefix: "discord:",
22
+ kind: "user"
23
+ }
24
+ ],
25
+ atUserPattern: /^\d+$/,
26
+ atUserErrorMessage: "Discord DMs require a user id (use user:<id> or a <@id> mention)"
27
+ });
28
+ if (userTarget) return userTarget;
29
+ if (/^\d+$/.test(trimmed)) {
30
+ if (options.defaultKind) return buildMessagingTarget(options.defaultKind, trimmed, trimmed);
31
+ throw new Error(options.ambiguousMessage ?? `Ambiguous Discord recipient "${trimmed}". For DMs use "user:${trimmed}" or "<@${trimmed}>"; for channels use "channel:${trimmed}".`);
32
+ }
33
+ return buildMessagingTarget("channel", trimmed, trimmed);
34
+ }
35
+ function parseDiscordProviderPrefixedTarget(raw) {
36
+ const match = /^discord:(channel|user):(.+)$/i.exec(raw);
37
+ if (!match) return;
38
+ const kind = match[1]?.toLowerCase();
39
+ const id = match[2]?.trim();
40
+ if (!kind || !id) return;
41
+ return buildMessagingTarget(kind, id, `${kind}:${id}`);
42
+ }
43
+ function resolveDiscordChannelId(raw) {
44
+ return requireTargetKind({
45
+ platform: "Discord",
46
+ target: parseDiscordTarget(raw, { defaultKind: "channel" }),
47
+ kind: "channel"
48
+ });
49
+ }
50
+ //#endregion
51
+ export { resolveDiscordChannelId as n, parseDiscordTarget as t };