@openclaw/discord 2026.7.2-beta.7 → 2026.8.1-beta.3

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 (114) hide show
  1. package/dist/{account-inspect-SXiCBCgP.js → account-inspect-D5xmUpnj.js} +49 -43
  2. package/dist/account-inspect-api.js +1 -1
  3. package/dist/accounts-DNl-oCEw.js +371 -0
  4. package/dist/action-runtime-api.js +1 -1
  5. package/dist/{active-turn-thread-route-MlKWp8RD.js → active-turn-thread-route-fmHl1HNd.js} +9 -11
  6. package/dist/{activities-api-DTKsuDxf.js → activities-api-KCBAmWxD.js} +133 -175
  7. package/dist/activities-api.js +1 -1
  8. package/dist/{allow-list-DzKrtfah.js → allow-list-BDMimASD.js} +2 -3
  9. package/dist/{api-DnrK9gML.js → api-DNVbJyEy.js} +7 -2
  10. package/dist/api.js +18 -18
  11. package/dist/{approval-handler.runtime-HymvFTYn.js → approval-handler.runtime-B12RCYr8.js} +6 -6
  12. package/dist/{approval-message-safety-DEyKVsAw.js → approval-message-safety-XGFPbDoI.js} +89 -3
  13. package/dist/{audit-CjsrabP8.js → audit-Yc7eZDd6.js} +5 -5
  14. package/dist/{channel-actions-uXFTJX3o.js → channel-actions-Dr2QI8Bf.js} +11 -7
  15. package/dist/{channel-actions.runtime-CIYU90sl.js → channel-actions.runtime-CODTvo7c.js} +99 -97
  16. package/dist/{channel-vKa-76xY.js → channel-cXYzGc4L.js} +102 -104
  17. package/dist/channel-config-api.js +1 -1
  18. package/dist/channel-plugin-api.js +1 -1
  19. package/dist/{channel.setup-CmcwZ_qd.js → channel.setup-CSiwnMgs.js} +16 -54
  20. package/dist/{outbound-session-route-H-HoyH5U.js → components-ezGKo_Yh.js} +69 -142
  21. package/dist/{config-schema-WHRQcY19.js → config-schema-DC5kDtQ5.js} +42 -11
  22. package/dist/conversation-binding-route-D6rCQ5S0.js +43 -0
  23. package/dist/{directory-config-D_LojtCe.js → directory-config-XyCfoqLg.js} +2 -2
  24. package/dist/directory-contract-api.js +1 -1
  25. package/dist/{directory-live-Bw5Ephzv.js → directory-live-Df0NbFJB.js} +7 -4
  26. package/dist/{doctor-Bc4S1qyd.js → doctor-DYY31GrO.js} +34 -13
  27. package/dist/{doctor-contract-CCFMIDk9.js → doctor-contract-DsWvKIXF.js} +2 -3
  28. package/dist/doctor-contract-api.js +147 -2
  29. package/dist/{handle-action.guild-admin-D6VRRW-C.js → handle-action.guild-admin-6Tvvinsa.js} +4 -7
  30. package/dist/{inbound-event-delivery-CEPlt2uz.js → inbound-event-delivery-De2qxTrP.js} +4 -25
  31. package/dist/index.js +5 -4
  32. package/dist/{message-handler-CeiSulIw.js → message-handler-B61q5MOF.js} +118 -33
  33. package/dist/{message-handler.preflight-DibgQFf2.js → message-handler.preflight-Bzg_Hawz.js} +75 -61
  34. package/dist/{message-handler.process-Dnc_oz9y.js → message-handler.process--4_712Ec.js} +236 -296
  35. package/dist/{message-utils-BgTwT_q7.js → message-utils-BXLLnFl6.js} +34 -35
  36. package/dist/{model-picker-preference-primitives-D25pnCOu.js → model-picker-preference-primitives-BHT1LkR_.js} +3 -3
  37. package/dist/{outbound-adapter-DtE-i2OJ.js → outbound-adapter-DxHTOqiN.js} +157 -68
  38. package/dist/{outbound-components-C7GVyfPh.js → outbound-components-B2PL0ooH.js} +3 -3
  39. package/dist/owner-access-Bg41VzAf.js +107 -0
  40. package/dist/{pluralkit-CD4B11JB.js → pluralkit-dUl4v1X3.js} +1 -1
  41. package/dist/{preflight-audio-BjnQZ5yS.js → preflight-audio-DrnqFA8U.js} +22 -28
  42. package/dist/{probe-BeWKhjqX.js → probe-BTdtVRwU.js} +37 -13
  43. package/dist/probe.runtime-Dq5-PRKT.js +2 -0
  44. package/dist/{provider-DfQJX3z5.js → provider-DlK_ynqt.js} +1131 -2021
  45. package/dist/{provider-session.runtime-Bo88k0pV.js → provider-session.runtime-CvvphHvs.js} +3 -3
  46. package/dist/provider.runtime-CzKGRiAF.js +2 -0
  47. package/dist/realtime-session.runtime-ysbMG8v7.js +1351 -0
  48. package/dist/{resolve-allowlist-common-DHERApxi.js → resolve-allowlist-common-DIVXbD1P.js} +3 -3
  49. package/dist/{resolve-channels-BjepAj8b.js → resolve-channels-CGeUoIqb.js} +4 -4
  50. package/dist/{resolve-users-Bc28htgt.js → resolve-users-BtKxLUZv.js} +3 -3
  51. package/dist/{chunk-DX4jpFQP.js → retry-DNsVTeTo.js} +308 -131
  52. package/dist/{runtime-BmW_j_hl.js → runtime-CQovMsH3.js} +12 -15
  53. package/dist/{runtime-_aRC6V2s.js → runtime-D71_VFLr.js} +49 -58
  54. package/dist/runtime-api.actions.js +2 -2
  55. package/dist/runtime-api.js +23 -23
  56. package/dist/runtime-api.lookup.js +5 -5
  57. package/dist/runtime-api.monitor-CzeTYF32.js +6 -0
  58. package/dist/runtime-api.monitor.js +6 -5
  59. package/dist/runtime-api.send.js +6 -6
  60. package/dist/runtime-api.threads.js +5 -6
  61. package/dist/sdk-runtime-37OU6_Yh.js +369 -0
  62. package/dist/{secret-config-contract-B1akrlyY.js → secret-config-contract-B3i6WxV5.js} +53 -25
  63. package/dist/secret-contract-api.js +1 -1
  64. package/dist/security-audit-contract-api.js +1 -1
  65. package/dist/{security-audit.runtime-CPN0xFYz.js → security-audit.runtime-BVKF9VtY.js} +1 -1
  66. package/dist/{send-CdkZ6zeW.js → send-rQIffSYu.js} +180 -91
  67. package/dist/{send.components-5uqwkjgE.js → send.components-ChK1wS7w.js} +32 -46
  68. package/dist/{send.outbound-D-80Ej-t.js → send.outbound-HIkgji_7.js} +57 -34
  69. package/dist/{send.reactions-CtlmGd_o.js → send.reactions-gmJ6yFPo.js} +14 -21
  70. package/dist/{send.receipt-CuwRrpFz.js → send.receipt-Cnhoautb.js} +29 -1
  71. package/dist/{send.shared-jpvAG_u6.js → send.shared-B3fpaLWJ.js} +112 -181
  72. package/dist/{sender-identity-mG_zsdox.js → sender-identity-BJtfyise.js} +1 -1
  73. package/dist/setup-entry.js +0 -5
  74. package/dist/setup-plugin-api.js +1 -1
  75. package/dist/{shared-CXF1tup1.js → shared-CaAaoksy.js} +27 -23
  76. package/dist/subagent-hooks-CNT2ZJTJ.js +49 -0
  77. package/dist/subagent-hooks-api.js +2 -6
  78. package/dist/subagent-progress-FPLqBY1s.js +110 -0
  79. package/dist/{system-events-DdUqf91B.js → system-events-Nuwoq_au.js} +2 -2
  80. package/dist/{target-resolver-C3s_2m0t.js → target-resolver-DIXShHaZ.js} +3 -3
  81. package/dist/targets-B2pf49zc.js +3 -0
  82. package/dist/{thread-bindings-C-M-ly7P.js → thread-bindings-VlymUnbz.js} +29 -28
  83. package/dist/{thread-bindings.manager-DYvSlrva.js → thread-bindings.manager-CngsgErq.js} +258 -29
  84. package/dist/{thread-bindings.session-updates-DAIlp7Px.js → thread-bindings.session-updates-CJb-BpPL.js} +1 -1
  85. package/dist/{thread-bindings.state-Cgi5uRn-.js → thread-bindings.state-D8OMdk4O.js} +3 -16
  86. package/dist/threading-DU6pgeGm.js +456 -0
  87. package/dist/transcripts-source-DeIMNbRh.js +265 -0
  88. package/dist/transcripts-source-api.js +7 -2
  89. package/dist/{typing--Mzo2kM7.js → typing-oLiS5Z13.js} +1 -1
  90. package/dist/voice-runtime-CjNFaynA.js +2549 -0
  91. package/openclaw.plugin.json +215 -25
  92. package/package.json +15 -11
  93. package/skills/discord/SKILL.md +22 -115
  94. package/dist/accounts-DJTf1LtA.js +0 -219
  95. package/dist/channel-api-CAJ0wMoV.js +0 -21
  96. package/dist/legacy-state-migrations-api.js +0 -138
  97. package/dist/manager.runtime-Bjav3pfC.js +0 -3655
  98. package/dist/preflight-audio.runtime-CoCXMM8r.js +0 -7
  99. package/dist/probe.runtime-DqFGFMbZ.js +0 -2
  100. package/dist/provider.runtime-Cy7XZmyh.js +0 -2
  101. package/dist/runtime-api.monitor-CCRubd3-.js +0 -5
  102. package/dist/session-binding-contract-api.js +0 -2
  103. package/dist/subagent-hooks-Dxy7Fmnq.js +0 -120
  104. package/dist/subagent-progress-DI3sYLLo.js +0 -664
  105. package/dist/targets-Dv_RN7vT.js +0 -3
  106. package/dist/thread-bindings.discord-api-BoDNqamb.js +0 -246
  107. package/dist/transcripts-source-DIKGsTGT.js +0 -123
  108. package/node_modules/p-map/index.d.ts +0 -155
  109. package/node_modules/p-map/index.js +0 -285
  110. package/node_modules/p-map/license +0 -9
  111. package/node_modules/p-map/package.json +0 -57
  112. package/node_modules/p-map/readme.md +0 -190
  113. package/dist/{audit-core-xwjIczO0.js → audit-core-BCX8UeFH.js} +1 -1
  114. package/dist/{security-audit-jGnJF__m.js → security-audit-BfJhAXZp.js} +1 -1
