@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,81 @@
1
+ import { a as mergeDiscordAccountConfig, l as resolveDiscordAccountConfig, o as resolveDefaultDiscordAccountId } from "./accounts-B7OBFePq.js";
2
+ import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "klaw/plugin-sdk/account-id";
3
+ import { hasConfiguredSecretInput, normalizeSecretInputString } from "klaw/plugin-sdk/secret-input";
4
+ import { normalizeOptionalString } from "klaw/plugin-sdk/string-coerce-runtime";
5
+ //#region extensions/discord/src/account-inspect.ts
6
+ function inspectDiscordTokenValue(value) {
7
+ const normalized = normalizeSecretInputString(value);
8
+ if (normalized) return {
9
+ token: normalized.replace(/^Bot\s+/i, ""),
10
+ tokenSource: "config",
11
+ tokenStatus: "available"
12
+ };
13
+ if (hasConfiguredSecretInput(value)) return {
14
+ token: "",
15
+ tokenSource: "config",
16
+ tokenStatus: "configured_unavailable"
17
+ };
18
+ return null;
19
+ }
20
+ function inspectDiscordAccount(params) {
21
+ const accountId = normalizeAccountId(params.accountId ?? resolveDefaultDiscordAccountId(params.cfg));
22
+ const merged = mergeDiscordAccountConfig(params.cfg, accountId);
23
+ const enabled = params.cfg.channels?.discord?.enabled !== false && merged.enabled !== false;
24
+ const accountConfig = resolveDiscordAccountConfig(params.cfg, accountId);
25
+ const hasAccountToken = Boolean(accountConfig && Object.prototype.hasOwnProperty.call(accountConfig, "token"));
26
+ const accountToken = inspectDiscordTokenValue(accountConfig?.token);
27
+ if (accountToken) return {
28
+ accountId,
29
+ enabled,
30
+ name: normalizeOptionalString(merged.name),
31
+ token: accountToken.token,
32
+ tokenSource: accountToken.tokenSource,
33
+ tokenStatus: accountToken.tokenStatus,
34
+ configured: true,
35
+ config: merged
36
+ };
37
+ if (hasAccountToken) return {
38
+ accountId,
39
+ enabled,
40
+ name: normalizeOptionalString(merged.name),
41
+ token: "",
42
+ tokenSource: "none",
43
+ tokenStatus: "missing",
44
+ configured: false,
45
+ config: merged
46
+ };
47
+ const channelToken = inspectDiscordTokenValue(params.cfg.channels?.discord?.token);
48
+ if (channelToken) return {
49
+ accountId,
50
+ enabled,
51
+ name: normalizeOptionalString(merged.name),
52
+ token: channelToken.token,
53
+ tokenSource: channelToken.tokenSource,
54
+ tokenStatus: channelToken.tokenStatus,
55
+ configured: true,
56
+ config: merged
57
+ };
58
+ const envToken = accountId === DEFAULT_ACCOUNT_ID ? normalizeSecretInputString(params.envToken ?? process.env.DISCORD_BOT_TOKEN) : void 0;
59
+ if (envToken) return {
60
+ accountId,
61
+ enabled,
62
+ name: normalizeOptionalString(merged.name),
63
+ token: envToken.replace(/^Bot\s+/i, ""),
64
+ tokenSource: "env",
65
+ tokenStatus: "available",
66
+ configured: true,
67
+ config: merged
68
+ };
69
+ return {
70
+ accountId,
71
+ enabled,
72
+ name: normalizeOptionalString(merged.name),
73
+ token: "",
74
+ tokenSource: "none",
75
+ tokenStatus: "missing",
76
+ configured: false,
77
+ config: merged
78
+ };
79
+ }
80
+ //#endregion
81
+ export { inspectDiscordAccount as t };
@@ -0,0 +1,10 @@
1
+ import { t as inspectDiscordAccount } from "./account-inspect-Dqw-enky.js";
2
+ //#region extensions/discord/account-inspect-api.ts
3
+ function inspectDiscordReadOnlyAccount(cfg, accountId) {
4
+ return inspectDiscordAccount({
5
+ cfg,
6
+ accountId
7
+ });
8
+ }
9
+ //#endregion
10
+ export { inspectDiscordReadOnlyAccount };
@@ -0,0 +1,224 @@
1
+ import { normalizeAccountId } from "klaw/plugin-sdk/account-id";
2
+ import { normalizeResolvedSecretInputString, resolveSecretInputString } from "klaw/plugin-sdk/secret-input";
3
+ import { normalizeOptionalString } from "klaw/plugin-sdk/string-coerce-runtime";
4
+ import { createAccountActionGate, createAccountListHelpers, resolveMergedAccountConfig } from "klaw/plugin-sdk/account-helpers";
5
+ import { mapAllowFromEntries, normalizeChannelDmPolicy, resolveChannelDmAllowFrom, resolveChannelDmPolicy } from "klaw/plugin-sdk/channel-config-helpers";
6
+ import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1, normalizeAccountId as normalizeAccountId$1, resolveAccountEntry } from "klaw/plugin-sdk/routing";
7
+ import { getRuntimeConfigSnapshot, getRuntimeConfigSourceSnapshot, selectApplicableRuntimeConfig } from "klaw/plugin-sdk/runtime-config-snapshot";
8
+ //#region extensions/discord/src/runtime-config.ts
9
+ function selectDiscordRuntimeConfig(inputConfig) {
10
+ return selectApplicableRuntimeConfig({
11
+ inputConfig,
12
+ runtimeConfig: getRuntimeConfigSnapshot(),
13
+ runtimeSourceConfig: getRuntimeConfigSourceSnapshot()
14
+ }) ?? inputConfig;
15
+ }
16
+ //#endregion
17
+ //#region extensions/discord/src/token.ts
18
+ function stripDiscordBotPrefix(token) {
19
+ return token.replace(/^Bot\s+/i, "");
20
+ }
21
+ function normalizeDiscordToken(raw, path) {
22
+ const trimmed = normalizeResolvedSecretInputString({
23
+ value: raw,
24
+ path
25
+ });
26
+ if (!trimmed) return;
27
+ return stripDiscordBotPrefix(trimmed);
28
+ }
29
+ function resolveDiscordTokenValue(params) {
30
+ const resolved = resolveSecretInputString({
31
+ value: params.value,
32
+ path: params.path,
33
+ defaults: params.cfg.secrets?.defaults,
34
+ mode: "inspect"
35
+ });
36
+ if (resolved.status === "available") return {
37
+ status: "available",
38
+ value: stripDiscordBotPrefix(resolved.value)
39
+ };
40
+ if (resolved.status === "configured_unavailable") return { status: "configured_unavailable" };
41
+ return { status: "missing" };
42
+ }
43
+ function resolveDiscordToken(cfg, opts = {}) {
44
+ const selectedCfg = selectDiscordRuntimeConfig(cfg);
45
+ const accountId = normalizeAccountId$1(opts.accountId);
46
+ const discordCfg = selectedCfg?.channels?.discord;
47
+ const accountCfg = resolveAccountEntry(discordCfg?.accounts, accountId);
48
+ const hasAccountToken = Boolean(accountCfg && Object.prototype.hasOwnProperty.call(accountCfg, "token"));
49
+ const accountToken = resolveDiscordTokenValue({
50
+ cfg: selectedCfg,
51
+ value: accountCfg?.token,
52
+ path: `channels.discord.accounts.${accountId}.token`
53
+ });
54
+ if (accountToken.status === "available" && accountToken.value) return {
55
+ token: accountToken.value,
56
+ source: "config",
57
+ tokenStatus: "available"
58
+ };
59
+ if (accountToken.status === "configured_unavailable") return {
60
+ token: "",
61
+ source: "config",
62
+ tokenStatus: "configured_unavailable"
63
+ };
64
+ if (hasAccountToken) return {
65
+ token: "",
66
+ source: "none",
67
+ tokenStatus: "missing"
68
+ };
69
+ const configToken = resolveDiscordTokenValue({
70
+ cfg: selectedCfg,
71
+ value: discordCfg?.token,
72
+ path: "channels.discord.token"
73
+ });
74
+ if (configToken.status === "available" && configToken.value) return {
75
+ token: configToken.value,
76
+ source: "config",
77
+ tokenStatus: "available"
78
+ };
79
+ if (configToken.status === "configured_unavailable") return {
80
+ token: "",
81
+ source: "config",
82
+ tokenStatus: "configured_unavailable"
83
+ };
84
+ const envToken = accountId === DEFAULT_ACCOUNT_ID$1 ? normalizeDiscordToken(opts.envToken ?? process.env.DISCORD_BOT_TOKEN, "DISCORD_BOT_TOKEN") : void 0;
85
+ if (envToken) return {
86
+ token: envToken,
87
+ source: "env",
88
+ tokenStatus: "available"
89
+ };
90
+ return {
91
+ token: "",
92
+ source: "none",
93
+ tokenStatus: "missing"
94
+ };
95
+ }
96
+ //#endregion
97
+ //#region extensions/discord/src/accounts.ts
98
+ const { listAccountIds, resolveDefaultAccountId } = createAccountListHelpers("discord", { implicitDefaultAccount: {
99
+ channelKeys: ["token"],
100
+ envVars: ["DISCORD_BOT_TOKEN"]
101
+ } });
102
+ const listDiscordAccountIds = listAccountIds;
103
+ const resolveDefaultDiscordAccountId = resolveDefaultAccountId;
104
+ function resolveDiscordAccountConfig(cfg, accountId) {
105
+ return resolveAccountEntry(cfg.channels?.discord?.accounts, accountId);
106
+ }
107
+ function mergeDiscordAccountConfig(cfg, accountId) {
108
+ return resolveMergedAccountConfig({
109
+ channelConfig: cfg.channels?.discord,
110
+ accounts: cfg.channels?.discord?.accounts,
111
+ accountId,
112
+ nestedObjectKeys: ["botLoopProtection"]
113
+ });
114
+ }
115
+ function resolveDiscordAccountAllowFrom(params) {
116
+ const accountId = normalizeAccountId(params.accountId ?? resolveDefaultDiscordAccountId(params.cfg));
117
+ const accountConfig = resolveDiscordAccountConfig(params.cfg, accountId);
118
+ const rootConfig = params.cfg.channels?.discord;
119
+ const allowFrom = resolveChannelDmAllowFrom({
120
+ account: accountConfig,
121
+ parent: rootConfig
122
+ });
123
+ return allowFrom ? mapAllowFromEntries(allowFrom) : void 0;
124
+ }
125
+ function resolveDiscordAccountDmPolicy(params) {
126
+ const accountId = normalizeAccountId(params.accountId ?? resolveDefaultDiscordAccountId(params.cfg));
127
+ const accountConfig = resolveDiscordAccountConfig(params.cfg, accountId);
128
+ const rootConfig = params.cfg.channels?.discord;
129
+ return normalizeChannelDmPolicy(resolveChannelDmPolicy({
130
+ account: accountConfig,
131
+ parent: rootConfig,
132
+ defaultPolicy: "pairing"
133
+ }));
134
+ }
135
+ function createDiscordActionGate(params) {
136
+ const accountId = normalizeAccountId(params.accountId ?? resolveDefaultDiscordAccountId(params.cfg));
137
+ return createAccountActionGate({
138
+ baseActions: params.cfg.channels?.discord?.actions,
139
+ accountActions: resolveDiscordAccountConfig(params.cfg, accountId)?.actions
140
+ });
141
+ }
142
+ function resolveDiscordAccount(params) {
143
+ const cfg = selectDiscordRuntimeConfig(params.cfg);
144
+ const accountId = normalizeAccountId(params.accountId ?? resolveDefaultDiscordAccountId(cfg));
145
+ const baseEnabled = cfg.channels?.discord?.enabled !== false;
146
+ const merged = mergeDiscordAccountConfig(cfg, accountId);
147
+ const accountEnabled = merged.enabled !== false;
148
+ const enabled = baseEnabled && accountEnabled;
149
+ const tokenResolution = resolveDiscordToken(cfg, { accountId });
150
+ return {
151
+ accountId,
152
+ enabled,
153
+ name: normalizeOptionalString(merged.name),
154
+ token: tokenResolution.token,
155
+ tokenSource: tokenResolution.source,
156
+ tokenStatus: tokenResolution.tokenStatus,
157
+ config: merged
158
+ };
159
+ }
160
+ function resolveDiscordMaxLinesPerMessage(params) {
161
+ if (typeof params.discordConfig?.maxLinesPerMessage === "number") return params.discordConfig.maxLinesPerMessage;
162
+ return resolveDiscordAccount({
163
+ cfg: params.cfg,
164
+ accountId: params.accountId
165
+ }).config.maxLinesPerMessage;
166
+ }
167
+ function resolveDiscordAccountTokenOwner(params) {
168
+ const token = params.token.trim();
169
+ if (!token) return;
170
+ let owner;
171
+ const accountIds = listDiscordAccountIds(params.cfg);
172
+ for (const [index, accountId] of accountIds.entries()) {
173
+ const account = resolveDiscordAccount({
174
+ cfg: params.cfg,
175
+ accountId
176
+ });
177
+ const accountToken = account.token.trim();
178
+ if (!account.enabled || accountToken !== token) continue;
179
+ const priority = account.tokenSource === "config" ? 2 : account.tokenSource === "env" ? 1 : 0;
180
+ if (!owner || priority > owner.priority) {
181
+ owner = {
182
+ accountId: account.accountId,
183
+ priority,
184
+ index
185
+ };
186
+ continue;
187
+ }
188
+ if (priority === owner.priority && index < owner.index) owner = {
189
+ accountId: account.accountId,
190
+ priority,
191
+ index
192
+ };
193
+ }
194
+ return owner?.accountId;
195
+ }
196
+ function resolveDiscordDuplicateTokenOwner(params) {
197
+ const owner = resolveDiscordAccountTokenOwner({
198
+ cfg: params.cfg,
199
+ token: params.account.token
200
+ });
201
+ return owner && owner !== params.account.accountId ? owner : void 0;
202
+ }
203
+ function isDiscordAccountEnabledForRuntime(account, cfg) {
204
+ return account.enabled && !resolveDiscordDuplicateTokenOwner({
205
+ cfg,
206
+ account
207
+ });
208
+ }
209
+ function resolveDiscordAccountDisabledReason(account, cfg) {
210
+ if (!account.enabled) return "disabled";
211
+ const owner = resolveDiscordDuplicateTokenOwner({
212
+ cfg,
213
+ account
214
+ });
215
+ return owner ? `duplicate bot token; using account "${owner}"` : "disabled";
216
+ }
217
+ function listEnabledDiscordAccounts(cfg) {
218
+ return listDiscordAccountIds(cfg).map((accountId) => resolveDiscordAccount({
219
+ cfg,
220
+ accountId
221
+ })).filter((account) => isDiscordAccountEnabledForRuntime(account, cfg));
222
+ }
223
+ //#endregion
224
+ export { mergeDiscordAccountConfig as a, resolveDiscordAccountAllowFrom as c, resolveDiscordAccountDmPolicy as d, resolveDiscordMaxLinesPerMessage as f, listEnabledDiscordAccounts as i, resolveDiscordAccountConfig as l, resolveDiscordToken as m, isDiscordAccountEnabledForRuntime as n, resolveDefaultDiscordAccountId as o, normalizeDiscordToken as p, listDiscordAccountIds as r, resolveDiscordAccount as s, createDiscordActionGate as t, resolveDiscordAccountDisabledReason as u };
@@ -0,0 +1,2 @@
1
+ import { t as handleDiscordAction } from "./runtime-DUaw66V_.js";
2
+ export { handleDiscordAction };
@@ -0,0 +1,4 @@
1
+ import { buildPluginBindingResolvedText, parsePluginBindingApprovalCustomId, recordInboundSession, resolvePluginConversationBindingApproval } from "klaw/plugin-sdk/conversation-runtime";
2
+ import { dispatchPluginInteractiveHandler } from "klaw/plugin-sdk/plugin-runtime";
3
+ import { createReplyReferencePlanner, dispatchReplyWithBufferedBlockDispatcher, finalizeInboundContext, resolveChunkMode, resolveTextChunkLimit } from "klaw/plugin-sdk/reply-runtime";
4
+ export { buildPluginBindingResolvedText, createReplyReferencePlanner, dispatchPluginInteractiveHandler, dispatchReplyWithBufferedBlockDispatcher, finalizeInboundContext, parsePluginBindingApprovalCustomId, recordInboundSession, resolveChunkMode, resolvePluginConversationBindingApproval, resolveTextChunkLimit };
@@ -0,0 +1,354 @@
1
+ import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "klaw/plugin-sdk/string-coerce-runtime";
2
+ import { buildChannelKeyCandidates, resolveChannelEntryMatchWithFallback, resolveChannelMatchConfig } from "klaw/plugin-sdk/channel-targets";
3
+ //#region extensions/discord/src/monitor/format.ts
4
+ function resolveDiscordSystemLocation(params) {
5
+ const { isDirectMessage, isGroupDm, guild, channelName } = params;
6
+ if (isDirectMessage) return "DM";
7
+ if (isGroupDm) return `Group DM #${channelName}`;
8
+ return guild?.name ? `${guild.name} #${channelName}` : `#${channelName}`;
9
+ }
10
+ function formatDiscordReactionEmoji(emoji) {
11
+ if (emoji.id && emoji.name) return `<:${emoji.name}:${emoji.id}>`;
12
+ if (emoji.id) return `emoji:${emoji.id}`;
13
+ return emoji.name ?? "emoji";
14
+ }
15
+ function formatDiscordUserTag(user) {
16
+ const discriminator = (user.discriminator ?? "").trim();
17
+ if (discriminator && discriminator !== "0") return `${user.username}#${discriminator}`;
18
+ return user.username ?? user.id;
19
+ }
20
+ function resolveTimestampMs(timestamp) {
21
+ if (!timestamp) return;
22
+ const parsed = Date.parse(timestamp);
23
+ return Number.isNaN(parsed) ? void 0 : parsed;
24
+ }
25
+ //#endregion
26
+ //#region extensions/discord/src/monitor/allow-list.ts
27
+ const DISCORD_OWNER_ALLOWLIST_PREFIXES = [
28
+ "discord:",
29
+ "user:",
30
+ "pk:"
31
+ ];
32
+ function normalizeDiscordAllowList(raw, prefixes) {
33
+ if (!raw || raw.length === 0) return null;
34
+ const ids = /* @__PURE__ */ new Set();
35
+ const names = /* @__PURE__ */ new Set();
36
+ const allowAll = raw.some((entry) => (normalizeOptionalString(entry) ?? "") === "*");
37
+ for (const entry of raw) {
38
+ const text = normalizeOptionalString(entry) ?? "";
39
+ if (!text || text === "*") continue;
40
+ const normalized = normalizeDiscordSlug(text);
41
+ const maybeId = text.replace(/^<@!?/, "").replace(/>$/, "");
42
+ if (/^\d+$/.test(maybeId)) {
43
+ ids.add(maybeId);
44
+ continue;
45
+ }
46
+ const prefix = prefixes.find((entry) => text.startsWith(entry));
47
+ if (prefix) {
48
+ const candidate = text.slice(prefix.length);
49
+ if (candidate) ids.add(candidate);
50
+ continue;
51
+ }
52
+ if (normalized) names.add(normalized);
53
+ }
54
+ return {
55
+ allowAll,
56
+ ids,
57
+ names
58
+ };
59
+ }
60
+ function normalizeDiscordSlug(value) {
61
+ return normalizeLowercaseStringOrEmpty(value).replace(/^#/, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
62
+ }
63
+ function normalizeDiscordDisplaySlug(value) {
64
+ return normalizeLowercaseStringOrEmpty(value).normalize("NFC").replace(/^#/, "").replace(/[\s_]+/g, "-").replace(/[^\p{L}\p{M}\p{N}-]+/gu, "-").replace(/-{2,}/g, "-").replace(/^-+|-+$/g, "");
65
+ }
66
+ function resolveDiscordAllowListNameMatch(list, candidate) {
67
+ const nameSlug = candidate.name ? normalizeDiscordSlug(candidate.name) : "";
68
+ if (nameSlug && list.names.has(nameSlug)) return {
69
+ matchKey: nameSlug,
70
+ matchSource: "name"
71
+ };
72
+ const tagSlug = candidate.tag ? normalizeDiscordSlug(candidate.tag) : "";
73
+ if (tagSlug && list.names.has(tagSlug)) return {
74
+ matchKey: tagSlug,
75
+ matchSource: "tag"
76
+ };
77
+ return null;
78
+ }
79
+ function allowListMatches(list, candidate, params) {
80
+ if (list.allowAll) return true;
81
+ if (candidate.id && list.ids.has(candidate.id)) return true;
82
+ if (params?.allowNameMatching === true) {
83
+ if (resolveDiscordAllowListNameMatch(list, candidate)) return true;
84
+ }
85
+ return false;
86
+ }
87
+ function resolveDiscordAllowListMatch(params) {
88
+ const { allowList, candidate } = params;
89
+ if (allowList.allowAll) return {
90
+ allowed: true,
91
+ matchKey: "*",
92
+ matchSource: "wildcard"
93
+ };
94
+ if (candidate.id && allowList.ids.has(candidate.id)) return {
95
+ allowed: true,
96
+ matchKey: candidate.id,
97
+ matchSource: "id"
98
+ };
99
+ if (params.allowNameMatching === true) {
100
+ const namedMatch = resolveDiscordAllowListNameMatch(allowList, candidate);
101
+ if (namedMatch) return {
102
+ allowed: true,
103
+ ...namedMatch
104
+ };
105
+ }
106
+ return { allowed: false };
107
+ }
108
+ function resolveDiscordUserAllowed(params) {
109
+ const allowList = normalizeDiscordAllowList(params.allowList, [
110
+ "discord:",
111
+ "user:",
112
+ "pk:"
113
+ ]);
114
+ if (!allowList) return true;
115
+ return allowListMatches(allowList, {
116
+ id: params.userId,
117
+ name: params.userName,
118
+ tag: params.userTag
119
+ }, { allowNameMatching: params.allowNameMatching });
120
+ }
121
+ function resolveDiscordRoleAllowed(params) {
122
+ const allowList = normalizeDiscordAllowList(params.allowList, ["role:"]);
123
+ if (!allowList) return true;
124
+ if (allowList.allowAll) return true;
125
+ return params.memberRoleIds.some((roleId) => allowList.ids.has(roleId));
126
+ }
127
+ function resolveDiscordMemberAllowed(params) {
128
+ const hasUserRestriction = Array.isArray(params.userAllowList) && params.userAllowList.length > 0;
129
+ const hasRoleRestriction = Array.isArray(params.roleAllowList) && params.roleAllowList.length > 0;
130
+ if (!hasUserRestriction && !hasRoleRestriction) return true;
131
+ const userOk = hasUserRestriction ? resolveDiscordUserAllowed({
132
+ allowList: params.userAllowList,
133
+ userId: params.userId,
134
+ userName: params.userName,
135
+ userTag: params.userTag,
136
+ allowNameMatching: params.allowNameMatching
137
+ }) : false;
138
+ const roleOk = hasRoleRestriction ? resolveDiscordRoleAllowed({
139
+ allowList: params.roleAllowList,
140
+ memberRoleIds: params.memberRoleIds
141
+ }) : false;
142
+ return userOk || roleOk;
143
+ }
144
+ function resolveDiscordMemberAccessState(params) {
145
+ const channelUsers = params.channelConfig?.users ?? params.guildInfo?.users;
146
+ const channelRoles = params.channelConfig?.roles ?? params.guildInfo?.roles;
147
+ return {
148
+ channelUsers,
149
+ channelRoles,
150
+ hasAccessRestrictions: Array.isArray(channelUsers) && channelUsers.length > 0 || Array.isArray(channelRoles) && channelRoles.length > 0,
151
+ memberAllowed: resolveDiscordMemberAllowed({
152
+ userAllowList: channelUsers,
153
+ roleAllowList: channelRoles,
154
+ memberRoleIds: params.memberRoleIds,
155
+ userId: params.sender.id,
156
+ userName: params.sender.name,
157
+ userTag: params.sender.tag,
158
+ allowNameMatching: params.allowNameMatching
159
+ })
160
+ };
161
+ }
162
+ function resolveDiscordOwnerAllowFrom(params) {
163
+ const rawAllowList = params.channelConfig?.users ?? params.guildInfo?.users;
164
+ if (!Array.isArray(rawAllowList) || rawAllowList.length === 0) return;
165
+ const allowList = normalizeDiscordAllowList(rawAllowList, [
166
+ "discord:",
167
+ "user:",
168
+ "pk:"
169
+ ]);
170
+ if (!allowList) return;
171
+ const match = resolveDiscordAllowListMatch({
172
+ allowList,
173
+ candidate: {
174
+ id: params.sender.id,
175
+ name: params.sender.name,
176
+ tag: params.sender.tag
177
+ },
178
+ allowNameMatching: params.allowNameMatching
179
+ });
180
+ if (!match.allowed || !match.matchKey || match.matchKey === "*") return;
181
+ return [match.matchKey];
182
+ }
183
+ function resolveDiscordOwnerAccess(params) {
184
+ const ownerAllowFrom = params.allowFrom?.filter((entry) => (normalizeOptionalString(entry) ?? "") !== "*");
185
+ const ownerAllowList = normalizeDiscordAllowList(ownerAllowFrom && ownerAllowFrom.length > 0 ? ownerAllowFrom : void 0, DISCORD_OWNER_ALLOWLIST_PREFIXES);
186
+ return {
187
+ ownerAllowList,
188
+ ownerAllowed: ownerAllowList ? allowListMatches(ownerAllowList, {
189
+ id: params.sender.id,
190
+ name: params.sender.name,
191
+ tag: params.sender.tag
192
+ }, { allowNameMatching: params.allowNameMatching }) : false
193
+ };
194
+ }
195
+ function resolveDiscordCommandAuthorized(params) {
196
+ if (!params.isDirectMessage) return true;
197
+ const allowList = normalizeDiscordAllowList(params.allowFrom, [
198
+ "discord:",
199
+ "user:",
200
+ "pk:"
201
+ ]);
202
+ if (!allowList) return true;
203
+ return allowListMatches(allowList, {
204
+ id: params.author.id,
205
+ name: params.author.username,
206
+ tag: formatDiscordUserTag(params.author)
207
+ }, { allowNameMatching: params.allowNameMatching });
208
+ }
209
+ function resolveDiscordGuildEntry(params) {
210
+ const guild = params.guild;
211
+ const entries = params.guildEntries;
212
+ const guildId = params.guildId?.trim() || guild?.id;
213
+ if (!entries) return null;
214
+ const byId = guildId ? entries[guildId] : void 0;
215
+ if (byId) return {
216
+ ...byId,
217
+ id: guildId
218
+ };
219
+ if (!guild) return null;
220
+ const slug = normalizeDiscordSlug(guild.name ?? "");
221
+ const bySlug = entries[slug];
222
+ if (bySlug) return {
223
+ ...bySlug,
224
+ id: guildId ?? guild.id,
225
+ slug: slug || bySlug.slug
226
+ };
227
+ const wildcard = entries["*"];
228
+ if (wildcard) return {
229
+ ...wildcard,
230
+ id: guildId ?? guild.id,
231
+ slug: slug || wildcard.slug
232
+ };
233
+ return null;
234
+ }
235
+ function buildDiscordChannelKeys(params) {
236
+ const allowNameMatch = params.allowNameMatch !== false;
237
+ return buildChannelKeyCandidates(params.id, allowNameMatch ? params.slug : void 0, allowNameMatch ? params.name : void 0);
238
+ }
239
+ function resolveDiscordChannelEntryMatch(channels, params, parentParams) {
240
+ return resolveChannelEntryMatchWithFallback({
241
+ entries: channels,
242
+ keys: buildDiscordChannelKeys(params),
243
+ parentKeys: parentParams ? buildDiscordChannelKeys(parentParams) : void 0,
244
+ wildcardKey: "*"
245
+ });
246
+ }
247
+ function hasConfiguredDiscordChannels(channels) {
248
+ return Boolean(channels && Object.keys(channels).length > 0);
249
+ }
250
+ function resolveDiscordChannelConfigEntry(entry) {
251
+ return {
252
+ allowed: entry.enabled !== false,
253
+ requireMention: entry.requireMention,
254
+ ignoreOtherMentions: entry.ignoreOtherMentions,
255
+ skills: entry.skills,
256
+ enabled: entry.enabled,
257
+ users: entry.users,
258
+ roles: entry.roles,
259
+ systemPrompt: entry.systemPrompt,
260
+ includeThreadStarter: entry.includeThreadStarter,
261
+ autoThread: entry.autoThread,
262
+ autoThreadName: entry.autoThreadName,
263
+ autoArchiveDuration: entry.autoArchiveDuration
264
+ };
265
+ }
266
+ function resolveDiscordChannelConfig(params) {
267
+ const { guildInfo, channelId, channelName, channelSlug } = params;
268
+ const channels = guildInfo?.channels;
269
+ if (!hasConfiguredDiscordChannels(channels)) return null;
270
+ return resolveChannelMatchConfig(resolveDiscordChannelEntryMatch(channels, {
271
+ id: channelId,
272
+ name: channelName,
273
+ slug: channelSlug
274
+ }), resolveDiscordChannelConfigEntry) ?? { allowed: false };
275
+ }
276
+ function resolveDiscordChannelConfigWithFallback(params) {
277
+ const { guildInfo, channelId, channelName, channelSlug, parentId, parentName, parentSlug, scope } = params;
278
+ const channels = guildInfo?.channels;
279
+ if (!hasConfiguredDiscordChannels(channels)) return null;
280
+ const resolvedParentSlug = parentSlug ?? (parentName ? normalizeDiscordSlug(parentName) : "");
281
+ return resolveChannelMatchConfig(resolveDiscordChannelEntryMatch(channels, {
282
+ id: channelId,
283
+ name: channelName,
284
+ slug: channelSlug,
285
+ allowNameMatch: scope !== "thread"
286
+ }, parentId || parentName || parentSlug ? {
287
+ id: parentId ?? "",
288
+ name: parentName,
289
+ slug: resolvedParentSlug
290
+ } : void 0), resolveDiscordChannelConfigEntry) ?? { allowed: false };
291
+ }
292
+ function resolveDiscordShouldRequireMention(params) {
293
+ if (!params.isGuildMessage) return false;
294
+ if (params.isAutoThreadOwnedByBot ?? isDiscordAutoThreadOwnedByBot(params)) return false;
295
+ return params.channelConfig?.requireMention ?? params.guildInfo?.requireMention ?? true;
296
+ }
297
+ function isDiscordAutoThreadOwnedByBot(params) {
298
+ if (!params.isThread) return false;
299
+ if (!params.channelConfig?.autoThread) return false;
300
+ const botId = params.botId?.trim();
301
+ const threadOwnerId = params.threadOwnerId?.trim();
302
+ return Boolean(botId && threadOwnerId && botId === threadOwnerId);
303
+ }
304
+ function isDiscordGroupAllowedByPolicy(params) {
305
+ if (params.groupPolicy === "allowlist" && !params.guildAllowlisted) return false;
306
+ if (params.groupPolicy === "disabled") return false;
307
+ return params.groupPolicy !== "allowlist" || !params.channelAllowlistConfigured || params.channelAllowed;
308
+ }
309
+ function resolveDiscordChannelPolicyCommandAuthorizer(params) {
310
+ const channelAllowlistConfigured = Boolean(params.guildInfo?.channels) && Object.keys(params.guildInfo?.channels ?? {}).length > 0;
311
+ return {
312
+ configured: params.groupPolicy === "allowlist" && (Boolean(params.guildInfo) || channelAllowlistConfigured),
313
+ allowed: isDiscordGroupAllowedByPolicy({
314
+ groupPolicy: params.groupPolicy,
315
+ guildAllowlisted: Boolean(params.guildInfo),
316
+ channelAllowlistConfigured,
317
+ channelAllowed: params.channelConfig?.allowed !== false
318
+ })
319
+ };
320
+ }
321
+ function resolveGroupDmAllow(params) {
322
+ const { channels, channelId, channelName, channelSlug } = params;
323
+ if (!channels || channels.length === 0) return true;
324
+ const allowList = new Set(channels.map((entry) => normalizeDiscordSlug(entry)));
325
+ const candidates = [
326
+ normalizeDiscordSlug(channelId),
327
+ channelSlug,
328
+ channelName ? normalizeDiscordSlug(channelName) : ""
329
+ ].filter(Boolean);
330
+ return allowList.has("*") || candidates.some((candidate) => allowList.has(candidate));
331
+ }
332
+ function shouldEmitDiscordReactionNotification(params) {
333
+ const mode = params.mode ?? "own";
334
+ if (mode === "off") return false;
335
+ const accessGuildInfo = params.guildInfo ?? (params.allowlist ? { users: params.allowlist } : null);
336
+ const { hasAccessRestrictions, memberAllowed } = resolveDiscordMemberAccessState({
337
+ channelConfig: params.channelConfig,
338
+ guildInfo: accessGuildInfo,
339
+ memberRoleIds: params.memberRoleIds ?? [],
340
+ sender: {
341
+ id: params.userId,
342
+ name: params.userName,
343
+ tag: params.userTag
344
+ },
345
+ allowNameMatching: params.allowNameMatching
346
+ });
347
+ if (mode === "allowlist") return hasAccessRestrictions && memberAllowed;
348
+ if (hasAccessRestrictions && !memberAllowed) return false;
349
+ if (mode === "all") return true;
350
+ if (mode === "own") return Boolean(params.botId && params.messageAuthorId === params.botId);
351
+ return false;
352
+ }
353
+ //#endregion
354
+ export { resolveTimestampMs as S, resolveGroupDmAllow as _, normalizeDiscordSlug as a, formatDiscordUserTag as b, resolveDiscordChannelConfigWithFallback as c, resolveDiscordGuildEntry as d, resolveDiscordMemberAccessState as f, resolveDiscordShouldRequireMention as g, resolveDiscordOwnerAllowFrom as h, normalizeDiscordDisplaySlug as i, resolveDiscordChannelPolicyCommandAuthorizer as l, resolveDiscordOwnerAccess as m, isDiscordGroupAllowedByPolicy as n, resolveDiscordAllowListMatch as o, resolveDiscordMemberAllowed as p, normalizeDiscordAllowList as r, resolveDiscordChannelConfig as s, allowListMatches as t, resolveDiscordCommandAuthorized as u, shouldEmitDiscordReactionNotification as v, resolveDiscordSystemLocation as x, formatDiscordReactionEmoji as y };