@kodelyth/discord 2026.5.39 → 2026.6.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 (126) hide show
  1. package/dist/account-inspect-Dqw-enky.js +81 -0
  2. package/dist/account-inspect-api.js +10 -0
  3. package/dist/accounts-B7OBFePq.js +224 -0
  4. package/dist/action-runtime-api.js +2 -0
  5. package/dist/agent-components.runtime-DVY_1VB4.js +4 -0
  6. package/dist/allow-list-B0s7evD7.js +354 -0
  7. package/dist/api-CXAcv9nZ.js +130 -0
  8. package/dist/api.js +23 -0
  9. package/dist/approval-handler.runtime-B9xUAF3n.js +426 -0
  10. package/dist/audit-DoiK49WO.js +24 -0
  11. package/dist/audit-core-BGrq3G7r.js +105 -0
  12. package/dist/channel-U_aeoFwW.js +795 -0
  13. package/dist/channel-actions-BxEBnEuv.js +173 -0
  14. package/dist/channel-actions.runtime-CPtpH-yl.js +263 -0
  15. package/dist/channel-api-BfjklLby.js +21 -0
  16. package/dist/channel-config-api.js +2 -0
  17. package/dist/channel-plugin-api.js +2 -0
  18. package/dist/channel.setup-BUSC0apv.js +337 -0
  19. package/dist/components-luonoe13.js +909 -0
  20. package/dist/config-api-DSYGqaLQ.js +2 -0
  21. package/dist/config-schema-DIqJBGwC.js +357 -0
  22. package/dist/configured-state.js +6 -0
  23. package/dist/contract-api.js +8 -0
  24. package/dist/conversation-identity-DXAm0_Mk.js +270 -0
  25. package/dist/directory-config-CYbuMmPS.js +49 -0
  26. package/dist/directory-contract-api.js +2 -0
  27. package/dist/directory-live-DX4dLRpJ.js +159 -0
  28. package/dist/doctor-bbKSvGVD.js +244 -0
  29. package/dist/doctor-contract-Btjt6NJD.js +383 -0
  30. package/dist/doctor-contract-api.js +2 -0
  31. package/dist/gateway-registry-BKSpa4GB.js +74 -0
  32. package/dist/handle-action.guild-admin-B5BArS2n.js +286 -0
  33. package/dist/inbound-context-WAOqhGlT.js +48 -0
  34. package/dist/inbound-event-delivery-C-1Ji3WP.js +65 -0
  35. package/dist/index.js +26 -0
  36. package/dist/manager.runtime-DXHynKE4.js +2356 -0
  37. package/dist/message-handler-mXzc3tA_.js +381 -0
  38. package/dist/message-handler.preflight-BPD1a347.js +1113 -0
  39. package/dist/message-handler.process-GUa3aV8z.js +1438 -0
  40. package/dist/message-utils-dUbem16p.js +549 -0
  41. package/dist/outbound-adapter-C18OAc1y.js +536 -0
  42. package/dist/pluralkit-D1Q2x0w5.js +22 -0
  43. package/dist/preflight-audio-CZtpWcIm.js +72 -0
  44. package/dist/preflight-audio.runtime-Brx_0_xW.js +7 -0
  45. package/dist/preview-streaming-D_slNIiO.js +8 -0
  46. package/dist/probe-D--Ca4JF.js +139 -0
  47. package/dist/probe.runtime-DQBchZzv.js +2 -0
  48. package/dist/provider-B2-31CIT.js +9565 -0
  49. package/dist/provider-session.runtime-BwzzSsrH.js +6 -0
  50. package/dist/provider.runtime-CP3oHLls.js +2 -0
  51. package/dist/resolve-allowlist-common-CqxPLcJO.js +34 -0
  52. package/dist/resolve-channels-0LX4pUbB.js +265 -0
  53. package/dist/resolve-users-CztOv0Qs.js +120 -0
  54. package/dist/runtime-DUaw66V_.js +1073 -0
  55. package/dist/runtime-api.actions.js +3 -0
  56. package/dist/runtime-api.js +30 -0
  57. package/dist/runtime-api.lookup.js +7 -0
  58. package/dist/runtime-api.monitor-CvVKvEXW.js +5 -0
  59. package/dist/runtime-api.monitor.js +8 -0
  60. package/dist/runtime-api.send.js +6 -0
  61. package/dist/runtime-api.threads.js +6 -0
  62. package/dist/runtime-fC6f4UF2.js +8 -0
  63. package/dist/runtime-setter-api.js +2 -0
  64. package/dist/secret-config-contract-B6WW5V88.js +115 -0
  65. package/dist/secret-contract-api.js +2 -0
  66. package/dist/security-audit-CnyIQKz6.js +120 -0
  67. package/dist/security-audit-contract-api.js +2 -0
  68. package/dist/security-audit.runtime-CQSkjNLu.js +2 -0
  69. package/dist/security-contract-DLvYOgLM.js +26 -0
  70. package/dist/security-contract-api.js +2 -0
  71. package/dist/security-doctor-DepqtNCI.js +18 -0
  72. package/dist/send-DCtPCHGk.js +881 -0
  73. package/dist/send.components-Bcgxvm52.js +474 -0
  74. package/dist/send.outbound-S9t0UuHc.js +330 -0
  75. package/dist/send.receipt-CDn3GBWC.js +3119 -0
  76. package/dist/send.shared-D4iBnAmn.js +669 -0
  77. package/dist/sender-identity-CxCe3_1a.js +43 -0
  78. package/dist/session-contract-Dwhw3RTY.js +6 -0
  79. package/dist/session-key-api.js +2 -0
  80. package/dist/session-key-normalization-CP8dPUid.js +23 -0
  81. package/dist/setup-entry.js +11 -0
  82. package/dist/setup-plugin-api.js +2 -0
  83. package/dist/shared-AIlvuZXt.js +171 -0
  84. package/dist/subagent-hooks-8bK-mgiU.js +120 -0
  85. package/dist/subagent-hooks-api.js +22 -0
  86. package/dist/system-events-Ba1TklaL.js +34 -0
  87. package/dist/target-resolver-BrtFQtoK.js +82 -0
  88. package/dist/targets-DWLLZE2l.js +3 -0
  89. package/dist/test-api.js +45 -0
  90. package/dist/thread-binding-api.js +4 -0
  91. package/dist/thread-bindings-9aKRmZv0.js +255 -0
  92. package/dist/thread-bindings.discord-api-ssGH5wc2.js +244 -0
  93. package/dist/thread-bindings.manager-0YBHGemk.js +534 -0
  94. package/dist/thread-bindings.session-updates-DJZGIwaU.js +54 -0
  95. package/dist/thread-bindings.state-eTFl-PqJ.js +318 -0
  96. package/dist/timeouts-CEwuGaWT.js +52 -0
  97. package/dist/timeouts.js +2 -0
  98. package/dist/typing-BmJKRpCS.js +14 -0
  99. package/package.json +19 -7
  100. package/account-inspect-api.js +0 -7
  101. package/action-runtime-api.js +0 -7
  102. package/api.js +0 -7
  103. package/channel-config-api.js +0 -7
  104. package/channel-plugin-api.js +0 -7
  105. package/configured-state.js +0 -7
  106. package/contract-api.js +0 -7
  107. package/directory-contract-api.js +0 -7
  108. package/doctor-contract-api.js +0 -7
  109. package/index.js +0 -7
  110. package/runtime-api.actions.js +0 -7
  111. package/runtime-api.js +0 -7
  112. package/runtime-api.lookup.js +0 -7
  113. package/runtime-api.monitor.js +0 -7
  114. package/runtime-api.send.js +0 -7
  115. package/runtime-api.threads.js +0 -7
  116. package/runtime-setter-api.js +0 -7
  117. package/secret-contract-api.js +0 -7
  118. package/security-audit-contract-api.js +0 -7
  119. package/security-contract-api.js +0 -7
  120. package/session-key-api.js +0 -7
  121. package/setup-entry.js +0 -7
  122. package/setup-plugin-api.js +0 -7
  123. package/subagent-hooks-api.js +0 -7
  124. package/test-api.js +0 -7
  125. package/thread-binding-api.js +0 -7
  126. package/timeouts.js +0 -7
