@openclaw/discord 2026.5.12 → 2026.5.14-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/dist/{account-inspect-D7jL5YDH.js → account-inspect-B_N30NV0.js} +1 -1
  2. package/dist/account-inspect-api.js +1 -1
  3. package/dist/{accounts-BcwyaFd-.js → accounts-DnNVBDfc.js} +95 -4
  4. package/dist/action-runtime-api.js +1 -1
  5. package/dist/{allow-list-n8Ki-Rt3.js → allow-list-CBI-M84K.js} +24 -2
  6. package/dist/api.js +19 -21
  7. package/dist/{approval-handler.runtime-S-ircYcz.js → approval-handler.runtime-Uco62pII.js} +4 -4
  8. package/dist/{audit-BliEqCEc.js → audit-eSlKbMHw.js} +5 -5
  9. package/dist/{channel-Bliqi-Qi.js → channel-BjBa8nYY.js} +23 -25
  10. package/dist/{channel-actions-Cn_K00Vy.js → channel-actions-DANVAtKL.js} +4 -4
  11. package/dist/{channel-actions.runtime-DcsRvPnx.js → channel-actions.runtime-CpIslHS9.js} +7 -5
  12. package/dist/channel-config-api.js +1 -1
  13. package/dist/channel-plugin-api.js +1 -1
  14. package/dist/{channel.setup-DR-xVYso.js → channel.setup-DBFcGRFD.js} +4 -5
  15. package/dist/{components-Dxq2mU57.js → components-Cgm7XT8-.js} +120 -3
  16. package/dist/{config-schema-D2KGskAp.js → config-schema-D7AtCpJa.js} +21 -1
  17. package/dist/contract-api.js +7 -7
  18. package/dist/{approval-native-Gtqpyfdj.js → conversation-identity-C3AI-1tz.js} +123 -6
  19. package/dist/{directory-config-CDl4JTCA.js → directory-config-CW_JusGS.js} +2 -2
  20. package/dist/directory-contract-api.js +1 -1
  21. package/dist/directory-live-MrDSKsMf.js +159 -0
  22. package/dist/doctor-contract-api.js +1 -1
  23. package/dist/{doctor-contract-BGjjFBdq.js → doctor-contract-ftWAMvBl.js} +1 -1
  24. package/dist/{doctor-jcX_qXsS.js → doctor-mn2XyjuF.js} +5 -5
  25. package/dist/{handle-action.guild-admin-C4phin-a.js → handle-action.guild-admin-DriifPwO.js} +1 -1
  26. package/dist/{inbound-context-jtKcY9on.js → inbound-context-DD7n3Q6U.js} +1 -1
  27. package/dist/{manager.runtime-DqMGETqp.js → manager.runtime-DauS2xA3.js} +107 -25
  28. package/dist/{message-handler-DIsnboy2.js → message-handler-CMHwRlxG.js} +7 -7
  29. package/dist/{message-handler.preflight-BRH-dv1o.js → message-handler.preflight-C0sT-ewp.js} +27 -17
  30. package/dist/{message-handler.process-Bs5wropA.js → message-handler.process-Cy7_-0H0.js} +46 -37
  31. package/dist/{message-utils-ByofKwPe.js → message-utils-N5UTOXQ2.js} +16 -12
  32. package/dist/{outbound-adapter-lWjkSeyP.js → outbound-adapter-Cw9JsRTY.js} +7 -10
  33. package/dist/{pluralkit-B1HTaBc9.js → pluralkit-B2AqgTHV.js} +1 -1
  34. package/dist/{preflight-audio-CD97vnac.js → preflight-audio-DFGpAvzi.js} +1 -1
  35. package/dist/{probe-BZtr8qle.js → probe-CiBYm-vD.js} +2 -2
  36. package/dist/{probe.runtime-0F0UzBoJ.js → probe.runtime-9hi1GYNU.js} +1 -1
  37. package/dist/{provider-DABvNRT0.js → provider-nzJg2k5t.js} +1039 -45
  38. package/dist/{provider-session.runtime-BZyP90-i.js → provider-session.runtime-DMxaLPB3.js} +3 -3
  39. package/dist/provider.runtime-S-wZdzK5.js +2 -0
  40. package/dist/{resolve-allowlist-common-CVHYb5Hb.js → resolve-allowlist-common-DybgkAjk.js} +3 -3
  41. package/dist/{resolve-channels-JNt3Ak6P.js → resolve-channels-u7_agBcm.js} +4 -4
  42. package/dist/{resolve-users-CrjbUxrL.js → resolve-users-Bc25I6OP.js} +3 -3
  43. package/dist/{runtime-CdnAT8R5.js → runtime-DL82ijB1.js} +102 -46
  44. package/dist/runtime-api.actions.js +2 -2
  45. package/dist/runtime-api.js +25 -26
  46. package/dist/runtime-api.lookup.js +6 -6
  47. package/dist/runtime-api.monitor-DbLcHuhE.js +5 -0
  48. package/dist/runtime-api.monitor.js +7 -8
  49. package/dist/runtime-api.send.js +5 -5
  50. package/dist/runtime-api.threads.js +5 -5
  51. package/dist/runtime-setter-api.js +1 -1
  52. package/dist/secret-contract-api.js +1 -1
  53. package/dist/{security-audit-BQ_sGK3J.js → security-audit-CLPZKYi4.js} +1 -1
  54. package/dist/security-audit-contract-api.js +1 -1
  55. package/dist/{security-audit.runtime-B7Gmz2DX.js → security-audit.runtime-CCm9leFJ.js} +1 -1
  56. package/dist/security-contract-api.js +1 -1
  57. package/dist/{send-DCFuSiBi.js → send-BqzTEkt9.js} +4 -6
  58. package/dist/{send.components-DxDqPJZQ.js → send.components-D6pXHVrU.js} +8 -10
  59. package/dist/{send.outbound-PM0J0F60.js → send.outbound-D8o8BW6q.js} +91 -7
  60. package/dist/{discord-BqYcwxvG.js → send.receipt-nKLxvA1s.js} +319 -1
  61. package/dist/{send.shared-Dza0jdso.js → send.shared-DSpva7uA.js} +4 -6
  62. package/dist/{sender-identity-w9rSI-nD.js → sender-identity-BTGL3VbF.js} +1 -1
  63. package/dist/session-key-api.js +1 -1
  64. package/dist/setup-plugin-api.js +1 -1
  65. package/dist/{shared-Yp_M6Cfp.js → shared-0kdaIxXP.js} +16 -14
  66. package/dist/{subagent-hooks-CtN-hfXy.js → subagent-hooks-DhuBhwRw.js} +3 -3
  67. package/dist/subagent-hooks-api.js +1 -1
  68. package/dist/{system-events-B04UOvPg.js → system-events-Bnit0zkQ.js} +2 -2
  69. package/dist/{target-resolver-CgJei-kD.js → target-resolver-BsGT9hI7.js} +3 -6
  70. package/dist/targets-DwW6OieO.js +3 -0
  71. package/dist/test-api.js +4 -4
  72. package/dist/{thread-bindings-B4of4OmR.js → thread-bindings-C1f7Iim4.js} +6 -7
  73. package/dist/{thread-bindings.discord-api-BAw15EQb.js → thread-bindings.discord-api-DJACBZJ1.js} +67 -8
  74. package/dist/{thread-bindings.manager-DNFl10CA.js → thread-bindings.manager-DN_q0IW7.js} +4 -5
  75. package/dist/{thread-bindings.session-updates-D18cCLmN.js → thread-bindings.session-updates-ZnRRzzgf.js} +1 -1
  76. package/dist/timeouts.js +1 -1
  77. package/dist/{typing-_jePdFIw.js → typing-C_8U8J7E.js} +2 -2
  78. package/openclaw.plugin.json +68 -0
  79. package/package.json +6 -6
  80. package/dist/access-Dxmzr0ix.js +0 -89
  81. package/dist/approval-shared-BFnWKSQD.js +0 -93
  82. package/dist/channel-access-BL-wemES.js +0 -62
  83. package/dist/chunk-DYl-_5RL.js +0 -179
  84. package/dist/conversation-identity-CvIx6J7M.js +0 -31
  85. package/dist/directory-cache-Ddl-Oxue.js +0 -62
  86. package/dist/directory-live-ApUXOSj0.js +0 -101
  87. package/dist/doctor-shared-D_QLzu30.js +0 -4
  88. package/dist/format-D8TsaXxW.js +0 -24
  89. package/dist/mentions-BZoGn0ul.js +0 -88
  90. package/dist/normalize-Cu94FOqy.js +0 -58
  91. package/dist/outbound-session-route-BaJRt05p.js +0 -43
  92. package/dist/provider.runtime-Cmv1SFtb.js +0 -2
  93. package/dist/reply-delivery-CUSK6SA_.js +0 -191
  94. package/dist/route-resolution-BFfF9xmG.js +0 -268
  95. package/dist/runtime-api.monitor-W_dJ5EQu.js +0 -6
  96. package/dist/send.receipt-BAZw2Zsz.js +0 -35
  97. package/dist/shared-interactive-DavY6jYt.js +0 -79
  98. package/dist/target-parsing-D-H7nnh2.js +0 -51
  99. package/dist/targets-DToZUkgV.js +0 -3
  100. package/dist/threading-CLZ3v7-y.js +0 -475
  101. package/dist/token-BZtonk7d.js +0 -93
  102. /package/dist/{agent-components.runtime-zT8qPsnM.js → agent-components.runtime-CEMbMQcQ.js} +0 -0
  103. /package/dist/{api-DzNBVTto.js → api-DgQLz1wq.js} +0 -0
  104. /package/dist/{audit-core-BgDZSkIR.js → audit-core-DRyoXREU.js} +0 -0
  105. /package/dist/{channel-api-CTSWMrnD.js → channel-api-JudoSiJv.js} +0 -0
  106. /package/dist/{config-api-CFZtoMaS.js → config-api-oLS_52S7.js} +0 -0
  107. /package/dist/{gateway-registry-BKG4KIVC.js → gateway-registry-BKSpa4GB.js} +0 -0
  108. /package/dist/{preflight-audio.runtime-fXnUxxBa.js → preflight-audio.runtime-Drc-OFcp.js} +0 -0
  109. /package/dist/{preview-streaming-DCPAe24T.js → preview-streaming-CXTZydhx.js} +0 -0
  110. /package/dist/{runtime-BqCoo-zp.js → runtime-Tqtvj5GX.js} +0 -0
  111. /package/dist/{secret-config-contract-BCQNNS7N.js → secret-config-contract-B3347_eU.js} +0 -0
  112. /package/dist/{security-contract-DkCMKSvb.js → security-contract-DyCRvz_Q.js} +0 -0
  113. /package/dist/{security-doctor-BJH5YIGL.js → security-doctor-Cp-NqNdS.js} +0 -0
  114. /package/dist/{session-contract-D871HDFG.js → session-contract-ugfEa9Xc.js} +0 -0
  115. /package/dist/{session-key-normalization-BV82IME9.js → session-key-normalization-B7h83qD2.js} +0 -0
  116. /package/dist/{thread-bindings.state-SPlv6mh7.js → thread-bindings.state-BdBeo7Rx.js} +0 -0
  117. /package/dist/{timeouts-C3FYXWJX.js → timeouts-snXNwR4m.js} +0 -0
