@openclaw/discord 2026.5.12 → 2026.5.14-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/dist/{account-inspect-D7jL5YDH.js → account-inspect-B_N30NV0.js} +1 -1
  2. package/dist/account-inspect-api.js +1 -1
  3. package/dist/{accounts-BcwyaFd-.js → accounts-DnNVBDfc.js} +95 -4
  4. package/dist/action-runtime-api.js +1 -1
  5. package/dist/{allow-list-n8Ki-Rt3.js → allow-list-CBI-M84K.js} +24 -2
  6. package/dist/api.js +19 -21
  7. package/dist/{approval-handler.runtime-S-ircYcz.js → approval-handler.runtime-Uco62pII.js} +4 -4
  8. package/dist/{audit-BliEqCEc.js → audit-eSlKbMHw.js} +5 -5
  9. package/dist/{channel-Bliqi-Qi.js → channel-BjBa8nYY.js} +23 -25
  10. package/dist/{channel-actions-Cn_K00Vy.js → channel-actions-DANVAtKL.js} +4 -4
  11. package/dist/{channel-actions.runtime-DcsRvPnx.js → channel-actions.runtime-CpIslHS9.js} +7 -5
  12. package/dist/channel-config-api.js +1 -1
  13. package/dist/channel-plugin-api.js +1 -1
  14. package/dist/{channel.setup-DR-xVYso.js → channel.setup-DBFcGRFD.js} +4 -5
  15. package/dist/{components-Dxq2mU57.js → components-Cgm7XT8-.js} +120 -3
  16. package/dist/{config-schema-D2KGskAp.js → config-schema-D7AtCpJa.js} +21 -1
  17. package/dist/contract-api.js +7 -7
  18. package/dist/{approval-native-Gtqpyfdj.js → conversation-identity-C3AI-1tz.js} +123 -6
  19. package/dist/{directory-config-CDl4JTCA.js → directory-config-CW_JusGS.js} +2 -2
  20. package/dist/directory-contract-api.js +1 -1
  21. package/dist/directory-live-MrDSKsMf.js +159 -0
  22. package/dist/doctor-contract-api.js +1 -1
  23. package/dist/{doctor-contract-BGjjFBdq.js → doctor-contract-ftWAMvBl.js} +1 -1
  24. package/dist/{doctor-jcX_qXsS.js → doctor-mn2XyjuF.js} +5 -5
  25. package/dist/{handle-action.guild-admin-C4phin-a.js → handle-action.guild-admin-DriifPwO.js} +1 -1
  26. package/dist/{inbound-context-jtKcY9on.js → inbound-context-DD7n3Q6U.js} +1 -1
  27. package/dist/{manager.runtime-DqMGETqp.js → manager.runtime-DauS2xA3.js} +107 -25
  28. package/dist/{message-handler-DIsnboy2.js → message-handler-CMHwRlxG.js} +7 -7
  29. package/dist/{message-handler.preflight-BRH-dv1o.js → message-handler.preflight-C0sT-ewp.js} +27 -17
  30. package/dist/{message-handler.process-Bs5wropA.js → message-handler.process-Cy7_-0H0.js} +46 -37
  31. package/dist/{message-utils-ByofKwPe.js → message-utils-N5UTOXQ2.js} +16 -12
  32. package/dist/{outbound-adapter-lWjkSeyP.js → outbound-adapter-Cw9JsRTY.js} +7 -10
  33. package/dist/{pluralkit-B1HTaBc9.js → pluralkit-B2AqgTHV.js} +1 -1
  34. package/dist/{preflight-audio-CD97vnac.js → preflight-audio-DFGpAvzi.js} +1 -1
  35. package/dist/{probe-BZtr8qle.js → probe-CiBYm-vD.js} +2 -2
  36. package/dist/{probe.runtime-0F0UzBoJ.js → probe.runtime-9hi1GYNU.js} +1 -1
  37. package/dist/{provider-DABvNRT0.js → provider-nzJg2k5t.js} +1039 -45
  38. package/dist/{provider-session.runtime-BZyP90-i.js → provider-session.runtime-DMxaLPB3.js} +3 -3
  39. package/dist/provider.runtime-S-wZdzK5.js +2 -0
  40. package/dist/{resolve-allowlist-common-CVHYb5Hb.js → resolve-allowlist-common-DybgkAjk.js} +3 -3
  41. package/dist/{resolve-channels-JNt3Ak6P.js → resolve-channels-u7_agBcm.js} +4 -4
  42. package/dist/{resolve-users-CrjbUxrL.js → resolve-users-Bc25I6OP.js} +3 -3
  43. package/dist/{runtime-CdnAT8R5.js → runtime-DL82ijB1.js} +102 -46
  44. package/dist/runtime-api.actions.js +2 -2
  45. package/dist/runtime-api.js +25 -26
  46. package/dist/runtime-api.lookup.js +6 -6
  47. package/dist/runtime-api.monitor-DbLcHuhE.js +5 -0
  48. package/dist/runtime-api.monitor.js +7 -8
  49. package/dist/runtime-api.send.js +5 -5
  50. package/dist/runtime-api.threads.js +5 -5
  51. package/dist/runtime-setter-api.js +1 -1
  52. package/dist/secret-contract-api.js +1 -1
  53. package/dist/{security-audit-BQ_sGK3J.js → security-audit-CLPZKYi4.js} +1 -1
  54. package/dist/security-audit-contract-api.js +1 -1
  55. package/dist/{security-audit.runtime-B7Gmz2DX.js → security-audit.runtime-CCm9leFJ.js} +1 -1
  56. package/dist/security-contract-api.js +1 -1
  57. package/dist/{send-DCFuSiBi.js → send-BqzTEkt9.js} +4 -6
  58. package/dist/{send.components-DxDqPJZQ.js → send.components-D6pXHVrU.js} +8 -10
  59. package/dist/{send.outbound-PM0J0F60.js → send.outbound-D8o8BW6q.js} +91 -7
  60. package/dist/{discord-BqYcwxvG.js → send.receipt-nKLxvA1s.js} +319 -1
  61. package/dist/{send.shared-Dza0jdso.js → send.shared-DSpva7uA.js} +4 -6
  62. package/dist/{sender-identity-w9rSI-nD.js → sender-identity-BTGL3VbF.js} +1 -1
  63. package/dist/session-key-api.js +1 -1
  64. package/dist/setup-plugin-api.js +1 -1
  65. package/dist/{shared-Yp_M6Cfp.js → shared-0kdaIxXP.js} +16 -14
  66. package/dist/{subagent-hooks-CtN-hfXy.js → subagent-hooks-DhuBhwRw.js} +3 -3
  67. package/dist/subagent-hooks-api.js +1 -1
  68. package/dist/{system-events-B04UOvPg.js → system-events-Bnit0zkQ.js} +2 -2
  69. package/dist/{target-resolver-CgJei-kD.js → target-resolver-BsGT9hI7.js} +3 -6
  70. package/dist/targets-DwW6OieO.js +3 -0
  71. package/dist/test-api.js +4 -4
  72. package/dist/{thread-bindings-B4of4OmR.js → thread-bindings-C1f7Iim4.js} +6 -7
  73. package/dist/{thread-bindings.discord-api-BAw15EQb.js → thread-bindings.discord-api-DJACBZJ1.js} +67 -8
  74. package/dist/{thread-bindings.manager-DNFl10CA.js → thread-bindings.manager-DN_q0IW7.js} +4 -5
  75. package/dist/{thread-bindings.session-updates-D18cCLmN.js → thread-bindings.session-updates-ZnRRzzgf.js} +1 -1
  76. package/dist/timeouts.js +1 -1
  77. package/dist/{typing-_jePdFIw.js → typing-C_8U8J7E.js} +2 -2
  78. package/openclaw.plugin.json +68 -0
  79. package/package.json +6 -6
  80. package/dist/access-Dxmzr0ix.js +0 -89
  81. package/dist/approval-shared-BFnWKSQD.js +0 -93
  82. package/dist/channel-access-BL-wemES.js +0 -62
  83. package/dist/chunk-DYl-_5RL.js +0 -179
  84. package/dist/conversation-identity-CvIx6J7M.js +0 -31
  85. package/dist/directory-cache-Ddl-Oxue.js +0 -62
  86. package/dist/directory-live-ApUXOSj0.js +0 -101
  87. package/dist/doctor-shared-D_QLzu30.js +0 -4
  88. package/dist/format-D8TsaXxW.js +0 -24
  89. package/dist/mentions-BZoGn0ul.js +0 -88
  90. package/dist/normalize-Cu94FOqy.js +0 -58
  91. package/dist/outbound-session-route-BaJRt05p.js +0 -43
  92. package/dist/provider.runtime-Cmv1SFtb.js +0 -2
  93. package/dist/reply-delivery-CUSK6SA_.js +0 -191
  94. package/dist/route-resolution-BFfF9xmG.js +0 -268
  95. package/dist/runtime-api.monitor-W_dJ5EQu.js +0 -6
  96. package/dist/send.receipt-BAZw2Zsz.js +0 -35
  97. package/dist/shared-interactive-DavY6jYt.js +0 -79
  98. package/dist/target-parsing-D-H7nnh2.js +0 -51
  99. package/dist/targets-DToZUkgV.js +0 -3
  100. package/dist/threading-CLZ3v7-y.js +0 -475
  101. package/dist/token-BZtonk7d.js +0 -93
  102. /package/dist/{agent-components.runtime-zT8qPsnM.js → agent-components.runtime-CEMbMQcQ.js} +0 -0
  103. /package/dist/{api-DzNBVTto.js → api-DgQLz1wq.js} +0 -0
  104. /package/dist/{audit-core-BgDZSkIR.js → audit-core-DRyoXREU.js} +0 -0
  105. /package/dist/{channel-api-CTSWMrnD.js → channel-api-JudoSiJv.js} +0 -0
  106. /package/dist/{config-api-CFZtoMaS.js → config-api-oLS_52S7.js} +0 -0
  107. /package/dist/{gateway-registry-BKG4KIVC.js → gateway-registry-BKSpa4GB.js} +0 -0
  108. /package/dist/{preflight-audio.runtime-fXnUxxBa.js → preflight-audio.runtime-Drc-OFcp.js} +0 -0
  109. /package/dist/{preview-streaming-DCPAe24T.js → preview-streaming-CXTZydhx.js} +0 -0
  110. /package/dist/{runtime-BqCoo-zp.js → runtime-Tqtvj5GX.js} +0 -0
  111. /package/dist/{secret-config-contract-BCQNNS7N.js → secret-config-contract-B3347_eU.js} +0 -0
  112. /package/dist/{security-contract-DkCMKSvb.js → security-contract-DyCRvz_Q.js} +0 -0
  113. /package/dist/{security-doctor-BJH5YIGL.js → security-doctor-Cp-NqNdS.js} +0 -0
  114. /package/dist/{session-contract-D871HDFG.js → session-contract-ugfEa9Xc.js} +0 -0
  115. /package/dist/{session-key-normalization-BV82IME9.js → session-key-normalization-B7h83qD2.js} +0 -0
  116. /package/dist/{thread-bindings.state-SPlv6mh7.js → thread-bindings.state-BdBeo7Rx.js} +0 -0
  117. /package/dist/{timeouts-C3FYXWJX.js → timeouts-snXNwR4m.js} +0 -0
