@openclaw/discord 2026.7.1-beta.6 → 2026.7.2-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 (92) hide show
  1. package/dist/action-runtime-api.js +1 -1
  2. package/dist/{allow-list-C-MqM-B_.js → allow-list-B7qOH5xu.js} +22 -1
  3. package/dist/{api-DPRqYi4Z.js → api--f62GFaS.js} +38 -23
  4. package/dist/api.js +15 -15
  5. package/dist/approval-custom-id-NYPYj9Po.js +58 -0
  6. package/dist/{approval-handler.runtime-Bw2pZNk1.js → approval-handler.runtime-DeyIiw5I.js} +28 -23
  7. package/dist/approval-message-safety-C-8BL6Kv.js +47 -0
  8. package/dist/{audit-MLpDpN3Z.js → audit-Df2w046a.js} +3 -3
  9. package/dist/{channel-actions-D_fjVUZ_.js → channel-actions-ChpBSRcu.js} +6 -4
  10. package/dist/{channel-actions.runtime-CVHlFqQg.js → channel-actions.runtime-D8V8tyCq.js} +41 -12
  11. package/dist/channel-config-api.js +1 -1
  12. package/dist/{channel-DGWPH5u3.js → channel-nYmJ7FKQ.js} +275 -62
  13. package/dist/channel-plugin-api.js +1 -1
  14. package/dist/{channel.setup-tZcpIn4e.js → channel.setup-DyihrqHH.js} +3 -3
  15. package/dist/{components-BIBizbtZ.js → components-BVrfRS-F.js} +78 -52
  16. package/dist/config-api-B18fR8M5.js +3 -0
  17. package/dist/{config-schema-BgIhO3ko.js → config-schema-_bUKcWRm.js} +42 -82
  18. package/dist/conversation-identity-BpkAzklg.js +94 -0
  19. package/dist/{directory-config-ByaUKL1f.js → directory-config-BUe-qq_C.js} +1 -1
  20. package/dist/directory-contract-api.js +1 -1
  21. package/dist/{directory-live-BX79ImQA.js → directory-live-DZByMdPO.js} +6 -6
  22. package/dist/{doctor-Bgoxm5AN.js → doctor-bMaWXFKu.js} +5 -4
  23. package/dist/doctor-contract-api.js +1 -1
  24. package/dist/{doctor-contract-CU7lnZTF.js → doctor-contract-wId6pV41.js} +41 -37
  25. package/dist/{handle-action.guild-admin-CgJSNVui.js → handle-action.guild-admin-C_PQcBEV.js} +12 -12
  26. package/dist/index.js +1 -1
  27. package/dist/legacy-state-migrations-api.js +24 -2
  28. package/dist/{manager.runtime-DaB-CTrt.js → manager.runtime-3RVMVkyx.js} +546 -154
  29. package/dist/{message-handler-DcgvugZt.js → message-handler-CIxWq5Yh.js} +8 -9
  30. package/dist/{message-handler.preflight-DvLXiYVH.js → message-handler.preflight-BI86IbHz.js} +46 -22
  31. package/dist/{message-handler.process-Cjf30P_B.js → message-handler.process-bPS_9_tb.js} +241 -107
  32. package/dist/{message-utils-B_3yA5bN.js → message-utils-D4j07taS.js} +2 -3
  33. package/dist/{outbound-adapter-82RWi_SR.js → outbound-adapter-Czny0Fae.js} +16 -68
  34. package/dist/outbound-components-oJKLj62G.js +99 -0
  35. package/dist/pluralkit-UXq1OyUI.js +40 -0
  36. package/dist/{probe-D1ImJEo2.js → probe-DxjMBeVG.js} +1 -1
  37. package/dist/{probe.runtime-B1dsEeBD.js → probe.runtime-Bc8Oo6e8.js} +1 -1
  38. package/dist/{provider-BkfbC9FQ.js → provider-DWvDNb4J.js} +702 -236
  39. package/dist/{provider-session.runtime-BDjyFw6Y.js → provider-session.runtime-D5pCGibh.js} +3 -3
  40. package/dist/provider.runtime-C2iIfbTs.js +2 -0
  41. package/dist/{resolve-allowlist-common-CWbE8XlH.js → resolve-allowlist-common-B9S8LLBd.js} +5 -5
  42. package/dist/{resolve-channels-CcpvWoRa.js → resolve-channels-BrkWOKdG.js} +7 -7
  43. package/dist/{resolve-users-DJamun9s.js → resolve-users-OjrXXvJP.js} +5 -5
  44. package/dist/{runtime-C6rRmQ6l.js → runtime-C618lis9.js} +223 -33
  45. package/dist/runtime-api.actions.js +2 -2
  46. package/dist/runtime-api.js +23 -23
  47. package/dist/runtime-api.lookup.js +5 -5
  48. package/dist/runtime-api.monitor-DSbfGnzS.js +6 -0
  49. package/dist/runtime-api.monitor.js +7 -7
  50. package/dist/runtime-api.send.js +5 -5
  51. package/dist/runtime-api.threads.js +5 -5
  52. package/dist/{send-iJ0B4bAX.js → send-BFpa_DHn.js} +21 -12
  53. package/dist/{send.components-D0I39utR.js → send.components-BaXQJKWT.js} +15 -10
  54. package/dist/{send.outbound-Bj61Q3a0.js → send.outbound-BlA6VzSE.js} +22 -12
  55. package/dist/{send.receipt-BpBQED_5.js → send.receipt-aegk69an.js} +59 -75
  56. package/dist/{send.shared-wAwMhHDN.js → send.shared-Xz7IMVpu.js} +44 -20
  57. package/dist/{sender-identity-CEsfDF0L.js → sender-identity-C62lBe18.js} +1 -1
  58. package/dist/session-binding-contract-api.js +1 -1
  59. package/dist/setup-plugin-api.js +1 -1
  60. package/dist/{shared-BQVKfnev.js → shared-BLYBt5SA.js} +3 -3
  61. package/dist/{subagent-hooks-B-bJxxGg.js → subagent-hooks-DKJ4p-Oy.js} +2 -2
  62. package/dist/subagent-hooks-api.js +1 -1
  63. package/dist/{system-events-DVnqSyTt.js → system-events-DKwfE-2z.js} +2 -2
  64. package/dist/{target-resolver-CwHaSLt3.js → target-resolver-BQyEHyeS.js} +2 -2
  65. package/dist/targets-DvItNIvP.js +3 -0
  66. package/dist/thread-binding-api-BDZJD4na.js +4 -0
  67. package/dist/thread-binding-api.js +1 -3
  68. package/dist/{thread-bindings-DsTxqu3E.js → thread-bindings-BbzjUuNB.js} +26 -43
  69. package/dist/{thread-bindings.discord-api-BjIf9lGs.js → thread-bindings.discord-api-DJD3qwIN.js} +8 -10
  70. package/dist/{thread-bindings.manager-Bwmtqc3E.js → thread-bindings.manager-BIBm6bQd.js} +4 -4
  71. package/dist/{thread-bindings.session-updates-Chs3HgGa.js → thread-bindings.session-updates-eRcJlzIU.js} +1 -1
  72. package/dist/{thread-bindings.state-iSWjCYjB.js → thread-bindings.state-9VAxhVf6.js} +3 -14
  73. package/dist/{timeouts-C5TBc_9x.js → timeouts-ZRc9Lw4y.js} +3 -15
  74. package/dist/timeouts.js +1 -1
  75. package/dist/{transcripts-source-BvvM5Ns9.js → transcripts-source-CLZ5X8fh.js} +1 -1
  76. package/dist/transcripts-source-api.js +1 -1
  77. package/dist/{typing-BVcJgILg.js → typing-BnYT7Szq.js} +2 -2
  78. package/node_modules/p-map/index.d.ts +155 -0
  79. package/node_modules/p-map/index.js +284 -0
  80. package/node_modules/p-map/license +9 -0
  81. package/node_modules/p-map/package.json +57 -0
  82. package/node_modules/p-map/readme.md +190 -0
  83. package/npm-shrinkwrap.json +16 -3
  84. package/openclaw.plugin.json +70 -2
  85. package/package.json +6 -4
  86. package/dist/config-api-JiPdJeb0.js +0 -2
  87. package/dist/conversation-identity-DWC5d8Sy.js +0 -272
  88. package/dist/pluralkit-DcD-3EcL.js +0 -24
  89. package/dist/preview-streaming-DXT8oJdo.js +0 -8
  90. package/dist/provider.runtime-WrJXikSv.js +0 -2
  91. package/dist/runtime-api.monitor-C2_WVtJf.js +0 -6
  92. package/dist/targets-69w7c3vU.js +0 -3