@@ -1,10 +1,9 @@
1
- import { Ft as __exportAll } from "./discord-BqYcwxvG.js";
2
- import { t as parseDiscordTarget } from "./target-parsing-D-H7nnh2.js";
3
- import "./targets-DToZUkgV.js";
4
- import { C as resolveThreadBindingMaxAgeMs$1, O as shouldPersistBindingMutations, S as resolveThreadBindingMaxAgeExpiresAt, T as saveBindingsToDisk, b as resolveThreadBindingIdleTimeoutMs$1, c as getThreadBindingToken, f as normalizeThreadId, g as removeBindingRecord, l as isRecentlyUnboundThreadWebhookMessage, n as MANAGERS_BY_ACCOUNT_ID, p as rememberRecentUnboundWebhookEcho, t as BINDINGS_BY_THREAD_ID, x as resolveThreadBindingInactivityExpiresAt } from "./thread-bindings.state-SPlv6mh7.js";
5
- import { n as setThreadBindingMaxAgeBySessionKey, r as resolveBindingIdsForTargetSession, t as setThreadBindingIdleTimeoutBySessionKey } from "./thread-bindings.session-updates-D18cCLmN.js";
6
- import { d as formatThreadBindingDurationLabel, l as resolveThreadBindingPersona, m as resolveThreadBindingThreadName, p as resolveThreadBindingIntroText, s as resolveChannelIdForBinding, u as resolveThreadBindingPersonaFromRecord } from "./thread-bindings.discord-api-BAw15EQb.js";
7
- import { i as getThreadBindingManager, n as createNoopThreadBindingManager, r as createThreadBindingManager, t as __testing } from "./thread-bindings.manager-DNFl10CA.js";
1
+ import { Ht as parseDiscordTarget, Wt as __exportAll } from "./send.receipt-nKLxvA1s.js";
2
+ import "./targets-DwW6OieO.js";
3
+ import { C as resolveThreadBindingMaxAgeMs$1, O as shouldPersistBindingMutations, S as resolveThreadBindingMaxAgeExpiresAt, T as saveBindingsToDisk, b as resolveThreadBindingIdleTimeoutMs$1, c as getThreadBindingToken, f as normalizeThreadId, g as removeBindingRecord, l as isRecentlyUnboundThreadWebhookMessage, n as MANAGERS_BY_ACCOUNT_ID, p as rememberRecentUnboundWebhookEcho, t as BINDINGS_BY_THREAD_ID, x as resolveThreadBindingInactivityExpiresAt } from "./thread-bindings.state-BdBeo7Rx.js";
4
+ import { n as setThreadBindingMaxAgeBySessionKey, r as resolveBindingIdsForTargetSession, t as setThreadBindingIdleTimeoutBySessionKey } from "./thread-bindings.session-updates-ZnRRzzgf.js";
5
+ import { _ as formatThreadBindingDurationLabel, b as resolveThreadBindingThreadName, g as resolveThreadBindingPersonaFromRecord, h as resolveThreadBindingPersona, s as resolveChannelIdForBinding, y as resolveThreadBindingIntroText } from "./thread-bindings.discord-api-DJACBZJ1.js";
6
+ import { i as getThreadBindingManager, n as createNoopThreadBindingManager, r as createThreadBindingManager, t as __testing } from "./thread-bindings.manager-DN_q0IW7.js";
8
7
  import { normalizeOptionalLowercaseString, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
9
8
  import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
10
9
  import { resolveThreadBindingIdleTimeoutMs, resolveThreadBindingMaxAgeMs, resolveThreadBindingsEnabled } from "openclaw/plugin-sdk/conversation-runtime";
@@ -1,10 +1,8 @@
1
- import { J as createChannelWebhook, ot as getChannel } from "./discord-BqYcwxvG.js";
2
- import { n as resolveDiscordChannelId } from "./target-parsing-D-H7nnh2.js";
3
- import { j as createDiscordRestClient } from "./send.shared-Dza0jdso.js";
4
- import { c as sendWebhookMessageDiscord, u as createThreadDiscord } from "./send-DCFuSiBi.js";
5
- import { t as sendMessageDiscord } from "./send.outbound-PM0J0F60.js";
6
- import { i as REUSABLE_WEBHOOKS_BY_ACCOUNT_CHANNEL, k as toReusableWebhookKey, m as rememberReusableWebhook, t as BINDINGS_BY_THREAD_ID } from "./thread-bindings.state-SPlv6mh7.js";
7
- import { n as resolveDiscordChannelInfoSafe, t as resolveDiscordChannelIdSafe } from "./channel-access-BL-wemES.js";
1
+ import { Ut as resolveDiscordChannelId, pt as getChannel, tt as createChannelWebhook } from "./send.receipt-nKLxvA1s.js";
2
+ import { M as createDiscordRestClient } from "./send.shared-DSpva7uA.js";
3
+ import { c as sendWebhookMessageDiscord, u as createThreadDiscord } from "./send-BqzTEkt9.js";
4
+ import { t as sendMessageDiscord } from "./send.outbound-D8o8BW6q.js";
5
+ import { i as REUSABLE_WEBHOOKS_BY_ACCOUNT_CHANNEL, k as toReusableWebhookKey, m as rememberReusableWebhook, t as BINDINGS_BY_THREAD_ID } from "./thread-bindings.state-BdBeo7Rx.js";
8
6
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
9
7
  import { ChannelType } from "discord-api-types/v10";
10
8
  import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
@@ -26,6 +24,67 @@ function resolveThreadBindingPersonaFromRecord(record) {
26
24
  });