@@ -1,35 +1,26 @@
1
- import { C as Message, H as StringSelectMenu, K as BaseMessageInteractiveComponent, N as Container, O as Modal, S as Guild, U as TextDisplay, V as Separator, a as MessageReactionRemoveListener, b as Command, f as Client, g as RateLimitError, i as MessageReactionAddListener, j as Button, l as ThreadUpdateListener, n as InteractionCreateListener, o as PresenceUpdateListener, p as Plugin, r as MessageCreateListener, s as ReadyListener, t as discord_exports, w as User, x as CommandWithSubcommands, z as Row } from "./discord-BqYcwxvG.js";
2
- import { t as normalizeDiscordToken } from "./token-BZtonk7d.js";
3
- import { c as resolveDiscordAccountAllowFrom, d as resolveDiscordAccountDmPolicy, f as resolveDiscordMaxLinesPerMessage, s as resolveDiscordAccount } from "./accounts-BcwyaFd-.js";
4
- import { a as resolveDiscordComponentEntryWithPersistence, o as resolveDiscordModalEntryWithPersistence, t as editDiscordComponentMessage } from "./send.components-DxDqPJZQ.js";
5
- import { c as setPresence, i as unregisterGateway, r as registerGateway } from "./gateway-registry-BKG4KIVC.js";
6
- import { t as chunkDiscordTextWithMode } from "./chunk-DYl-_5RL.js";
7
- import { F as DISCORD_REST_TIMEOUT_MS, I as validateDiscordProxyUrl, L as withValidatedDiscordProxy, j as createDiscordRestClient } from "./send.shared-Dza0jdso.js";
8
- import { a as summarizeDiscordResponseBody, i as isDiscordRateLimitResponseBody } from "./api-DzNBVTto.js";
9
- import { n as formatDiscordUserTag, t as formatDiscordReactionEmoji } from "./format-D8TsaXxW.js";
10
- import { _ as resolveGroupDmAllow, a as normalizeDiscordSlug, c as resolveDiscordChannelConfigWithFallback, d as resolveDiscordGuildEntry, f as resolveDiscordMemberAccessState, i as normalizeDiscordDisplaySlug, l as resolveDiscordChannelPolicyCommandAuthorizer, m as resolveDiscordOwnerAccess, n as isDiscordGroupAllowedByPolicy, o as resolveDiscordAllowListMatch, r as normalizeDiscordAllowList, v as shouldEmitDiscordReactionNotification } from "./allow-list-n8Ki-Rt3.js";
11
- import { t as formatMention } from "./mentions-BZoGn0ul.js";
12
- import { _ as parseDiscordModalCustomIdForInteraction, g as parseDiscordModalCustomId, h as parseDiscordComponentCustomIdForInteraction, m as parseDiscordComponentCustomId } from "./components-Dxq2mU57.js";
13
- import { i as isDiscordExecApprovalClientEnabled, n as getDiscordExecApprovalApprovers } from "./approval-shared-BFnWKSQD.js";
14
- import "./approval-native-Gtqpyfdj.js";
15
- import { t as resolveDiscordConversationIdentity } from "./conversation-identity-CvIx6J7M.js";
16
- import { t as resolveDiscordChannelAllowlist } from "./resolve-channels-JNt3Ak6P.js";
17
- import { t as resolveDiscordUserAllowlist } from "./resolve-users-CrjbUxrL.js";
18
- import { a as isThreadArchived, d as formatThreadBindingDurationLabel } from "./thread-bindings.discord-api-BAw15EQb.js";
19
- import { i as resolveDiscordChannelParentIdSafe, n as resolveDiscordChannelInfoSafe, o as resolveDiscordChannelTopicSafe, r as resolveDiscordChannelNameSafe, t as resolveDiscordChannelIdSafe } from "./channel-access-BL-wemES.js";
20
- import { r as parseApplicationIdFromToken, t as fetchDiscordApplicationId } from "./probe-BZtr8qle.js";
21
- import { o as raceWithTimeout, s as withAbortTimeout } from "./timeouts-C3FYXWJX.js";
22
- import { i as resolveDiscordEffectiveRoute, n as resolveDiscordBoundConversationRoute, o as handleDiscordDmCommandDecision, s as resolveDiscordDmCommandAccess } from "./route-resolution-BFfF9xmG.js";
23
- import { c as resolveDiscordChannelInfo } from "./message-utils-ByofKwPe.js";
24
- import { i as resolveDiscordThreadParentInfo } from "./threading-CLZ3v7-y.js";
25
- import { t as resolveDiscordSenderIdentity } from "./sender-identity-w9rSI-nD.js";
26
- import { n as buildDiscordInboundAccessContext, t as buildDiscordGroupSystemPrompt } from "./inbound-context-jtKcY9on.js";
27
- import { n as resolveDiscordVoiceEnabled, t as authorizeDiscordVoiceIngress } from "./access-Dxmzr0ix.js";
28
- import { n as buildDirectLabel, r as buildGuildLabel, t as deliverDiscordReply } from "./reply-delivery-CUSK6SA_.js";
29
- import "./approval-handler.runtime-S-ircYcz.js";
1
+ import { $ as BaseMessageInteractiveComponent, A as Message, B as Container, C as RateLimitError, D as Command, F as Modal, J as Separator, K as Row, O as CommandWithSubcommands, R as Button, Wt as __exportAll, X as TextDisplay, Y as StringSelectMenu, b as Plugin, c as discord_exports, ct as createThread, d as MessageReactionAddListener, dt as editChannel, f as MessageReactionRemoveListener, g as ThreadUpdateListener, j as User, k as Guild, l as InteractionCreateListener, m as ReadyListener, mt as getChannelMessage, p as PresenceUpdateListener, s as chunkDiscordTextWithMode, u as MessageCreateListener, y as Client } from "./send.receipt-nKLxvA1s.js";
2
+ import { c as resolveDiscordAccountAllowFrom, d as resolveDiscordAccountDmPolicy, f as resolveDiscordMaxLinesPerMessage, p as normalizeDiscordToken, s as resolveDiscordAccount } from "./accounts-DnNVBDfc.js";
3
+ import { _ as parseDiscordComponentCustomId, b as parseDiscordModalCustomIdForInteraction, v as parseDiscordComponentCustomIdForInteraction, y as parseDiscordModalCustomId } from "./components-Cgm7XT8-.js";
4
+ import { a as resolveDiscordComponentEntryWithPersistence, o as resolveDiscordModalEntryWithPersistence, t as editDiscordComponentMessage } from "./send.components-D6pXHVrU.js";
5
+ import { c as setPresence, i as unregisterGateway, r as registerGateway } from "./gateway-registry-BKSpa4GB.js";
6
+ import { I as DISCORD_REST_TIMEOUT_MS, L as validateDiscordProxyUrl, M as createDiscordRestClient, R as withValidatedDiscordProxy, w as canViewDiscordGuildChannel } from "./send.shared-DSpva7uA.js";
7
+ import { a as summarizeDiscordResponseBody, i as isDiscordRateLimitResponseBody } from "./api-DgQLz1wq.js";
8
+ import { S as resolveTimestampMs, _ as resolveGroupDmAllow, a as normalizeDiscordSlug, b as formatDiscordUserTag, c as resolveDiscordChannelConfigWithFallback, d as resolveDiscordGuildEntry, f as resolveDiscordMemberAccessState, i as normalizeDiscordDisplaySlug, l as resolveDiscordChannelPolicyCommandAuthorizer, m as resolveDiscordOwnerAccess, n as isDiscordGroupAllowedByPolicy, o as resolveDiscordAllowListMatch, r as normalizeDiscordAllowList, v as shouldEmitDiscordReactionNotification, y as formatDiscordReactionEmoji } from "./allow-list-CBI-M84K.js";
9
+ import { s as sendVoiceMessageDiscord } from "./send-BqzTEkt9.js";
10
+ import { i as formatMention, t as sendMessageDiscord } from "./send.outbound-D8o8BW6q.js";
11
+ import { a as getDiscordExecApprovalApprovers, s as isDiscordExecApprovalClientEnabled, t as resolveDiscordConversationIdentity } from "./conversation-identity-C3AI-1tz.js";
12
+ import { t as resolveDiscordChannelAllowlist } from "./resolve-channels-u7_agBcm.js";
13
+ import { t as resolveDiscordUserAllowlist } from "./resolve-users-Bc25I6OP.js";
14
+ import { _ as formatThreadBindingDurationLabel, a as isThreadArchived, d as resolveDiscordChannelNameSafe, f as resolveDiscordChannelParentIdSafe, l as resolveDiscordChannelIdSafe, m as resolveDiscordChannelTopicSafe, p as resolveDiscordChannelParentSafe, u as resolveDiscordChannelInfoSafe } from "./thread-bindings.discord-api-DJACBZJ1.js";
15
+ import { r as parseApplicationIdFromToken, t as fetchDiscordApplicationId } from "./probe-CiBYm-vD.js";
16
+ import { o as raceWithTimeout, s as withAbortTimeout } from "./timeouts-snXNwR4m.js";
17
+ import { c as resolveDiscordChannelInfo, l as resolveDiscordMessageChannelId, n as resolveDiscordForwardedMessagesTextFromSnapshots, t as resolveDiscordEmbedText } from "./message-utils-N5UTOXQ2.js";
18
+ import { t as resolveDiscordSenderIdentity } from "./sender-identity-BTGL3VbF.js";
19
+ import { n as buildDiscordInboundAccessContext, t as buildDiscordGroupSystemPrompt } from "./inbound-context-DD7n3Q6U.js";
20
+ import "./approval-handler.runtime-Uco62pII.js";
30
21
  import { normalizeAccountId } from "openclaw/plugin-sdk/account-id";
31
- import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries, summarizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
32
- import { resolveAgentRoute } from "openclaw/plugin-sdk/routing";
22
+ import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeOptionalStringifiedId, normalizeStringEntries, summarizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
23
+ import { buildAgentSessionKey, deriveLastRoutePolicy, isAcpSessionKey, isSubagentSessionKey, parseAgentSessionKey, resolveAgentIdFromSessionKey, resolveAgentRoute } from "openclaw/plugin-sdk/routing";
33
24
  import { getRuntimeConfig } from "openclaw/plugin-sdk/runtime-config-snapshot";