@@ -1,16 +1,17 @@
1
- import { Kt as parseDiscordTarget, c as normalizeDiscordMessagingTarget, s as looksLikeDiscordTargetId } from "./send.receipt-BpBQED_5.js";
2
- import { c as resolveDiscordAccountAllowFrom, i as listEnabledDiscordAccounts, o as resolveDefaultDiscordAccountId, s as resolveDiscordAccount } from "./accounts-P19jm1lf.js";
1
+ import { Jt as parseDiscordTarget, c as normalizeDiscordMessagingTarget, s as looksLikeDiscordTargetId } from "./send.receipt-aegk69an.js";
2
+ import { c as resolveDiscordAccountAllowFrom, i as listEnabledDiscordAccounts, o as resolveDefaultDiscordAccountId, r as listDiscordAccountIds, s as resolveDiscordAccount } from "./accounts-P19jm1lf.js";
3
3
  import { a as projectCredentialSnapshotFields, n as PAIRING_APPROVED_MESSAGE, o as resolveConfiguredFromCredentialStatuses, r as buildTokenChannelStatusSummary, t as DEFAULT_ACCOUNT_ID } from "./channel-api-CAJ0wMoV.js";
4
- import { x as resolveDiscordOutboundSessionRoute } from "./components-BIBizbtZ.js";
4
+ import { C as resolveDiscordOutboundSessionRoute } from "./components-BVrfRS-F.js";
5
+ import { d as withAbortTimeout } from "./timeouts-ZRc9Lw4y.js";
5
6
  import { t as getDiscordRuntime } from "./runtime-DgnVQ7zW.js";
6
- import { c as shouldSuppressLocalDiscordExecApprovalPrompt, n as resolveDiscordCurrentConversationIdentity, r as getDiscordApprovalCapability } from "./conversation-identity-DWC5d8Sy.js";
7
+ import { a as isDiscordExecApprovalClientEnabled, c as createChannelApproverDmTargetResolver, d as matchesApprovalRequestFilters, i as isDiscordExecApprovalApprover, l as createChannelNativeOriginTargetResolver, n as resolveDiscordCurrentConversationIdentity, o as shouldSuppressLocalDiscordExecApprovalPrompt, r as getDiscordExecApprovalApprovers, s as createApproverRestrictedNativeApprovalCapability, u as isChannelExecApprovalClientEnabledFromConfig } from "./conversation-identity-BpkAzklg.js";
7
8
  import { r as resolveRequiredDiscordChannelPermissions } from "./audit-core-xwjIczO0.js";
8
- import { t as discordMessageActions$1 } from "./channel-actions-D_fjVUZ_.js";
9
- import { n as setThreadBindingMaxAgeBySessionKey, t as setThreadBindingIdleTimeoutBySessionKey } from "./thread-bindings.session-updates-Chs3HgGa.js";
10
- import { d as withAbortTimeout } from "./timeouts-C5TBc_9x.js";
11
- import { n as discordOutbound } from "./outbound-adapter-82RWi_SR.js";
12
- import { a as discordSecurityAdapter, i as discordSetupAdapter, n as discordConfigAdapter, t as createDiscordPluginBase } from "./shared-BQVKfnev.js";
9
+ import { t as discordMessageActions$1 } from "./channel-actions-ChpBSRcu.js";
10
+ import { n as setThreadBindingMaxAgeBySessionKey, t as setThreadBindingIdleTimeoutBySessionKey } from "./thread-bindings.session-updates-eRcJlzIU.js";
11
+ import { n as discordOutbound } from "./outbound-adapter-Czny0Fae.js";
12
+ import { a as discordSecurityAdapter, i as discordSetupAdapter, n as discordConfigAdapter, t as createDiscordPluginBase } from "./shared-BLYBt5SA.js";
13
13
  import { t as normalizeExplicitDiscordSessionKey } from "./session-key-normalization-wJgsKPNF.js";
14
+ import { t as defaultTopLevelPlacement } from "./thread-binding-api-BDZJD4na.js";
14
15
  import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