27
25
  }
28
26
  //#endregion
27
+ //#region extensions/discord/src/monitor/channel-access.ts
28
+ function readDiscordChannelPropertySafe(channel, key) {
29
+ if (!channel || typeof channel !== "object") return;
30
+ try {
31
+ if (!(key in channel)) return;
32
+ return channel[key];
33
+ } catch {
34
+ return;
35
+ }
36
+ }
37
+ function resolveDiscordChannelStringPropertySafe(channel, key) {
38
+ const value = readDiscordChannelPropertySafe(channel, key);
39
+ return typeof value === "string" ? value : void 0;
40
+ }
41
+ function resolveDiscordChannelNumberPropertySafe(channel, key) {
42
+ const value = readDiscordChannelPropertySafe(channel, key);
43
+ return typeof value === "number" ? value : void 0;
44
+ }
45
+ const DISCORD_CHANNEL_SNAKE_CASE_ALIASES = {
46
+ ownerId: "owner_id",
47
+ parentId: "parent_id"
48
+ };
49
+ function resolveDiscordChannelStringWithAliasSafe(channel, camelKey) {
50
+ const camelValue = resolveDiscordChannelStringPropertySafe(channel, camelKey);
51
+ if (camelValue !== void 0) return camelValue;
52
+ const snakeKey = DISCORD_CHANNEL_SNAKE_CASE_ALIASES[camelKey];
53
+ if (!snakeKey) return;
54
+ const directSnakeValue = resolveDiscordChannelStringPropertySafe(channel, snakeKey);
55
+ if (directSnakeValue !== void 0) return directSnakeValue;
56
+ return resolveDiscordChannelStringPropertySafe(readDiscordChannelPropertySafe(channel, "rawData"), snakeKey);
57
+ }
58
+ function resolveDiscordChannelNameSafe(channel) {
59
+ return resolveDiscordChannelStringPropertySafe(channel, "name");
60
+ }
61
+ function resolveDiscordChannelIdSafe(channel) {
62
+ return resolveDiscordChannelStringPropertySafe(channel, "id");
63
+ }
64
+ function resolveDiscordChannelTopicSafe(channel) {
65
+ return resolveDiscordChannelStringPropertySafe(channel, "topic");
66
+ }
67
+ function resolveDiscordChannelParentIdSafe(channel) {
68
+ return resolveDiscordChannelStringWithAliasSafe(channel, "parentId");
69
+ }
70
+ function resolveDiscordChannelOwnerIdSafe(channel) {
71
+ return resolveDiscordChannelStringWithAliasSafe(channel, "ownerId");
72
+ }
73
+ function resolveDiscordChannelParentSafe(channel) {
74
+ return readDiscordChannelPropertySafe(channel, "parent");
75
+ }
76
+ function resolveDiscordChannelInfoSafe(channel) {
77
+ const parent = resolveDiscordChannelParentSafe(channel);
78
+ return {
79
+ name: resolveDiscordChannelNameSafe(channel),
80
+ topic: resolveDiscordChannelTopicSafe(channel),
81
+ type: resolveDiscordChannelNumberPropertySafe(channel, "type"),
82
+ parentId: resolveDiscordChannelParentIdSafe(channel),
83
+ ownerId: resolveDiscordChannelOwnerIdSafe(channel),
84
+ parentName: resolveDiscordChannelNameSafe(parent)
85
+ };
86
+ }
87
+ //#endregion
29
88
  //#region extensions/discord/src/monitor/thread-bindings.discord-api.ts