@@ -0,0 +1,536 @@
1
+ import { S as DiscordError, o as normalizeDiscordOutboundTarget, s as chunkDiscordTextWithMode, t as createDiscordSendReceipt } from "./send.receipt-CDn3GBWC.js";
2
+ import { s as resolveDiscordAccount } from "./accounts-B7OBFePq.js";
3
+ import { d as readDiscordComponentSpec } from "./components-luonoe13.js";
4
+ import { n as notifyDiscordInboundEventOutboundPayloadSuccess } from "./inbound-event-delivery-C-1Ji3WP.js";
5
+ import { normalizeLowercaseStringOrEmpty, normalizeOptionalString, normalizeOptionalStringifiedId } from "klaw/plugin-sdk/string-coerce-runtime";
6
+ import { resolvePayloadMediaUrls, sendPayloadMediaSequenceOrFallback, sendTextMediaPayload } from "klaw/plugin-sdk/reply-payload";
7
+ import { resolveRetryConfig, retryAsync } from "klaw/plugin-sdk/retry-runtime";
8
+ import { attachChannelToResult, createAttachedChannelResultAdapter } from "klaw/plugin-sdk/channel-send-result";
9
+ import { resolveOutboundSendDep } from "klaw/plugin-sdk/outbound-send-deps";
10
+ import { createReplyToFanout } from "klaw/plugin-sdk/outbound-runtime";
11
+ //#region extensions/discord/src/delivery-retry.ts
12
+ const DISCORD_DELIVERY_RETRY_DEFAULTS = {
13
+ attempts: 3,
14
+ minDelayMs: 1e3,
15
+ maxDelayMs: 3e4,
16
+ jitter: 0
17
+ };
18
+ function isRetryableDiscordDeliveryError(err) {
19
+ if (err instanceof DiscordError) return false;
20
+ const status = err.status ?? err.statusCode;
21
+ return status === 429 || status !== void 0 && status >= 500;
22
+ }
23
+ function getDiscordDeliveryRetryAfterMs(err) {
24
+ if (!err || typeof err !== "object") return;
25
+ if ("retryAfter" in err && typeof err.retryAfter === "number" && Number.isFinite(err.retryAfter)) return err.retryAfter * 1e3;
26
+ const retryAfterRaw = err.headers?.["retry-after"];
27
+ if (!retryAfterRaw) return;
28
+ const retryAfterMs = Number(retryAfterRaw) * 1e3;
29
+ return Number.isFinite(retryAfterMs) ? retryAfterMs : void 0;
30
+ }
31
+ async function withDiscordDeliveryRetry(params) {
32
+ const retryConfig = resolveRetryConfig(DISCORD_DELIVERY_RETRY_DEFAULTS, resolveDiscordAccount({
33
+ cfg: params.cfg,
34
+ accountId: params.accountId
35
+ }).config.retry);
36
+ return await retryAsync(params.fn, {
37
+ ...retryConfig,
38
+ shouldRetry: (err) => isRetryableDiscordDeliveryError(err),
39
+ retryAfterMs: getDiscordDeliveryRetryAfterMs
40
+ });
41
+ }
42
+ //#endregion
43
+ //#region extensions/discord/src/media-detection.ts
44
+ const DISCORD_VIDEO_MEDIA_EXTENSIONS = new Set([
45
+ ".avi",
46
+ ".m4v",
47
+ ".mkv",
48
+ ".mov",
49
+ ".mp4",
50
+ ".webm"
51
+ ]);
52
+ function normalizeMediaPathForExtension(mediaUrl) {
53
+ const trimmed = mediaUrl.trim();
54
+ if (!trimmed) return "";
55
+ try {
56
+ return normalizeLowercaseStringOrEmpty(new URL(trimmed).pathname);
57
+ } catch {
58
+ const withoutHash = trimmed.split("#", 1)[0] ?? trimmed;
59
+ return normalizeLowercaseStringOrEmpty(withoutHash.split("?", 1)[0] ?? withoutHash);
60
+ }
61
+ }
62
+ function isLikelyDiscordVideoMedia(mediaUrl) {
63
+ const normalized = normalizeMediaPathForExtension(mediaUrl);
64
+ for (const ext of DISCORD_VIDEO_MEDIA_EXTENSIONS) if (normalized.endsWith(ext)) return true;
65
+ return false;
66
+ }
67
+ //#endregion
68
+ //#region extensions/discord/src/outbound-approval.ts
69
+ function hasApprovalChannelData(payload) {
70
+ const channelData = payload.channelData;
71
+ if (!channelData || typeof channelData !== "object" || Array.isArray(channelData)) return false;
72
+ return Boolean(channelData.execApproval);
73
+ }
74
+ function neutralizeDiscordApprovalMentions(value) {
75
+ return value.replace(/@everyone/gi, "@​everyone").replace(/@here/gi, "@​here").replace(/<@/g, "<@​").replace(/<#/g, "<#​");
76
+ }
77
+ function normalizeDiscordApprovalPayload(payload) {
78
+ return hasApprovalChannelData(payload) && payload.text ? {
79
+ ...payload,
80
+ text: neutralizeDiscordApprovalMentions(payload.text)
81
+ } : payload;
82
+ }
83
+ //#endregion
84
+ //#region extensions/discord/src/outbound-components.ts
85
+ let discordComponentSendPromise;
86
+ let discordSharedInteractivePromise;
87
+ async function sendDiscordComponentMessageLazy(...args) {
88
+ discordComponentSendPromise ??= import("./send.components-Bcgxvm52.js").then((n) => n.i).then((module) => module.sendDiscordComponentMessage);
89
+ return await (await discordComponentSendPromise)(...args);
90
+ }
91
+ function loadDiscordSharedInteractive() {
92
+ discordSharedInteractivePromise ??= import("./components-luonoe13.js").then((n) => n.a);
93
+ return discordSharedInteractivePromise;
94
+ }
95
+ function addPayloadTextFallback(spec, payload) {
96
+ return spec.text ? spec : {
97
+ ...spec,
98
+ text: payload.text?.trim() ? payload.text : void 0
99
+ };
100
+ }
101
+ async function buildDiscordPresentationPayload(params) {
102
+ const componentSpec = (await loadDiscordSharedInteractive()).buildDiscordPresentationComponents(params.presentation);
103
+ if (!componentSpec) return null;
104
+ return {
105
+ ...params.payload,
106
+ channelData: {
107
+ ...params.payload.channelData,
108
+ discord: {
109
+ ...params.payload.channelData?.discord,
110
+ presentationComponents: componentSpec
111
+ }
112
+ }
113
+ };
114
+ }
115
+ async function resolveDiscordComponentSpec(payload) {
116
+ const discordData = payload.channelData?.discord;
117
+ const rawComponentSpec = discordData?.presentationComponents ?? (discordData?.components && typeof discordData.components === "object" && !Array.isArray(discordData.components) ? readDiscordComponentSpec(discordData.components) : null);
118
+ if (rawComponentSpec) return addPayloadTextFallback(rawComponentSpec, payload);
119
+ if (!payload.interactive) return;
120
+ const interactiveSpec = (await loadDiscordSharedInteractive()).buildDiscordInteractiveComponents(payload.interactive);
121
+ return interactiveSpec ? addPayloadTextFallback(interactiveSpec, payload) : void 0;
122
+ }
123
+ //#endregion
124
+ //#region extensions/discord/src/outbound-send-context.ts
125
+ let discordSendRuntimePromise;
126
+ async function loadDiscordSendRuntime() {
127
+ discordSendRuntimePromise ??= import("./send-DCtPCHGk.js").then((n) => n.t);
128
+ return await discordSendRuntimePromise;
129
+ }
130
+ function resolveDiscordOutboundTarget(params) {
131
+ if (params.threadId == null) return params.to;
132
+ const threadId = normalizeOptionalStringifiedId(params.threadId) ?? "";
133
+ if (!threadId) return params.to;
134
+ return `channel:${threadId}`;
135
+ }
136
+ function resolveDiscordFormattingOptions(ctx) {
137
+ const formatting = ctx.formatting;
138
+ return {
139
+ textLimit: formatting?.textLimit,
140
+ maxLinesPerMessage: formatting?.maxLinesPerMessage,
141
+ tableMode: formatting?.tableMode,
142
+ chunkMode: formatting?.chunkMode
143
+ };
144
+ }
145
+ async function createDiscordPayloadSendContext(ctx) {
146
+ const runtime = await loadDiscordSendRuntime();
147
+ return {
148
+ target: resolveDiscordOutboundTarget({
149
+ to: ctx.to,
150
+ threadId: ctx.threadId
151
+ }),
152
+ formatting: resolveDiscordFormattingOptions(ctx),
153
+ resolveReplyTo: createReplyToFanout({
154
+ replyToId: ctx.replyToId,
155
+ replyToIdSource: ctx.replyToIdSource,
156
+ replyToMode: ctx.replyToMode
157
+ }),
158
+ send: resolveOutboundSendDep(ctx.deps, "discord") ?? runtime.sendMessageDiscord,
159
+ sendVoice: resolveOutboundSendDep(ctx.deps, "discordVoice") ?? runtime.sendVoiceMessageDiscord,
160
+ withRetry: async (fn) => await withDiscordDeliveryRetry({
161
+ cfg: ctx.cfg,
162
+ accountId: ctx.accountId,
163
+ fn
164
+ })
165
+ };
166
+ }
167
+ //#endregion
168
+ //#region extensions/discord/src/outbound-payload.ts
169
+ async function sendDiscordOutboundPayload(params) {
170
+ const ctx = params.ctx;
171
+ const payload = normalizeDiscordApprovalPayload({
172
+ ...ctx.payload,
173
+ text: ctx.payload.text ?? ""
174
+ });
175
+ const mediaUrls = resolvePayloadMediaUrls(payload);
176
+ const sendContext = await createDiscordPayloadSendContext(ctx);
177
+ if (payload.audioAsVoice && mediaUrls.length > 0) {
178
+ let lastResult = await sendContext.withRetry(async () => await sendContext.sendVoice(sendContext.target, mediaUrls[0], {
179
+ cfg: ctx.cfg,
180
+ replyTo: sendContext.resolveReplyTo(),
181
+ accountId: ctx.accountId ?? void 0,
182
+ silent: ctx.silent ?? void 0
183
+ }));
184
+ if (payload.text?.trim()) lastResult = await sendContext.withRetry(async () => await sendContext.send(sendContext.target, payload.text, {
185
+ verbose: false,
186
+ replyTo: sendContext.resolveReplyTo(),
187
+ accountId: ctx.accountId ?? void 0,
188
+ silent: ctx.silent ?? void 0,
189
+ cfg: ctx.cfg,
190
+ ...sendContext.formatting
191
+ }));
192
+ for (const mediaUrl of mediaUrls.slice(1)) lastResult = await sendContext.withRetry(async () => await sendContext.send(sendContext.target, "", {
193
+ verbose: false,
194
+ mediaUrl,
195
+ mediaAccess: ctx.mediaAccess,
196
+ mediaLocalRoots: ctx.mediaLocalRoots,
197
+ mediaReadFile: ctx.mediaReadFile,
198
+ replyTo: sendContext.resolveReplyTo(),
199
+ accountId: ctx.accountId ?? void 0,
200
+ silent: ctx.silent ?? void 0,
201
+ cfg: ctx.cfg,
202
+ ...sendContext.formatting
203
+ }));
204
+ return attachChannelToResult("discord", lastResult);
205
+ }
206
+ const componentSpec = await resolveDiscordComponentSpec(payload);
207
+ if (!componentSpec) {
208
+ const discordData = payload.channelData?.discord && typeof payload.channelData.discord === "object" && !Array.isArray(payload.channelData.discord) ? payload.channelData.discord : {};
209
+ const nativeComponents = Array.isArray(discordData.components) ? discordData.components : void 0;
210
+ const embeds = Array.isArray(discordData.embeds) ? discordData.embeds : void 0;
211
+ const filename = normalizeOptionalString(discordData.filename);
212
+ if (nativeComponents || embeds?.length || filename) return attachChannelToResult("discord", await sendPayloadMediaSequenceOrFallback({
213
+ text: payload.text ?? "",
214
+ mediaUrls,
215
+ fallbackResult: {
216
+ messageId: "",
217
+ channelId: sendContext.target,
218
+ receipt: createDiscordSendReceipt({
219
+ platformMessageIds: [],
220
+ channelId: sendContext.target,
221
+ kind: "unknown"
222
+ })
223
+ },
224
+ sendNoMedia: async () => await sendContext.withRetry(async () => await sendContext.send(sendContext.target, payload.text ?? "", {
225
+ verbose: false,
226
+ components: nativeComponents,
227
+ embeds,
228
+ filename,
229
+ replyTo: sendContext.resolveReplyTo(),
230
+ accountId: ctx.accountId ?? void 0,
231
+ silent: ctx.silent ?? void 0,
232
+ cfg: ctx.cfg,
233
+ ...sendContext.formatting
234
+ })),
235
+ send: async ({ text, mediaUrl, isFirst }) => await sendContext.withRetry(async () => await sendContext.send(sendContext.target, text, {
236
+ verbose: false,
237
+ mediaUrl,
238
+ mediaAccess: ctx.mediaAccess,
239
+ mediaLocalRoots: ctx.mediaLocalRoots,
240
+ mediaReadFile: ctx.mediaReadFile,
241
+ components: isFirst ? nativeComponents : void 0,
242
+ embeds: isFirst ? embeds : void 0,
243
+ filename: isFirst ? filename : void 0,
244
+ replyTo: sendContext.resolveReplyTo(),
245
+ accountId: ctx.accountId ?? void 0,
246
+ silent: ctx.silent ?? void 0,
247
+ cfg: ctx.cfg,
248
+ ...sendContext.formatting
249
+ }))
250
+ }));
251
+ return await sendTextMediaPayload({
252
+ channel: "discord",
253
+ ctx: {
254
+ ...ctx,
255
+ payload
256
+ },
257
+ adapter: params.fallbackAdapter
258
+ });
259
+ }
260
+ return attachChannelToResult("discord", await sendPayloadMediaSequenceOrFallback({
261
+ text: payload.text ?? "",
262
+ mediaUrls,
263
+ fallbackResult: {
264
+ messageId: "",
265
+ channelId: sendContext.target,
266
+ receipt: createDiscordSendReceipt({
267
+ platformMessageIds: [],
268
+ channelId: sendContext.target,
269
+ kind: "unknown"
270
+ })
271
+ },
272
+ sendNoMedia: async () => await sendContext.withRetry(async () => await sendDiscordComponentMessageLazy(sendContext.target, componentSpec, {
273
+ replyTo: sendContext.resolveReplyTo(),
274
+ accountId: ctx.accountId ?? void 0,
275
+ silent: ctx.silent ?? void 0,
276
+ cfg: ctx.cfg,
277
+ ...sendContext.formatting
278
+ })),
279
+ send: async ({ text, mediaUrl, isFirst }) => {
280
+ if (isFirst) return await sendContext.withRetry(async () => await sendDiscordComponentMessageLazy(sendContext.target, componentSpec, {
281
+ mediaUrl,
282
+ mediaAccess: ctx.mediaAccess,
283
+ mediaLocalRoots: ctx.mediaLocalRoots,
284
+ mediaReadFile: ctx.mediaReadFile,
285
+ replyTo: sendContext.resolveReplyTo(),
286
+ accountId: ctx.accountId ?? void 0,
287
+ silent: ctx.silent ?? void 0,
288
+ cfg: ctx.cfg,
289
+ ...sendContext.formatting
290
+ }));
291
+ return await sendContext.withRetry(async () => await sendContext.send(sendContext.target, text, {
292
+ verbose: false,
293
+ mediaUrl,
294
+ mediaAccess: ctx.mediaAccess,
295
+ mediaLocalRoots: ctx.mediaLocalRoots,
296
+ mediaReadFile: ctx.mediaReadFile,
297
+ replyTo: sendContext.resolveReplyTo(),
298
+ accountId: ctx.accountId ?? void 0,
299
+ silent: ctx.silent ?? void 0,
300
+ cfg: ctx.cfg,
301
+ ...sendContext.formatting
302
+ }));
303
+ }
304
+ }));
305
+ }
306
+ //#endregion
307
+ //#region extensions/discord/src/outbound-adapter.ts
308
+ const DISCORD_TEXT_CHUNK_LIMIT = 2e3;
309
+ const DISCORD_INTERNAL_RUNTIME_SCAFFOLDING_BLOCK_RE = /<\s*(system-reminder|previous_response)\b[^>]*>[\s\S]*?<\s*\/\s*\1\s*>/gi;
310
+ const DISCORD_INTERNAL_RUNTIME_SCAFFOLDING_SELF_CLOSING_RE = /<\s*(?:system-reminder|previous_response)\b[^>]*\/\s*>/gi;
311
+ const DISCORD_INTERNAL_RUNTIME_SCAFFOLDING_TAG_RE = /<\s*\/?\s*(?:system-reminder|previous_response)\b[^>]*>/gi;
312
+ function stripDiscordInternalRuntimeScaffolding(text) {
313
+ return text.replace(DISCORD_INTERNAL_RUNTIME_SCAFFOLDING_BLOCK_RE, "").replace(DISCORD_INTERNAL_RUNTIME_SCAFFOLDING_SELF_CLOSING_RE, "").replace(DISCORD_INTERNAL_RUNTIME_SCAFFOLDING_TAG_RE, "");
314
+ }
315
+ let discordThreadBindingsPromise;
316
+ function loadDiscordThreadBindings() {
317
+ discordThreadBindingsPromise ??= import("./thread-bindings-9aKRmZv0.js").then((n) => n.t);
318
+ return discordThreadBindingsPromise;
319
+ }
320
+ function resolveDiscordWebhookIdentity(params) {
321
+ const usernameRaw = normalizeOptionalString(params.identity?.name);
322
+ const fallbackUsername = normalizeOptionalString(params.binding.label) ?? params.binding.agentId;
323
+ return {
324
+ username: (usernameRaw || fallbackUsername || "").slice(0, 80) || void 0,
325
+ avatarUrl: normalizeOptionalString(params.identity?.avatarUrl)
326
+ };
327
+ }
328
+ async function maybeSendDiscordWebhookText(params) {
329
+ if (params.threadId == null) return null;
330
+ const threadId = normalizeOptionalStringifiedId(params.threadId) ?? "";
331
+ if (!threadId) return null;
332
+ const { getThreadBindingManager } = await loadDiscordThreadBindings();
333
+ const manager = getThreadBindingManager(params.accountId ?? void 0);
334
+ if (!manager) return null;
335
+ const binding = manager.getByThreadId(threadId);
336
+ if (!binding?.webhookId || !binding?.webhookToken) return null;
337
+ const persona = resolveDiscordWebhookIdentity({
338
+ identity: params.identity,
339
+ binding
340
+ });
341
+ const { sendWebhookMessageDiscord } = await loadDiscordSendRuntime();
342
+ return await sendWebhookMessageDiscord(params.text, {
343
+ webhookId: binding.webhookId,
344
+ webhookToken: binding.webhookToken,
345
+ accountId: binding.accountId,
346
+ threadId: binding.threadId,
347
+ cfg: params.cfg,
348
+ replyTo: params.replyToId ?? void 0,
349
+ username: persona.username,
350
+ avatarUrl: persona.avatarUrl
351
+ });
352
+ }
353
+ const discordOutbound = {
354
+ deliveryMode: "direct",
355
+ chunker: (text, limit, ctx) => chunkDiscordTextWithMode(text, {
356
+ maxChars: limit,
357
+ maxLines: ctx?.formatting?.maxLinesPerMessage
358
+ }),
359
+ textChunkLimit: DISCORD_TEXT_CHUNK_LIMIT,
360
+ sanitizeText: ({ text }) => stripDiscordInternalRuntimeScaffolding(text),
361
+ pollMaxOptions: 10,
362
+ normalizePayload: ({ payload }) => normalizeDiscordApprovalPayload(payload),
363
+ presentationCapabilities: {
364
+ supported: true,
365
+ buttons: true,
366
+ selects: true,
367
+ context: true,
368
+ divider: true,
369
+ limits: {
370
+ actions: {
371
+ maxActions: 25,
372
+ maxActionsPerRow: 5,
373
+ maxRows: 5,
374
+ maxLabelLength: 80
375
+ },
376
+ selects: {
377
+ maxOptions: 25,
378
+ maxLabelLength: 100,
379
+ maxValueBytes: 100
380
+ },
381
+ text: {
382
+ maxLength: DISCORD_TEXT_CHUNK_LIMIT,
383
+ encoding: "characters",
384
+ markdownDialect: "discord-markdown"
385
+ }
386
+ }
387
+ },
388
+ deliveryCapabilities: { durableFinal: {
389
+ text: true,
390
+ media: true,
391
+ payload: true,
392
+ silent: true,
393
+ replyTo: true,
394
+ thread: true,
395
+ messageSendingHooks: true
396
+ } },
397
+ renderPresentation: async ({ payload, presentation }) => {
398
+ return await buildDiscordPresentationPayload({
399
+ payload,
400
+ presentation
401
+ });
402
+ },
403
+ resolveTarget: ({ to, allowFrom }) => normalizeDiscordOutboundTarget(to, allowFrom),
404
+ sendPayload: async (ctx) => await sendDiscordOutboundPayload({
405
+ ctx,
406
+ fallbackAdapter: discordOutbound
407
+ }),
408
+ ...createAttachedChannelResultAdapter({
409
+ channel: "discord",
410
+ sendText: async ({ cfg, to, text, accountId, deps, replyToId, threadId, identity, silent, formatting }) => {
411
+ if (!silent) {
412
+ const webhookResult = await maybeSendDiscordWebhookText({
413
+ cfg,
414
+ text,
415
+ threadId,
416
+ accountId,
417
+ identity,
418
+ replyToId
419
+ }).catch(() => null);
420
+ if (webhookResult) return webhookResult;
421
+ }
422
+ const send = resolveOutboundSendDep(deps, "discord") ?? (await loadDiscordSendRuntime()).sendMessageDiscord;
423
+ return await withDiscordDeliveryRetry({
424
+ cfg,
425
+ accountId,
426
+ fn: async () => await send(resolveDiscordOutboundTarget({
427
+ to,
428
+ threadId
429
+ }), text, {
430
+ verbose: false,
431
+ replyTo: replyToId ?? void 0,
432
+ accountId: accountId ?? void 0,
433
+ silent: silent ?? void 0,
434
+ cfg,
435
+ ...resolveDiscordFormattingOptions({ formatting })
436
+ })
437
+ });
438
+ },
439
+ sendMedia: async ({ cfg, to, text, mediaUrl, audioAsVoice, mediaAccess, mediaLocalRoots, mediaReadFile, accountId, deps, replyToId, threadId, silent, formatting }) => {
440
+ const send = resolveOutboundSendDep(deps, "discord") ?? (await loadDiscordSendRuntime()).sendMessageDiscord;
441
+ const target = resolveDiscordOutboundTarget({
442
+ to,
443
+ threadId
444
+ });
445
+ const formattingOptions = resolveDiscordFormattingOptions({ formatting });
446
+ if (audioAsVoice && mediaUrl) {
447
+ const sendVoice = resolveOutboundSendDep(deps, "discordVoice") ?? (await loadDiscordSendRuntime()).sendVoiceMessageDiscord;
448
+ return await withDiscordDeliveryRetry({
449
+ cfg,
450
+ accountId,
451
+ fn: async () => await sendVoice(target, mediaUrl, {
452
+ cfg,
453
+ replyTo: replyToId ?? void 0,
454
+ accountId: accountId ?? void 0,
455
+ silent: silent ?? void 0
456
+ })
457
+ });
458
+ }
459
+ if (text.trim() && mediaUrl && isLikelyDiscordVideoMedia(mediaUrl)) {
460
+ await withDiscordDeliveryRetry({
461
+ cfg,
462
+ accountId,
463
+ fn: async () => await send(target, text, {
464
+ verbose: false,
465
+ replyTo: replyToId ?? void 0,
466
+ accountId: accountId ?? void 0,
467
+ silent: silent ?? void 0,
468
+ cfg,
469
+ ...formattingOptions
470
+ })
471
+ });
472
+ return await withDiscordDeliveryRetry({
473
+ cfg,
474
+ accountId,
475
+ fn: async () => await send(target, "", {
476
+ verbose: false,
477
+ mediaUrl,
478
+ mediaAccess,
479
+ mediaLocalRoots,
480
+ mediaReadFile,
481
+ accountId: accountId ?? void 0,
482
+ silent: silent ?? void 0,
483
+ cfg,
484
+ ...formattingOptions
485
+ })
486
+ });
487
+ }
488
+ return await withDiscordDeliveryRetry({
489
+ cfg,
490
+ accountId,
491
+ fn: async () => await send(target, text, {
492
+ verbose: false,
493
+ mediaUrl,
494
+ mediaAccess,
495
+ mediaLocalRoots,
496
+ mediaReadFile,
497
+ replyTo: replyToId ?? void 0,
498
+ accountId: accountId ?? void 0,
499
+ silent: silent ?? void 0,
500
+ cfg,
501
+ ...formattingOptions
502
+ })
503
+ });
504
+ },
505
+ sendPoll: async ({ cfg, to, poll, accountId, threadId, silent }) => await withDiscordDeliveryRetry({
506
+ cfg,
507
+ accountId,
508
+ fn: async () => await (await loadDiscordSendRuntime()).sendPollDiscord(resolveDiscordOutboundTarget({
509
+ to,
510
+ threadId
511
+ }), poll, {
512
+ accountId: accountId ?? void 0,
513
+ silent: silent ?? void 0,
514
+ cfg
515
+ })
516
+ })
517
+ }),
518
+ afterDeliverPayload: async ({ target, payload }) => {
519
+ notifyDiscordInboundEventOutboundPayloadSuccess({
520
+ payload,
521
+ to: resolveDiscordOutboundTarget({
522
+ to: target.to,
523
+ threadId: target.threadId
524
+ }),
525
+ accountId: target.accountId
526
+ });
527
+ const threadId = normalizeOptionalStringifiedId(target.threadId);
528
+ if (!threadId) return;
529
+ const { getThreadBindingManager } = await loadDiscordThreadBindings();
530
+ const manager = getThreadBindingManager(target.accountId ?? void 0);
531
+ if (!manager?.getByThreadId(threadId)) return;
532
+ manager.touchThread({ threadId });
533
+ }
534
+ };
535
+ //#endregion
536
+ export { discordOutbound as n, DISCORD_TEXT_CHUNK_LIMIT as t };
@@ -0,0 +1,22 @@
1
+ import { Wt as __exportAll } from "./send.receipt-CDn3GBWC.js";
2
+ import { resolveFetch } from "klaw/plugin-sdk/fetch-runtime";
3
+ //#region extensions/discord/src/pluralkit.ts
4
+ var pluralkit_exports = /* @__PURE__ */ __exportAll({ fetchPluralKitMessageInfo: () => fetchPluralKitMessageInfo });
5
+ const PLURALKIT_API_BASE = "https://api.pluralkit.me/v2";
6
+ async function fetchPluralKitMessageInfo(params) {
7
+ if (!params.config?.enabled) return null;
8
+ const fetchImpl = resolveFetch(params.fetcher);
9
+ if (!fetchImpl) return null;
10
+ const headers = {};
11
+ if (params.config.token?.trim()) headers.Authorization = params.config.token.trim();
12
+ const res = await fetchImpl(`${PLURALKIT_API_BASE}/messages/${params.messageId}`, { headers });
13
+ if (res.status === 404) return null;
14
+ if (!res.ok) {
15
+ const text = await res.text().catch(() => "");
16
+ const detail = text.trim() ? `: ${text.trim()}` : "";
17
+ throw new Error(`PluralKit API failed (${res.status})${detail}`);
18
+ }
19
+ return await res.json();
20
+ }
21
+ //#endregion
22
+ export { pluralkit_exports as n, fetchPluralKitMessageInfo as t };
@@ -0,0 +1,72 @@
1
+ import { normalizeOptionalString } from "klaw/plugin-sdk/string-coerce-runtime";
2
+ import { logVerbose } from "klaw/plugin-sdk/runtime-env";
3
+ import { getFileExtension } from "klaw/plugin-sdk/media-mime";
4
+ //#region extensions/discord/src/monitor/preflight-audio.ts
5
+ let discordPreflightAudioRuntimePromise;
6
+ function loadDiscordPreflightAudioRuntime() {
7
+ discordPreflightAudioRuntimePromise ??= import("./preflight-audio.runtime-Brx_0_xW.js");
8
+ return discordPreflightAudioRuntimePromise;
9
+ }
10
+ const AUDIO_ATTACHMENT_MIME_BY_EXT = new Map([
11
+ [".aac", "audio/aac"],
12
+ [".caf", "audio/x-caf"],
13
+ [".flac", "audio/flac"],
14
+ [".m4a", "audio/mp4"],
15
+ [".mp3", "audio/mpeg"],
16
+ [".oga", "audio/ogg"],
17
+ [".ogg", "audio/ogg"],
18
+ [".opus", "audio/opus"],
19
+ [".wav", "audio/wav"]
20
+ ]);
21
+ function inferAudioAttachmentMime(attachment) {
22
+ const contentType = normalizeOptionalString(attachment.content_type);
23
+ if (contentType?.startsWith("audio/")) return contentType;
24
+ if (typeof attachment.duration_secs === "number" || typeof normalizeOptionalString(attachment.waveform) === "string") return "audio/ogg";
25
+ const ext = getFileExtension(attachment.filename ?? attachment.url);
26
+ return ext ? AUDIO_ATTACHMENT_MIME_BY_EXT.get(ext) : void 0;
27
+ }
28
+ function collectAudioAttachments(attachments) {
29
+ if (!Array.isArray(attachments)) return [];
30
+ return attachments.filter((att) => normalizeOptionalString(att.url) && inferAudioAttachmentMime(att));
31
+ }
32
+ async function resolveDiscordPreflightAudioMentionContext(params) {
33
+ const audioAttachments = collectAudioAttachments(params.message.attachments);
34
+ const hasAudioAttachment = audioAttachments.length > 0;
35
+ const hasTypedText = Boolean(params.message.content?.trim());
36
+ const needsPreflightTranscription = hasAudioAttachment && !hasTypedText && (params.isDirectMessage || params.shouldRequireMention && params.mentionRegexes.length > 0);
37
+ let transcript;
38
+ if (needsPreflightTranscription) {
39
+ if (params.abortSignal?.aborted) return {
40
+ hasAudioAttachment,
41
+ hasTypedText
42
+ };
43
+ try {
44
+ const { transcribeFirstAudio } = await loadDiscordPreflightAudioRuntime();
45
+ if (params.abortSignal?.aborted) return {
46
+ hasAudioAttachment,
47
+ hasTypedText
48
+ };
49
+ const audioUrls = audioAttachments.map((att) => att.url).map((url) => normalizeOptionalString(url)).filter((url) => Boolean(url));
50
+ if (audioUrls.length > 0) {
51
+ transcript = await transcribeFirstAudio({
52
+ ctx: {
53
+ MediaUrls: audioUrls,
54
+ MediaTypes: audioAttachments.map((att) => inferAudioAttachmentMime(att)).filter((contentType) => Boolean(contentType))
55
+ },
56
+ cfg: params.cfg,
57
+ agentDir: void 0
58
+ });
59
+ if (params.abortSignal?.aborted) transcript = void 0;
60
+ }
61
+ } catch (err) {
62
+ logVerbose(`discord: audio preflight transcription failed: ${String(err)}`);
63
+ }
64
+ }
65
+ return {
66
+ hasAudioAttachment,
67
+ hasTypedText,
68
+ transcript
69
+ };
70
+ }
71
+ //#endregion
72
+ export { resolveDiscordPreflightAudioMentionContext };
@@ -0,0 +1,7 @@
1
+ import { transcribeFirstAudio as transcribeFirstAudio$1 } from "klaw/plugin-sdk/media-runtime";
2
+ //#region extensions/discord/src/monitor/preflight-audio.runtime.ts
3
+ async function transcribeFirstAudio(...args) {
4
+ return await transcribeFirstAudio$1(...args);
5
+ }
6
+ //#endregion
7
+ export { transcribeFirstAudio };
@@ -0,0 +1,8 @@
1
+ import { resolveChannelPreviewStreamMode } from "klaw/plugin-sdk/channel-streaming";
2
+ //#region extensions/discord/src/preview-streaming.ts
3
+ function resolveDiscordPreviewStreamMode(params = {}) {
4
+ if (params.streaming === void 0 && params.streamMode === void 0) return "progress";
5
+ return resolveChannelPreviewStreamMode(params, "off");
6
+ }
7
+ //#endregion
8
+ export { resolveDiscordPreviewStreamMode as t };