15
16
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalString, normalizeOptionalStringifiedId } from "openclaw/plugin-sdk/string-coerce-runtime";
16
17
  import { createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core";
@@ -22,8 +23,187 @@ import { createPairingPrefixStripper } from "openclaw/plugin-sdk/channel-pairing
22
23
  import { createChannelDirectoryAdapter, createRuntimeDirectoryLiveAdapter } from "openclaw/plugin-sdk/directory-runtime";
23
24
  import { appendMatchMetadata, asString, createComputedAccountStatusAdapter, createDefaultChannelRuntimeState, isRecord as isRecord$1, resolveEnabledConfiguredAccountId } from "openclaw/plugin-sdk/status-helpers";
24
25
  import { resolveTargetsWithOptionalToken } from "openclaw/plugin-sdk/target-resolver-runtime";
25
- import { resolveToolsBySender } from "openclaw/plugin-sdk/channel-policy";
26
+ import { createLazyChannelApprovalNativeRuntimeAdapter } from "openclaw/plugin-sdk/approval-handler-adapter-runtime";
27
+ import { doesApprovalRequestMatchChannelAccount, resolveApprovalRequestSessionConversation } from "openclaw/plugin-sdk/approval-native-runtime";
28
+ import { resolveScopeRequireMention, resolveScopeToolsPolicy } from "openclaw/plugin-sdk/channel-policy";
26
29
  import { normalizeAtHashSlug } from "openclaw/plugin-sdk/string-normalization-runtime";
30
+ //#region extensions/discord/src/approval-shared.ts
31
+ function shouldHandleDiscordApprovalRequest(params) {
32
+ const config = params.configOverride ?? resolveDiscordAccount({
33
+ cfg: params.cfg,
34
+ accountId: params.accountId
35
+ }).config.execApprovals;
36
+ const approvers = getDiscordExecApprovalApprovers({
37
+ cfg: params.cfg,
38
+ accountId: params.accountId,
39
+ configOverride: params.configOverride
40
+ });
41
+ if (!doesApprovalRequestMatchChannelAccount({
42
+ cfg: params.cfg,
43
+ request: params.request,
44
+ channel: "discord",
45
+ accountId: params.accountId
46
+ })) return false;
47
+ if (!isChannelExecApprovalClientEnabledFromConfig({
48
+ enabled: config?.enabled,
49
+ approverCount: approvers.length
50
+ })) return false;
51
+ return matchesApprovalRequestFilters({
52
+ request: params.request.request,
53
+ agentFilter: config?.agentFilter,
54
+ sessionFilter: config?.sessionFilter
55
+ });
56
+ }
57
+ //#endregion
58
+ //#region extensions/discord/src/approval-native.ts
59
+ function extractDiscordSessionKind(sessionKey) {
60
+ if (!sessionKey) return null;
61
+ const match = sessionKey.match(/discord:(?:[^:]+:)?(channel|group|dm|direct):/);
62
+ if (!match) return null;
63
+ const raw = match[1];
64
+ if (raw === "direct") return "dm";
65
+ return raw === "channel" || raw === "group" || raw === "dm" ? raw : null;
66
+ }
67
+ function normalizeDiscordOriginChannelId(value) {
68
+ if (!value) return null;
69
+ const trimmed = value.trim();
70
+ if (!trimmed) return null;
71
+ const prefixed = trimmed.match(/^(?:channel|group):(\d+)$/i);
72
+ if (prefixed) return prefixed[1] ?? null;
73
+ return /^\d+$/.test(trimmed) ? trimmed : null;
74
+ }
75
+ function normalizeDiscordThreadId(value) {
76
+ if (typeof value === "number") return Number.isFinite(value) ? String(value) : void 0;
77
+ if (typeof value !== "string") return;
78
+ const normalized = value.trim();
79
+ return /^\d+$/.test(normalized) ? normalized : void 0;
80
+ }
81
+ function createDiscordOriginTargetResolver(configOverride) {
82
+ return createChannelNativeOriginTargetResolver({
83
+ channel: "discord",
84
+ shouldHandleRequest: ({ cfg, accountId, request }) => shouldHandleDiscordApprovalRequest({
85
+ cfg,
86
+ accountId,
87
+ request,
88
+ configOverride
89
+ }),
90
+ resolveTurnSourceTarget: (request) => {
91
+ const sessionConversation = resolveApprovalRequestSessionConversation({
92
+ request,
93
+ channel: "discord",
94
+ bundledFallback: false
95
+ });
96
+ const sessionKind = extractDiscordSessionKind(normalizeOptionalString(request.request.sessionKey) ?? null);
97
+ const turnSourceChannel = normalizeLowercaseStringOrEmpty(request.request.turnSourceChannel);
98
+ const rawTurnSourceTo = normalizeOptionalString(request.request.turnSourceTo) ?? "";
99
+ const turnSourceTo = normalizeDiscordOriginChannelId(rawTurnSourceTo);
100
+ const threadId = normalizeDiscordThreadId(request.request.turnSourceThreadId) ?? normalizeDiscordThreadId(sessionConversation?.threadId) ?? void 0;
101
+ const hasExplicitOriginTarget = /^(?:channel|group):/i.test(rawTurnSourceTo);
102
+ if (turnSourceChannel !== "discord" || !turnSourceTo || sessionKind === "dm") return null;
103
+ return hasExplicitOriginTarget || sessionKind === "channel" || sessionKind === "group" ? {
104
+ to: turnSourceTo,
105
+ threadId
106
+ } : null;
107
+ },
108
+ resolveSessionTarget: (sessionTarget, request) => {
109
+ const sessionConversation = resolveApprovalRequestSessionConversation({
110
+ request,
111
+ channel: "discord",
112
+ bundledFallback: false
113
+ });
114
+ if (extractDiscordSessionKind(request.request.sessionKey?.trim() || null) === "dm") return null;
115
+ const targetTo = normalizeDiscordOriginChannelId(sessionTarget.to);
116
+ return targetTo ? {
117
+ to: targetTo,
118
+ threadId: normalizeDiscordThreadId(sessionTarget.threadId) ?? normalizeDiscordThreadId(sessionConversation?.threadId) ?? void 0
119
+ } : null;
120
+ },
121
+ resolveFallbackTarget: (request) => {
122
+ const sessionConversation = resolveApprovalRequestSessionConversation({
123
+ request,
124
+ channel: "discord",
125
+ bundledFallback: false
126
+ });
127
+ if (extractDiscordSessionKind(request.request.sessionKey?.trim() || null) === "dm") return null;
128
+ const fallbackChannelId = normalizeDiscordOriginChannelId(sessionConversation?.id);
129
+ return fallbackChannelId ? {
130
+ to: fallbackChannelId,
131
+ threadId: normalizeDiscordThreadId(sessionConversation?.threadId) ?? void 0
132
+ } : null;
133
+ }
134
+ });
135
+ }
136
+ function createDiscordApproverDmTargetResolver(configOverride) {
137
+ return createChannelApproverDmTargetResolver({
138
+ shouldHandleRequest: ({ cfg, accountId, request }) => shouldHandleDiscordApprovalRequest({
139
+ cfg,
140
+ accountId,
141
+ request,
142
+ configOverride
143
+ }),
144
+ resolveApprovers: ({ cfg, accountId }) => getDiscordExecApprovalApprovers({
145
+ cfg,
146
+ accountId,
147
+ configOverride
148
+ }),
149
+ mapApprover: (approver) => ({ to: approver })
150
+ });
151
+ }
152
+ function createDiscordApprovalCapability(configOverride) {
153
+ return createApproverRestrictedNativeApprovalCapability({
154
+ channel: "discord",
155
+ channelLabel: "Discord",
156
+ describeExecApprovalSetup: ({ accountId }) => {
157
+ const prefix = accountId && accountId !== "default" ? `channels.discord.accounts.${accountId}` : "channels.discord";
158
+ return `Approve it from the Web UI or terminal UI for now. Discord supports native exec approvals for this account. Configure \`${prefix}.execApprovals.approvers\` or \`commands.ownerAllowFrom\`; set \`${prefix}.execApprovals.enabled\` to \`auto\` or \`true\`.`;
159
+ },
160
+ listAccountIds: listDiscordAccountIds,
161
+ hasApprovers: ({ cfg, accountId }) => getDiscordExecApprovalApprovers({
162
+ cfg,
163
+ accountId,
164
+ configOverride
165
+ }).length > 0,
166
+ isExecAuthorizedSender: ({ cfg, accountId, senderId }) => isDiscordExecApprovalApprover({
167
+ cfg,
168
+ accountId,
169
+ senderId,
170
+ configOverride
171
+ }),
172
+ isNativeDeliveryEnabled: ({ cfg, accountId }) => isDiscordExecApprovalClientEnabled({
173
+ cfg,
174
+ accountId,
175
+ configOverride
176
+ }),
177
+ resolveNativeDeliveryMode: ({ cfg, accountId }) => configOverride?.target ?? resolveDiscordAccount({
178
+ cfg,
179
+ accountId
180
+ }).config.execApprovals?.target ?? "dm",
181
+ resolveOriginTarget: createDiscordOriginTargetResolver(configOverride),
182
+ resolveApproverDmTargets: createDiscordApproverDmTargetResolver(configOverride),
183
+ notifyOriginWhenDmOnly: true,
184
+ nativeRuntime: createLazyChannelApprovalNativeRuntimeAdapter({
185
+ eventKinds: ["exec", "plugin"],
186
+ isConfigured: ({ cfg, accountId }) => isDiscordExecApprovalClientEnabled({
187
+ cfg,
188
+ accountId,
189
+ configOverride
190
+ }),
191
+ shouldHandle: ({ cfg, accountId, request }) => shouldHandleDiscordApprovalRequest({
192
+ cfg,
193
+ accountId,
194
+ request,
195
+ configOverride
196
+ }),
197
+ load: async () => (await import("./approval-handler.runtime-DeyIiw5I.js")).discordApprovalNativeRuntime
198
+ })
199
+ });
200
+ }
201
+ let cachedDiscordApprovalCapability;
202
+ function getDiscordApprovalCapability() {
203
+ cachedDiscordApprovalCapability ??= createDiscordApprovalCapability();
204
+ return cachedDiscordApprovalCapability;
205
+ }
206
+ //#endregion
27
207
  //#region extensions/discord/src/channel.conversation.ts
28
208
  function resolveDiscordAttachedOutboundTarget(params) {
29
209
  if (params.threadId == null) return params.to;
@@ -121,68 +301,87 @@ function resolveDiscordInboundConversation(params) {
121
301
  }
122
302
  //#endregion
123
303
  //#region extensions/discord/src/channel.loaders.ts
124
- const loadDiscordDirectoryConfigModule = createLazyRuntimeModule(() => import("./directory-config-ByaUKL1f.js").then((n) => n.t));
125
- const loadDiscordResolveChannelsModule = createLazyRuntimeModule(() => import("./resolve-channels-CcpvWoRa.js").then((n) => n.n));
126
- const loadDiscordResolveUsersModule = createLazyRuntimeModule(() => import("./resolve-users-DJamun9s.js").then((n) => n.n));
127
- const loadDiscordThreadBindingsManagerModule = createLazyRuntimeModule(() => import("./thread-bindings.manager-Bwmtqc3E.js").then((n) => n.a));
128
- const loadDiscordTargetResolverModule = createLazyRuntimeModule(() => import("./target-resolver-CwHaSLt3.js").then((n) => n.r));
129
- const loadDiscordProviderRuntime = createLazyRuntimeModule(() => import("./provider.runtime-WrJXikSv.js"));
130
- const loadDiscordProbeRuntime = createLazyRuntimeModule(() => import("./probe.runtime-B1dsEeBD.js"));
131
- const loadDiscordAuditModule = createLazyRuntimeModule(() => import("./audit-MLpDpN3Z.js").then((n) => n.n));
132
- const loadDiscordSendModule = createLazyRuntimeModule(() => import("./send-iJ0B4bAX.js").then((n) => n.t));
133
- const loadDiscordDirectoryLiveModule = createLazyRuntimeModule(() => import("./directory-live-BX79ImQA.js").then((n) => n.t));
304
+ const loadDiscordDirectoryConfigModule = createLazyRuntimeModule(() => import("./directory-config-BUe-qq_C.js").then((n) => n.t));
305
+ const loadDiscordResolveChannelsModule = createLazyRuntimeModule(() => import("./resolve-channels-BrkWOKdG.js").then((n) => n.n));
306
+ const loadDiscordResolveUsersModule = createLazyRuntimeModule(() => import("./resolve-users-OjrXXvJP.js").then((n) => n.n));
307
+ const loadDiscordThreadBindingsManagerModule = createLazyRuntimeModule(() => import("./thread-bindings.manager-BIBm6bQd.js").then((n) => n.a));
308
+ const loadDiscordTargetResolverModule = createLazyRuntimeModule(() => import("./target-resolver-BQyEHyeS.js").then((n) => n.r));
309
+ const loadDiscordProviderRuntime = createLazyRuntimeModule(() => import("./provider.runtime-C2iIfbTs.js"));
310
+ const loadDiscordProbeRuntime = createLazyRuntimeModule(() => import("./probe.runtime-Bc8Oo6e8.js"));
311
+ const loadDiscordAuditModule = createLazyRuntimeModule(() => import("./audit-Df2w046a.js").then((n) => n.n));
312
+ const loadDiscordSendModule = createLazyRuntimeModule(() => import("./send-BFpa_DHn.js").then((n) => n.t));
313
+ const loadDiscordDirectoryLiveModule = createLazyRuntimeModule(() => import("./directory-live-DZByMdPO.js").then((n) => n.t));
134
314
  //#endregion
135
315
  //#region extensions/discord/src/group-policy.ts
136
316
  function normalizeDiscordSlug(value) {
137
317
  return normalizeAtHashSlug(value);
138
318
  }
139
- function resolveDiscordGuildEntry(guilds, groupSpace) {
140
- if (!guilds || Object.keys(guilds).length === 0) return null;
319
+ const encodeScopeSegment = (value) => `${value.length}:${value}`;
320
+ const guildScopeKey = (guildKey) => `guild:${encodeScopeSegment(guildKey)}`;
321
+ const channelScopeKey = (guildKey, channelKey) => `${guildScopeKey(guildKey)}/channel:${encodeScopeSegment(channelKey)}`;
322
+ function resolveDiscordGuildKey(guilds, groupSpace) {
323
+ if (!guilds || Object.keys(guilds).length === 0) return;
141
324
  const space = normalizeOptionalString(groupSpace) ?? "";
142
- if (space && guilds[space]) return guilds[space];
325
+ if (space && guilds[space]) return space;
143
326
  const normalized = normalizeDiscordSlug(space);
144
- if (normalized && guilds[normalized]) return guilds[normalized];
327
+ if (normalized && guilds[normalized]) return normalized;
145
328
  if (normalized) {
146
- const match = Object.values(guilds).find((entry) => normalizeDiscordSlug(entry?.slug ?? void 0) === normalized);
147
- if (match) return match;
329
+ const match = Object.entries(guilds).find(([, entry]) => normalizeDiscordSlug(entry?.slug ?? void 0) === normalized);
330
+ if (match) return match[0];
148
331
  }
149
- return guilds["*"] ?? null;
332
+ return guilds["*"] ? "*" : void 0;
150
333
  }
151
- function resolveDiscordChannelEntry(channelEntries, params) {
334
+ function resolveDiscordChannelKey(channelEntries, params) {
152
335
  if (!channelEntries || Object.keys(channelEntries).length === 0) return;
153
336
  const groupChannel = params.groupChannel;
154
337
  const channelSlug = normalizeDiscordSlug(groupChannel);
155
- return (params.groupId ? channelEntries[params.groupId] : void 0) ?? (channelSlug ? channelEntries[channelSlug] ?? channelEntries[`#${channelSlug}`] : void 0) ?? (groupChannel ? channelEntries[normalizeDiscordSlug(groupChannel)] : void 0);
338
+ if (params.groupId && channelEntries[params.groupId]) return params.groupId;
339
+ if (channelSlug && channelEntries[channelSlug]) return channelSlug;
340
+ if (channelSlug && channelEntries[`#${channelSlug}`]) return `#${channelSlug}`;
341
+ const normalizedGroupChannel = groupChannel ? normalizeDiscordSlug(groupChannel) : void 0;
342
+ return normalizedGroupChannel !== void 0 && channelEntries[normalizedGroupChannel] ? normalizedGroupChannel : void 0;
156
343
  }
157
- function resolveSenderToolsEntry(entry, params) {
158
- if (!entry) return;
159
- return resolveToolsBySender({
160
- toolsBySender: entry.toolsBySender,
161
- senderId: params.senderId,
162
- senderName: params.senderName,
163
- senderUsername: params.senderUsername,
164
- senderE164: params.senderE164
165
- }) ?? entry.tools;
344
+ function buildDiscordPolicyTree(guilds) {
345
+ const scopes = {};
346
+ for (const [guildKey, guild] of Object.entries(guilds ?? {})) {
347
+ scopes[guildScopeKey(guildKey)] = {
348
+ requireMention: guild.requireMention,
349
+ tools: guild.tools,
350
+ toolsBySender: guild.toolsBySender
351
+ };
352
+ for (const [channelKey, channel] of Object.entries(guild.channels ?? {})) scopes[channelScopeKey(guildKey, channelKey)] = {
353
+ requireMention: channel.requireMention,
354
+ tools: channel.tools,
355
+ toolsBySender: channel.toolsBySender
356
+ };
357
+ }
358
+ return { scopes };
166
359
  }
167
- function resolveDiscordPolicyContext(params) {
168
- const guildEntry = resolveDiscordGuildEntry((params.accountId ? params.cfg.channels?.discord?.accounts?.[params.accountId]?.guilds : void 0) ?? params.cfg.channels?.discord?.guilds, params.groupSpace);
169
- const channelEntries = guildEntry?.channels;
360
+ function resolveDiscordPolicyScope(params) {
361
+ const guilds = (params.accountId ? params.cfg.channels?.discord?.accounts?.[params.accountId]?.guilds : void 0) ?? params.cfg.channels?.discord?.guilds;
362
+ const tree = buildDiscordPolicyTree(guilds);
363
+ const guildKey = resolveDiscordGuildKey(guilds, params.groupSpace);
364
+ if (!guildKey) return {
365
+ tree,
366
+ path: []
367
+ };
368
+ const channelKey = resolveDiscordChannelKey(guilds?.[guildKey]?.channels, params);
170
369
  return {
171
- guildEntry,
172
- channelEntry: channelEntries && Object.keys(channelEntries).length > 0 ? resolveDiscordChannelEntry(channelEntries, params) : void 0
370
+ tree,
371
+ path: [guildScopeKey(guildKey), ...channelKey !== void 0 ? [channelScopeKey(guildKey, channelKey)] : []]
173
372
  };
174
373
  }
175
374
  function resolveDiscordGroupRequireMention(params) {
176
- const context = resolveDiscordPolicyContext(params);
177
- if (typeof context.channelEntry?.requireMention === "boolean") return context.channelEntry.requireMention;
178
- if (typeof context.guildEntry?.requireMention === "boolean") return context.guildEntry.requireMention;
179
- return true;
375
+ return resolveScopeRequireMention(resolveDiscordPolicyScope(params));
180
376
  }
181
377
  function resolveDiscordGroupToolPolicy(params) {
182
- const context = resolveDiscordPolicyContext(params);
183
- const channelPolicy = resolveSenderToolsEntry(context.channelEntry, params);
184
- if (channelPolicy) return channelPolicy;
185
- return resolveSenderToolsEntry(context.guildEntry, params);
378
+ return resolveScopeToolsPolicy({
379
+ ...resolveDiscordPolicyScope(params),
380
+ senderId: params.senderId,
381
+ senderName: params.senderName,
382
+ senderUsername: params.senderUsername,
383
+ senderE164: params.senderE164
384
+ });
186
385
  }
187
386
  //#endregion
188
387
  //#region extensions/discord/src/status-issues.ts
@@ -459,10 +658,11 @@ const discordPlugin = createChatChannelPlugin({
459
658
  looksLikeId: looksLikeDiscordTargetId,
460
659
  hint: "<channelId|user:ID|channel:ID>",
461
660
  resolveTarget: async ({ cfg, accountId, input, normalized, preferredKind }) => {
661
+ const defaultKind = preferredKind === "user" || normalized.startsWith("user:") ? "user" : preferredKind === "channel" || preferredKind === "group" || normalized.startsWith("channel:") ? "channel" : void 0;
462
662
  const resolved = await (await loadDiscordTargetResolverModule()).resolveDiscordTarget(input, {
463
663
  cfg,
464
664
  accountId
465
- }, preferredKind === "user" ? { defaultKind: "user" } : preferredKind === "channel" || preferredKind === "group" ? { defaultKind: "channel" } : {});
665
+ }, defaultKind ? { defaultKind } : {});
466
666
  if (!resolved) return null;
467
667
  return {
468
668
  to: resolved.normalized,
@@ -543,7 +743,7 @@ const discordPlugin = createChatChannelPlugin({
543
743
  },
544
744
  conversationBindings: {
545
745
  supportsCurrentConversationBinding: true,
546
- defaultTopLevelPlacement: "child",
746
+ defaultTopLevelPlacement,
547
747
  createManager: async ({ cfg, accountId }) => (await loadDiscordThreadBindingsManagerModule()).createThreadBindingManager({
548
748
  cfg,
549
749
  accountId: accountId ?? void 0,
@@ -767,14 +967,27 @@ const discordPlugin = createChatChannelPlugin({
767
967
  }
768
968
  } },
769
969
  security: discordSecurityAdapter,
770
- threading: { scopedAccountReplyToMode: {
771
- resolveAccount: (cfg, accountId) => resolveDiscordAccount({
772
- cfg,
773
- accountId
774
- }),
775
- resolveReplyToMode: (account) => account.config.replyToMode,
776
- fallback: "off"
777
- } },
970
+ threading: {
971
+ scopedAccountReplyToMode: {
972
+ resolveAccount: (cfg, accountId) => resolveDiscordAccount({
973
+ cfg,
974
+ accountId
975
+ }),
976
+ resolveReplyToMode: (account) => account.config.replyToMode,
977
+ fallback: "off"
978
+ },
979
+ buildToolContext: ({ context, hasRepliedRef }) => {
980
+ const currentMessagingTarget = normalizeOptionalString(context.To);
981
+ const currentChatType = context.ChatType === "direct" || context.ChatType === "group" || context.ChatType === "channel" ? context.ChatType : void 0;
982
+ return {
983
+ currentChannelId: normalizeOptionalString(context.NativeChannelId) ?? currentMessagingTarget,
984
+ currentChatType,
985
+ currentMessagingTarget,
986
+ currentMessageId: context.CurrentMessageId,
987
+ hasRepliedRef
988
+ };
989
+ }
990
+ },
778
991
  outbound: {
779
992
  ...discordOutbound,
780
993
  preferFinalAssistantVisibleText: true,
@@ -788,4 +1001,4 @@ const discordPlugin = createChatChannelPlugin({
788
1001
  }
789
1002
  });
790
1003
  //#endregion
791
- export { resolveDiscordGroupToolPolicy as i, collectDiscordStatusIssues as n, resolveDiscordGroupRequireMention as r, discordPlugin as t };
1004
+ export { shouldHandleDiscordApprovalRequest as a, resolveDiscordGroupToolPolicy as i, collectDiscordStatusIssues as n, resolveDiscordGroupRequireMention as r, discordPlugin as t };
@@ -1,2 +1,2 @@
1
- import { t as discordPlugin } from "./channel-DGWPH5u3.js";
1
+ import { t as discordPlugin } from "./channel-nYmJ7FKQ.js";
2
2
  export { discordPlugin };
@@ -1,8 +1,8 @@
1
1
  import { n as inspectDiscordConfiguredToken } from "./account-inspect-DDZtT5C8.js";
2
2
  import { a as mergeDiscordAccountConfig, c as resolveDiscordAccountAllowFrom, l as resolveDiscordAccountConfig, m as resolveDiscordToken, o as resolveDefaultDiscordAccountId } from "./accounts-P19jm1lf.js";
3
- import { i as discordSetupAdapter, t as createDiscordPluginBase } from "./shared-BQVKfnev.js";
4
- import { t as resolveDiscordChannelAllowlist } from "./resolve-channels-CcpvWoRa.js";
5
- import { t as resolveDiscordUserAllowlist } from "./resolve-users-DJamun9s.js";
3
+ import { i as discordSetupAdapter, t as createDiscordPluginBase } from "./shared-BLYBt5SA.js";
4
+ import { t as resolveDiscordChannelAllowlist } from "./resolve-channels-BrkWOKdG.js";
5
+ import { t as resolveDiscordUserAllowlist } from "./resolve-users-OjrXXvJP.js";
6
6
  import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-id";
7
7
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
8
8
  import { createAccountScopedAllowFromSection, createAccountScopedGroupAccessSection, createLegacyCompatChannelDmPolicy, createSetupTranslator, createStandardChannelSetupStatus, parseMentionOrPrefixedId, patchChannelConfigForAccount, promptLegacyChannelAllowFromForAccount, resolveEntriesWithOptionalToken, setSetupChannelEnabled } from "openclaw/plugin-sdk/setup-runtime";
@@ -1,10 +1,11 @@
1
- import { $ as StringSelectMenu, B as RadioGroup, G as File, H as Button, J as MentionableSelectMenu, Jt as __exportAll, K as LinkButton, Kt as parseDiscordTarget, L as CheckboxGroup, Q as Separator, R as Label, U as ChannelSelectMenu, V as TextInput, W as Container, X as Row, Y as RoleSelectMenu, Z as Section, et as TextDisplay, it as parseCustomId, nt as UserSelectMenu, q as MediaGallery, tt as Thumbnail, z as Modal } from "./send.receipt-BpBQED_5.js";
1
+ import { $ as Section, B as Label, G as ChannelSelectMenu, H as RadioGroup, J as LinkButton, Jt as parseDiscordTarget, K as Container, Q as Row, U as TextInput, V as Modal, W as Button, X as MentionableSelectMenu, Xt as __exportAll, Y as MediaGallery, Z as RoleSelectMenu, et as Separator, it as UserSelectMenu, nt as TextDisplay, ot as parseCustomId, q as File, rt as Thumbnail, tt as StringSelectMenu, z as CheckboxGroup } from "./send.receipt-aegk69an.js";
2
+ import { t as buildDiscordApprovalCustomId } from "./approval-custom-id-NYPYj9Po.js";
2
3
  import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
3
4
  import { buildOutboundBaseSessionKey } from "openclaw/plugin-sdk/routing";
4
5
  import { buildThreadAwareOutboundSessionRoute } from "openclaw/plugin-sdk/channel-core";
5
6
  import { ButtonStyle, MessageFlags, TextInputStyle } from "discord-api-types/v10";
6
7
  import crypto from "node:crypto";
7
- import { reduceInteractiveReply, resolveMessagePresentationControlValue } from "openclaw/plugin-sdk/interactive-runtime";
8
+ import { reduceInteractiveReply, resolveMessagePresentationButtonAction, resolveMessagePresentationOptionAction } from "openclaw/plugin-sdk/interactive-runtime";
8
9
  //#region extensions/discord/src/outbound-session-route.ts
9
10
  function resolveDiscordOutboundSessionRoute(params) {
10
11
  const parsed = parseDiscordTarget(params.target, { defaultKind: resolveDiscordOutboundTargetKindHint(params) });
@@ -49,33 +50,57 @@ function resolveDiscordOutboundTargetKindHint(params) {
49
50
  return "channel";
50
51
  }
51
52
  //#endregion
52
- //#region extensions/discord/src/component-custom-id.ts
53
- const DISCORD_COMPONENT_CUSTOM_ID_KEY = "occomp";
54
- const DISCORD_MODAL_CUSTOM_ID_KEY = "ocmodal";
55
- const ENCODED_CUSTOM_ID_VERSION = "1";
56
- function encodeCustomIdValue(value) {
53
+ //#region extensions/discord/src/custom-id-codec.ts
54
+ /**
55
+ * URI-component codec for values embedded in `k=v;` custom-id grammars
56
+ * (exec approvals, model picker, command args, agent components).
57
+ * Decode falls back to the raw value: Discord redelivers old component ids
58
+ * indefinitely and historical values may predate strict encoding.
59
+ */
60
+ function encodeCustomIdComponent(value) {
61
+ return encodeURIComponent(value);
62
+ }
63
+ function decodeCustomIdComponent(value) {
64
+ try {
65
+ return decodeURIComponent(value);
66
+ } catch {
67
+ return value;
68
+ }
69
+ }
70
+ /**
71
+ * Minimal field escape for the versioned `occomp`/`ocmodal` grammar: only `%`
72
+ * and the `;` field separator are escaped to preserve the 100-char custom-id
73
+ * budget. The wire format is versioned (`e=1`); do not swap this for the URI
74
+ * codec — in-flight component ids must keep decoding byte-exactly.
75
+ */
76
+ function escapeCustomIdFieldValue(value) {
57
77
  return value.replace(/%/g, "%25").replace(/;/g, "%3B");
58
78
  }
59
- function needsCustomIdEncoding(value) {
79
+ function needsCustomIdFieldEscaping(value) {
60
80
  return /[%;]/.test(value);
61
81
  }
62
- function decodeCustomIdValue(value) {
82
+ function unescapeCustomIdFieldValue(value) {
63
83
  return value.replace(/%(25|3B)/gi, (match) => match.toLowerCase() === "%25" ? "%" : ";");
64
84
  }
85
+ //#endregion
86
+ //#region extensions/discord/src/component-custom-id.ts
87
+ const DISCORD_COMPONENT_CUSTOM_ID_KEY = "occomp";
88
+ const DISCORD_MODAL_CUSTOM_ID_KEY = "ocmodal";
89
+ const ENCODED_CUSTOM_ID_VERSION = "1";
65
90
  function decodeParsedCustomIdData(data) {
66
91
  if (data.e !== ENCODED_CUSTOM_ID_VERSION) return data;
67
- return Object.fromEntries(Object.entries(data).map(([key, value]) => [key, typeof value === "string" ? decodeCustomIdValue(value) : value]));
92
+ return Object.fromEntries(Object.entries(data).map(([key, value]) => [key, typeof value === "string" ? unescapeCustomIdFieldValue(value) : value]));
68
93
  }
69
94
  function buildDiscordComponentCustomId(params) {
70
- const encoded = needsCustomIdEncoding(params.componentId) || needsCustomIdEncoding(params.modalId ?? "");
71
- const componentId = encoded ? encodeCustomIdValue(params.componentId) : params.componentId;
95
+ const encoded = needsCustomIdFieldEscaping(params.componentId) || needsCustomIdFieldEscaping(params.modalId ?? "");
96
+ const componentId = encoded ? escapeCustomIdFieldValue(params.componentId) : params.componentId;
72
97
  const base = encoded ? `${DISCORD_COMPONENT_CUSTOM_ID_KEY}:e=${ENCODED_CUSTOM_ID_VERSION};cid=${componentId}` : `${DISCORD_COMPONENT_CUSTOM_ID_KEY}:cid=${componentId}`;
73
98
  const modalId = params.modalId;
74
99
  if (!modalId) return base;
75
- return `${base};mid=${encoded ? encodeCustomIdValue(modalId) : modalId}`;
100
+ return `${base};mid=${encoded ? escapeCustomIdFieldValue(modalId) : modalId}`;
76
101
  }
77
102
  function buildDiscordModalCustomId(modalId) {
78
- return needsCustomIdEncoding(modalId) ? `${DISCORD_MODAL_CUSTOM_ID_KEY}:e=${ENCODED_CUSTOM_ID_VERSION};mid=${encodeCustomIdValue(modalId)}` : `${DISCORD_MODAL_CUSTOM_ID_KEY}:mid=${modalId}`;
103
+ return needsCustomIdFieldEscaping(modalId) ? `${DISCORD_MODAL_CUSTOM_ID_KEY}:e=${ENCODED_CUSTOM_ID_VERSION};mid=${escapeCustomIdFieldValue(modalId)}` : `${DISCORD_MODAL_CUSTOM_ID_KEY}:mid=${modalId}`;
79
104
  }
80
105
  function parseDiscordComponentCustomId(id) {
81
106
  const parsed = parseCustomId(id);
@@ -836,14 +861,10 @@ var shared_interactive_exports = /* @__PURE__ */ __exportAll({
836
861
  function resolveDiscordInteractiveButtonStyle(style) {
837
862
  return style ?? "secondary";
838
863
  }
839
- function applyDiscordButtonCallback(spec, button) {
840
- const callbackData = resolveMessagePresentationControlValue(button);
841
- if (!callbackData) return;
842
- spec.callbackData = callbackData;
843
- if (button.action?.type === "command" || button.action?.type === "callback") spec.callbackDataKind = button.action.type;
844
- }
845
864
  function resolveDiscordSelectOptionValue(option) {
846
- return resolveMessagePresentationControlValue(option);
865
+ const action = resolveMessagePresentationOptionAction(option);
866
+ if (action?.type === "command") return action.command;
867
+ if (action?.type === "callback") return action.value;
847
868
  }
848
869
  function resolveDiscordSelectCallbackDataKind(options) {
849
870
  const renderableOptions = options.filter((option) => resolveDiscordSelectOptionValue(option));
@@ -852,6 +873,39 @@ function resolveDiscordSelectCallbackDataKind(options) {
852
873
  if (renderableOptions.some((option) => option.action)) return "mixed";
853
874
  }
854
875
  const DISCORD_INTERACTIVE_BUTTON_ROW_SIZE = 5;
876
+ function buildDiscordButtonComponent(button) {
877
+ const action = resolveMessagePresentationButtonAction(button);
878
+ if (!action) return;
879
+ if (action.type === "approval") {
880
+ const internalCustomId = buildDiscordApprovalCustomId(action);
881
+ if (!internalCustomId) return;
882
+ return {
883
+ label: button.label,
884
+ style: resolveDiscordInteractiveButtonStyle(button.style),
885
+ internalCustomId,
886
+ ...button.disabled === true ? { disabled: true } : {}
887
+ };
888
+ }
889
+ const component = {
890
+ label: button.label,
891
+ style: action.type === "url" || action.type === "web-app" ? "link" : resolveDiscordInteractiveButtonStyle(button.style)
892
+ };
893
+ if (action.type === "url" || action.type === "web-app") component.url = action.url;
894
+ else {
895
+ component.callbackData = action.type === "command" ? action.command : action.value;
896
+ if (button.action?.type === "command" || button.action?.type === "callback") component.callbackDataKind = button.action.type;
897
+ }
898
+ if (button.disabled === true) component.disabled = true;
899
+ if (button.reusable === true) component.reusable = true;
900
+ return component;
901
+ }
902
+ function appendDiscordButtonBlocks(blocks, buttons) {
903
+ const components = buttons.map((button) => buildDiscordButtonComponent(button)).filter((button) => Boolean(button));
904
+ for (let index = 0; index < components.length; index += DISCORD_INTERACTIVE_BUTTON_ROW_SIZE) blocks.push({
905
+ type: "actions",
906
+ buttons: components.slice(index, index + DISCORD_INTERACTIVE_BUTTON_ROW_SIZE)
907
+ });
908
+ }
855
909
  /**
856
910
  * @deprecated Use buildDiscordPresentationComponents with MessagePresentation.
857
911
  */
@@ -866,21 +920,7 @@ function buildDiscordInteractiveComponents(interactive) {
866
920
  return state;
867
921
  }
868
922
  if (block.type === "buttons") {
869
- if (block.buttons.length === 0) return state;
870
- for (let index = 0; index < block.buttons.length; index += DISCORD_INTERACTIVE_BUTTON_ROW_SIZE) state.push({
871
- type: "actions",
872
- buttons: block.buttons.slice(index, index + DISCORD_INTERACTIVE_BUTTON_ROW_SIZE).map((button) => {
873
- const spec = {
874
- label: button.label,
875
- style: button.url ? "link" : resolveDiscordInteractiveButtonStyle(button.style)
876
- };
877
- applyDiscordButtonCallback(spec, button);
878
- if (button.url) spec.url = button.url;
879
- if (button.disabled === true) spec.disabled = true;
880
- if (button.reusable === true) spec.reusable = true;
881
- return spec;
882
- })
883
- });
923
+ appendDiscordButtonBlocks(state, block.buttons);
884
924
  return state;
885
925
  }
886
926
  if (block.type === "select" && block.options.length > 0) {
@@ -953,21 +993,7 @@ function buildDiscordPresentationComponents(presentation) {
953
993
  return spec.blocks?.length ? spec : void 0;
954
994
  }
955
995
  function appendDiscordPresentationButtonBlocks(spec, buttons) {
956
- if (buttons.length === 0) return;
957
- for (let index = 0; index < buttons.length; index += DISCORD_INTERACTIVE_BUTTON_ROW_SIZE) spec.blocks?.push({
958
- type: "actions",
959
- buttons: buttons.slice(index, index + DISCORD_INTERACTIVE_BUTTON_ROW_SIZE).map((button) => {
960
- const component = {
961
- label: button.label,
962
- style: button.url ? "link" : resolveDiscordInteractiveButtonStyle(button.style)
963
- };
964
- applyDiscordButtonCallback(component, button);
965
- if (button.url) component.url = button.url;
966
- if (button.disabled === true) component.disabled = true;
967
- if (button.reusable === true) component.reusable = true;
968
- return component;
969
- })
970
- });
996
+ if (spec.blocks) appendDiscordButtonBlocks(spec.blocks, buttons);
971
997
  }
972
998
  //#endregion
973
999
  //#region extensions/discord/src/components.ts
@@ -998,4 +1024,4 @@ function formatDiscordComponentEventText(params) {
998
1024
  return `Selected ${values.join(", ")} from "${params.label}".`;
999
1025
  }
1000
1026
  //#endregion
1001
- export { parseDiscordComponentCustomId as _, shared_interactive_exports as a, parseDiscordModalCustomIdForInteraction as b, buildDiscordComponentMessage as c, readDiscordComponentSpec as d, resolveDiscordComponentAttachmentName as f, buildDiscordModalCustomId as g, buildDiscordComponentCustomId as h, buildDiscordPresentationComponents as i, buildDiscordComponentMessageFlags as l, DISCORD_MODAL_CUSTOM_ID_KEY as m, formatDiscordComponentEventText as n, DiscordFormModal as o, DISCORD_COMPONENT_CUSTOM_ID_KEY as p, buildDiscordInteractiveComponents as r, createDiscordFormModal as s, components_exports as t, DISCORD_COMPONENT_ATTACHMENT_PREFIX as u, parseDiscordComponentCustomIdForInteraction as v, resolveDiscordOutboundSessionRoute as x, parseDiscordModalCustomId as y };
1027
+ export { resolveDiscordOutboundSessionRoute as C, encodeCustomIdComponent as S, parseDiscordComponentCustomId as _, shared_interactive_exports as a, parseDiscordModalCustomIdForInteraction as b, buildDiscordComponentMessage as c, readDiscordComponentSpec as d, resolveDiscordComponentAttachmentName as f, buildDiscordModalCustomId as g, buildDiscordComponentCustomId as h, buildDiscordPresentationComponents as i, buildDiscordComponentMessageFlags as l, DISCORD_MODAL_CUSTOM_ID_KEY as m, formatDiscordComponentEventText as n, DiscordFormModal as o, DISCORD_COMPONENT_CUSTOM_ID_KEY as p, buildDiscordInteractiveComponents as r, createDiscordFormModal as s, components_exports as t, DISCORD_COMPONENT_ATTACHMENT_PREFIX as u, parseDiscordComponentCustomIdForInteraction as v, decodeCustomIdComponent as x, parseDiscordModalCustomId as y };
@@ -0,0 +1,3 @@
1
+ import { buildChannelConfigSchema } from "openclaw/plugin-sdk/channel-config-schema";
2
+ import { DiscordConfigSchema } from "openclaw/plugin-sdk/bundled-channel-config-schema";
3
+ export { buildChannelConfigSchema as n, DiscordConfigSchema as t };