30
89
  function buildThreadTarget(threadId) {
31
90
  return /^(channel:|user:)/i.test(threadId) ? threadId : `channel:${threadId}`;
@@ -182,4 +241,4 @@ async function createThreadForBinding(params) {
182
241
  }
183
242
  }
184
243
  //#endregion
185
- export { isThreadArchived as a, summarizeDiscordError as c, formatThreadBindingDurationLabel as d, resolveThreadBindingFarewellText as f, isDiscordThreadGoneError as i, resolveThreadBindingPersona as l, resolveThreadBindingThreadName as m, createWebhookForChannel as n, maybeSendBindingMessage as o, resolveThreadBindingIntroText as p, findReusableWebhook as r, resolveChannelIdForBinding as s, createThreadForBinding as t, resolveThreadBindingPersonaFromRecord as u };
244
+ export { formatThreadBindingDurationLabel as _, isThreadArchived as a, resolveThreadBindingThreadName as b, summarizeDiscordError as c, resolveDiscordChannelNameSafe as d, resolveDiscordChannelParentIdSafe as f, resolveThreadBindingPersonaFromRecord as g, resolveThreadBindingPersona as h, isDiscordThreadGoneError as i, resolveDiscordChannelIdSafe as l, resolveDiscordChannelTopicSafe as m, createWebhookForChannel as n, maybeSendBindingMessage as o, resolveDiscordChannelParentSafe as p, findReusableWebhook as r, resolveChannelIdForBinding as s, createThreadForBinding as t, resolveDiscordChannelInfoSafe as u, resolveThreadBindingFarewellText as v, resolveThreadBindingIntroText as y };
@@ -1,8 +1,7 @@
1
- import { Ft as __exportAll, ot as getChannel } from "./discord-BqYcwxvG.js";
2
- import { n as resolveDiscordChannelId } from "./target-parsing-D-H7nnh2.js";
3
- import { j as createDiscordRestClient } from "./send.shared-Dza0jdso.js";
4
- import { A as DEFAULT_THREAD_BINDING_IDLE_TIMEOUT_MS, C as resolveThreadBindingMaxAgeMs$1, D as shouldDefaultPersist, E as setBindingRecord, M as THREAD_BINDINGS_SWEEP_INTERVAL_MS, S as resolveThreadBindingMaxAgeExpiresAt, T as saveBindingsToDisk, _ as resetThreadBindingsForTests, a as THREAD_BINDING_TOUCH_PERSIST_MIN_INTERVAL_MS, b as resolveThreadBindingIdleTimeoutMs$1, c as getThreadBindingToken, d as normalizeThreadBindingDurationMs, f as normalizeThreadId, g as removeBindingRecord, h as rememberThreadBindingToken, n as MANAGERS_BY_ACCOUNT_ID, o as ensureBindingsLoaded, p as rememberRecentUnboundWebhookEcho, r as PERSIST_BY_ACCOUNT_ID, s as forgetThreadBindingToken, t as BINDINGS_BY_THREAD_ID, u as normalizeTargetKind, v as resolveBindingIdsForSession, w as resolveThreadBindingsPath, x as resolveThreadBindingInactivityExpiresAt, y as resolveBindingRecordKey } from "./thread-bindings.state-SPlv6mh7.js";
5
- import { a as isThreadArchived, c as summarizeDiscordError, f as resolveThreadBindingFarewellText, i as isDiscordThreadGoneError, m as resolveThreadBindingThreadName, n as createWebhookForChannel, o as maybeSendBindingMessage, r as findReusableWebhook, s as resolveChannelIdForBinding, t as createThreadForBinding } from "./thread-bindings.discord-api-BAw15EQb.js";
1
+ import { Ut as resolveDiscordChannelId, Wt as __exportAll, pt as getChannel } from "./send.receipt-nKLxvA1s.js";
2
+ import { M as createDiscordRestClient } from "./send.shared-DSpva7uA.js";
3
+ import { A as DEFAULT_THREAD_BINDING_IDLE_TIMEOUT_MS, C as resolveThreadBindingMaxAgeMs$1, D as shouldDefaultPersist, E as setBindingRecord, M as THREAD_BINDINGS_SWEEP_INTERVAL_MS, S as resolveThreadBindingMaxAgeExpiresAt, T as saveBindingsToDisk, _ as resetThreadBindingsForTests, a as THREAD_BINDING_TOUCH_PERSIST_MIN_INTERVAL_MS, b as resolveThreadBindingIdleTimeoutMs$1, c as getThreadBindingToken, d as normalizeThreadBindingDurationMs, f as normalizeThreadId, g as removeBindingRecord, h as rememberThreadBindingToken, n as MANAGERS_BY_ACCOUNT_ID, o as ensureBindingsLoaded, p as rememberRecentUnboundWebhookEcho, r as PERSIST_BY_ACCOUNT_ID, s as forgetThreadBindingToken, t as BINDINGS_BY_THREAD_ID, u as normalizeTargetKind, v as resolveBindingIdsForSession, w as resolveThreadBindingsPath, x as resolveThreadBindingInactivityExpiresAt, y as resolveBindingRecordKey } from "./thread-bindings.state-BdBeo7Rx.js";
4
+ import { a as isThreadArchived, b as resolveThreadBindingThreadName, c as summarizeDiscordError, i as isDiscordThreadGoneError, n as createWebhookForChannel, o as maybeSendBindingMessage, r as findReusableWebhook, s as resolveChannelIdForBinding, t as createThreadForBinding, v as resolveThreadBindingFarewellText } from "./thread-bindings.discord-api-DJACBZJ1.js";
6
5
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
7
6
  import { normalizeAccountId, resolveAgentIdFromSessionKey } from "openclaw/plugin-sdk/routing";
