@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,43 @@
1
+ import { b as formatDiscordUserTag } from "./allow-list-B0s7evD7.js";
2
+ import { normalizeOptionalString } from "klaw/plugin-sdk/string-coerce-runtime";
3
+ //#region extensions/discord/src/monitor/sender-identity.ts
4
+ function resolveDiscordWebhookId(message) {
5
+ const candidate = message.webhookId ?? message.webhook_id;
6
+ return typeof candidate === "string" && candidate.trim() ? candidate.trim() : null;
7
+ }
8
+ function resolveDiscordSenderIdentity(params) {
9
+ const pkInfo = params.pluralkitInfo ?? null;
10
+ const pkMember = pkInfo?.member ?? void 0;
11
+ const pkSystem = pkInfo?.system ?? void 0;
12
+ const memberId = pkMember?.id?.trim();
13
+ const memberName = (pkMember?.display_name ?? pkMember?.name ?? "")?.trim();
14
+ if (memberId && memberName) {
15
+ const systemName = pkSystem?.name?.trim();
16
+ const label = systemName ? `${memberName} (PK:${systemName})` : `${memberName} (PK)`;
17
+ return {
18
+ id: memberId,
19
+ name: memberName,
20
+ tag: normalizeOptionalString(pkMember?.name),
21
+ label,
22
+ isPluralKit: true,
23
+ pluralkit: {
24
+ memberId,
25
+ memberName,
26
+ systemId: normalizeOptionalString(pkSystem?.id),
27
+ systemName
28
+ }
29
+ };
30
+ }
31
+ const senderTag = formatDiscordUserTag(params.author);
32
+ const senderDisplay = params.member?.nickname ?? params.member?.nick ?? params.author.globalName ?? params.author.username;
33
+ const senderLabel = senderDisplay && senderTag && senderDisplay !== senderTag ? `${senderDisplay} (${senderTag})` : senderDisplay ?? senderTag ?? params.author.id;
34
+ return {
35
+ id: params.author.id,
36
+ name: params.author.username ?? void 0,
37
+ tag: senderTag,
38
+ label: senderLabel,
39
+ isPluralKit: false
40
+ };
41
+ }
42
+ //#endregion
43
+ export { resolveDiscordWebhookId as n, resolveDiscordSenderIdentity as t };
@@ -0,0 +1,6 @@
1
+ //#region extensions/discord/src/session-contract.ts
2
+ function deriveLegacySessionChatType(sessionKey) {
3
+ return /^discord:(?:[^:]+:)?guild-[^:]+:channel-[^:]+$/.test(sessionKey) ? "channel" : void 0;
4
+ }
5
+ //#endregion
6
+ export { deriveLegacySessionChatType as t };
@@ -0,0 +1,2 @@
1
+ import { t as normalizeExplicitDiscordSessionKey } from "./session-key-normalization-CP8dPUid.js";
2
+ export { normalizeExplicitDiscordSessionKey };
@@ -0,0 +1,23 @@
1
+ import { normalizeLowercaseStringOrEmpty } from "klaw/plugin-sdk/string-coerce-runtime";
2
+ //#region extensions/discord/src/session-key-normalization.ts
3
+ function normalizeDiscordChatType(raw) {
4
+ const normalized = normalizeLowercaseStringOrEmpty(raw);
5
+ if (!normalized) return;
6
+ if (normalized === "dm") return "direct";
7
+ if (normalized === "group" || normalized === "channel" || normalized === "direct") return normalized;
8
+ }
9
+ function normalizeExplicitDiscordSessionKey(sessionKey, ctx) {
10
+ let normalized = normalizeLowercaseStringOrEmpty(sessionKey);
11
+ if (normalizeDiscordChatType(ctx.ChatType) !== "direct") return normalized;
12
+ normalized = normalized.replace(/^(discord:)dm:/, "$1direct:");
13
+ normalized = normalized.replace(/^(agent:[^:]+:discord:)dm:/, "$1direct:");
14
+ const match = normalized.match(/^((?:agent:[^:]+:)?)discord:channel:([^:]+)$/);
15
+ if (!match) return normalized;
16
+ const from = normalizeLowercaseStringOrEmpty(ctx.From);
17
+ const senderId = normalizeLowercaseStringOrEmpty(ctx.SenderId);
18
+ const fromDiscordId = from.startsWith("discord:") && !from.includes(":channel:") && !from.includes(":group:") ? from.slice(8) : "";
19
+ const directId = senderId || fromDiscordId;
20
+ return directId && directId === match[2] ? `${match[1]}discord:direct:${match[2]}` : normalized;
21
+ }
22
+ //#endregion
23
+ export { normalizeExplicitDiscordSessionKey as t };
@@ -0,0 +1,11 @@
1
+ import { defineBundledChannelSetupEntry } from "klaw/plugin-sdk/channel-entry-contract";
2
+ //#region extensions/discord/setup-entry.ts
3
+ var setup_entry_default = defineBundledChannelSetupEntry({
4
+ importMetaUrl: import.meta.url,
5
+ plugin: {
6
+ specifier: "./setup-plugin-api.js",
7
+ exportName: "discordSetupPlugin"
8
+ }
9
+ });
10
+ //#endregion
11
+ export { setup_entry_default as default };
@@ -0,0 +1,2 @@
1
+ import { t as discordSetupPlugin } from "./channel.setup-BUSC0apv.js";
2
+ export { discordSetupPlugin };
@@ -0,0 +1,171 @@
1
+ import { a as mergeDiscordAccountConfig, c as resolveDiscordAccountAllowFrom, d as resolveDiscordAccountDmPolicy, n as isDiscordAccountEnabledForRuntime, o as resolveDefaultDiscordAccountId, r as listDiscordAccountIds, s as resolveDiscordAccount, u as resolveDiscordAccountDisabledReason } from "./accounts-B7OBFePq.js";
2
+ import { t as inspectDiscordAccount } from "./account-inspect-Dqw-enky.js";
3
+ import { i as getChatChannelMeta, o as resolveConfiguredFromCredentialStatuses } from "./channel-api-BfjklLby.js";
4
+ import { t as DiscordChannelConfigSchema } from "./config-schema-DIqJBGwC.js";
5
+ import { n as normalizeCompatibilityConfig } from "./doctor-contract-Btjt6NJD.js";
6
+ import { n as secretTargetRegistryEntries, t as collectRuntimeConfigAssignments } from "./secret-config-contract-B6WW5V88.js";
7
+ import { n as unsupportedSecretRefSurfacePatterns, t as collectUnsupportedSecretRefConfigCandidates } from "./security-contract-DLvYOgLM.js";
8
+ import { t as deriveLegacySessionChatType } from "./session-contract-Dwhw3RTY.js";
9
+ import { normalizeAccountId } from "klaw/plugin-sdk/account-id";
10
+ import { describeAccountSnapshot } from "klaw/plugin-sdk/account-helpers";
11
+ import { adaptScopedAccountAccessor, createScopedChannelConfigAdapter, createScopedDmSecurityResolver } from "klaw/plugin-sdk/channel-config-helpers";
12
+ import { createOpenProviderConfiguredRouteWarningCollector } from "klaw/plugin-sdk/channel-policy";
13
+ import { createEnvPatchedAccountSetupAdapter } from "klaw/plugin-sdk/setup-runtime";
14
+ import { formatAllowFromLowercase } from "klaw/plugin-sdk/allow-from";
15
+ //#region extensions/discord/src/security.ts
16
+ const resolveDiscordDmPolicy = createScopedDmSecurityResolver({
17
+ channelKey: "discord",
18
+ resolvePolicy: (account) => account.config.dmPolicy,
19
+ resolveAllowFrom: (account) => account.config.allowFrom,
20
+ resolveAccess: ({ cfg, account }) => ({
21
+ dmPolicy: resolveDiscordAccountDmPolicy({
22
+ cfg,
23
+ accountId: account.accountId
24
+ }),
25
+ allowFrom: resolveDiscordAccountAllowFrom({
26
+ cfg,
27
+ accountId: account.accountId
28
+ })
29
+ }),
30
+ policyPathSuffix: "dmPolicy",
31
+ normalizeEntry: (raw) => raw.trim().replace(/^(discord|user):/i, "").replace(/^<@!?(\d+)>$/, "$1")
32
+ });
33
+ const collectDiscordSecurityWarnings = createOpenProviderConfiguredRouteWarningCollector({
34
+ providerConfigPresent: (cfg) => cfg.channels?.discord !== void 0,
35
+ resolveGroupPolicy: (account) => account.config.groupPolicy,
36
+ resolveRouteAllowlistConfigured: (account) => Object.keys(account.config.guilds ?? {}).length > 0,
37
+ configureRouteAllowlist: {
38
+ surface: "Discord guilds",
39
+ openScope: "any channel not explicitly denied",
40
+ groupPolicyPath: "channels.discord.groupPolicy",
41
+ routeAllowlistPath: "channels.discord.guilds.<id>.channels"
42
+ },
43
+ missingRouteAllowlist: {
44
+ surface: "Discord guilds",
45
+ openBehavior: "with no guild/channel allowlist; any channel can trigger (mention-gated)",
46
+ remediation: "Set channels.discord.groupPolicy=\"allowlist\" and configure channels.discord.guilds.<id>.channels"
47
+ }
48
+ });
49
+ let discordSecurityAuditModulePromise;
50
+ async function loadDiscordSecurityAuditModule() {
51
+ discordSecurityAuditModulePromise ??= import("./security-audit.runtime-CQSkjNLu.js");
52
+ return await discordSecurityAuditModulePromise;
53
+ }
54
+ const discordSecurityAdapter = {
55
+ resolveDmPolicy: resolveDiscordDmPolicy,
56
+ collectWarnings: collectDiscordSecurityWarnings,
57
+ collectAuditFindings: async (params) => (await loadDiscordSecurityAuditModule()).collectDiscordSecurityAuditFindings(params)
58
+ };
59
+ const discordSetupAdapter = createEnvPatchedAccountSetupAdapter({
60
+ channelKey: "discord",
61
+ defaultAccountOnlyEnvError: "DISCORD_BOT_TOKEN can only be used for the default account.",
62
+ missingCredentialError: "Discord requires token (or --use-env).",
63
+ hasCredentials: (input) => Boolean(input.token),
64
+ buildPatch: (input) => input.token ? { token: input.token } : {}
65
+ });
66
+ //#endregion
67
+ //#region extensions/discord/src/doctor-shared.ts
68
+ const DISCORD_LEGACY_CONFIG_RULES = [];
69
+ //#endregion
70
+ //#region extensions/discord/src/shared.ts
71
+ const DISCORD_CHANNEL = "discord";
72
+ let discordDoctorModulePromise;
73
+ async function loadDiscordDoctorModule() {
74
+ discordDoctorModulePromise ??= import("./doctor-bbKSvGVD.js");
75
+ return await discordDoctorModulePromise;
76
+ }
77
+ const discordDoctor = {
78
+ dmAllowFromMode: "topOnly",
79
+ groupModel: "route",
80
+ groupAllowFromFallbackToAllowFrom: false,
81
+ warnOnEmptyGroupSenderAllowlist: false,
82
+ legacyConfigRules: DISCORD_LEGACY_CONFIG_RULES,
83
+ normalizeCompatibilityConfig,
84
+ collectPreviewWarnings: async (params) => (await loadDiscordDoctorModule()).discordDoctor.collectPreviewWarnings?.(params) ?? [],
85
+ collectMutableAllowlistWarnings: async (params) => (await loadDiscordDoctorModule()).discordDoctor.collectMutableAllowlistWarnings?.(params) ?? [],
86
+ repairConfig: async (params) => (await loadDiscordDoctorModule()).discordDoctor.repairConfig?.(params) ?? {
87
+ config: params.cfg,
88
+ changes: []
89
+ }
90
+ };
91
+ function resolveDiscordConfigAccessorAccount(params) {
92
+ const accountId = normalizeAccountId(params.accountId ?? resolveDefaultDiscordAccountId(params.cfg));
93
+ const config = mergeDiscordAccountConfig(params.cfg, accountId);
94
+ return {
95
+ allowFrom: resolveDiscordAccountAllowFrom({
96
+ cfg: params.cfg,
97
+ accountId
98
+ }),
99
+ defaultTo: config.defaultTo
100
+ };
101
+ }
102
+ const discordConfigAdapter = createScopedChannelConfigAdapter({
103
+ sectionKey: DISCORD_CHANNEL,
104
+ listAccountIds: listDiscordAccountIds,
105
+ resolveAccount: adaptScopedAccountAccessor(resolveDiscordAccount),
106
+ resolveAccessorAccount: resolveDiscordConfigAccessorAccount,
107
+ inspectAccount: adaptScopedAccountAccessor(inspectDiscordAccount),
108
+ defaultAccountId: resolveDefaultDiscordAccountId,
109
+ clearBaseFields: ["token", "name"],
110
+ resolveAllowFrom: (account) => account.allowFrom,
111
+ formatAllowFrom: (allowFrom) => formatAllowFromLowercase({ allowFrom }),
112
+ resolveDefaultTo: (account) => account.defaultTo
113
+ });
114
+ function createDiscordPluginBase(params) {
115
+ return {
116
+ id: DISCORD_CHANNEL,
117
+ ...params.setupWizard ? { setupWizard: params.setupWizard } : {},
118
+ meta: { ...getChatChannelMeta(DISCORD_CHANNEL) },
119
+ capabilities: {
120
+ chatTypes: [
121
+ "direct",
122
+ "channel",
123
+ "thread"
124
+ ],
125
+ polls: true,
126
+ reactions: true,
127
+ threads: true,
128
+ media: true,
129
+ tts: { voice: { synthesisTarget: "voice-note" } },
130
+ nativeCommands: true
131
+ },
132
+ commands: {
133
+ nativeCommandsAutoEnabled: true,
134
+ nativeSkillsAutoEnabled: true,
135
+ resolveNativeCommandName: ({ commandKey, defaultName }) => commandKey === "tts" ? "voice" : defaultName
136
+ },
137
+ doctor: discordDoctor,
138
+ streaming: { blockStreamingCoalesceDefaults: {
139
+ minChars: 1500,
140
+ idleMs: 1e3
141
+ } },
142
+ reload: { configPrefixes: ["channels.discord"] },
143
+ configSchema: DiscordChannelConfigSchema,
144
+ config: {
145
+ ...discordConfigAdapter,
146
+ hasConfiguredState: ({ env }) => typeof env?.DISCORD_BOT_TOKEN === "string" && env.DISCORD_BOT_TOKEN.trim().length > 0,
147
+ isEnabled: (account, cfg) => isDiscordAccountEnabledForRuntime(account, cfg),
148
+ disabledReason: (account, cfg) => resolveDiscordAccountDisabledReason(account, cfg),
149
+ isConfigured: (account) => resolveConfiguredFromCredentialStatuses(account) ?? Boolean(account.token?.trim()),
150
+ describeAccount: (account) => describeAccountSnapshot({
151
+ account,
152
+ configured: resolveConfiguredFromCredentialStatuses(account) ?? Boolean(account.token?.trim()),
153
+ extra: {
154
+ tokenSource: account.tokenSource,
155
+ tokenStatus: account.tokenStatus
156
+ }
157
+ })
158
+ },
159
+ messaging: { deriveLegacySessionChatType },
160
+ security: discordSecurityAdapter,
161
+ secrets: {
162
+ secretTargetRegistryEntries,
163
+ unsupportedSecretRefSurfacePatterns,
164
+ collectUnsupportedSecretRefConfigCandidates,
165
+ collectRuntimeConfigAssignments
166
+ },
167
+ setup: params.setup
168
+ };
169
+ }
170
+ //#endregion
171
+ export { discordSecurityAdapter as a, discordSetupAdapter as i, discordConfigAdapter as n, DISCORD_LEGACY_CONFIG_RULES as r, createDiscordPluginBase as t };
@@ -0,0 +1,120 @@
1
+ import { Wt as __exportAll } from "./send.receipt-CDn3GBWC.js";
2
+ import { s as resolveDiscordAccount } from "./accounts-B7OBFePq.js";
3
+ import { n as autoBindSpawnedDiscordSubagent, o as unbindThreadBindingsBySessionKey, r as listThreadBindingsBySessionKey } from "./thread-bindings-9aKRmZv0.js";
4
+ import { normalizeOptionalLowercaseString, normalizeOptionalStringifiedId } from "klaw/plugin-sdk/string-coerce-runtime";
5
+ import { formatThreadBindingDisabledError, formatThreadBindingSpawnDisabledError, resolveThreadBindingSpawnPolicy } from "klaw/plugin-sdk/conversation-runtime";
6
+ //#region extensions/discord/src/subagent-hooks.ts
7
+ var subagent_hooks_exports = /* @__PURE__ */ __exportAll({
8
+ handleDiscordSubagentDeliveryTarget: () => handleDiscordSubagentDeliveryTarget,
9
+ handleDiscordSubagentEnded: () => handleDiscordSubagentEnded,
10
+ handleDiscordSubagentSpawning: () => handleDiscordSubagentSpawning
11
+ });
12
+ function summarizeError(err) {
13
+ if (err instanceof Error) return err.message;
14
+ if (typeof err === "string") return err;
15
+ return "error";
16
+ }
17
+ function normalizeThreadBindingTargetKind(raw) {
18
+ const normalized = normalizeOptionalLowercaseString(raw);
19
+ if (normalized === "subagent" || normalized === "acp") return normalized;
20
+ }
21
+ async function handleDiscordSubagentSpawning(api, event) {
22
+ if (!event.threadRequested) return;
23
+ if (normalizeOptionalLowercaseString(event.requester?.channel) !== "discord") return;
24
+ const account = resolveDiscordAccount({
25
+ cfg: api.config,
26
+ accountId: event.requester?.accountId
27
+ });
28
+ const threadBindingPolicy = resolveThreadBindingSpawnPolicy({
29
+ cfg: api.config,
30
+ channel: "discord",
31
+ accountId: account.accountId,
32
+ kind: "subagent"
33
+ });
34
+ if (!threadBindingPolicy.enabled) return {
35
+ status: "error",
36
+ error: formatThreadBindingDisabledError({
37
+ channel: threadBindingPolicy.channel,
38
+ accountId: threadBindingPolicy.accountId,
39
+ kind: "subagent"
40
+ })
41
+ };
42
+ if (!threadBindingPolicy.spawnEnabled) return {
43
+ status: "error",
44
+ error: formatThreadBindingSpawnDisabledError({
45
+ channel: threadBindingPolicy.channel,
46
+ accountId: threadBindingPolicy.accountId,
47
+ kind: "subagent"
48
+ })
49
+ };
50
+ try {
51
+ const agentId = event.agentId?.trim() || "subagent";
52
+ const binding = await autoBindSpawnedDiscordSubagent({
53
+ cfg: api.config,
54
+ accountId: account.accountId,
55
+ channel: event.requester?.channel,
56
+ to: event.requester?.to,
57
+ threadId: event.requester?.threadId,
58
+ childSessionKey: event.childSessionKey,
59
+ agentId,
60
+ label: event.label,
61
+ boundBy: "system"
62
+ });
63
+ if (!binding) return {
64
+ status: "error",
65
+ error: "Unable to create or bind a Discord thread for this subagent session. Session mode is unavailable for this target."
66
+ };
67
+ return {
68
+ status: "ok",
69
+ threadBindingReady: true,
70
+ deliveryOrigin: {
71
+ channel: "discord",
72
+ accountId: account.accountId,
73
+ to: `channel:${binding.threadId}`,
74
+ threadId: binding.threadId
75
+ }
76
+ };
77
+ } catch (err) {
78
+ return {
79
+ status: "error",
80
+ error: `Discord thread bind failed: ${summarizeError(err)}`
81
+ };
82
+ }
83
+ }
84
+ function handleDiscordSubagentEnded(event) {
85
+ unbindThreadBindingsBySessionKey({
86
+ targetSessionKey: event.targetSessionKey,
87
+ accountId: event.accountId,
88
+ targetKind: normalizeThreadBindingTargetKind(event.targetKind),
89
+ reason: event.reason,
90
+ sendFarewell: event.sendFarewell
91
+ });
92
+ }
93
+ function handleDiscordSubagentDeliveryTarget(event) {
94
+ if (!event.expectsCompletionMessage) return;
95
+ if (normalizeOptionalLowercaseString(event.requesterOrigin?.channel) !== "discord") return;
96
+ const requesterAccountId = event.requesterOrigin?.accountId?.trim();
97
+ const requesterThreadId = event.requesterOrigin?.threadId != null && event.requesterOrigin.threadId !== "" ? normalizeOptionalStringifiedId(event.requesterOrigin.threadId) ?? "" : "";
98
+ const bindings = listThreadBindingsBySessionKey({
99
+ targetSessionKey: event.childSessionKey,
100
+ ...requesterAccountId ? { accountId: requesterAccountId } : {},
101
+ targetKind: "subagent"
102
+ });
103
+ if (bindings.length === 0) return;
104
+ let binding;
105
+ if (requesterThreadId) binding = bindings.find((entry) => {
106
+ if (entry.threadId !== requesterThreadId) return false;
107
+ if (requesterAccountId && entry.accountId !== requesterAccountId) return false;
108
+ return true;
109
+ });
110
+ if (!binding && bindings.length === 1) binding = bindings[0];
111
+ if (!binding) return;
112
+ return { origin: {
113
+ channel: "discord",
114
+ accountId: binding.accountId,
115
+ to: `channel:${binding.threadId}`,
116
+ threadId: binding.threadId
117
+ } };
118
+ }
119
+ //#endregion
120
+ export { subagent_hooks_exports as i, handleDiscordSubagentEnded as n, handleDiscordSubagentSpawning as r, handleDiscordSubagentDeliveryTarget as t };
@@ -0,0 +1,22 @@
1
+ //#region extensions/discord/subagent-hooks-api.ts
2
+ let discordSubagentHooksPromise = null;
3
+ function loadDiscordSubagentHooksModule() {
4
+ discordSubagentHooksPromise ??= import("./subagent-hooks-8bK-mgiU.js").then((n) => n.i);
5
+ return discordSubagentHooksPromise;
6
+ }
7
+ function registerDiscordSubagentHooks(api) {
8
+ api.on("subagent_spawning", async (event) => {
9
+ const { handleDiscordSubagentSpawning } = await loadDiscordSubagentHooksModule();
10
+ return await handleDiscordSubagentSpawning(api, event);
11
+ });
12
+ api.on("subagent_ended", async (event) => {
13
+ const { handleDiscordSubagentEnded } = await loadDiscordSubagentHooksModule();
14
+ handleDiscordSubagentEnded(event);
15
+ });
16
+ api.on("subagent_delivery_target", async (event) => {
17
+ const { handleDiscordSubagentDeliveryTarget } = await loadDiscordSubagentHooksModule();
18
+ return handleDiscordSubagentDeliveryTarget(event);
19
+ });
20
+ }
21
+ //#endregion
22
+ export { registerDiscordSubagentHooks };
@@ -0,0 +1,34 @@
1
+ import { c as discord_exports } from "./send.receipt-CDn3GBWC.js";
2
+ import { b as formatDiscordUserTag } from "./allow-list-B0s7evD7.js";
3
+ //#region extensions/discord/src/monitor/system-events.ts
4
+ function resolveDiscordSystemEvent(message, location) {
5
+ switch (message.type) {
6
+ case discord_exports.MessageType.ChannelPinnedMessage: return buildDiscordSystemEvent(message, location, "pinned a message");
7
+ case discord_exports.MessageType.RecipientAdd: return buildDiscordSystemEvent(message, location, "added a recipient");
8
+ case discord_exports.MessageType.RecipientRemove: return buildDiscordSystemEvent(message, location, "removed a recipient");
9
+ case discord_exports.MessageType.UserJoin: return buildDiscordSystemEvent(message, location, "user joined");
10
+ case discord_exports.MessageType.GuildBoost: return buildDiscordSystemEvent(message, location, "boosted the server");
11
+ case discord_exports.MessageType.GuildBoostTier1: return buildDiscordSystemEvent(message, location, "boosted the server (Tier 1 reached)");
12
+ case discord_exports.MessageType.GuildBoostTier2: return buildDiscordSystemEvent(message, location, "boosted the server (Tier 2 reached)");
13
+ case discord_exports.MessageType.GuildBoostTier3: return buildDiscordSystemEvent(message, location, "boosted the server (Tier 3 reached)");
14
+ case discord_exports.MessageType.ThreadCreated: return buildDiscordSystemEvent(message, location, "created a thread");
15
+ case discord_exports.MessageType.AutoModerationAction: return buildDiscordSystemEvent(message, location, "auto moderation action");
16
+ case discord_exports.MessageType.GuildIncidentAlertModeEnabled: return buildDiscordSystemEvent(message, location, "raid protection enabled");
17
+ case discord_exports.MessageType.GuildIncidentAlertModeDisabled: return buildDiscordSystemEvent(message, location, "raid protection disabled");
18
+ case discord_exports.MessageType.GuildIncidentReportRaid: return buildDiscordSystemEvent(message, location, "raid reported");
19
+ case discord_exports.MessageType.GuildIncidentReportFalseAlarm: return buildDiscordSystemEvent(message, location, "raid report marked false alarm");
20
+ case discord_exports.MessageType.StageStart: return buildDiscordSystemEvent(message, location, "stage started");
21
+ case discord_exports.MessageType.StageEnd: return buildDiscordSystemEvent(message, location, "stage ended");
22
+ case discord_exports.MessageType.StageSpeaker: return buildDiscordSystemEvent(message, location, "stage speaker updated");
23
+ case discord_exports.MessageType.StageTopic: return buildDiscordSystemEvent(message, location, "stage topic updated");
24
+ case discord_exports.MessageType.PollResult: return buildDiscordSystemEvent(message, location, "poll results posted");
25
+ case discord_exports.MessageType.PurchaseNotification: return buildDiscordSystemEvent(message, location, "purchase notification");
26
+ default: return null;
27
+ }
28
+ }
29
+ function buildDiscordSystemEvent(message, location, action) {
30
+ const authorLabel = message.author ? formatDiscordUserTag(message.author) : "";
31
+ return `Discord system: ${authorLabel ? `${authorLabel} ` : ""}${action} in ${location}`;
32
+ }
33
+ //#endregion
34
+ export { resolveDiscordSystemEvent };
@@ -0,0 +1,82 @@
1
+ import { Ht as parseDiscordTarget, Wt as __exportAll, r as allowFromContainsDiscordUserId } from "./send.receipt-CDn3GBWC.js";
2
+ import { c as resolveDiscordAccountAllowFrom, s as resolveDiscordAccount } from "./accounts-B7OBFePq.js";
3
+ import { i as rememberDiscordDirectoryUser, r as listDiscordDirectoryPeersLive } from "./directory-live-DX4dLRpJ.js";
4
+ import { buildMessagingTarget } from "klaw/plugin-sdk/messaging-targets";
5
+ //#region extensions/discord/src/send-target-parsing.ts
6
+ const parseDiscordSendTarget = (raw, options = {}) => parseDiscordTarget(raw, options);
7
+ //#endregion
8
+ //#region extensions/discord/src/target-resolver.ts
9
+ var target_resolver_exports = /* @__PURE__ */ __exportAll({
10
+ parseAndResolveDiscordTarget: () => parseAndResolveDiscordTarget,
11
+ resolveDiscordTarget: () => resolveDiscordTarget
12
+ });
13
+ /**
14
+ * Resolve a Discord username to user ID using the directory lookup.
15
+ * This enables sending DMs by username instead of requiring explicit user IDs.
16
+ */
17
+ async function resolveDiscordTarget(raw, options, parseOptions = {}) {
18
+ const trimmed = raw.trim();
19
+ if (!trimmed) return;
20
+ const likelyUsername = isLikelyUsername(trimmed);
21
+ const shouldLookup = isExplicitUserLookup(trimmed, parseOptions) || likelyUsername;
22
+ if (/^\d+$/.test(trimmed) && parseOptions.defaultKind !== "user" && isConfiguredAllowedDiscordDmUser(trimmed, options)) return buildMessagingTarget("user", trimmed, trimmed);
23
+ const directParse = safeParseDiscordTarget(trimmed, parseOptions);
24
+ if (directParse && directParse.kind !== "channel" && !likelyUsername) return directParse;
25
+ if (!shouldLookup) return directParse ?? parseDiscordSendTarget(trimmed, parseOptions);
26
+ try {
27
+ const match = (await listDiscordDirectoryPeersLive({
28
+ ...options,
29
+ query: trimmed,
30
+ limit: 1
31
+ }))[0];
32
+ if (match && match.kind === "user") {
33
+ const userId = match.id.replace(/^user:/, "");
34
+ const resolvedAccountId = resolveDiscordAccount({
35
+ cfg: options.cfg,
36
+ accountId: options.accountId
37
+ }).accountId;
38
+ rememberDiscordDirectoryUser({
39
+ accountId: resolvedAccountId,
40
+ userId,
41
+ handles: [
42
+ trimmed,
43
+ match.name,
44
+ match.handle
45
+ ]
46
+ });
47
+ return buildMessagingTarget("user", userId, trimmed);
48
+ }
49
+ } catch {}
50
+ return parseDiscordSendTarget(trimmed, parseOptions);
51
+ }
52
+ async function parseAndResolveDiscordTarget(raw, options, parseOptions = {}) {
53
+ const resolved = await resolveDiscordTarget(raw, options, parseOptions) ?? parseDiscordSendTarget(raw, parseOptions);
54
+ if (!resolved) throw new Error("Recipient is required for Discord sends");
55
+ return resolved;
56
+ }
57
+ function safeParseDiscordTarget(input, options) {
58
+ try {
59
+ return parseDiscordSendTarget(input, options);
60
+ } catch {
61
+ return;
62
+ }
63
+ }
64
+ function isConfiguredAllowedDiscordDmUser(input, options) {
65
+ return allowFromContainsDiscordUserId(resolveDiscordAccountAllowFrom({
66
+ cfg: options.cfg,
67
+ accountId: options.accountId
68
+ }) ?? [], input);
69
+ }
70
+ function isExplicitUserLookup(input, options) {
71
+ if (/^<@!?(\d+)>$/.test(input)) return true;
72
+ if (/^(user:|discord:)/.test(input)) return true;
73
+ if (input.startsWith("@")) return true;
74
+ if (/^\d+$/.test(input)) return options.defaultKind === "user";
75
+ return false;
76
+ }
77
+ function isLikelyUsername(input) {
78
+ if (/^(user:|channel:|discord:|@|<@!?)|[\d]+$/.test(input)) return false;
79
+ return true;
80
+ }
81
+ //#endregion
82
+ export { parseDiscordSendTarget as i, resolveDiscordTarget as n, target_resolver_exports as r, parseAndResolveDiscordTarget as t };
@@ -0,0 +1,3 @@
1
+ import "./send.receipt-CDn3GBWC.js";
2
+ import "./target-resolver-BrtFQtoK.js";
3
+ export {};
@@ -0,0 +1,45 @@
1
+ import { t as discordPlugin } from "./channel-U_aeoFwW.js";
2
+ import { n as discordOutbound } from "./outbound-adapter-C18OAc1y.js";
3
+ import { i as testing } from "./thread-bindings.manager-0YBHGemk.js";
4
+ import { n as buildDiscordInboundAccessContext } from "./inbound-context-WAOqhGlT.js";
5
+ import { finalizeInboundContext } from "klaw/plugin-sdk/reply-dispatch-runtime";
6
+ //#region extensions/discord/src/monitor/inbound-context.test-helpers.ts
7
+ function buildFinalizedDiscordDirectInboundContext() {
8
+ const { groupSystemPrompt, ownerAllowFrom, untrustedContext } = buildDiscordInboundAccessContext({
9
+ channelConfig: null,
10
+ guildInfo: null,
11
+ sender: {
12
+ id: "U1",
13
+ name: "Alice",
14
+ tag: "alice"
15
+ },
16
+ isGuild: false
17
+ });
18
+ return finalizeInboundContext({
19
+ Body: "hi",
20
+ BodyForAgent: "hi",
21
+ RawBody: "hi",
22
+ CommandBody: "hi",
23
+ From: "discord:U1",
24
+ To: "user:U1",
25
+ SessionKey: "agent:main:discord:direct:u1",
26
+ AccountId: "default",
27
+ ChatType: "direct",
28
+ ConversationLabel: "Alice",
29
+ SenderName: "Alice",
30
+ SenderId: "U1",
31
+ SenderUsername: "alice",
32
+ GroupSystemPrompt: groupSystemPrompt,
33
+ OwnerAllowFrom: ownerAllowFrom,
34
+ UntrustedStructuredContext: untrustedContext,
35
+ Provider: "discord",
36
+ Surface: "discord",
37
+ WasMentioned: false,
38
+ MessageSid: "m1",
39
+ CommandAuthorized: true,
40
+ OriginatingChannel: "discord",
41
+ OriginatingTo: "user:U1"
42
+ });
43
+ }
44
+ //#endregion
45
+ export { buildFinalizedDiscordDirectInboundContext, discordOutbound, discordPlugin, testing as discordThreadBindingTesting };
@@ -0,0 +1,4 @@
1
+ //#region extensions/discord/thread-binding-api.ts
2
+ const defaultTopLevelPlacement = "child";
3
+ //#endregion
4
+ export { defaultTopLevelPlacement };