@@ -1,19 +1,14 @@
1
- import { u as resolveDiscordChannelId$1 } from "./chunk-DX4jpFQP.js";
2
- import { n as isDiscordAccountEnabledForRuntime, r as listDiscordAccountIds, s as resolveDiscordAccount } from "./accounts-DJTf1LtA.js";
3
- import { i as resolveDiscordActivitiesConfig, r as setDiscordActivitiesRuntime, t as DiscordActivitiesRuntime } from "./runtime-BmW_j_hl.js";
4
- import { S as parseDiscordActivityCustomId, a as buildDiscordPresentationComponents } from "./outbound-session-route-H-HoyH5U.js";
5
- import { r as sendDiscordComponentMessage } from "./send.components-5uqwkjgE.js";
1
+ import { i as buildDiscordPresentationComponents, x as parseDiscordActivityCustomId } from "./components-ezGKo_Yh.js";
2
+ import { A as resolveDiscordChannelId$1, c as resolveDiscordAccount } from "./accounts-DNl-oCEw.js";
3
+ import { r as sendDiscordComponentMessage } from "./send.components-ChK1wS7w.js";
4
+ import { r as setDiscordActivitiesRuntime, t as DiscordActivitiesRuntime } from "./runtime-CQovMsH3.js";
6
5
  import fs from "node:fs/promises";
7
6
  import { logError } from "openclaw/plugin-sdk/logging-core";
8
7
  import { resolveRequestClientIp } from "openclaw/plugin-sdk/webhook-ingress";
9
8
  import { WEBHOOK_BODY_READ_DEFAULTS, readJsonBodyWithLimit } from "openclaw/plugin-sdk/webhook-request-guards";
10
9
  import { randomBytes } from "node:crypto";
11
- import { Type } from "typebox";
12
10
  import { readProviderJsonResponse } from "openclaw/plugin-sdk/provider-http";
13
11
  import { fetchWithSsrFGuard as fetchWithSsrFGuard$1 } from "openclaw/plugin-sdk/ssrf-runtime";
14
- import { jsonResult, readStringParam } from "openclaw/plugin-sdk/channel-actions";
15
- import { escapeHtml } from "openclaw/plugin-sdk/text-utility-runtime";
16
- import { WidgetHtmlInputError, assertWidgetHtmlSize, isCompleteHtmlDocument } from "openclaw/plugin-sdk/widget-html";
17
12
  //#region extensions/discord/src/activities/discord-api.ts
18
13
  const DISCORD_TOKEN_URL = "https://discord.com/api/oauth2/token";
19
14
  const DISCORD_USER_URL = "https://discord.com/api/v10/users/@me";