8
7
  import { getRuntimeConfigSnapshot } from "openclaw/plugin-sdk/runtime-config-snapshot";
@@ -1,4 +1,4 @@
1
- import { E as setBindingRecord, O as shouldPersistBindingMutations, T as saveBindingsToDisk, o as ensureBindingsLoaded, t as BINDINGS_BY_THREAD_ID, v as resolveBindingIdsForSession } from "./thread-bindings.state-SPlv6mh7.js";
1
+ import { E as setBindingRecord, O as shouldPersistBindingMutations, T as saveBindingsToDisk, o as ensureBindingsLoaded, t as BINDINGS_BY_THREAD_ID, v as resolveBindingIdsForSession } from "./thread-bindings.state-BdBeo7Rx.js";
2
2
  import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
3
3
  //#region extensions/discord/src/monitor/thread-bindings.session-shared.ts
4
4
  function normalizeNonNegativeMs(raw) {
package/dist/timeouts.js CHANGED
@@ -1,2 +1,2 @@
1
- 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-C3FYXWJX.js";
1
+ 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-snXNwR4m.js";
2
2
  export { DISCORD_ATTACHMENT_IDLE_TIMEOUT_MS, DISCORD_ATTACHMENT_TOTAL_TIMEOUT_MS, DISCORD_DEFAULT_INBOUND_WORKER_TIMEOUT_MS, DISCORD_DEFAULT_LISTENER_TIMEOUT_MS };
@@ -1,5 +1,5 @@
1
- import { Ft as __exportAll, pt as sendChannelTyping } from "./discord-BqYcwxvG.js";
2
- import { o as raceWithTimeout } from "./timeouts-C3FYXWJX.js";
1
+ import { Wt as __exportAll, bt as sendChannelTyping } from "./send.receipt-nKLxvA1s.js";
2
+ import { o as raceWithTimeout } from "./timeouts-snXNwR4m.js";
3
3
  //#region extensions/discord/src/monitor/typing.ts
4
4
  var typing_exports = /* @__PURE__ */ __exportAll({ sendTyping: () => sendTyping });
5
5
  const DISCORD_TYPING_START_TIMEOUT_MS = 5e3;
@@ -190,6 +190,30 @@
190
190
  }
191
191
  ]
192
192
  },
193
+ "botLoopProtection": {
194
+ "type": "object",
195
+ "properties": {
196
+ "enabled": {
197
+ "type": "boolean"
198
+ },
199
+ "maxEventsPerWindow": {
200
+ "type": "integer",
201
+ "exclusiveMinimum": 0,
202
+ "maximum": 9007199254740991
203
+ },
204
+ "windowSeconds": {
205
+ "type": "integer",
206
+ "exclusiveMinimum": 0,
207
+ "maximum": 9007199254740991
208
+ },
209
+ "cooldownSeconds": {
210
+ "type": "integer",
211
+ "exclusiveMinimum": 0,
212
+ "maximum": 9007199254740991
213
+ }
214
+ },
215
+ "additionalProperties": false
216
+ },
193
217
  "dangerouslyAllowNameMatching": {
194
218
  "type": "boolean"
195
219
  },