34
25
  import { ApplicationCommandOptionType, ButtonStyle, ChannelType, ComponentType, GatewayCloseCodes, GatewayCloseCodes as GatewayCloseCodes$1, GatewayDispatchEvents, GatewayIntentBits, GatewayOpcodes } from "discord-api-types/v10";
35
26
  import { randomUUID } from "node:crypto";
@@ -46,24 +37,27 @@ import { wrapFetchWithAbortSignal } from "openclaw/plugin-sdk/fetch-runtime";
46
37
  import { createNonExitingRuntime, createSubsystemLogger, danger, formatDurationSeconds, isVerbose, logVerbose, shouldLogVerbose, warn } from "openclaw/plugin-sdk/runtime-env";
47
38
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
48
39
  import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
49
- import { chunkItems } from "openclaw/plugin-sdk/text-chunking";
50
- import { createChannelMessageReplyPipeline } from "openclaw/plugin-sdk/channel-message";
40
+ import { chunkItems, sanitizeAssistantVisibleText } from "openclaw/plugin-sdk/text-chunking";
41
+ import { createChannelMessageReplyPipeline, sendDurableMessageBatch } from "openclaw/plugin-sdk/channel-message";
51
42
  import { fetchWithSsrFGuard, formatErrorMessage as formatErrorMessage$1 } from "openclaw/plugin-sdk/ssrf-runtime";
52
43
  import { createChannelPairingChallengeIssuer } from "openclaw/plugin-sdk/channel-pairing";
53
44
  import { CHANNEL_APPROVAL_NATIVE_RUNTIME_CONTEXT_CAPABILITY } from "openclaw/plugin-sdk/approval-handler-adapter-runtime";
54
45
  import { readJsonFileWithFallback, writeJsonFileAtomically } from "openclaw/plugin-sdk/json-store";
55
46
  import { resolveStateDir } from "openclaw/plugin-sdk/state-paths";
47
+ import { buildOutboundSessionContext } from "openclaw/plugin-sdk/outbound-runtime";
56
48
  import { addAllowlistUserEntriesFromConfigEntry, buildAllowlistResolutionSummary, canonicalizeAllowlistWithResolvedIds, patchAllowlistUsersInConfigEntries, summarizeMapping } from "openclaw/plugin-sdk/allow-from";
57
49
  import { resolveChannelStreamingBlockEnabled } from "openclaw/plugin-sdk/channel-streaming";
58
- import { buildPairingReply, upsertChannelPairingRequest as upsertChannelPairingRequest$1 } from "openclaw/plugin-sdk/conversation-runtime";
59
- import { clearExpiredCooldowns, ensureAuthProfileStore, isProfileInCooldown, resolveDefaultModelForAgent, resolveHumanDelayConfig, resolveProfilesUnavailableReason } from "openclaw/plugin-sdk/agent-runtime";
50
+ import { buildPairingReply, upsertChannelPairingRequest, upsertChannelPairingRequest as upsertChannelPairingRequest$1 } from "openclaw/plugin-sdk/conversation-runtime";
51
+ import { clearExpiredCooldowns, ensureAuthProfileStore, isProfileInCooldown, resolveAgentAvatar, resolveDefaultModelForAgent, resolveHumanDelayConfig, resolveProfilesUnavailableReason } from "openclaw/plugin-sdk/agent-runtime";
60
52
  import { GROUP_POLICY_BLOCKED_LABEL, resolveDefaultGroupPolicy, resolveOpenProviderRuntimeGroupPolicy, warnMissingProviderGroupPolicyFallbackOnce } from "openclaw/plugin-sdk/runtime-group-policy";
61
- import { withTimeout } from "openclaw/plugin-sdk/text-utility-runtime";
53
+ import { truncateUtf16Safe, withTimeout } from "openclaw/plugin-sdk/text-utility-runtime";
62
54
  import { isDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/dangerous-name-runtime";
63
55
  import { resolveNativeCommandsEnabled, resolveNativeSkillsEnabled } from "openclaw/plugin-sdk/native-command-config-runtime";
64
56
  import { enqueueSystemEvent, enqueueSystemEvent as enqueueSystemEvent$1 } from "openclaw/plugin-sdk/system-event-runtime";
65
- import { readChannelIngressStoreAllowFromForDmPolicy } from "openclaw/plugin-sdk/channel-ingress-runtime";
66
- import { applyModelOverrideToSessionEntry } from "openclaw/plugin-sdk/model-session-runtime";
57
+ import { createChannelIngressResolver, defineStableChannelIngressIdentity, readChannelIngressStoreAllowFromForDmPolicy } from "openclaw/plugin-sdk/channel-ingress-runtime";
58
+ import { applyModelOverrideToSessionEntry, resolveChannelModelOverride } from "openclaw/plugin-sdk/model-session-runtime";
59
+ import { completeWithPreparedSimpleCompletionModel, extractAssistantText, prepareSimpleCompletionModelForAgent } from "openclaw/plugin-sdk/simple-completion-runtime";
60
+ import { createReplyReferencePlanner } from "openclaw/plugin-sdk/reply-reference";
67
61
  import { loadSessionStore, readSessionUpdatedAt as readSessionUpdatedAt$1, resolveStorePath, resolveStorePath as resolveStorePath$1, updateSessionStore } from "openclaw/plugin-sdk/session-store-runtime";
68
62
  import { formatInboundEnvelope, resolveEnvelopeFormatOptions } from "openclaw/plugin-sdk/channel-inbound";
69
63
  import { buildCommandTextFromArgs, findCommandByNativeName, formatCommandArgMenuTitle, listChatCommands, listNativeCommandSpecsForConfig, listSkillCommandsForAgents, resolveCommandAuthorizedFromAuthorizers, resolveNativeCommandSessionTargets, resolveStoredModelOverride, serializeCommandArgs } from "openclaw/plugin-sdk/command-auth-native";
@@ -147,6 +141,628 @@ async function runDiscordListenerWithSlowLog(params) {
147
141
  }
148
142
  }
149
143
  //#endregion