@@ -440,6 +435,7 @@ function createDiscordActivityHttpHandler(deps) {
440
435
  return { async handleHttpRequest(req, res) {
441
436
  const url = new URL(req.url ?? "/", "http://localhost");
442
437
  if (url.pathname !== "/discord/activity" && !url.pathname.startsWith(`/discord/activity/`)) return false;
438
+ if (!deps.runtime.hasEnabledAccounts()) return false;
443
439
  const relative = url.pathname.slice(17) || "/";
444
440
  if (req.method === "GET" && (relative === "/" || relative === "/index.html")) return respond(res, 200, DISCORD_ACTIVITY_SHELL_HTML, "text/html; charset=utf-8", { "Content-Security-Policy": DISCORD_ACTIVITY_SHELL_CSP });
445
441
  if (req.method === "GET" && relative === "/shell.js") return respond(res, 200, DISCORD_ACTIVITY_SHELL_JS, "text/javascript; charset=utf-8");
@@ -468,6 +464,133 @@ function createDiscordActivityHttpHandler(deps) {
468
464
  } };
469
465
  }
470
466
  //#endregion
467
+ //#region extensions/discord/src/activities/presenter.ts
468
+ const DISCORD_WIDGET_HTML_MAX_BYTES = 48 * 1024;
469
+ function resolveDiscordChannelId(context) {
470
+ const raw = context.nativeChannelId?.trim() || context.currentMessagingTarget?.trim() || context.currentChannelId?.trim() || context.deliveryContext?.to?.trim();
471
+ if (!raw) return;
472
+ try {
473
+ return resolveDiscordChannelId$1(raw);
474
+ } catch {
475
+ return;
476
+ }
477
+ }
478
+ function resolveDiscordPresentationRoute(context, runtime) {
479
+ if (context.messageChannel !== "discord") return;
480
+ const cfg = runtime.currentConfig();
481
+ const account = resolveDiscordAccount({
482
+ cfg,
483
+ accountId: context.accountId ?? context.deliveryContext?.accountId
484
+ });
485
+ const channelId = resolveDiscordChannelId(context);
486
+ const activityAccount = runtime.resolveAccount(account.accountId, cfg);
487
+ if (!channelId || !activityAccount) return;
488
+ return {
489
+ account: activityAccount,
490
+ cfg,
491
+ channelId
492
+ };
493
+ }
494
+ /** Presents a canonical core widget document in the active Discord channel. */
495
+ function createDiscordWidgetPresenter(runtime, deps = {}) {
496
+ return {
497
+ target: "current_channel",
498
+ description: "Post an Activity launch button in the current Discord channel",
499
+ capabilities: {
500
+ sourceKinds: ["html"],
501
+ maxSourceBytes: DISCORD_WIDGET_HTML_MAX_BYTES
502
+ },
503
+ match: (context) => resolveDiscordPresentationRoute(context, runtime) !== void 0,
504
+ async availability(context) {
505
+ return resolveDiscordPresentationRoute(context, runtime) ? {
506
+ ok: true,
507
+ value: { available: true }
508
+ } : {
509
+ ok: false,
510
+ error: {
511
+ code: "unavailable",
512
+ message: "Discord Activities are unavailable for the current channel and account."
513
+ }
514
+ };
515
+ },
516
+ async present({ context, document, title }) {
517
+ const route = resolveDiscordPresentationRoute(context, runtime);
518
+ if (!route) return {
519
+ ok: false,
520
+ error: {
521
+ code: "unavailable",
522
+ message: "Discord Activities are unavailable for the current channel and account."
523
+ }
524
+ };
525
+ if (title.length > 80) return {
526
+ ok: false,
527
+ error: {
528
+ code: "presentation_error",
529
+ message: "title must be 80 characters or fewer"
530
+ }
531
+ };
532
+ const widgetId = await runtime.store.createWidget({
533
+ html: document.html,
534
+ title,
535
+ channelId: route.channelId,
536
+ accountId: route.account.accountId,
537
+ createdAt: (deps.now ?? Date.now)()
538
+ });
539
+ let result;
540
+ let deliveredResult;
541
+ let deliveryRecord;
542
+ let deliveryRecordError;
543
+ const recordDelivery = async (deliveryResult) => {
544
+ deliveredResult = deliveryResult;
545
+ deliveryRecord ??= runtime.store.markWidgetDelivered(widgetId, deliveryResult.messageId);
546
+ try {
547
+ await deliveryRecord;
548
+ } catch (error) {
549
+ deliveryRecordError ??= new Error("Discord widget was delivered, but its delivery state could not be saved", { cause: error });
550
+ throw deliveryRecordError;
551
+ }
552
+ };
553
+ try {
554
+ const components = buildDiscordPresentationComponents({ blocks: [{
555
+ type: "buttons",
556
+ buttons: [{
557
+ label: "Open widget",
558
+ action: {
559
+ type: "web-app",
560
+ widgetId
561
+ }
562
+ }]
563
+ }] });
564
+ if (!components) throw new Error("Discord widget launch button could not be rendered");
565
+ result = await (deps.sendComponentMessage ?? sendDiscordComponentMessage)(`channel:${route.channelId}`, {
566
+ ...components,
567
+ text: title
568
+ }, {
569
+ cfg: route.cfg,
570
+ accountId: route.account.accountId,
571
+ allowedMentions: { parse: [] },
572
+ onDeliveryResult: recordDelivery
573
+ });
574
+ await recordDelivery(result);
575
+ } catch (error) {
576
+ if (deliveryRecordError) throw deliveryRecordError;
577
+ if (!deliveredResult) {
578
+ await runtime.store.deleteWidget(widgetId);
579
+ throw error;
580
+ }
581
+ result = deliveredResult;
582
+ }
583
+ return {
584
+ ok: true,
585
+ value: {
586
+ kind: "message",
587
+ receipt: result.receipt
588
+ }
589
+ };
590
+ }
591
+ };
592
+ }
593
+ //#endregion
471
594
  //#region extensions/discord/src/activities/store.ts
472
595
  const DAY_MS = 1440 * 60 * 1e3;
473
596
  const DISCORD_EPOCH_MS = 14200704e5;
@@ -595,173 +718,9 @@ var DiscordActivityStore = class {
595
718
  }
596
719
  };
597
720
  //#endregion