@@ -1881,6 +1905,30 @@
1881
1905
  }
1882
1906
  ]
1883
1907
  },
1908
+ "botLoopProtection": {
1909
+ "type": "object",
1910
+ "properties": {
1911
+ "enabled": {
1912
+ "type": "boolean"
1913
+ },
1914
+ "maxEventsPerWindow": {
1915
+ "type": "integer",
1916
+ "exclusiveMinimum": 0,
1917
+ "maximum": 9007199254740991
1918
+ },
1919
+ "windowSeconds": {
1920
+ "type": "integer",
1921
+ "exclusiveMinimum": 0,
1922
+ "maximum": 9007199254740991
1923
+ },
1924
+ "cooldownSeconds": {
1925
+ "type": "integer",
1926
+ "exclusiveMinimum": 0,
1927
+ "maximum": 9007199254740991
1928
+ }
1929
+ },
1930
+ "additionalProperties": false
1931
+ },
1884
1932
  "dangerouslyAllowNameMatching": {
1885
1933
  "type": "boolean"
1886
1934
  },
@@ -3724,6 +3772,26 @@
3724
3772
  "label": "Discord Allow Bot Messages",
3725
3773
  "help": "Allow bot-authored messages to trigger Discord replies (default: false). Set \"mentions\" to only accept bot messages that mention the bot."
3726
3774
  },