144
+ //#region extensions/discord/src/monitor/dm-command-auth.ts
145
+ const DISCORD_ALLOW_LIST_PREFIXES = [
146
+ "discord:",
147
+ "user:",
148
+ "pk:"
149
+ ];
150
+ const DISCORD_CHANNEL_ID = "discord";
151
+ const DISCORD_USER_ID_KIND = "stable-id";
152
+ const DISCORD_USER_NAME_KIND = "username";
153
+ function normalizeDiscordIdEntry(entry) {
154
+ const text = entry.trim();
155
+ if (!text) return null;
156
+ const maybeId = text.replace(/^<@!?/, "").replace(/>$/, "");
157
+ if (/^\d+$/.test(maybeId)) return maybeId;
158
+ const prefix = DISCORD_ALLOW_LIST_PREFIXES.find((entryPrefix) => text.startsWith(entryPrefix));
159
+ if (prefix) return text.slice(prefix.length).trim() || null;
160
+ return null;
161
+ }
162
+ function normalizeDiscordNameEntry(entry) {
163
+ const text = entry.trim();
164
+ if (!text || text === "*" || normalizeDiscordIdEntry(text)) return null;
165
+ const nameSlug = normalizeDiscordAllowList([text], DISCORD_ALLOW_LIST_PREFIXES)?.names.values().next().value;
166
+ return typeof nameSlug === "string" && nameSlug ? nameSlug : null;
167
+ }
168
+ function normalizeDiscordNameSubject(value) {
169
+ const nameSlug = normalizeDiscordAllowList([value], DISCORD_ALLOW_LIST_PREFIXES)?.names.values().next().value;
170
+ return typeof nameSlug === "string" && nameSlug ? nameSlug : null;
171
+ }
172
+ const discordIngressIdentity = defineStableChannelIngressIdentity({
173
+ key: "discordUserId",
174
+ kind: DISCORD_USER_ID_KIND,
175
+ normalizeEntry: normalizeDiscordIdEntry,
176
+ normalizeSubject: (value) => value.trim() || null,
177
+ sensitivity: "pii",
178
+ aliases: [["discordUserName", normalizeDiscordNameEntry], ["discordUserTag", () => null]].map(([key, normalizeEntry]) => ({
179
+ key,
180
+ kind: DISCORD_USER_NAME_KIND,
181
+ normalizeEntry,
182
+ normalizeSubject: normalizeDiscordNameSubject,
183
+ dangerous: true,
184
+ sensitivity: "pii"
185
+ }))
186
+ });
187
+ function createDiscordDmIngressSubject(sender) {
188
+ return {
189
+ stableId: sender.id,
190
+ aliases: {
191
+ discordUserName: sender.name,
192
+ discordUserTag: sender.tag
193
+ }
194
+ };
195
+ }
196
+ function createDiscordDynamicAccessGroupResolver(params) {
197
+ if (!params.cfg) return;
198
+ const cfg = params.cfg;
199
+ return async ({ name, group, accountId, subject }) => {
200
+ if (group.type !== "discord.channelAudience") return false;
201
+ const senderId = String(subject.stableId ?? "").trim();
202
+ if (!senderId) return false;
203
+ if ((group.membership ?? "canViewChannel") !== "canViewChannel") return false;
204
+ try {
205
+ return await canViewDiscordGuildChannel(group.guildId, group.channelId, senderId, {
206
+ cfg,
207
+ accountId,
208
+ token: params.token,
209
+ rest: params.rest
210
+ });
211
+ } catch (err) {
212
+ logVerbose(`discord: accessGroup:${name} lookup failed for user ${senderId}: ${String(err)}`);
213
+ throw err;
214
+ }
215
+ };
216
+ }
217
+ function createDiscordIngressResolver(params) {
218
+ return createChannelIngressResolver({
219
+ channelId: DISCORD_CHANNEL_ID,
220
+ accountId: params.accountId,
221
+ identity: discordIngressIdentity,
222
+ cfg: params.cfg,
223
+ resolveAccessGroupMembership: createDiscordDynamicAccessGroupResolver({
224
+ cfg: params.cfg,
225
+ token: params.token,
226
+ rest: params.rest
227
+ }),
228
+ ...params.readStoreAllowFrom ? { readStoreAllowFrom: params.readStoreAllowFrom } : {},
229
+ ...params.useDefaultPairingStore !== void 0 ? { useDefaultPairingStore: params.useDefaultPairingStore } : {}
230
+ });
231
+ }
232
+ function syntheticAccessGroupMembership(groupName, allowed) {
233
+ return allowed ? {
234
+ kind: "matched",
235
+ groupName,
236
+ source: "dynamic",
237
+ matchedEntryIds: [groupName]
238
+ } : {
239
+ kind: "not-matched",
240
+ groupName,
241
+ source: "dynamic"
242
+ };
243
+ }
244
+ async function resolveDiscordDmCommandAccess(params) {
245
+ return await createDiscordIngressResolver({
246
+ accountId: params.accountId,
247
+ cfg: params.cfg,
248
+ token: params.token,
249
+ rest: params.rest,
250
+ readStoreAllowFrom: params.readStoreAllowFrom,
251
+ useDefaultPairingStore: params.readStoreAllowFrom == null
252
+ }).message({
253
+ subject: createDiscordDmIngressSubject(params.sender),
254
+ conversation: {
255
+ kind: "direct",
256
+ id: params.sender.id
257
+ },
258
+ event: {
259
+ kind: params.eventKind ?? "native-command",
260
+ authMode: "inbound",
261
+ mayPair: true
262
+ },
263
+ dmPolicy: params.dmPolicy,
264
+ groupPolicy: "disabled",
265
+ policy: { mutableIdentifierMatching: params.allowNameMatching ? "enabled" : "disabled" },
266
+ allowFrom: params.configuredAllowFrom,
267
+ command: {
268
+ hasControlCommand: false,
269
+ modeWhenAccessGroupsOff: "configured"
270
+ }
271
+ });
272
+ }
273
+ async function resolveDiscordTextCommandAccess(params) {
274
+ const ownerAllowFrom = (params.ownerAllowFrom ?? []).filter((entry) => entry.trim() !== "*");
275
+ const memberAccessGroup = "discord-member-access";
276
+ const commandGroup = params.memberAccessConfigured ? [`accessGroup:${memberAccessGroup}`] : [];
277
+ const accessGroupMembership = params.memberAccessConfigured ? [syntheticAccessGroupMembership(memberAccessGroup, params.memberAllowed)] : [];
278
+ return (await createDiscordIngressResolver({
279
+ accountId: params.accountId,
280
+ cfg: params.cfg,
281
+ token: params.token,
282
+ rest: params.rest
283
+ }).command({
284
+ subject: createDiscordDmIngressSubject(params.sender),
285
+ conversation: {
286
+ kind: "group",
287
+ id: "discord-command"
288
+ },
289
+ accessGroupMembership,
290
+ dmPolicy: "allowlist",
291
+ groupPolicy: "allowlist",
292
+ policy: { mutableIdentifierMatching: params.allowNameMatching ? "enabled" : "disabled" },
293
+ allowFrom: ownerAllowFrom,
294
+ groupAllowFrom: commandGroup,
295
+ command: {
296
+ allowTextCommands: params.allowTextCommands,
297
+ hasControlCommand: params.hasControlCommand,
298
+ modeWhenAccessGroupsOff: "configured"
299
+ }
300
+ })).commandAccess;
301
+ }
302
+ //#endregion
303
+ //#region extensions/discord/src/monitor/thread-title.ts
304
+ const DEFAULT_THREAD_TITLE_TIMEOUT_MS = 1e4;
305
+ const MAX_THREAD_TITLE_SOURCE_CHARS = 600;
306
+ const MAX_THREAD_TITLE_CHANNEL_NAME_CHARS = 120;
307
+ const MAX_THREAD_TITLE_CHANNEL_DESCRIPTION_CHARS = 320;
308
+ const DISCORD_THREAD_TITLE_MAX_TOKENS = 512;
309
+ const DISCORD_THREAD_TITLE_SYSTEM_PROMPT = "Generate a concise Discord thread title (3-6 words). Return only the title. Use channel context when provided and avoid redundant channel-name words unless needed for clarity.";
310
+ async function generateThreadTitle(params) {
311
+ const sourceText = params.messageText.trim();
312
+ if (!sourceText) return null;
313
+ const prepared = await prepareSimpleCompletionModelForAgent({
314
+ cfg: params.cfg,
315
+ agentId: params.agentId,
316
+ ...params.modelRef ? { modelRef: params.modelRef } : {},
317
+ allowMissingApiKeyModes: ["aws-sdk"]
318
+ });
319
+ if ("error" in prepared) {
320
+ const modelLabel = prepared.selection ? `${prepared.selection.provider}/${prepared.selection.modelId}` : "unknown";
321
+ logVerbose(`thread-title: ${prepared.error} (agent=${params.agentId}, model=${modelLabel})`);
322
+ return null;
323
+ }
324
+ try {
325
+ const userMessage = buildThreadTitleUserMessage({
326
+ sourceText: truncateThreadTitleSourceText(sourceText),
327
+ channelName: params.channelName,
328
+ channelDescription: params.channelDescription
329
+ });
330
+ const timeoutMs = resolveThreadTitleTimeoutMs(params.timeoutMs);
331
+ return normalizeGeneratedThreadTitle(extractAssistantText(await completeThreadTitle({
332
+ model: prepared.model,
333
+ auth: prepared.auth,
334
+ userMessage,
335
+ timeoutMs
336
+ }))) || null;
337
+ } catch (err) {
338
+ logVerbose(`thread-title: title generation failed for agent ${params.agentId}: ${String(err)}`);
339
+ return null;
340
+ }
341
+ }
342
+ async function completeThreadTitle(params) {
343
+ return await withAbortTimeout({
344
+ timeoutMs: params.timeoutMs,
345
+ createTimeoutError: () => /* @__PURE__ */ new Error(`thread-title timed out after ${params.timeoutMs}ms`),
346
+ run: async (signal) => await completeWithPreparedSimpleCompletionModel({
347
+ model: params.model,
348
+ auth: params.auth,
349
+ context: {
350
+ systemPrompt: DISCORD_THREAD_TITLE_SYSTEM_PROMPT,
351
+ messages: [{
352
+ role: "user",
353
+ content: params.userMessage,
354
+ timestamp: Date.now()
355
+ }]
356
+ },
357
+ options: {
358
+ maxTokens: DISCORD_THREAD_TITLE_MAX_TOKENS,
359
+ signal
360
+ }
361
+ })
362
+ });
363
+ }
364
+ function buildThreadTitleUserMessage(params) {
365
+ const channelName = normalizeTitleContextField(params.channelName, MAX_THREAD_TITLE_CHANNEL_NAME_CHARS);
366
+ const channelDescription = normalizeTitleContextField(params.channelDescription, MAX_THREAD_TITLE_CHANNEL_DESCRIPTION_CHARS);
367
+ const messageLines = [];
368
+ if (channelName) messageLines.push(`Channel: ${channelName}`);
369
+ if (channelDescription) messageLines.push(`Channel description: ${channelDescription}`);
370
+ messageLines.push(`Message:\n${params.sourceText}`);
371
+ return messageLines.join("\n\n");
372
+ }
373
+ function truncateThreadTitleSourceText(sourceText) {
374
+ if (sourceText.length <= MAX_THREAD_TITLE_SOURCE_CHARS) return sourceText;
375
+ return `${sourceText.slice(0, MAX_THREAD_TITLE_SOURCE_CHARS)}...`;
376
+ }
377
+ function resolveThreadTitleTimeoutMs(timeoutMs) {
378
+ return Math.max(100, Math.floor(timeoutMs ?? DEFAULT_THREAD_TITLE_TIMEOUT_MS));
379
+ }
380
+ function normalizeGeneratedThreadTitle(raw) {
381
+ const lines = raw.replace(/\r/g, "").split("\n");
382
+ let firstLine = "";
383
+ for (const line of lines) {
384
+ const trimmed = line.trim();
385
+ if (!trimmed) continue;
386
+ if (!firstLine && trimmed.startsWith("```")) continue;
387
+ firstLine = trimmed;
388
+ break;
389
+ }
390
+ return stripThreadTitleWrappers(firstLine);
391
+ }
392
+ function stripThreadTitleWrappers(raw) {
393
+ let current = raw.trim();
394
+ let previous = "";
395
+ while (current && current !== previous) {
396
+ previous = current;
397
+ current = current.replace(/^["'`]+|["'`]+$/g, "").trim();
398
+ current = current.replace(/^\*\*(.+)\*\*$/u, "$1").trim();
399
+ current = current.replace(/^__(.+)__$/u, "$1").trim();
400
+ current = current.replace(/^\*(.+)\*$/u, "$1").trim();
401
+ current = current.replace(/^_(.+)_$/u, "$1").trim();
402
+ current = current.replace(/^~~(.+)~~$/u, "$1").trim();
403
+ }
404
+ return current;
405
+ }
406
+ function normalizeTitleContextField(raw, maxChars) {
407
+ const value = raw?.trim();
408
+ if (!value) return;
409
+ const singleLine = value.replace(/\s+/g, " ");
410
+ if (singleLine.length <= maxChars) return singleLine;
411
+ return `${singleLine.slice(0, maxChars)}...`;
412
+ }
413
+ //#endregion
414
+ //#region extensions/discord/src/monitor/threading.cache.ts
415
+ const DISCORD_THREAD_STARTER_CACHE_TTL_MS = 300 * 1e3;
416
+ const DISCORD_THREAD_STARTER_CACHE_MAX = 500;
417
+ const DISCORD_THREAD_STARTER_CACHE = /* @__PURE__ */ new Map();
418
+ function __resetDiscordThreadStarterCacheForTest() {
419
+ DISCORD_THREAD_STARTER_CACHE.clear();
420
+ }
421
+ function getCachedThreadStarter(key, now) {
422
+ const entry = DISCORD_THREAD_STARTER_CACHE.get(key);
423
+ if (!entry) return;
424
+ if (now - entry.updatedAt > DISCORD_THREAD_STARTER_CACHE_TTL_MS) {
425
+ DISCORD_THREAD_STARTER_CACHE.delete(key);
426
+ return;
427
+ }
428
+ DISCORD_THREAD_STARTER_CACHE.delete(key);
429
+ DISCORD_THREAD_STARTER_CACHE.set(key, {
430
+ ...entry,
431
+ updatedAt: now
432
+ });
433
+ return entry.value;
434
+ }
435
+ function setCachedThreadStarter(key, value, now) {
436
+ DISCORD_THREAD_STARTER_CACHE.delete(key);
437
+ DISCORD_THREAD_STARTER_CACHE.set(key, {
438
+ value,
439
+ updatedAt: now
440
+ });
441
+ while (DISCORD_THREAD_STARTER_CACHE.size > DISCORD_THREAD_STARTER_CACHE_MAX) {
442
+ const iter = DISCORD_THREAD_STARTER_CACHE.keys().next();
443
+ if (iter.done) break;
444
+ DISCORD_THREAD_STARTER_CACHE.delete(iter.value);
445
+ }
446
+ }
447
+ //#endregion
448
+ //#region extensions/discord/src/monitor/threading.starter.ts
449
+ function isDiscordThreadType(type) {
450
+ return type === discord_exports.ChannelType.PublicThread || type === discord_exports.ChannelType.PrivateThread || type === discord_exports.ChannelType.AnnouncementThread;
451
+ }
452
+ function isDiscordForumParentType(parentType) {
453
+ return parentType === discord_exports.ChannelType.GuildForum || parentType === discord_exports.ChannelType.GuildMedia;
454
+ }
455
+ function resolveDiscordThreadChannel(params) {
456
+ if (!params.isGuildMessage) return null;
457
+ const { message, channelInfo } = params;
458
+ const channel = "channel" in message ? message.channel : void 0;
459
+ if (channel && typeof channel === "object" && "isThread" in channel && typeof channel.isThread === "function" && channel.isThread()) return channel;
460
+ if (!isDiscordThreadType(channelInfo?.type)) return null;
461
+ const messageChannelId = params.messageChannelId || resolveDiscordMessageChannelId({ message });
462
+ if (!messageChannelId) return null;
463
+ return {
464
+ id: messageChannelId,
465
+ name: channelInfo?.name ?? void 0,
466
+ parentId: channelInfo?.parentId ?? void 0,
467
+ parent: void 0,
468
+ ownerId: channelInfo?.ownerId ?? void 0
469
+ };
470
+ }
471
+ async function resolveDiscordThreadParentInfo(params) {
472
+ const { threadChannel, channelInfo, client } = params;
473
+ const parent = resolveDiscordChannelParentSafe(threadChannel);
474
+ let parentId = resolveDiscordChannelParentIdSafe(threadChannel) ?? resolveDiscordChannelIdSafe(parent) ?? channelInfo?.parentId ?? void 0;
475
+ if (!parentId && threadChannel.id) parentId = (await resolveDiscordChannelInfo(client, threadChannel.id))?.parentId ?? void 0;
476
+ if (!parentId) return {};
477
+ let parentName = resolveDiscordChannelNameSafe(parent);
478
+ const parentInfo = await resolveDiscordChannelInfo(client, parentId);
479
+ parentName = parentName ?? parentInfo?.name;
480
+ const parentType = parentInfo?.type;
481
+ return {
482
+ id: parentId,
483
+ name: parentName,
484
+ type: parentType
485
+ };
486
+ }
487
+ async function resolveDiscordThreadStarter(params) {
488
+ const cacheKey = params.channel.id;
489
+ const cached = getCachedThreadStarter(cacheKey, Date.now());
490
+ if (cached) return cached;
491
+ try {
492
+ const messageChannelId = resolveDiscordThreadStarterMessageChannelId(params);
493
+ if (!messageChannelId) return null;
494
+ const starter = await fetchDiscordThreadStarterMessage({
495
+ client: params.client,
496
+ messageChannelId,
497
+ threadId: params.channel.id
498
+ });
499
+ if (!starter) return null;
500
+ const payload = buildDiscordThreadStarterPayload({
501
+ starter,
502
+ resolveTimestampMs: params.resolveTimestampMs
503
+ });
504
+ if (!payload) return null;
505
+ setCachedThreadStarter(cacheKey, payload, Date.now());
506
+ return payload;
507
+ } catch {
508
+ return null;
509
+ }
510
+ }
511
+ function resolveDiscordThreadStarterMessageChannelId(params) {
512
+ return isDiscordForumParentType(params.parentType) ? params.channel.id : params.parentId;
513
+ }
514
+ async function fetchDiscordThreadStarterMessage(params) {
515
+ const starter = await getChannelMessage(params.client.rest, params.messageChannelId, params.threadId);
516
+ return starter ? starter : null;
517
+ }
518
+ function buildDiscordThreadStarterPayload(params) {
519
+ const text = resolveDiscordThreadStarterText(params.starter);
520
+ if (!text) return null;
521
+ return {
522
+ text,
523
+ ...resolveDiscordThreadStarterIdentity(params.starter),
524
+ timestamp: params.resolveTimestampMs(params.starter.timestamp) ?? void 0
525
+ };
526
+ }
527
+ function resolveDiscordThreadStarterText(starter) {
528
+ const content = normalizeOptionalString(starter.content) ?? "";
529
+ const embedText = resolveDiscordEmbedText(starter.embeds?.[0]);
530
+ const forwardedText = resolveDiscordForwardedMessagesTextFromSnapshots(starter.message_snapshots);
531
+ return content || embedText || forwardedText;
532
+ }
533
+ function resolveDiscordThreadStarterIdentity(starter) {
534
+ return {
535
+ author: resolveDiscordThreadStarterAuthor(starter),
536
+ authorId: starter.author?.id ?? void 0,
537
+ authorName: starter.author?.username ?? void 0,
538
+ authorTag: resolveDiscordThreadStarterAuthorTag(starter.author),
539
+ memberRoleIds: resolveDiscordThreadStarterRoleIds(starter.member)
540
+ };
541
+ }
542
+ function resolveDiscordThreadStarterAuthor(starter) {
543
+ return starter.member?.nick ?? starter.member?.displayName ?? resolveDiscordThreadStarterAuthorTag(starter.author) ?? starter.author?.username ?? starter.author?.id ?? "Unknown";
544
+ }
545
+ function resolveDiscordThreadStarterAuthorTag(author) {
546
+ if (!author?.username || !author.discriminator) return;
547
+ if (author.discriminator !== "0") return `${author.username}#${author.discriminator}`;
548
+ return author.username;
549
+ }
550
+ function resolveDiscordThreadStarterRoleIds(member) {
551
+ return Array.isArray(member?.roles) ? member.roles : void 0;
552
+ }
553
+ function resolveDiscordReplyTarget(opts) {
554
+ if (opts.replyToMode === "off") return;
555
+ const replyToId = normalizeOptionalString(opts.replyToId);
556
+ if (!replyToId) return;
557
+ if (opts.replyToMode === "all") return replyToId;
558
+ return opts.hasReplied ? void 0 : replyToId;
559
+ }
560
+ function sanitizeDiscordThreadName(rawName, fallbackId) {
561
+ return truncateUtf16Safe(truncateUtf16Safe(rawName.replace(/<@!?\d+>/g, "").replace(/<@&\d+>/g, "").replace(/<#\d+>/g, "").replace(/\s+/g, " ").trim() || `Thread ${fallbackId}`, 80), 100) || `Thread ${fallbackId}`;
562
+ }
563
+ function resolveDiscordReplyDeliveryPlan(params) {
564
+ const originalReplyTarget = params.replyTarget;
565
+ let deliverTarget = originalReplyTarget;
566
+ let replyTarget = originalReplyTarget;
567
+ if (params.createdThreadId) {
568
+ deliverTarget = `channel:${params.createdThreadId}`;
569
+ replyTarget = deliverTarget;
570
+ }
571
+ const allowReference = deliverTarget === originalReplyTarget;
572
+ const replyReference = createReplyReferencePlanner({
573
+ replyToMode: allowReference ? params.replyToMode : "off",
574
+ existingId: params.threadChannel ? params.messageId : void 0,
575
+ startId: params.messageId,
576
+ allowReference
577
+ });
578
+ return {
579
+ deliverTarget,
580
+ replyTarget,
581
+ replyReference
582
+ };
583
+ }
584
+ //#endregion
585
+ //#region extensions/discord/src/monitor/threading.auto-thread.ts
586
+ function resolveTrimmedDiscordMessageChannelId(params) {
587
+ return (params.messageChannelId || resolveDiscordMessageChannelId({ message: params.message })).trim();
588
+ }
589
+ function resolveDiscordAutoThreadContext(params) {
590
+ const createdThreadId = normalizeOptionalStringifiedId(params.createdThreadId) ?? "";
591
+ if (!createdThreadId) return null;
592
+ const messageChannelId = normalizeOptionalString(params.messageChannelId) ?? "";
593
+ if (!messageChannelId) return null;
594
+ const threadSessionKey = buildAgentSessionKey({
595
+ agentId: params.agentId,
596
+ channel: params.channel,
597
+ peer: {
598
+ kind: "channel",
599
+ id: createdThreadId
600
+ }
601
+ });
602
+ const parentSessionKey = buildAgentSessionKey({
603
+ agentId: params.agentId,
604
+ channel: params.channel,
605
+ peer: {
606
+ kind: "channel",
607
+ id: messageChannelId
608
+ }
609
+ });
610
+ return {
611
+ createdThreadId,
612
+ From: `${params.channel}:channel:${createdThreadId}`,
613
+ To: `channel:${createdThreadId}`,
614
+ OriginatingTo: `channel:${createdThreadId}`,
615
+ SessionKey: threadSessionKey,
616
+ ModelParentSessionKey: parentSessionKey,
617
+ ...params.parentInheritanceEnabled === true ? { ParentSessionKey: parentSessionKey } : {}
618
+ };
619
+ }
620
+ async function resolveDiscordAutoThreadReplyPlan(params) {
621
+ const messageChannelId = resolveTrimmedDiscordMessageChannelId(params);
622
+ const originalReplyTarget = `channel:${params.threadChannel?.id ?? (messageChannelId || "unknown")}`;
623
+ const createdThreadId = await maybeCreateDiscordAutoThread({
624
+ client: params.client,
625
+ message: params.message,
626
+ messageChannelId: messageChannelId || void 0,
627
+ channel: params.channel,
628
+ isGuildMessage: params.isGuildMessage,
629
+ channelConfig: params.channelConfig,
630
+ threadChannel: params.threadChannel,
631
+ channelType: params.channelType,
632
+ channelName: params.channelName,
633
+ channelDescription: params.channelDescription,
634
+ baseText: params.baseText,
635
+ combinedBody: params.combinedBody,
636
+ cfg: params.cfg,
637
+ agentId: params.agentId
638
+ });
639
+ const deliveryPlan = resolveDiscordReplyDeliveryPlan({
640
+ replyTarget: originalReplyTarget,
641
+ replyToMode: params.replyToMode,
642
+ messageId: params.message.id,
643
+ threadChannel: params.threadChannel,
644
+ createdThreadId
645
+ });
646
+ const autoThreadContext = params.isGuildMessage ? resolveDiscordAutoThreadContext({
647
+ agentId: params.agentId,
648
+ channel: params.channel,
649
+ messageChannelId,
650
+ createdThreadId,
651
+ parentInheritanceEnabled: params.threadParentInheritanceEnabled
652
+ }) : null;
653
+ return {
654
+ ...deliveryPlan,
655
+ createdThreadId,
656
+ autoThreadContext
657
+ };
658
+ }
659
+ async function maybeCreateDiscordAutoThread(params) {
660
+ if (!params.isGuildMessage) return;
661
+ if (!params.channelConfig?.autoThread) return;
662
+ if (params.threadChannel) return;
663
+ if (params.channelType === discord_exports.ChannelType.GuildForum || params.channelType === discord_exports.ChannelType.GuildMedia || params.channelType === discord_exports.ChannelType.GuildVoice || params.channelType === discord_exports.ChannelType.GuildStageVoice) return;
664
+ const messageChannelId = resolveTrimmedDiscordMessageChannelId(params);
665
+ if (!messageChannelId) return;
666
+ try {
667
+ const rawThreadSource = params.baseText || params.combinedBody || "Thread";
668
+ const threadName = sanitizeDiscordThreadName(rawThreadSource, params.message.id);
669
+ const archiveDuration = params.channelConfig?.autoArchiveDuration ? Number(params.channelConfig.autoArchiveDuration) : 60;
670
+ const createdId = (await createThread(params.client.rest, messageChannelId, { body: {
671
+ name: threadName,
672
+ auto_archive_duration: archiveDuration
673
+ } }, params.message.id))?.id || "";
674
+ if (createdId && params.channelConfig?.autoThreadName === "generated" && params.cfg && params.agentId) {
675
+ const modelRef = resolveDiscordThreadTitleModelRef({
676
+ cfg: params.cfg,
677
+ channel: params.channel,
678
+ agentId: params.agentId,
679
+ threadId: createdId,
680
+ messageChannelId,
681
+ channelName: params.channelName
682
+ });
683
+ maybeRenameDiscordAutoThread({
684
+ client: params.client,
685
+ threadId: createdId,
686
+ currentName: threadName,
687
+ fallbackId: params.message.id,
688
+ sourceText: rawThreadSource,
689
+ modelRef,
690
+ channelName: params.channelName,
691
+ channelDescription: params.channelDescription,
692
+ cfg: params.cfg,
693
+ agentId: params.agentId
694
+ });
695
+ }
696
+ return createdId || void 0;
697
+ } catch (err) {
698
+ logVerbose(`discord: autoThread creation failed for ${messageChannelId}/${params.message.id}: ${String(err)}`);
699
+ try {
700
+ const existingThreadId = (await getChannelMessage(params.client.rest, messageChannelId, params.message.id))?.thread?.id || "";
701
+ if (existingThreadId) {
702
+ logVerbose(`discord: autoThread reusing existing thread ${existingThreadId} on ${messageChannelId}/${params.message.id}`);
703
+ return existingThreadId;
704
+ }
705
+ } catch {}
706
+ return;
707
+ }
708
+ }
709
+ function resolveDiscordThreadTitleModelRef(params) {
710
+ const channel = params.channel?.trim();
711
+ if (!channel) return;
712
+ const parentSessionKey = buildAgentSessionKey({
713
+ agentId: params.agentId,
714
+ channel,
715
+ peer: {
716
+ kind: "channel",
717
+ id: params.messageChannelId
718
+ }
719
+ });
720
+ const channelLabel = params.channelName?.trim();
721
+ const groupChannel = channelLabel ? `#${channelLabel}` : void 0;
722
+ return resolveChannelModelOverride({
723
+ cfg: params.cfg,
724
+ channel,
725
+ groupId: params.threadId,
726
+ groupChatType: "channel",
727
+ groupChannel,
728
+ groupSubject: groupChannel,
729
+ parentSessionKey
730
+ })?.model;
731
+ }
732
+ async function maybeRenameDiscordAutoThread(params) {
733
+ try {
734
+ const fallbackName = sanitizeDiscordThreadName("", params.fallbackId);
735
+ const generated = await generateThreadTitle({
736
+ cfg: params.cfg,
737
+ agentId: params.agentId,
738
+ messageText: params.sourceText,
739
+ modelRef: params.modelRef,
740
+ channelName: params.channelName,
741
+ channelDescription: params.channelDescription
742
+ });
743
+ if (!generated) return;
744
+ const nextName = sanitizeDiscordThreadName(generated, params.fallbackId);
745
+ if (!nextName || nextName === params.currentName || nextName === fallbackName) return;
746
+ await editChannel(params.client.rest, params.threadId, { body: { name: nextName } });
747
+ } catch (err) {
748
+ logVerbose(`discord: autoThread rename failed for ${params.threadId}: ${String(err)}`);
749
+ }
750
+ }
751
+ //#endregion
752
+ //#region extensions/discord/src/monitor/threading.ts
753
+ var threading_exports = /* @__PURE__ */ __exportAll({
754
+ __resetDiscordThreadStarterCacheForTest: () => __resetDiscordThreadStarterCacheForTest,
755
+ maybeCreateDiscordAutoThread: () => maybeCreateDiscordAutoThread,
756
+ resolveDiscordAutoThreadContext: () => resolveDiscordAutoThreadContext,
757
+ resolveDiscordAutoThreadReplyPlan: () => resolveDiscordAutoThreadReplyPlan,
758
+ resolveDiscordReplyDeliveryPlan: () => resolveDiscordReplyDeliveryPlan,
759
+ resolveDiscordReplyTarget: () => resolveDiscordReplyTarget,
760
+ resolveDiscordThreadChannel: () => resolveDiscordThreadChannel,
761
+ resolveDiscordThreadParentInfo: () => resolveDiscordThreadParentInfo,
762
+ resolveDiscordThreadStarter: () => resolveDiscordThreadStarter,
763
+ sanitizeDiscordThreadName: () => sanitizeDiscordThreadName
764
+ });
765
+ //#endregion
150
766
  //#region extensions/discord/src/monitor/thread-channel-context.ts
151
767
  function isDiscordThreadChannelType(type) {
152
768
  return type === discord_exports.ChannelType.PublicThread || type === discord_exports.ChannelType.PrivateThread || type === discord_exports.ChannelType.AnnouncementThread;
@@ -694,6 +1310,35 @@ var DiscordThreadUpdateListener = class extends ThreadUpdateListener {
694
1310
  }
695
1311
  };
696
1312
  //#endregion
1313
+ //#region extensions/discord/src/monitor/dm-command-decision.ts
1314
+ async function handleDiscordDmCommandDecision(params) {
1315
+ if (params.senderAccess.decision === "allow") return true;
1316
+ if (params.senderAccess.decision === "pairing") {
1317
+ const upsertPairingRequest = params.upsertPairingRequest ?? upsertChannelPairingRequest;
1318
+ const result = await createChannelPairingChallengeIssuer({
1319
+ channel: "discord",
1320
+ upsertPairingRequest: async ({ id, meta }) => await upsertPairingRequest({
1321
+ channel: "discord",
1322
+ id,
1323
+ accountId: params.accountId,
1324
+ meta
1325
+ })
1326
+ })({
1327
+ senderId: params.sender.id,
1328
+ senderIdLine: `Your Discord user id: ${params.sender.id}`,
1329
+ meta: {
1330
+ tag: params.sender.tag,
1331
+ name: params.sender.name
1332
+ },
1333
+ sendPairingReply: async () => {}
1334
+ });
1335
+ if (result.created && result.code) await params.onPairingCreated(result.code);
1336
+ return false;
1337
+ }
1338
+ await params.onUnauthorized();
1339
+ return false;
1340
+ }
1341
+ //#endregion
697
1342
  //#region extensions/discord/src/monitor/native-command-reply.ts
698
1343
  const DISCORD_EMPTY_VISIBLE_REPLY_WARNING = "⚠️ Command produced no visible reply.";
699
1344
  function isDiscordUnknownInteraction(error) {
@@ -794,6 +1439,78 @@ async function deliverDiscordInteractionReply(params) {
794
1439
  }
795
1440
  }
796
1441
  //#endregion
1442
+ //#region extensions/discord/src/monitor/route-resolution.ts
1443
+ function buildDiscordRoutePeer(params) {
1444
+ return {
1445
+ kind: params.isDirectMessage ? "direct" : params.isGroupDm ? "group" : "channel",
1446
+ id: params.isDirectMessage ? params.directUserId?.trim() || params.conversationId : params.conversationId
1447
+ };
1448
+ }
1449
+ function resolveDiscordConversationRoute(params) {
1450
+ return resolveAgentRoute({
1451
+ cfg: params.cfg,
1452
+ channel: "discord",
1453
+ accountId: params.accountId,
1454
+ guildId: params.guildId ?? void 0,
1455
+ memberRoleIds: params.memberRoleIds,
1456
+ peer: params.peer,
1457
+ parentPeer: params.parentConversationId ? {
1458
+ kind: "channel",
1459
+ id: params.parentConversationId
1460
+ } : void 0
1461
+ });
1462
+ }
1463
+ function resolveDiscordBoundConversationRoute(params) {
1464
+ return resolveDiscordEffectiveRoute({
1465
+ route: resolveDiscordConversationRoute({
1466
+ cfg: params.cfg,
1467
+ accountId: params.accountId,
1468
+ guildId: params.guildId,
1469
+ memberRoleIds: params.memberRoleIds,
1470
+ peer: buildDiscordRoutePeer({
1471
+ isDirectMessage: params.isDirectMessage,
1472
+ isGroupDm: params.isGroupDm,
1473
+ directUserId: params.directUserId,
1474
+ conversationId: params.conversationId
1475
+ }),
1476
+ parentConversationId: params.parentConversationId
1477
+ }),
1478
+ boundSessionKey: params.boundSessionKey,
1479
+ configuredRoute: params.configuredRoute,
1480
+ matchedBy: params.matchedBy
1481
+ });
1482
+ }
1483
+ function resolveDiscordEffectiveRoute(params) {
1484
+ const boundSessionKey = params.boundSessionKey?.trim();
1485
+ if (!boundSessionKey) return params.configuredRoute?.route ?? params.route;
1486
+ return {
1487
+ ...params.route,
1488
+ sessionKey: boundSessionKey,
1489
+ agentId: resolveAgentIdFromSessionKey(boundSessionKey),
1490
+ lastRoutePolicy: deriveLastRoutePolicy({
1491
+ sessionKey: boundSessionKey,
1492
+ mainSessionKey: params.route.mainSessionKey
1493
+ }),
1494
+ ...params.matchedBy ? { matchedBy: params.matchedBy } : {}
1495
+ };
1496
+ }
1497
+ function hasExplicitRuntimeBindingIntent(record) {
1498
+ if (record.targetKind === "subagent") return true;
1499
+ if (isAcpSessionKey(record.targetSessionKey) || isSubagentSessionKey(record.targetSessionKey)) return true;
1500
+ const metadata = record.metadata;
1501
+ if (!metadata || typeof metadata !== "object") return false;
1502
+ return typeof metadata.boundBy === "string" || typeof metadata.label === "string" || typeof metadata.threadName === "string" || metadata.pluginBindingOwner === "plugin";
1503
+ }
1504
+ function shouldIgnoreStaleDiscordRouteBinding(params) {
1505
+ const bindingRecord = params.bindingRecord;
1506
+ const boundSessionKey = bindingRecord?.targetSessionKey?.trim();
1507
+ if (!bindingRecord || !boundSessionKey || hasExplicitRuntimeBindingIntent(bindingRecord)) return false;
1508
+ const bound = parseAgentSessionKey(boundSessionKey);
1509
+ const routed = parseAgentSessionKey(params.route.sessionKey);
1510
+ if (!bound || !routed || bound.rest !== routed.rest) return false;
1511
+ return bound.agentId !== params.route.agentId;
1512
+ }
1513
+ //#endregion
797
1514
  //#region extensions/discord/src/monitor/native-command-route.ts
798
1515
  async function resolveDiscordNativeInteractionRouteState(params) {
799
1516
  const route = resolveDiscordBoundConversationRoute({
@@ -1205,6 +1922,12 @@ function buildDiscordNativeCommandContext(params) {
1205
1922
  MessageThreadId: params.isThreadChannel ? params.channelId : void 0,
1206
1923
  Timestamp: params.timestampMs ?? Date.now(),
1207
1924
  CommandAuthorized: params.commandAuthorized,
1925
+ CommandTurn: {
1926
+ kind: "native",
1927
+ source: "native",
1928
+ authorized: params.commandAuthorized,
1929
+ body: params.prompt
1930
+ },
1208
1931
  CommandSource: "native",
1209
1932
  OriginatingChannel: "discord",
1210
1933
  OriginatingTo: resolveDiscordConversationIdentity({
@@ -3778,6 +4501,12 @@ var GatewayPlugin = class extends Plugin {
3778
4501
  }
3779
4502
  };
3780
4503
  //#endregion
4504
+ //#region extensions/discord/src/voice/config.ts
4505
+ function resolveDiscordVoiceEnabled(voice) {
4506
+ if (voice?.enabled !== void 0) return voice.enabled;
4507
+ return voice !== void 0;
4508
+ }
4509
+ //#endregion
3781
4510
  //#region extensions/discord/src/monitor/presence.ts
3782
4511
  const DEFAULT_CUSTOM_ACTIVITY_TYPE$1 = 4;
3783
4512
  const CUSTOM_STATUS_NAME$1 = "Custom Status";
@@ -5258,6 +5987,85 @@ function runDiscordCommandDeployInBackground(params) {
5258
5987
  });
5259
5988
  }
5260
5989
  //#endregion
5990
+ //#region extensions/discord/src/voice/access.ts
5991
+ async function authorizeDiscordVoiceIngress(params) {
5992
+ const groupPolicy = params.groupPolicy ?? resolveOpenProviderRuntimeGroupPolicy({
5993
+ providerConfigPresent: params.cfg.channels?.discord !== void 0,
5994
+ groupPolicy: params.discordConfig.groupPolicy,
5995
+ defaultGroupPolicy: params.cfg.channels?.defaults?.groupPolicy
5996
+ }).groupPolicy;
5997
+ const guildInfo = resolveDiscordGuildEntry({
5998
+ guild: params.guild ?? {
5999
+ id: params.guildId,
6000
+ ...params.guildName ? { name: params.guildName } : {}
6001
+ },
6002
+ guildId: params.guildId,
6003
+ guildEntries: params.discordConfig.guilds
6004
+ });
6005
+ const channelConfig = params.channelId ? resolveDiscordChannelConfigWithFallback({
6006
+ guildInfo,
6007
+ channelId: params.channelId,
6008
+ channelName: params.channelName,
6009
+ channelSlug: params.channelSlug,
6010
+ parentId: params.parentId,
6011
+ parentName: params.parentName,
6012
+ parentSlug: params.parentSlug,
6013
+ scope: params.scope
6014
+ }) : null;
6015
+ if (channelConfig?.enabled === false) return {
6016
+ ok: false,
6017
+ message: "This channel is disabled."
6018
+ };
6019
+ const channelAllowlistConfigured = Boolean(guildInfo?.channels) && Object.keys(guildInfo?.channels ?? {}).length > 0;
6020
+ if (!params.channelId && groupPolicy === "allowlist" && channelAllowlistConfigured) return {
6021
+ ok: false,
6022
+ message: `${params.channelLabel ?? "This channel"} is not allowlisted for voice commands.`
6023
+ };
6024
+ const channelAllowed = channelConfig ? channelConfig.allowed : !channelAllowlistConfigured;
6025
+ if (!isDiscordGroupAllowedByPolicy({
6026
+ groupPolicy,
6027
+ guildAllowlisted: Boolean(guildInfo),
6028
+ channelAllowlistConfigured,
6029
+ channelAllowed
6030
+ }) || channelConfig?.allowed === false) return {
6031
+ ok: false,
6032
+ message: `${params.channelLabel ?? "This channel"} is not allowlisted for voice commands.`
6033
+ };
6034
+ const { hasAccessRestrictions, memberAllowed } = resolveDiscordMemberAccessState({
6035
+ channelConfig,
6036
+ guildInfo,
6037
+ memberRoleIds: params.memberRoleIds,
6038
+ sender: params.sender,
6039
+ allowNameMatching: false
6040
+ });
6041
+ const { ownerAllowList, ownerAllowed } = resolveDiscordOwnerAccess({
6042
+ allowFrom: params.ownerAllowFrom ?? params.discordConfig.allowFrom ?? params.discordConfig.dm?.allowFrom,
6043
+ sender: params.sender,
6044
+ allowNameMatching: false
6045
+ });
6046
+ const useAccessGroups = params.useAccessGroups ?? params.cfg.commands?.useAccessGroups !== false;
6047
+ return resolveCommandAuthorizedFromAuthorizers({
6048
+ useAccessGroups,
6049
+ authorizers: useAccessGroups ? [{
6050
+ configured: ownerAllowList != null,
6051
+ allowed: ownerAllowed
6052
+ }, {
6053
+ configured: hasAccessRestrictions,
6054
+ allowed: memberAllowed
6055
+ }] : [{
6056
+ configured: hasAccessRestrictions,
6057
+ allowed: memberAllowed
6058
+ }],
6059
+ modeWhenAccessGroupsOff: "configured"
6060
+ }) ? {
6061
+ ok: true,
6062
+ channelConfig
6063
+ } : {
6064
+ ok: false,
6065
+ message: "You are not authorized to use this command."
6066
+ };
6067
+ }
6068
+ //#endregion
5261
6069
  //#region extensions/discord/src/voice/command.ts
5262
6070
  const VOICE_CHANNEL_TYPES = [ChannelType.GuildVoice, ChannelType.GuildStageVoice];
5263
6071
  async function authorizeVoiceCommand(interaction, params, options) {
@@ -6054,15 +6862,195 @@ function resolveDiscordInteractionId(interaction) {
6054
6862
  const AGENT_BUTTON_KEY = "agent";
6055
6863
  const AGENT_SELECT_KEY = "agentsel";
6056
6864
  //#endregion
6865
+ //#region extensions/discord/src/monitor/reply-context.ts
6866
+ function resolveReplyContext(message, resolveDiscordMessageText) {
6867
+ const referenced = message.referencedMessage;
6868
+ if (!referenced?.author) return null;
6869
+ const referencedText = resolveDiscordMessageText(referenced, { includeForwarded: true });
6870
+ if (!referencedText) return null;
6871
+ const sender = resolveDiscordSenderIdentity({
6872
+ author: referenced.author,
6873
+ pluralkitInfo: null
6874
+ });
6875
+ return {
6876
+ id: referenced.id,
6877
+ channelId: referenced.channelId,
6878
+ sender: sender.tag ?? sender.label ?? "unknown",
6879
+ senderId: referenced.author.id,
6880
+ senderName: referenced.author.username ?? void 0,
6881
+ senderTag: sender.tag ?? void 0,
6882
+ memberRoleIds: (() => {
6883
+ const roles = referenced.member?.roles;
6884
+ return Array.isArray(roles) ? roles.map((roleId) => roleId) : void 0;
6885
+ })(),
6886
+ body: referencedText,
6887
+ timestamp: resolveTimestampMs(referenced.timestamp)
6888
+ };
6889
+ }
6890
+ function buildDirectLabel(author, tagOverride) {
6891
+ return `${(tagOverride?.trim() || resolveDiscordSenderIdentity({
6892
+ author,
6893
+ pluralkitInfo: null
6894
+ }).tag) ?? "unknown"} user id:${author.id}`;
6895
+ }
6896
+ function buildGuildLabel(params) {
6897
+ const { guild, channelName, channelId } = params;
6898
+ return `${guild?.name ?? "Guild"} #${channelName} channel id:${channelId}`;
6899
+ }
6900
+ //#endregion
6901
+ //#region extensions/discord/src/monitor/reply-safety.ts
6902
+ const DISCORD_INTERNAL_TRACE_LINE_RE = /^(?:>\s*)?(?:📊|🛠️|📖|📝|🔍|🔎|⚙️)\s*(?:Session Status|Exec|Read|Edit|Write|Patch|Search|Open|Click|Find|Screenshot|Update Plan|Tool Call|Tool Result|Function Call|Shell|Command)\s*:/i;
6903
+ const DISCORD_INTERNAL_COMPACT_COMMAND_TRACE_LINE_RE = /^(?:>\s*)?🛠️\s*(?:(?:(?:elevated|pty)\b\s*(?:·|,)\s*)+)?(?:`{1,2}\s*\S|(?:run|check|fetch|pull|push|view|show|list|switch|create|merge|rebase|stage|restore|reset|stash|search|find|print|copy|move|remove|install|start|cd|git|pnpm|npm|yarn|bun|node|python|python3|bash|sh)\b)/i;
6904
+ const DISCORD_INTERNAL_CHANNEL_LINE_RE = /^(?:>\s*)?(?:analysis|commentary|tool[-_ ]?call|tool[-_ ]?result|function[-_ ]?call|thinking|reasoning)\s*[:=]/i;
6905
+ function hasNonEmptyRecord(value) {
6906
+ return Boolean(value && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length > 0);
6907
+ }
6908
+ function hasInteractiveOrPresentationBlocks(value) {
6909
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
6910
+ const record = value;
6911
+ if (typeof record.title === "string" && record.title.trim().length > 0) return true;
6912
+ return Array.isArray(record.blocks) && record.blocks.length > 0;
6913
+ }
6914
+ function hasNonTextReplyPayloadContent(payload) {
6915
+ return payload.audioAsVoice === true || hasNonEmptyRecord(payload.channelData) || hasInteractiveOrPresentationBlocks(payload.interactive) || hasInteractiveOrPresentationBlocks(payload.presentation);
6916
+ }
6917
+ function stripDiscordInternalTraceLines(text) {
6918
+ let inFence = false;
6919
+ const kept = [];
6920
+ for (const line of text.split(/\r?\n/)) {
6921
+ if (/^\s*```/.test(line)) {
6922
+ inFence = !inFence;
6923
+ kept.push(line);
6924
+ continue;
6925
+ }
6926
+ if (!inFence) {
6927
+ const trimmed = line.trim();
6928
+ if (DISCORD_INTERNAL_TRACE_LINE_RE.test(trimmed) || DISCORD_INTERNAL_COMPACT_COMMAND_TRACE_LINE_RE.test(trimmed) || DISCORD_INTERNAL_CHANNEL_LINE_RE.test(trimmed)) continue;
6929
+ }
6930
+ kept.push(line);
6931
+ }
6932
+ return kept.join("\n");
6933
+ }
6934
+ function collapseExcessBlankLines(text) {
6935
+ return text.replace(/[ \t]+\n/g, "\n").replace(/\n{3,}/g, "\n\n");
6936
+ }
6937
+ function sanitizeDiscordFrontChannelText(text) {
6938
+ return collapseExcessBlankLines(stripDiscordInternalTraceLines(sanitizeAssistantVisibleText(text))).trim();
6939
+ }
6940
+ function sanitizeDiscordFrontChannelReplyPayloads(payloads) {
6941
+ const safePayloads = [];
6942
+ for (const payload of payloads) {
6943
+ const safeText = typeof payload.text === "string" ? sanitizeDiscordFrontChannelText(payload.text) : payload.text;
6944
+ const nextPayload = safeText === payload.text ? payload : {
6945
+ ...payload,
6946
+ text: safeText || void 0
6947
+ };
6948
+ if (!resolveSendableOutboundReplyParts(nextPayload).hasContent && !hasNonTextReplyPayloadContent(nextPayload)) continue;
6949
+ safePayloads.push(nextPayload);
6950
+ }
6951
+ return safePayloads;
6952
+ }
6953
+ //#endregion
6954
+ //#region extensions/discord/src/monitor/reply-delivery.ts
6955
+ function resolveTargetChannelId(target) {
6956
+ if (!target.startsWith("channel:")) return;
6957
+ return target.slice(8).trim() || void 0;
6958
+ }
6959
+ function resolveBoundThreadBinding(params) {
6960
+ const sessionKey = params.sessionKey?.trim();
6961
+ if (!params.threadBindings || !sessionKey) return;
6962
+ const targetChannelId = resolveTargetChannelId(params.target);
6963
+ if (!targetChannelId) return;
6964
+ return params.threadBindings.listBySessionKey(sessionKey).find((entry) => entry.threadId === targetChannelId);
6965
+ }
6966
+ function resolveBindingIdentity(cfg, binding) {
6967
+ if (!binding) return;
6968
+ const identity = { name: (`🤖 ${binding.label?.trim() || binding.agentId}`.trim() || "🤖 agent").slice(0, 80) };
6969
+ try {
6970
+ const avatar = resolveAgentAvatar(cfg, binding.agentId);
6971
+ if (avatar.kind === "remote") identity.avatarUrl = avatar.url;
6972
+ } catch {}
6973
+ return identity;
6974
+ }
6975
+ function createDiscordDeliveryDeps(params) {
6976
+ return {
6977
+ discord: (to, text, opts) => sendMessageDiscord(to, text, {
6978
+ ...opts,
6979
+ cfg: opts?.cfg ?? params.cfg,
6980
+ token: params.token,
6981
+ rest: params.rest
6982
+ }),
6983
+ discordVoice: (to, audioPath, opts) => sendVoiceMessageDiscord(to, audioPath, {
6984
+ ...opts,
6985
+ cfg: opts?.cfg ?? params.cfg,
6986
+ token: params.token,
6987
+ rest: params.rest
6988
+ })
6989
+ };
6990
+ }
6991
+ function resolveDiscordDeliveryOptions(params) {
6992
+ const binding = resolveBoundThreadBinding({
6993
+ threadBindings: params.threadBindings,
6994
+ sessionKey: params.sessionKey,
6995
+ target: params.target
6996
+ });
6997
+ return {
6998
+ to: binding ? `channel:${binding.channelId}` : params.target,
6999
+ threadId: binding?.threadId,
7000
+ agentId: binding?.agentId,
7001
+ identity: resolveBindingIdentity(params.cfg, binding),
7002
+ mediaAccess: params.mediaLocalRoots?.length ? { localRoots: params.mediaLocalRoots } : void 0,
7003
+ replyToMode: params.replyToMode ?? "all",
7004
+ formatting: {
7005
+ textLimit: params.textLimit,
7006
+ maxLinesPerMessage: params.maxLinesPerMessage,
7007
+ tableMode: params.tableMode,
7008
+ chunkMode: params.chunkMode
7009
+ }
7010
+ };
7011
+ }
7012
+ async function deliverDiscordReply(params) {
7013
+ params.runtime;
7014
+ const delivery = resolveDiscordDeliveryOptions(params);
7015
+ const payloads = sanitizeDiscordFrontChannelReplyPayloads(params.replies);
7016
+ if (payloads.length === 0) return;
7017
+ const send = await sendDurableMessageBatch({
7018
+ cfg: params.cfg,
7019
+ channel: "discord",
7020
+ to: delivery.to,
7021
+ accountId: params.accountId,
7022
+ payloads,
7023
+ replyToId: normalizeOptionalString(params.replyToId),
7024
+ replyToMode: delivery.replyToMode,
7025
+ formatting: delivery.formatting,
7026
+ threadId: delivery.threadId,
7027
+ identity: delivery.identity,
7028
+ deps: createDiscordDeliveryDeps({
7029
+ cfg: params.cfg,
7030
+ token: params.token,
7031
+ rest: params.rest
7032
+ }),
7033
+ mediaAccess: delivery.mediaAccess,
7034
+ session: buildOutboundSessionContext({
7035
+ cfg: params.cfg,
7036
+ sessionKey: params.sessionKey,
7037
+ agentId: delivery.agentId,
7038
+ requesterAccountId: params.accountId
7039
+ })
7040
+ });
7041
+ if (send.status === "failed" || send.status === "partial_failed") throw send.error;
7042
+ if ((send.status === "sent" ? send.results : []).length === 0) throw new Error(`discord final reply produced no delivered message for ${delivery.to}`);
7043
+ }
7044
+ //#endregion
6057
7045
  //#region extensions/discord/src/monitor/agent-components.dispatch.ts
6058
7046
  let conversationRuntimePromise$1;
6059
7047
  let typingRuntimePromise;
6060
7048
  async function loadConversationRuntime$1() {
6061
- conversationRuntimePromise$1 ??= import("./agent-components.runtime-zT8qPsnM.js");
7049
+ conversationRuntimePromise$1 ??= import("./agent-components.runtime-CEMbMQcQ.js");
6062
7050
  return await conversationRuntimePromise$1;
6063
7051
  }
6064
7052
  async function loadTypingRuntime() {
6065
- typingRuntimePromise ??= import("./typing-_jePdFIw.js").then((n) => n.n);
7053
+ typingRuntimePromise ??= import("./typing-C_8U8J7E.js").then((n) => n.n);
6066
7054
  return await typingRuntimePromise;
6067
7055
  }
6068
7056
  function buildDiscordComponentConversationLabel(params) {
@@ -6200,6 +7188,12 @@ async function dispatchDiscordComponentEvent(params) {
6200
7188
  Surface: "discord",
6201
7189
  WasMentioned: true,
6202
7190
  CommandAuthorized: commandAuthorized,
7191
+ CommandTurn: {
7192
+ kind: "text-slash",
7193
+ source: "text",
7194
+ authorized: commandAuthorized,
7195
+ body: eventText
7196
+ },
6203
7197
  CommandSource: "text",
6204
7198
  MessageSid: interaction.rawData.id,
6205
7199
  Timestamp: timestamp,
@@ -6349,7 +7343,7 @@ async function dispatchDiscordPluginInteractiveHandler(params) {
6349
7343
  //#region extensions/discord/src/monitor/agent-components.plugin-interactive.ts
6350
7344
  let conversationRuntimePromise;
6351
7345
  async function loadConversationRuntime() {
6352
- conversationRuntimePromise ??= import("./agent-components.runtime-zT8qPsnM.js");
7346
+ conversationRuntimePromise ??= import("./agent-components.runtime-CEMbMQcQ.js");
6353
7347
  return await conversationRuntimePromise;
6354
7348
  }
6355
7349
  async function dispatchPluginDiscordInteractiveEvent(params) {
@@ -6475,7 +7469,7 @@ async function dispatchPluginDiscordInteractiveEvent(params) {
6475
7469
  //#region extensions/discord/src/monitor/agent-components.handlers.ts
6476
7470
  let componentsRuntimePromise;
6477
7471
  async function loadComponentsRuntime() {
6478
- componentsRuntimePromise ??= import("./components-Dxq2mU57.js").then((n) => n.t);
7472
+ componentsRuntimePromise ??= import("./components-Cgm7XT8-.js").then((n) => n.t);
6479
7473
  return await componentsRuntimePromise;
6480
7474
  }
6481
7475
  async function handleDiscordComponentEvent(params) {
@@ -7982,7 +8976,7 @@ function logDiscordStartupPhase(params) {
7982
8976
  });
7983
8977
  }
7984
8978
  async function loadDiscordVoiceRuntime() {
7985
- const promise = discordVoiceRuntimePromise ?? import("./manager.runtime-DqMGETqp.js");
8979
+ const promise = discordVoiceRuntimePromise ?? import("./manager.runtime-DauS2xA3.js");
7986
8980
  discordVoiceRuntimePromise = promise;
7987
8981
  try {
7988
8982
  return await promise;
@@ -7992,7 +8986,7 @@ async function loadDiscordVoiceRuntime() {
7992
8986
  }
7993
8987
  }
7994
8988
  async function loadDiscordProviderSessionRuntime() {
7995
- const promise = discordProviderSessionRuntimePromise ?? import("./provider-session.runtime-BZyP90-i.js");
8989
+ const promise = discordProviderSessionRuntimePromise ?? import("./provider-session.runtime-DMxaLPB3.js");
7996
8990
  discordProviderSessionRuntimePromise = promise;
7997
8991
  try {
7998
8992
  return await promise;
@@ -8362,4 +9356,4 @@ async function monitorDiscordProvider(opts = {}) {
8362
9356
  }
8363
9357
  }
8364
9358
  //#endregion
8365
- export { createDiscordNativeCommand as a, waitForDiscordGatewayPluginRegistration as i, createDiscordGatewayPlugin as n, registerDiscordListener as o, resolveDiscordGatewayIntents as r, monitorDiscordProvider as t };
9359
+ export { resolveDiscordDmCommandAccess as C, sanitizeDiscordThreadName as S, registerDiscordListener as _, resolveReplyContext as a, resolveDiscordReplyTarget as b, resolveDiscordGatewayIntents as c, createDiscordNativeCommand as d, buildDiscordRoutePeer as f, handleDiscordDmCommandDecision as g, shouldIgnoreStaleDiscordRouteBinding as h, buildGuildLabel as i, waitForDiscordGatewayPluginRegistration as l, resolveDiscordEffectiveRoute as m, deliverDiscordReply as n, authorizeDiscordVoiceIngress as o, resolveDiscordConversationRoute as p, buildDirectLabel as r, createDiscordGatewayPlugin as s, monitorDiscordProvider as t, resolveDiscordVoiceEnabled as u, threading_exports as v, resolveDiscordTextCommandAccess as w, resolveDiscordThreadStarter as x, resolveDiscordAutoThreadReplyPlan as y };