598
- //#region extensions/discord/src/activities/tool.ts
599
- const DISCORD_WIDGET_HTML_MAX_BYTES = 48 * 1024;
600
- const DiscordWidgetParameters = Type.Object({
601
- html: Type.String({ description: "Self-contained HTML document or body fragment" }),
602
- title: Type.String({
603
- minLength: 1,
604
- maxLength: 80
605
- }),
606
- button_label: Type.Optional(Type.String({
607
- minLength: 1,
608
- maxLength: 80
609
- }))
610
- });
611
- const ShowWidgetParameters = Type.Object({
612
- title: Type.String({
613
- minLength: 1,
614
- maxLength: 80
615
- }),
616
- widget_code: Type.String({ description: "Self-contained HTML document or body fragment" }),
617
- button_label: Type.Optional(Type.String({
618
- minLength: 1,
619
- maxLength: 80
620
- }))
621
- });
622
- function currentConfig(context, runtime) {
623
- return context.getRuntimeConfig?.() ?? context.runtimeConfig ?? context.config ?? runtime.currentConfig();
624
- }
625
- function resolveDiscordChannelId(context) {
626
- const raw = context.nativeChannelId?.trim() || context.deliveryContext?.to?.trim();
627
- if (!raw) return;
628
- try {
629
- return resolveDiscordChannelId$1(raw);
630
- } catch {
631
- return;
632
- }
633
- }
634
- function buildDiscordWidgetDocument(title, html) {
635
- if (isCompleteHtmlDocument(html)) return html;
636
- return `<!doctype html>
637
- <html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>${escapeHtml(title)}</title>
638
- <style>:root{color-scheme:dark;background:#111214;color:#dbdee1;font:14px system-ui,sans-serif}*{box-sizing:border-box}html,body{margin:0;min-height:100%}body{padding:16px}</style></head><body>${html}</body></html>`;
639
- }
640
- const DISCORD_WIDGET_VARIANT = {
641
- name: "discord_widget",
642
- label: "Discord Widget",
643
- description: "Deprecated: use show_widget. Show an interactive, self-contained HTML widget to the user in Discord.",
644
- htmlParam: "html",
645
- parameters: DiscordWidgetParameters
646
- };
647
- const SHOW_WIDGET_VARIANT = {
648
- name: "show_widget",
649
- label: "Show Widget",
650
- description: "Show an interactive, self-contained HTML widget to the user on their current surface. In Discord, posts an Activity launch button.",
651
- htmlParam: "widget_code",
652
- parameters: ShowWidgetParameters
653
- };
654
- function createDiscordWidgetToolVariant(context, deps, variant) {
655
- if (context.messageChannel !== "discord") return null;
656
- const cfg = currentConfig(context, deps.runtime);
657
- const account = resolveDiscordAccount({
658
- cfg,
659
- accountId: context.agentAccountId ?? context.deliveryContext?.accountId
660
- });
661
- if (!deps.runtime.isAccountEnabled(account.accountId, cfg)) return null;
662
- return {
663
- label: variant.label,
664
- name: variant.name,
665
- description: variant.description,
666
- parameters: variant.parameters,
667
- execute: async (_toolCallId, rawParams) => {
668
- const params = rawParams;
669
- const html = readStringParam(params, variant.htmlParam, {
670
- required: true,
671
- trim: false
672
- });
673
- const title = readStringParam(params, "title", { required: true });
674
- const buttonLabel = readStringParam(params, "button_label") || "Open widget";
675
- if (!html.trim()) throw new WidgetHtmlInputError(`${variant.htmlParam} is required`);
676
- assertWidgetHtmlSize(html, DISCORD_WIDGET_HTML_MAX_BYTES, { inputName: variant.htmlParam });
677
- if (title.length > 80) throw new WidgetHtmlInputError("title must be 80 characters or fewer");
678
- if (!buttonLabel.trim() || buttonLabel.length > 80) throw new WidgetHtmlInputError("button_label must be 1 to 80 characters");
679
- const channelId = resolveDiscordChannelId(context);
680
- if (!channelId) throw new WidgetHtmlInputError(`${variant.name} requires a concrete Discord channel in the current session`);
681
- const widgetId = await deps.runtime.store.createWidget({
682
- html: buildDiscordWidgetDocument(title, html),
683
- title,
684
- channelId,
685
- accountId: account.accountId,
686
- createdAt: (deps.now ?? Date.now)()
687
- });
688
- let result;
689
- let deliveredResult;
690
- let deliveryRecord;
691
- let deliveryRecordError;
692
- const recordDelivery = async (deliveryResult) => {
693
- deliveredResult = deliveryResult;
694
- deliveryRecord ??= deps.runtime.store.markWidgetDelivered(widgetId, deliveryResult.messageId);
695
- try {
696
- await deliveryRecord;
697
- } catch (error) {
698
- deliveryRecordError ??= new Error("Discord widget was delivered, but its delivery state could not be saved", { cause: error });
699
- throw deliveryRecordError;
700
- }
701
- };
702
- try {
703
- const components = buildDiscordPresentationComponents({ blocks: [{
704
- type: "buttons",
705
- buttons: [{
706
- label: buttonLabel.trim(),
707
- action: {
708
- type: "web-app",
709
- widgetId
710
- }
711
- }]
712
- }] });
713
- if (!components) throw new Error("Discord widget launch button could not be rendered");
714
- result = await (deps.sendComponentMessage ?? sendDiscordComponentMessage)(`channel:${channelId}`, {
715
- ...components,
716
- text: title
717
- }, {
718
- cfg,
719
- accountId: account.accountId,
720
- allowedMentions: { parse: [] },
721
- onDeliveryResult: recordDelivery
722
- });
723
- await recordDelivery(result);
724
- } catch (error) {
725
- if (deliveryRecordError) throw deliveryRecordError;
726
- if (!deliveredResult) {
727
- await deps.runtime.store.deleteWidget(widgetId);
728
- throw error;
729
- }
730
- result = deliveredResult;
731
- }
732
- return jsonResult({
733
- widgetId,
734
- messageId: result.messageId,
735
- channelId: result.channelId
736
- });
737
- }
738
- };
739
- }
740
- function createDiscordWidgetTool(context, deps) {
741
- return createDiscordWidgetToolVariant(context, deps, DISCORD_WIDGET_VARIANT);
742
- }
743
- function createDiscordShowWidgetTool(context, deps) {
744
- return createDiscordWidgetToolVariant(context, deps, SHOW_WIDGET_VARIANT);
745
- }
746
- //#endregion
747
721
  //#region extensions/discord/src/activities/register.ts
748
722
  function registerDiscordActivities$1(api) {
749
723
  setDiscordActivitiesRuntime(void 0);
750
- const enabledAccountIds = [];
751
- for (const accountId of listDiscordAccountIds(api.config)) {
752
- const account = resolveDiscordAccount({
753
- cfg: api.config,
754
- accountId
755
- });
756
- if (!isDiscordAccountEnabledForRuntime(account, api.config)) continue;
757
- const resolution = resolveDiscordActivitiesConfig(account.config);
758
- if (resolution.enabled) {
759
- enabledAccountIds.push(account.accountId);
760
- continue;
761
- }
762
- if (resolution.reason === "missing-client-secret") api.logger.warn(`[discord] activities configured for account ${account.accountId}, but no client secret resolved; feature disabled`);
763
- }
764
- if (enabledAccountIds.length === 0) return;
765
724
  const runtime = new DiscordActivitiesRuntime(new DiscordActivityStore(openDiscordActivityStores((options) => api.runtime.state.openKeyedStore(options))), api.config, api.runtime.config?.current ? () => api.runtime.config.current() : void 0);
766
725
  setDiscordActivitiesRuntime(runtime);
767
726
  const http = createDiscordActivityHttpHandler({
@@ -774,8 +733,7 @@ function registerDiscordActivities$1(api) {
774
733
  match: "prefix",
775
734
  handler: async (req, res) => await http.handleHttpRequest(req, res)
776
735
  });
777
- api.registerTool((context) => createDiscordShowWidgetTool(context, { runtime }), { name: "show_widget" });
778
- api.registerTool((context) => createDiscordWidgetTool(context, { runtime }), { name: "discord_widget" });
736
+ api.registerWidgetPresenter(createDiscordWidgetPresenter(runtime));
779
737
  }
780
738
  //#endregion
781
739
  //#region extensions/discord/activities-api.ts
@@ -1,2 +1,2 @@
1
- import { t as registerDiscordActivities } from "./activities-api-DTKsuDxf.js";
1
+ import { t as registerDiscordActivities } from "./activities-api-KCBAmWxD.js";
2
2
  export { registerDiscordActivities };
@@ -1,3 +1,4 @@
1
+ import { parseDateStringTimestampMs } from "openclaw/plugin-sdk/number-runtime";
1
2
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
2
3
  import { buildChannelKeyCandidates, resolveChannelEntryMatchWithFallback, resolveChannelMatchConfig } from "openclaw/plugin-sdk/channel-targets";
3
4
  import { resolveAllowlistMatchByCandidates } from "openclaw/plugin-sdk/allow-from";
@@ -19,9 +20,7 @@ function formatDiscordUserTag(user) {
19
20
  return user.username ?? user.id;
20
21
  }
21
22
  function resolveTimestampMs(timestamp) {
22
- if (!timestamp) return;
23
- const parsed = Date.parse(timestamp);
24
- return Number.isNaN(parsed) ? void 0 : parsed;
23
+ return parseDateStringTimestampMs(timestamp);
25
24
  }
26
25
  //#endregion
27
26
  //#region extensions/discord/src/monitor/allow-list.ts
@@ -1,4 +1,5 @@
1
1
  import { t as parseDiscordRetryAfterBodySeconds } from "./retry-after-DdLPmPoa.js";
2
+ import { redactToolPayloadText } from "openclaw/plugin-sdk/logging-core";
2
3
  import { resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
3
4
  import { readResponseWithLimit } from "openclaw/plugin-sdk/response-limit-runtime";
4
5
  import { parseRetryAfterHeaderSeconds, resolveRetryConfig, retryAsync } from "openclaw/plugin-sdk/retry-runtime";
@@ -11,7 +12,7 @@ const DISCORD_RESPONSE_BODY_SUMMARY_MAX_CHARS = 240;
11
12
  function summarizeDiscordResponseBody(body, opts = {}) {
12
13
  const summary = body.replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, " ").replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, " ").replace(/<[^>]+>/g, " ").replace(/&nbsp;/gi, " ").replace(/&amp;/gi, "&").replace(/&lt;/gi, "<").replace(/&gt;/gi, ">").replace(/\s+/g, " ").trim();
13
14
  if (!summary) return opts.emptyText;
14
- return truncateUtf16Safe(summary, DISCORD_RESPONSE_BODY_SUMMARY_MAX_CHARS);
15
+ return truncateUtf16Safe(redactToolPayloadText(summary), DISCORD_RESPONSE_BODY_SUMMARY_MAX_CHARS);
15
16
  }