3775
+ "botLoopProtection": {
3776
+ "label": "Discord Bot Loop Protection",
3777
+ "help": "Sliding-window guard for bot-to-bot Discord loops. Default is enabled whenever allowBots lets bot-authored messages reach dispatch."
3778
+ },
3779
+ "botLoopProtection.enabled": {
3780
+ "label": "Discord Bot Loop Protection Enabled",
3781
+ "help": "Enable the bot-pair loop guard. Defaults to true when allowBots is true or \"mentions\", and false when bot messages are ignored."
3782
+ },
3783
+ "botLoopProtection.maxEventsPerWindow": {
3784
+ "label": "Discord Bot Pair Events Per Window",
3785
+ "help": "Maximum messages a single Discord bot pair may exchange in the configured window before suppression starts. Default: 20."
3786
+ },
3787
+ "botLoopProtection.windowSeconds": {
3788
+ "label": "Discord Bot Loop Window Seconds",
3789
+ "help": "Sliding window length in seconds for Discord bot-pair loop budgets. Default: 60."
3790
+ },
3791
+ "botLoopProtection.cooldownSeconds": {
3792
+ "label": "Discord Bot Loop Cooldown Seconds",
3793
+ "help": "Seconds to suppress a Discord bot pair after it exceeds the loop budget. Default: 60."
3794
+ },
3727
3795
  "mentionAliases": {
3728
3796
  "label": "Discord Mention Aliases",
3729
3797
  "help": "Map outbound @handle text to stable Discord user IDs before sending. Set per account via channels.discord.accounts.<id>.mentionAliases."
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/discord",
3
- "version": "2026.5.12",
3
+ "version": "2026.5.14-beta.2",
4
4
  "description": "OpenClaw Discord channel plugin",
5
5
  "repository": {
6
6
  "type": "git",
@@ -13,15 +13,15 @@
13
13
  "https-proxy-agent": "9.0.0",
14
14
  "opusscript": "0.1.1",
15
15
  "typebox": "1.1.38",
16
- "undici": "8.2.0",
17
- "ws": "8.20.0"
16
+ "undici": "8.3.0",
17
+ "ws": "8.20.1"
18
18
  },
19
19
  "devDependencies": {
20
20
  "@openclaw/plugin-sdk": "workspace:*",
21
21
  "openclaw": "workspace:*"
22
22
  },
23
23
  "peerDependencies": {
24
- "openclaw": ">=2026.5.12"
24
+ "openclaw": ">=2026.5.14-beta.2"
25
25
  },
26
26
  "peerDependenciesMeta": {
27
27
  "openclaw": {
@@ -65,10 +65,10 @@
65
65
  "allowInvalidConfigRecovery": true
66
66
  },
67
67
  "compat": {
68
- "pluginApi": ">=2026.5.12"
68
+ "pluginApi": ">=2026.5.14-beta.2"
69
69
  },
70
70
  "build": {
71
- "openclawVersion": "2026.5.12"
71
+ "openclawVersion": "2026.5.14-beta.2"
72
72
  },
73
73
  "release": {
74
74
  "publishToClawHub": true,
@@ -1,89 +0,0 @@
1
- import { c as resolveDiscordChannelConfigWithFallback, d as resolveDiscordGuildEntry, f as resolveDiscordMemberAccessState, m as resolveDiscordOwnerAccess, n as isDiscordGroupAllowedByPolicy } from "./allow-list-n8Ki-Rt3.js";
2
- import { resolveOpenProviderRuntimeGroupPolicy } from "openclaw/plugin-sdk/runtime-group-policy";
3
- import { resolveCommandAuthorizedFromAuthorizers } from "openclaw/plugin-sdk/command-auth-native";
4
- //#region extensions/discord/src/voice/config.ts
5
- function resolveDiscordVoiceEnabled(voice) {
6
- if (voice?.enabled !== void 0) return voice.enabled;
7
- return voice !== void 0;
8
- }
9
- //#endregion
10
- //#region extensions/discord/src/voice/access.ts
11
- async function authorizeDiscordVoiceIngress(params) {
12
- const groupPolicy = params.groupPolicy ?? resolveOpenProviderRuntimeGroupPolicy({
13
- providerConfigPresent: params.cfg.channels?.discord !== void 0,
14
- groupPolicy: params.discordConfig.groupPolicy,
15
- defaultGroupPolicy: params.cfg.channels?.defaults?.groupPolicy
16
- }).groupPolicy;
17
- const guildInfo = resolveDiscordGuildEntry({
18
- guild: params.guild ?? {
19
- id: params.guildId,
20
- ...params.guildName ? { name: params.guildName } : {}
21
- },
22
- guildId: params.guildId,
23
- guildEntries: params.discordConfig.guilds
24
- });
25
- const channelConfig = params.channelId ? resolveDiscordChannelConfigWithFallback({
26
- guildInfo,
27
- channelId: params.channelId,
28
- channelName: params.channelName,
29
- channelSlug: params.channelSlug,
30
- parentId: params.parentId,
31
- parentName: params.parentName,
32
- parentSlug: params.parentSlug,
33
- scope: params.scope
34
- }) : null;
35
- if (channelConfig?.enabled === false) return {
36
- ok: false,
37
- message: "This channel is disabled."
38
- };
39
- const channelAllowlistConfigured = Boolean(guildInfo?.channels) && Object.keys(guildInfo?.channels ?? {}).length > 0;
40
- if (!params.channelId && groupPolicy === "allowlist" && channelAllowlistConfigured) return {
41
- ok: false,
42
- message: `${params.channelLabel ?? "This channel"} is not allowlisted for voice commands.`
43
- };
44
- const channelAllowed = channelConfig ? channelConfig.allowed : !channelAllowlistConfigured;
45
- if (!isDiscordGroupAllowedByPolicy({
46
- groupPolicy,
47
- guildAllowlisted: Boolean(guildInfo),
48
- channelAllowlistConfigured,
49
- channelAllowed
50
- }) || channelConfig?.allowed === false) return {
51
- ok: false,
52
- message: `${params.channelLabel ?? "This channel"} is not allowlisted for voice commands.`
53
- };
54
- const { hasAccessRestrictions, memberAllowed } = resolveDiscordMemberAccessState({
55
- channelConfig,
56
- guildInfo,
57
- memberRoleIds: params.memberRoleIds,
58
- sender: params.sender,
59
- allowNameMatching: false
60
- });
61
- const { ownerAllowList, ownerAllowed } = resolveDiscordOwnerAccess({
62
- allowFrom: params.ownerAllowFrom ?? params.discordConfig.allowFrom ?? params.discordConfig.dm?.allowFrom,
63
- sender: params.sender,
64
- allowNameMatching: false
65
- });
66
- const useAccessGroups = params.useAccessGroups ?? params.cfg.commands?.useAccessGroups !== false;
67
- return resolveCommandAuthorizedFromAuthorizers({
68
- useAccessGroups,
69
- authorizers: useAccessGroups ? [{
70
- configured: ownerAllowList != null,
71
- allowed: ownerAllowed
72
- }, {
73
- configured: hasAccessRestrictions,
74
- allowed: memberAllowed
75
- }] : [{
76
- configured: hasAccessRestrictions,
77
- allowed: memberAllowed
78
- }],
79
- modeWhenAccessGroupsOff: "configured"
80
- }) ? {
81
- ok: true,
82
- channelConfig
83
- } : {
84
- ok: false,
85
- message: "You are not authorized to use this command."
86
- };
87
- }
88
- //#endregion
89
- export { resolveDiscordVoiceEnabled as n, authorizeDiscordVoiceIngress as t };
@@ -1,93 +0,0 @@
1
- import { s as resolveDiscordAccount } from "./accounts-BcwyaFd-.js";
2
- import { t as parseDiscordTarget } from "./target-parsing-D-H7nnh2.js";
3
- import { createChannelApproverDmTargetResolver, createChannelNativeOriginTargetResolver, doesApprovalRequestMatchChannelAccount } from "openclaw/plugin-sdk/approval-native-runtime";
4
- import { getExecApprovalReplyMetadata, isChannelExecApprovalClientEnabledFromConfig, matchesApprovalRequestFilters } from "openclaw/plugin-sdk/approval-client-runtime";
5
- import { resolveApprovalApprovers } from "openclaw/plugin-sdk/approval-auth-runtime";
6
- import { createApproverRestrictedNativeApprovalCapability } from "openclaw/plugin-sdk/approval-delivery-runtime";
7
- //#region extensions/discord/src/exec-approvals.ts
8
- function normalizeDiscordApproverId(value) {
9
- const trimmed = value.trim();
10
- if (!trimmed) return;
11
- if (/^\d+$/.test(trimmed)) return trimmed;
12
- try {
13
- const target = parseDiscordTarget(trimmed);
14
- return target?.kind === "user" ? target.id : void 0;
15
- } catch {
16
- return;
17
- }
18
- }
19
- function resolveDiscordOwnerApprovers(cfg) {
20
- const ownerAllowFrom = cfg.commands?.ownerAllowFrom;
21
- if (!Array.isArray(ownerAllowFrom) || ownerAllowFrom.length === 0) return [];
22
- return resolveApprovalApprovers({
23
- explicit: ownerAllowFrom,
24
- normalizeApprover: (value) => normalizeDiscordApproverId(String(value))
25
- });
26
- }
27
- function getDiscordExecApprovalApprovers(params) {
28
- return resolveApprovalApprovers({
29
- explicit: params.configOverride?.approvers ?? resolveDiscordAccount(params).config.execApprovals?.approvers ?? resolveDiscordOwnerApprovers(params.cfg),
30
- normalizeApprover: (value) => normalizeDiscordApproverId(String(value))
31
- });
32
- }
33
- function isDiscordExecApprovalClientEnabled(params) {
34
- return isChannelExecApprovalClientEnabledFromConfig({
35
- enabled: (params.configOverride ?? resolveDiscordAccount(params).config.execApprovals)?.enabled,
36
- approverCount: getDiscordExecApprovalApprovers({
37
- cfg: params.cfg,
38
- accountId: params.accountId,
39
- configOverride: params.configOverride
40
- }).length
41
- });
42
- }
43
- function isDiscordExecApprovalApprover(params) {
44
- const senderId = params.senderId?.trim();
45
- if (!senderId) return false;
46
- return getDiscordExecApprovalApprovers({
47
- cfg: params.cfg,
48
- accountId: params.accountId,
49
- configOverride: params.configOverride
50
- }).includes(senderId);
51
- }
52
- function shouldSuppressLocalDiscordExecApprovalPrompt(params) {
53
- const metadata = getExecApprovalReplyMetadata(params.payload);
54
- const config = resolveDiscordAccount(params).config.execApprovals;
55
- return params.hint?.kind === "approval-pending" && params.hint.nativeRouteActive === true && isDiscordExecApprovalClientEnabled(params) && metadata !== null && matchesApprovalRequestFilters({
56
- request: {
57
- agentId: metadata.agentId,
58
- sessionKey: metadata.sessionKey
59
- },
60
- agentFilter: config?.agentFilter,
61
- sessionFilter: config?.sessionFilter
62
- });
63
- }
64
- //#endregion
65
- //#region extensions/discord/src/approval-shared.ts
66
- function shouldHandleDiscordApprovalRequest(params) {
67
- const config = params.configOverride ?? resolveDiscordAccount({
68
- cfg: params.cfg,
69
- accountId: params.accountId
70
- }).config.execApprovals;
71
- const approvers = getDiscordExecApprovalApprovers({
72
- cfg: params.cfg,
73
- accountId: params.accountId,
74
- configOverride: params.configOverride
75
- });
76
- if (!doesApprovalRequestMatchChannelAccount({
77
- cfg: params.cfg,
78
- request: params.request,
79
- channel: "discord",
80
- accountId: params.accountId
81
- })) return false;
82
- if (!isChannelExecApprovalClientEnabledFromConfig({
83
- enabled: config?.enabled,
84
- approverCount: approvers.length
85
- })) return false;
86
- return matchesApprovalRequestFilters({
87
- request: params.request.request,
88
- agentFilter: config?.agentFilter,
89
- sessionFilter: config?.sessionFilter
90
- });
91
- }
92
- //#endregion
93
- export { shouldSuppressLocalDiscordExecApprovalPrompt as a, createChannelNativeOriginTargetResolver as c, isDiscordExecApprovalClientEnabled as i, getDiscordExecApprovalApprovers as n, createApproverRestrictedNativeApprovalCapability as o, isDiscordExecApprovalApprover as r, createChannelApproverDmTargetResolver as s, shouldHandleDiscordApprovalRequest as t };
@@ -1,62 +0,0 @@
1
- //#region extensions/discord/src/monitor/channel-access.ts
2
- function readDiscordChannelPropertySafe(channel, key) {
3
- if (!channel || typeof channel !== "object") return;
4
- try {
5
- if (!(key in channel)) return;
6
- return channel[key];
7
- } catch {
8
- return;
9
- }
10
- }
11
- function resolveDiscordChannelStringPropertySafe(channel, key) {
12
- const value = readDiscordChannelPropertySafe(channel, key);
13
- return typeof value === "string" ? value : void 0;
14
- }
15
- function resolveDiscordChannelNumberPropertySafe(channel, key) {
16
- const value = readDiscordChannelPropertySafe(channel, key);
17
- return typeof value === "number" ? value : void 0;
18
- }
19
- const DISCORD_CHANNEL_SNAKE_CASE_ALIASES = {
20
- ownerId: "owner_id",
21
- parentId: "parent_id"
22
- };
23
- function resolveDiscordChannelStringWithAliasSafe(channel, camelKey) {
24
- const camelValue = resolveDiscordChannelStringPropertySafe(channel, camelKey);
25
- if (camelValue !== void 0) return camelValue;
26
- const snakeKey = DISCORD_CHANNEL_SNAKE_CASE_ALIASES[camelKey];
27
- if (!snakeKey) return;
28
- const directSnakeValue = resolveDiscordChannelStringPropertySafe(channel, snakeKey);
29
- if (directSnakeValue !== void 0) return directSnakeValue;
30
- return resolveDiscordChannelStringPropertySafe(readDiscordChannelPropertySafe(channel, "rawData"), snakeKey);
31
- }
32
- function resolveDiscordChannelNameSafe(channel) {
33
- return resolveDiscordChannelStringPropertySafe(channel, "name");
34
- }
35
- function resolveDiscordChannelIdSafe(channel) {
36
- return resolveDiscordChannelStringPropertySafe(channel, "id");
37
- }
38
- function resolveDiscordChannelTopicSafe(channel) {
39
- return resolveDiscordChannelStringPropertySafe(channel, "topic");
40
- }
41
- function resolveDiscordChannelParentIdSafe(channel) {
42
- return resolveDiscordChannelStringWithAliasSafe(channel, "parentId");
43
- }
44
- function resolveDiscordChannelOwnerIdSafe(channel) {
45
- return resolveDiscordChannelStringWithAliasSafe(channel, "ownerId");
46
- }
47
- function resolveDiscordChannelParentSafe(channel) {
48
- return readDiscordChannelPropertySafe(channel, "parent");
49
- }
50
- function resolveDiscordChannelInfoSafe(channel) {
51
- const parent = resolveDiscordChannelParentSafe(channel);
52
- return {
53
- name: resolveDiscordChannelNameSafe(channel),
54
- topic: resolveDiscordChannelTopicSafe(channel),
55
- type: resolveDiscordChannelNumberPropertySafe(channel, "type"),
56
- parentId: resolveDiscordChannelParentIdSafe(channel),
57
- ownerId: resolveDiscordChannelOwnerIdSafe(channel),
58
- parentName: resolveDiscordChannelNameSafe(parent)
59
- };
60
- }
61
- //#endregion
62
- export { resolveDiscordChannelParentSafe as a, resolveDiscordChannelParentIdSafe as i, resolveDiscordChannelInfoSafe as n, resolveDiscordChannelTopicSafe as o, resolveDiscordChannelNameSafe as r, resolveDiscordChannelIdSafe as t };