16
17
  function isDiscordHtmlResponseBody(body, contentType) {
17
18
  return /\bhtml\b/i.test(contentType ?? "") || /^\s*<!doctype\s+html\b/i.test(body) || /^\s*<html\b/i.test(body);
@@ -55,7 +56,7 @@ function formatRetryAfterSeconds(value) {
55
56
  if (value === void 0 || !Number.isFinite(value) || value < 0) return;
56
57
  return `${value < 10 ? value.toFixed(1) : Math.round(value).toString()}s`;
57
58
  }
58
- function formatDiscordApiErrorText(text, response) {
59
+ function formatDiscordApiErrorTextUntrusted(text, response) {
59
60
  const trimmed = text.trim();
60
61
  if (!trimmed) return;
61
62
  const payload = parseDiscordApiErrorPayload(trimmed);
@@ -72,6 +73,10 @@ function formatDiscordApiErrorText(text, response) {
72
73
  const retryAfter = formatRetryAfterSeconds(parseDiscordRetryAfterBodySeconds(payload.retry_after));
73
74
  return retryAfter ? `${message} (retry after ${retryAfter})` : message;
74
75
  }
76
+ function formatDiscordApiErrorText(text, response) {
77
+ const detail = formatDiscordApiErrorTextUntrusted(text, response);
78
+ return detail ? redactToolPayloadText(detail) : detail;
79
+ }
75
80
  var DiscordApiError = class extends Error {
76
81
  constructor(message, status, retryAfter) {
77
82
  super(message);
package/dist/api.js CHANGED
@@ -1,24 +1,24 @@
1
- import { c as normalizeDiscordOutboundTarget, l as parseDiscordTarget, o as looksLikeDiscordTargetId, s as normalizeDiscordMessagingTarget, u as resolveDiscordChannelId } from "./chunk-DX4jpFQP.js";
2
- import { a as mergeDiscordAccountConfig, f as resolveDiscordMaxLinesPerMessage, i as listEnabledDiscordAccounts, l as resolveDiscordAccountConfig, o as resolveDefaultDiscordAccountId, r as listDiscordAccountIds, s as resolveDiscordAccount, t as createDiscordActionGate } from "./accounts-DJTf1LtA.js";
3
- import { D as parseDiscordModalCustomIdForInteraction, E as parseDiscordModalCustomId, T as parseDiscordComponentCustomIdForInteraction, _ as DISCORD_COMPONENT_CUSTOM_ID_KEY, b as buildDiscordComponentCustomId, d as createDiscordFormModal, f as buildDiscordComponentMessage, g as resolveDiscordComponentAttachmentName, h as readDiscordComponentSpec, i as buildDiscordInteractiveComponents, m as DISCORD_COMPONENT_ATTACHMENT_PREFIX, p as buildDiscordComponentMessageFlags, r as formatDiscordComponentEventText, u as DiscordFormModal, v as DISCORD_MODAL_CUSTOM_ID_KEY, w as parseDiscordComponentCustomId, x as buildDiscordModalCustomId } from "./outbound-session-route-H-HoyH5U.js";
4
- import { i as requestDiscord, n as DiscordApiError, r as fetchDiscord } from "./api-DnrK9gML.js";
5
- import { i as parseDiscordSendTarget, n as resolveDiscordTarget } from "./target-resolver-C3s_2m0t.js";
6
- import { t as inspectDiscordAccount } from "./account-inspect-SXiCBCgP.js";
1
+ import { d as normalizeDiscordMessagingTarget, f as normalizeDiscordOutboundTarget, u as looksLikeDiscordTargetId } from "./retry-DNsVTeTo.js";
2
+ import { C as parseDiscordComponentCustomId, E as parseDiscordModalCustomIdForInteraction, T as parseDiscordModalCustomId, _ as DISCORD_MODAL_CUSTOM_ID_KEY, b as buildDiscordModalCustomId, d as buildDiscordComponentMessage, f as buildDiscordComponentMessageFlags, g as DISCORD_COMPONENT_CUSTOM_ID_KEY, h as resolveDiscordComponentAttachmentName, l as DiscordFormModal, m as readDiscordComponentSpec, n as formatDiscordComponentEventText, p as DISCORD_COMPONENT_ATTACHMENT_PREFIX, r as buildDiscordInteractiveComponents, u as createDiscordFormModal, w as parseDiscordComponentCustomIdForInteraction, y as buildDiscordComponentCustomId } from "./components-ezGKo_Yh.js";
3
+ import { A as resolveDiscordChannelId, a as listEnabledDiscordAccounts, c as resolveDiscordAccount, k as parseDiscordTarget, o as mergeDiscordAccountConfig, p as resolveDiscordMaxLinesPerMessage, r as listDiscordAccountIds, s as resolveDefaultDiscordAccountId, t as createDiscordActionGate, u as resolveDiscordAccountConfig } from "./accounts-DNl-oCEw.js";
4
+ import { i as requestDiscord, n as DiscordApiError, r as fetchDiscord } from "./api-DNVbJyEy.js";
5
+ import { i as parseDiscordSendTarget, n as resolveDiscordTarget } from "./target-resolver-DIXShHaZ.js";
6
+ import { t as inspectDiscordAccount } from "./account-inspect-D5xmUpnj.js";
7
7
  import { i as DISCORD_DEFAULT_LISTENER_TIMEOUT_MS, n as DISCORD_ATTACHMENT_TOTAL_TIMEOUT_MS, r as DISCORD_DEFAULT_INBOUND_WORKER_TIMEOUT_MS, t as DISCORD_ATTACHMENT_IDLE_TIMEOUT_MS } from "./timeouts-B9cy6RvQ.js";
8
- import "./targets-Dv_RN7vT.js";
9
- import { a as getDiscordExecApprovalApprovers, c as shouldSuppressLocalDiscordExecApprovalPrompt, o as isDiscordExecApprovalApprover, s as isDiscordExecApprovalClientEnabled } from "./approval-message-safety-DEyKVsAw.js";
10
- import { i as resolveDiscordGroupToolPolicy, n as collectDiscordStatusIssues, r as resolveDiscordGroupRequireMention, t as discordPlugin } from "./channel-vKa-76xY.js";
8
+ import "./targets-B2pf49zc.js";
9
+ import { f as getDiscordExecApprovalApprovers, h as shouldSuppressLocalDiscordExecApprovalPrompt, m as isDiscordExecApprovalClientEnabled, p as isDiscordExecApprovalApprover } from "./approval-message-safety-XGFPbDoI.js";
10
+ import { i as resolveDiscordGroupToolPolicy, n as collectDiscordStatusIssues, r as resolveDiscordGroupRequireMention, t as discordPlugin } from "./channel-cXYzGc4L.js";
11
11
  import { t as normalizeExplicitDiscordSessionKey } from "./session-key-normalization-wJgsKPNF.js";
12
- import { t as discordSetupPlugin } from "./channel.setup-CmcwZ_qd.js";
13
- import { n as handleDiscordSubagentEnded, r as handleDiscordSubagentSpawning, t as handleDiscordSubagentDeliveryTarget } from "./subagent-hooks-Dxy7Fmnq.js";
14
- import { t as tryHandleDiscordMessageActionGuildAdmin } from "./handle-action.guild-admin-D6VRRW-C.js";
15
- import { n as listDiscordDirectoryGroupsFromConfig, r as listDiscordDirectoryPeersFromConfig } from "./directory-config-D_LojtCe.js";
16
- import { t as fetchPluralKitMessageInfo } from "./pluralkit-CD4B11JB.js";
17
- import { a as resolveDiscordPrivilegedIntentsFromFlags, i as probeDiscord, n as fetchDiscordApplicationSummary, r as parseApplicationIdFromToken, t as fetchDiscordApplicationId } from "./probe-BeWKhjqX.js";
18
- import { t as collectDiscordSecurityAuditFindings } from "./security-audit-jGnJF__m.js";
12
+ import { t as discordSetupPlugin } from "./channel.setup-CSiwnMgs.js";
13
+ import { n as handleDiscordSubagentEnded, t as handleDiscordSubagentDeliveryTarget } from "./subagent-hooks-CNT2ZJTJ.js";
14
+ import { t as tryHandleDiscordMessageActionGuildAdmin } from "./handle-action.guild-admin-6Tvvinsa.js";
15
+ import { n as listDiscordDirectoryGroupsFromConfig, r as listDiscordDirectoryPeersFromConfig } from "./directory-config-XyCfoqLg.js";
16
+ import { t as fetchPluralKitMessageInfo } from "./pluralkit-dUl4v1X3.js";
17
+ import { i as probeDiscord, n as fetchDiscordApplicationSummary, o as resolveDiscordPrivilegedIntentsFromFlags, r as parseApplicationIdFromToken, t as fetchDiscordApplicationId } from "./probe-BTdtVRwU.js";
18
+ import { t as collectDiscordSecurityAuditFindings } from "./security-audit-BfJhAXZp.js";
19
19
  import { resolveOpenProviderRuntimeGroupPolicy as resolveDiscordRuntimeGroupPolicy } from "openclaw/plugin-sdk/runtime-group-policy";
20
20
  //#region extensions/discord/api.ts
21
- const handleDiscordMessageAction = async (...args) => (await import("./channel-actions.runtime-CIYU90sl.js")).handleDiscordMessageAction(...args);
21
+ const handleDiscordMessageAction = async (...args) => (await import("./channel-actions.runtime-CODTvo7c.js")).handleDiscordMessageAction(...args);
22
22
  /**
23
23
  * @deprecated Shipped `@openclaw/discord/api` compatibility only. Use native
24
24
  * `AbortSignal.any` after filtering optional signals. Removal with the next
@@ -29,4 +29,4 @@ function mergeAbortSignals(signals) {
29
29
  return activeSignals.length > 1 ? AbortSignal.any(activeSignals) : activeSignals[0];
30
30
  }
31
31
  //#endregion
32
- export { DISCORD_ATTACHMENT_IDLE_TIMEOUT_MS, DISCORD_ATTACHMENT_TOTAL_TIMEOUT_MS, DISCORD_COMPONENT_ATTACHMENT_PREFIX, DISCORD_COMPONENT_CUSTOM_ID_KEY, DISCORD_DEFAULT_INBOUND_WORKER_TIMEOUT_MS, DISCORD_DEFAULT_LISTENER_TIMEOUT_MS, DISCORD_MODAL_CUSTOM_ID_KEY, DiscordApiError, DiscordFormModal, buildDiscordComponentCustomId, buildDiscordComponentMessage, buildDiscordComponentMessageFlags, buildDiscordInteractiveComponents, buildDiscordModalCustomId, collectDiscordSecurityAuditFindings, collectDiscordStatusIssues, createDiscordActionGate, createDiscordFormModal, discordPlugin, discordSetupPlugin, fetchDiscord, fetchDiscordApplicationId, fetchDiscordApplicationSummary, fetchPluralKitMessageInfo, formatDiscordComponentEventText, getDiscordExecApprovalApprovers, handleDiscordMessageAction, handleDiscordSubagentDeliveryTarget, handleDiscordSubagentEnded, handleDiscordSubagentSpawning, inspectDiscordAccount, isDiscordExecApprovalApprover, isDiscordExecApprovalClientEnabled, listDiscordAccountIds, listDiscordDirectoryGroupsFromConfig, listDiscordDirectoryPeersFromConfig, listEnabledDiscordAccounts, looksLikeDiscordTargetId, mergeAbortSignals, mergeDiscordAccountConfig, normalizeDiscordMessagingTarget, normalizeDiscordOutboundTarget, normalizeExplicitDiscordSessionKey, parseApplicationIdFromToken, parseDiscordComponentCustomId, parseDiscordComponentCustomIdForInteraction as parseDiscordComponentCustomIdForCarbon, parseDiscordComponentCustomIdForInteraction, parseDiscordModalCustomId, parseDiscordModalCustomIdForInteraction as parseDiscordModalCustomIdForCarbon, parseDiscordModalCustomIdForInteraction, parseDiscordSendTarget, parseDiscordTarget, probeDiscord, readDiscordComponentSpec, requestDiscord, resolveDefaultDiscordAccountId, resolveDiscordAccount, resolveDiscordAccountConfig, resolveDiscordChannelId, resolveDiscordComponentAttachmentName, resolveDiscordGroupRequireMention, resolveDiscordGroupToolPolicy, resolveDiscordMaxLinesPerMessage, resolveDiscordPrivilegedIntentsFromFlags, resolveDiscordRuntimeGroupPolicy, resolveDiscordTarget, shouldSuppressLocalDiscordExecApprovalPrompt, tryHandleDiscordMessageActionGuildAdmin };
32
+ export { DISCORD_ATTACHMENT_IDLE_TIMEOUT_MS, DISCORD_ATTACHMENT_TOTAL_TIMEOUT_MS, DISCORD_COMPONENT_ATTACHMENT_PREFIX, DISCORD_COMPONENT_CUSTOM_ID_KEY, DISCORD_DEFAULT_INBOUND_WORKER_TIMEOUT_MS, DISCORD_DEFAULT_LISTENER_TIMEOUT_MS, DISCORD_MODAL_CUSTOM_ID_KEY, DiscordApiError, DiscordFormModal, buildDiscordComponentCustomId, buildDiscordComponentMessage, buildDiscordComponentMessageFlags, buildDiscordInteractiveComponents, buildDiscordModalCustomId, collectDiscordSecurityAuditFindings, collectDiscordStatusIssues, createDiscordActionGate, createDiscordFormModal, discordPlugin, discordSetupPlugin, fetchDiscord, fetchDiscordApplicationId, fetchDiscordApplicationSummary, fetchPluralKitMessageInfo, formatDiscordComponentEventText, getDiscordExecApprovalApprovers, handleDiscordMessageAction, handleDiscordSubagentDeliveryTarget, handleDiscordSubagentEnded, inspectDiscordAccount, isDiscordExecApprovalApprover, isDiscordExecApprovalClientEnabled, listDiscordAccountIds, listDiscordDirectoryGroupsFromConfig, listDiscordDirectoryPeersFromConfig, listEnabledDiscordAccounts, looksLikeDiscordTargetId, mergeAbortSignals, mergeDiscordAccountConfig, normalizeDiscordMessagingTarget, normalizeDiscordOutboundTarget, normalizeExplicitDiscordSessionKey, parseApplicationIdFromToken, parseDiscordComponentCustomId, parseDiscordComponentCustomIdForInteraction as parseDiscordComponentCustomIdForCarbon, parseDiscordComponentCustomIdForInteraction, parseDiscordModalCustomId, parseDiscordModalCustomIdForInteraction as parseDiscordModalCustomIdForCarbon, parseDiscordModalCustomIdForInteraction, parseDiscordSendTarget, parseDiscordTarget, probeDiscord, readDiscordComponentSpec, requestDiscord, resolveDefaultDiscordAccountId, resolveDiscordAccount, resolveDiscordAccountConfig, resolveDiscordChannelId, resolveDiscordComponentAttachmentName, resolveDiscordGroupRequireMention, resolveDiscordGroupToolPolicy, resolveDiscordMaxLinesPerMessage, resolveDiscordPrivilegedIntentsFromFlags, resolveDiscordRuntimeGroupPolicy, resolveDiscordTarget, shouldSuppressLocalDiscordExecApprovalPrompt, tryHandleDiscordMessageActionGuildAdmin };
@@ -1,11 +1,11 @@
1
- import { K as Container, L as serializePayload, Q as Row, W as Button, ct as createUserDmChannel, et as Separator, gt as deleteChannelMessage, nt as TextDisplay, pt as createChannelMessage, vt as editChannelMessage } from "./chunk-DX4jpFQP.js";
2
- import { c as buildExecApprovalCustomId } from "./outbound-session-route-H-HoyH5U.js";
3
- import { P as createDiscordClient, b as stripUndefinedFields, g as createDiscordMessageNonce } from "./send.shared-jpvAG_u6.js";
4
- import { n as formatDiscordApprovalDisplayValue, s as isDiscordExecApprovalClientEnabled, t as DISCORD_APPROVAL_ALLOWED_MENTIONS } from "./approval-message-safety-DEyKVsAw.js";
5
- import { a as shouldHandleDiscordApprovalRequest } from "./channel-vKa-76xY.js";
6
- import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
1
+ import { Ct as editChannelMessage, J as Button, V as serializePayload, X as Container, dt as stripUndefinedFields, it as Separator, nt as Row, ot as TextDisplay, pt as createUserDmChannel, vt as createChannelMessage, xt as deleteChannelMessage } from "./retry-DNsVTeTo.js";
2
+ import { s as buildExecApprovalCustomId } from "./components-ezGKo_Yh.js";
3
+ import { P as createDiscordClient, k as createDiscordMessageNonce } from "./send.shared-B3fpaLWJ.js";
4
+ import { m as isDiscordExecApprovalClientEnabled, n as formatDiscordApprovalDisplayValue, t as DISCORD_APPROVAL_ALLOWED_MENTIONS } from "./approval-message-safety-XGFPbDoI.js";
5
+ import { a as shouldHandleDiscordApprovalRequest } from "./channel-cXYzGc4L.js";
7
6
  import { logDebug, logError } from "openclaw/plugin-sdk/logging-core";
8
7
  import { ButtonStyle } from "discord-api-types/v10";
8
+ import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
9
9
  import { createChannelApprovalNativeRuntimeAdapter } from "openclaw/plugin-sdk/approval-handler-runtime";
10
10
  //#region extensions/discord/src/ui-colors.ts
11
11
  const DEFAULT_DISCORD_ACCENT_COLOR = "#5865F2";
@@ -1,5 +1,5 @@
1
- import { l as parseDiscordTarget } from "./chunk-DX4jpFQP.js";
2
- import { s as resolveDiscordAccount } from "./accounts-DJTf1LtA.js";
1
+ import { c as resolveDiscordAccount, k as parseDiscordTarget } from "./accounts-DNl-oCEw.js";
2
+ import { deriveLastRoutePolicy, isAcpSessionKey, isSubagentSessionKey, parseAgentSessionKey, resolveAgentIdFromSessionKey, resolveAgentRoute } from "openclaw/plugin-sdk/routing";
3
3
  import { normalizeOptionalLowercaseString, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
4
4
  import { createChannelApproverDmTargetResolver, createChannelNativeOriginTargetResolver } from "openclaw/plugin-sdk/approval-native-runtime";
5
5
  import { getExecApprovalReplyMetadata, isChannelExecApprovalClientEnabledFromConfig, matchesApprovalRequestFilters } from "openclaw/plugin-sdk/approval-client-runtime";
@@ -76,6 +76,10 @@ function buildDiscordConversationIdentity(kind, rawId) {
76
76
  function resolveDiscordConversationIdentity(params) {
77
77
  return params.isDirectMessage ? buildDiscordConversationIdentity("user", params.userId) : buildDiscordConversationIdentity("channel", params.channelId);
78
78
  }
79
+ function resolveDiscordRuntimeBindingConversationId(params) {
80
+ if (params.isDirectMessage && !params.isGroupDm) return buildDiscordConversationIdentity("user", params.userId) ?? params.channelId;
81
+ return params.channelId;
82
+ }
79
83
  function resolveDiscordCurrentConversationIdentity(params) {
80
84
  if (normalizeOptionalLowercaseString(params.chatType) === "direct") {
81
85
  const senderTarget = normalizeDiscordTarget(params.from, "user");
@@ -91,6 +95,88 @@ function resolveDiscordCurrentConversationIdentity(params) {
91
95
  }
92
96
  }
93
97
  //#endregion
98
+ //#region extensions/discord/src/monitor/route-resolution.ts
99
+ function buildDiscordRoutePeer(params) {
100
+ return {
101
+ kind: params.isGroupDm ? "group" : params.isDirectMessage ? "direct" : "channel",
102
+ id: params.isDirectMessage && !params.isGroupDm ? params.directUserId?.trim() || params.conversationId : params.conversationId
103
+ };
104
+ }
105
+ function buildDiscordConversationRouteContext(params) {
106
+ return {
107
+ ConversationRouteContextObserved: true,
108
+ ConversationRoutePeerId: buildDiscordRoutePeer(params).id,
109
+ NativeChannelId: params.conversationId,
110
+ InboundAccessAuthorized: true,
111
+ MessageThreadId: params.isThread ? params.conversationId : void 0,
112
+ ThreadParentId: params.isThread ? params.parentConversationId : void 0
113
+ };
114
+ }
115
+ function resolveDiscordConversationRoute(params) {
116
+ return resolveAgentRoute({
117
+ cfg: params.cfg,
118
+ channel: "discord",
119
+ accountId: params.accountId,
120
+ guildId: params.guildId ?? void 0,
121
+ memberRoleIds: params.memberRoleIds,
122
+ peer: params.peer,
123
+ parentPeer: params.parentConversationId ? {
124
+ kind: "channel",
125
+ id: params.parentConversationId
126
+ } : void 0
127
+ });
128
+ }
129
+ function resolveDiscordBoundConversationRoute(params) {
130
+ return resolveDiscordEffectiveRoute({
131
+ route: resolveDiscordConversationRoute({
132
+ cfg: params.cfg,
133
+ accountId: params.accountId,
134
+ guildId: params.guildId,
135
+ memberRoleIds: params.memberRoleIds,
136
+ peer: buildDiscordRoutePeer({
137
+ isDirectMessage: params.isDirectMessage,
138
+ isGroupDm: params.isGroupDm,
139
+ directUserId: params.directUserId,
140
+ conversationId: params.conversationId
141
+ }),
142
+ parentConversationId: params.parentConversationId
143
+ }),
144
+ boundSessionKey: params.boundSessionKey,
145
+ configuredRoute: params.configuredRoute,
146
+ matchedBy: params.matchedBy
147
+ });
148
+ }
149
+ function resolveDiscordEffectiveRoute(params) {
150
+ const boundSessionKey = params.boundSessionKey?.trim();
151
+ if (!boundSessionKey) return params.configuredRoute?.route ?? params.route;
152
+ return {
153
+ ...params.route,
154
+ sessionKey: boundSessionKey,
155
+ agentId: resolveAgentIdFromSessionKey(boundSessionKey),
156
+ lastRoutePolicy: deriveLastRoutePolicy({
157
+ sessionKey: boundSessionKey,
158
+ mainSessionKey: params.route.mainSessionKey
159
+ }),
160
+ ...params.matchedBy ? { matchedBy: params.matchedBy } : {}
161
+ };
162
+ }
163
+ function hasExplicitRuntimeBindingIntent(record) {
164
+ if (record.targetKind === "subagent") return true;
165
+ if (isAcpSessionKey(record.targetSessionKey) || isSubagentSessionKey(record.targetSessionKey)) return true;
166
+ const metadata = record.metadata;
167
+ if (!metadata || typeof metadata !== "object") return false;
168
+ return typeof metadata.boundBy === "string" || typeof metadata.label === "string" || typeof metadata.threadName === "string" || metadata.pluginBindingOwner === "plugin";
169
+ }
170
+ function shouldIgnoreStaleDiscordRouteBinding(params) {
171
+ const bindingRecord = params.bindingRecord;
172
+ const boundSessionKey = bindingRecord?.targetSessionKey?.trim();
173
+ if (!bindingRecord || !boundSessionKey || hasExplicitRuntimeBindingIntent(bindingRecord)) return false;
174
+ const bound = parseAgentSessionKey(boundSessionKey);
175
+ const routed = parseAgentSessionKey(params.route.sessionKey);
176
+ if (!bound || !routed || bound.rest !== routed.rest) return false;
177
+ return bound.agentId !== params.route.agentId;
178
+ }
179
+ //#endregion
94
180
  //#region extensions/discord/src/approval-message-safety.ts
95
181
  const DISCORD_APPROVAL_ALLOWED_MENTIONS = { parse: [] };
96
182
  const DISCORD_MARKDOWN_META_CHARACTERS = /* @__PURE__ */ new Set([
@@ -137,4 +223,4 @@ function formatDiscordApprovalDisplayValue(value, maxChars = 200) {
137
223
  return `${bounded}...`;
138
224
  }
139
225
  //#endregion
140
- export { getDiscordExecApprovalApprovers as a, shouldSuppressLocalDiscordExecApprovalPrompt as c, createChannelNativeOriginTargetResolver as d, isChannelExecApprovalClientEnabledFromConfig as f, resolveDiscordCurrentConversationIdentity as i, createApproverRestrictedNativeApprovalCapability as l, formatDiscordApprovalDisplayValue as n, isDiscordExecApprovalApprover as o, matchesApprovalRequestFilters as p, resolveDiscordConversationIdentity as r, isDiscordExecApprovalClientEnabled as s, DISCORD_APPROVAL_ALLOWED_MENTIONS as t, createChannelApproverDmTargetResolver as u };
226
+ export { createChannelApproverDmTargetResolver as _, resolveDiscordBoundConversationRoute as a, matchesApprovalRequestFilters as b, shouldIgnoreStaleDiscordRouteBinding as c, resolveDiscordRuntimeBindingConversationId as d, getDiscordExecApprovalApprovers as f, createApproverRestrictedNativeApprovalCapability as g, shouldSuppressLocalDiscordExecApprovalPrompt as h, buildDiscordRoutePeer as i, resolveDiscordConversationIdentity as l, isDiscordExecApprovalClientEnabled as m, formatDiscordApprovalDisplayValue as n, resolveDiscordConversationRoute as o, isDiscordExecApprovalApprover as p, buildDiscordConversationRouteContext as r, resolveDiscordEffectiveRoute as s, DISCORD_APPROVAL_ALLOWED_MENTIONS as t, resolveDiscordCurrentConversationIdentity as u, createChannelNativeOriginTargetResolver as v, isChannelExecApprovalClientEnabledFromConfig as y };
@@ -1,8 +1,8 @@
1
- import { Yt as __exportAll } from "./chunk-DX4jpFQP.js";
2
- import { O as fetchChannelPermissionsDiscord } from "./send.shared-jpvAG_u6.js";
3
- import { t as inspectDiscordAccount } from "./account-inspect-SXiCBCgP.js";
4
- import "./send-CdkZ6zeW.js";
5
- import { n as collectDiscordAuditChannelIdsForAccount, t as auditDiscordChannelPermissionsWithFetcher } from "./audit-core-xwjIczO0.js";
1
+ import { en as __exportAll } from "./retry-DNsVTeTo.js";
2
+ import { x as fetchChannelPermissionsDiscord } from "./send.shared-B3fpaLWJ.js";
3
+ import { t as inspectDiscordAccount } from "./account-inspect-D5xmUpnj.js";
4
+ import "./send-rQIffSYu.js";
5
+ import { n as collectDiscordAuditChannelIdsForAccount, t as auditDiscordChannelPermissionsWithFetcher } from "./audit-core-BCX8UeFH.js";
6
6
  //#region extensions/discord/src/audit.ts
7
7
  var audit_exports = /* @__PURE__ */ __exportAll({
8
8
  auditDiscordChannelPermissions: () => auditDiscordChannelPermissions,