@openclaw/discord 2026.8.1-beta.2 → 2026.8.1-beta.3
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.
- package/dist/{account-inspect-CqzrH14k.js → account-inspect-D5xmUpnj.js} +1 -1
- package/dist/account-inspect-api.js +1 -1
- package/dist/accounts-DNl-oCEw.js +371 -0
- package/dist/action-runtime-api.js +1 -1
- package/dist/{activities-api-DS7vpdtp.js → activities-api-KCBAmWxD.js} +133 -175
- package/dist/activities-api.js +1 -1
- package/dist/api.js +17 -17
- package/dist/{approval-handler.runtime-B6yEV79q.js → approval-handler.runtime-B12RCYr8.js} +6 -6
- package/dist/{approval-message-safety-AcIxvrf3.js → approval-message-safety-XGFPbDoI.js} +89 -3
- package/dist/{audit-Db-rlntl.js → audit-Yc7eZDd6.js} +5 -5
- package/dist/{channel-actions-5s_hjYKd.js → channel-actions-Dr2QI8Bf.js} +10 -6
- package/dist/{channel-actions.runtime-CLKrx6tr.js → channel-actions.runtime-CODTvo7c.js} +53 -68
- package/dist/{channel-CnnbJSt5.js → channel-cXYzGc4L.js} +74 -50
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.setup-BFAO-V1P.js → channel.setup-CSiwnMgs.js} +5 -5
- package/dist/{outbound-session-route-DxLkrgKQ.js → components-ezGKo_Yh.js} +3 -49
- package/dist/{config-schema-BgEskFAs.js → config-schema-DC5kDtQ5.js} +33 -7
- package/dist/conversation-binding-route-D6rCQ5S0.js +43 -0
- package/dist/{directory-config-BVX7Cflc.js → directory-config-XyCfoqLg.js} +2 -2
- package/dist/directory-contract-api.js +1 -1
- package/dist/{directory-live-DGIGxpIo.js → directory-live-Df0NbFJB.js} +3 -3
- package/dist/{doctor-BzC-TLnB.js → doctor-DYY31GrO.js} +33 -12
- package/dist/doctor-contract-api.js +3 -3
- package/dist/{handle-action.guild-admin-BNVTUISF.js → handle-action.guild-admin-6Tvvinsa.js} +2 -2
- package/dist/index.js +3 -4
- package/dist/{message-handler-Unk_f10F.js → message-handler-B61q5MOF.js} +82 -6
- package/dist/{message-handler.preflight-C9zecxR9.js → message-handler.preflight-Bzg_Hawz.js} +36 -46
- package/dist/{message-handler.process-DWQ6UHHu.js → message-handler.process--4_712Ec.js} +159 -183
- package/dist/{message-utils-BSCPVgy0.js → message-utils-BXLLnFl6.js} +31 -32
- package/dist/{outbound-adapter-D9nRivT1.js → outbound-adapter-DxHTOqiN.js} +83 -53
- package/dist/{outbound-components-cTzwBJ60.js → outbound-components-B2PL0ooH.js} +3 -3
- package/dist/owner-access-Bg41VzAf.js +107 -0
- package/dist/{pluralkit-DdiJ9KMK.js → pluralkit-dUl4v1X3.js} +1 -1
- package/dist/{probe-Bl-k5_Ku.js → probe-BTdtVRwU.js} +1 -1
- package/dist/{probe.runtime-M9fREKvp.js → probe.runtime-Dq5-PRKT.js} +1 -1
- package/dist/{provider-DvSNb-2v.js → provider-DlK_ynqt.js} +356 -967
- package/dist/{provider-session.runtime-BUEqD0rA.js → provider-session.runtime-CvvphHvs.js} +3 -3
- package/dist/provider.runtime-CzKGRiAF.js +2 -0
- package/dist/{realtime-session.runtime-C7wen-aF.js → realtime-session.runtime-ysbMG8v7.js} +24 -13
- package/dist/{resolve-allowlist-common-D04lpEzb.js → resolve-allowlist-common-DIVXbD1P.js} +2 -2
- package/dist/{resolve-channels-Dm7jEeg6.js → resolve-channels-CGeUoIqb.js} +3 -3
- package/dist/{resolve-users-bktrCUUU.js → resolve-users-BtKxLUZv.js} +2 -2
- package/dist/{retry-CLpJcXXf.js → retry-DNsVTeTo.js} +18 -64
- package/dist/{runtime-DoHjckYm.js → runtime-CQovMsH3.js} +9 -10
- package/dist/{runtime-DGsSyDTS.js → runtime-D71_VFLr.js} +29 -43
- package/dist/runtime-api.actions.js +2 -2
- package/dist/runtime-api.js +22 -21
- package/dist/runtime-api.lookup.js +5 -5
- package/dist/runtime-api.monitor-CzeTYF32.js +6 -0
- package/dist/runtime-api.monitor.js +6 -5
- package/dist/runtime-api.send.js +6 -6
- package/dist/runtime-api.threads.js +4 -4
- package/dist/{sdk-runtime-QpY8PvCh.js → sdk-runtime-37OU6_Yh.js} +3 -4
- package/dist/{secret-config-contract-B1akrlyY.js → secret-config-contract-B3i6WxV5.js} +53 -25
- package/dist/secret-contract-api.js +1 -1
- package/dist/security-audit-contract-api.js +1 -1
- package/dist/{security-audit.runtime-CPN0xFYz.js → security-audit.runtime-BVKF9VtY.js} +1 -1
- package/dist/{send-B7Q6Oc1I.js → send-rQIffSYu.js} +10 -10
- package/dist/{send.components-iJyFXw9L.js → send.components-ChK1wS7w.js} +14 -24
- package/dist/{send.outbound-DS5tHwfR.js → send.outbound-HIkgji_7.js} +26 -16
- package/dist/{send.reactions-BAn0iiVQ.js → send.reactions-gmJ6yFPo.js} +2 -2
- package/dist/{send.receipt-IPI1p-SP.js → send.receipt-Cnhoautb.js} +11 -1
- package/dist/{send.shared-BmwFjW6T.js → send.shared-B3fpaLWJ.js} +104 -104
- package/dist/{sender-identity-QtalnCYv.js → sender-identity-BJtfyise.js} +1 -1
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{shared-BIXIX6uJ.js → shared-CaAaoksy.js} +15 -10
- package/dist/subagent-hooks-CNT2ZJTJ.js +49 -0
- package/dist/subagent-hooks-api.js +2 -2
- package/dist/{subagent-progress-DhaE_h8a.js → subagent-progress-FPLqBY1s.js} +5 -4
- package/dist/{system-events-CTqDf6_s.js → system-events-Nuwoq_au.js} +2 -2
- package/dist/{target-resolver-maOKSqO0.js → target-resolver-DIXShHaZ.js} +3 -3
- package/dist/targets-B2pf49zc.js +3 -0
- package/dist/{thread-bindings-3L8p82GV.js → thread-bindings-VlymUnbz.js} +29 -26
- package/dist/{thread-bindings.manager-DCIH6WDC.js → thread-bindings.manager-CngsgErq.js} +9 -8
- package/dist/{thread-bindings.session-updates-bJ2KQFY6.js → thread-bindings.session-updates-CJb-BpPL.js} +1 -1
- package/dist/{thread-bindings.state-aeV8HNgV.js → thread-bindings.state-D8OMdk4O.js} +1 -1
- package/dist/threading-DU6pgeGm.js +456 -0
- package/dist/transcripts-source-DeIMNbRh.js +265 -0
- package/dist/transcripts-source-api.js +7 -2
- package/dist/{typing-CS-nNVoe.js → typing-oLiS5Z13.js} +1 -1
- package/dist/{voice-runtime-BEdqNcST.js → voice-runtime-CjNFaynA.js} +181 -91
- package/openclaw.plugin.json +12 -6
- package/package.json +4 -6
- package/dist/accounts-DJTf1LtA.js +0 -219
- package/dist/channel-api-CAJ0wMoV.js +0 -21
- package/dist/provider.runtime-C9PnJZbZ.js +0 -2
- package/dist/runtime-api.monitor-CHxrFPnW.js +0 -5
- package/dist/subagent-hooks-CTt5KCJr.js +0 -120
- package/dist/targets-yUFTHoAx.js +0 -3
- package/dist/transcripts-source-CfFMexGt.js +0 -123
- package/node_modules/p-map/index.d.ts +0 -155
- package/node_modules/p-map/index.js +0 -285
- package/node_modules/p-map/license +0 -9
- package/node_modules/p-map/package.json +0 -57
- package/node_modules/p-map/readme.md +0 -190
- package/dist/{allow-list-DnxIlPP2.js → allow-list-BDMimASD.js} +1 -1
- package/dist/{audit-core-xwjIczO0.js → audit-core-BCX8UeFH.js} +1 -1
- package/dist/{doctor-contract-DLa-BTiU.js → doctor-contract-DsWvKIXF.js} +1 -1
- package/dist/{security-audit-jGnJF__m.js → security-audit-BfJhAXZp.js} +1 -1
|
@@ -1,32 +1,30 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { D as canViewDiscordGuildChannel, F as createDiscordRestClient, H as registerGateway, K as validateDiscordProxyUrl, U as unregisterGateway, q as withValidatedDiscordProxy, z as DISCORD_REST_TIMEOUT_MS } from "./send.shared-BmwFjW6T.js";
|
|
6
|
-
import { _ as resolveDiscordModalEntryWithPersistence, g as resolveDiscordComponentEntryWithPersistence, t as editDiscordComponentMessage } from "./send.components-iJyFXw9L.js";
|
|
1
|
+
import { A as RateLimitError, B as hasDiscordV2Components, C as ThreadDeleteListener, D as Plugin, E as Client, F as Command, G as Modal, I as CommandWithSubcommands, J as Button, L as Guild, R as Message, X as Container, _ as MessageCreateListener, a as chunkDiscordTextWithMode, at as StringSelectMenu, b as PresenceUpdateListener, g as InteractionCreateListener, h as GuildDeleteListener, it as Separator, lt as BaseMessageInteractiveComponent, m as GuildCreateListener, nt as Row, ot as TextDisplay, p as discord_exports, v as MessageReactionAddListener, w as ThreadUpdateListener, x as ReadyListener, y as MessageReactionRemoveListener, z as User } from "./retry-DNsVTeTo.js";
|
|
2
|
+
import { C as parseDiscordComponentCustomId, D as decodeCustomIdComponent, E as parseDiscordModalCustomIdForInteraction, O as encodeCustomIdComponent, S as parseDiscordActivityCustomIdForInteraction, T as parseDiscordModalCustomId, c as parseExecApprovalData, o as parseDiscordQuestionData, v as buildDiscordActivityCustomId, w as parseDiscordComponentCustomIdForInteraction } from "./components-ezGKo_Yh.js";
|
|
3
|
+
import { c as resolveDiscordAccount, f as resolveDiscordAccountDmPolicy, l as resolveDiscordAccountAllowFrom, m as normalizeDiscordToken, p as resolveDiscordMaxLinesPerMessage } from "./accounts-DNl-oCEw.js";
|
|
4
|
+
import { a as resolveDiscordComponentEntryWithPersistence, o as resolveDiscordModalEntryWithPersistence, t as editDiscordComponentMessage } from "./send.components-ChK1wS7w.js";
|
|
7
5
|
import { t as getDiscordRuntime } from "./runtime-DgnVQ7zW.js";
|
|
8
6
|
import { a as isDiscordRateLimitResponseBody, o as summarizeDiscordResponseBody } from "./api-DNVbJyEy.js";
|
|
9
|
-
import { C as resolveTimestampMs, a as normalizeDiscordSlug, b as formatDiscordReactionEmoji, c as resolveDiscordChannelConfigWithFallback, d as resolveDiscordCommandOwnerAllowFrom, f as resolveDiscordGuildEntry, g as resolveDiscordOwnerAllowFrom, h as resolveDiscordOwnerAccess, i as normalizeDiscordDisplaySlug, l as resolveDiscordChannelPolicyCommandAuthorizer, m as resolveDiscordMemberAllowed, n as isDiscordGroupAllowedByPolicy, o as resolveDiscordAllowListMatch, p as resolveDiscordMemberAccessState, r as normalizeDiscordAllowList,
|
|
10
|
-
import {
|
|
7
|
+
import { C as resolveTimestampMs, a as normalizeDiscordSlug, b as formatDiscordReactionEmoji, c as resolveDiscordChannelConfigWithFallback, d as resolveDiscordCommandOwnerAllowFrom, f as resolveDiscordGuildEntry, g as resolveDiscordOwnerAllowFrom, h as resolveDiscordOwnerAccess, i as normalizeDiscordDisplaySlug, l as resolveDiscordChannelPolicyCommandAuthorizer, m as resolveDiscordMemberAllowed, n as isDiscordGroupAllowedByPolicy, o as resolveDiscordAllowListMatch, p as resolveDiscordMemberAccessState, r as normalizeDiscordAllowList, v as resolveGroupDmAllow, x as formatDiscordUserTag, y as shouldEmitDiscordReactionNotification } from "./allow-list-BDMimASD.js";
|
|
8
|
+
import { F as createDiscordRestClient, G as registerGateway, H as withValidatedDiscordProxy, K as unregisterGateway, V as validateDiscordProxyUrl, b as canViewDiscordGuildChannel, z as DISCORD_REST_TIMEOUT_MS } from "./send.shared-B3fpaLWJ.js";
|
|
9
|
+
import { a as formatMention, t as sendMessageDiscord } from "./send.outbound-HIkgji_7.js";
|
|
10
|
+
import { n as getDiscordActivitiesRuntime } from "./runtime-CQovMsH3.js";
|
|
11
|
+
import { n as resolveDiscordVoiceEnabled, r as authorizeDiscordVoiceIngress, t as resolveDiscordVoiceAccess } from "./owner-access-Bg41VzAf.js";
|
|
11
12
|
import { i as setPresence, t as clearPresences } from "./presence-cache-z1N8MbJ3.js";
|
|
12
|
-
import { r as sendVoiceMessageDiscord } from "./send-
|
|
13
|
+
import { r as sendVoiceMessageDiscord } from "./send-rQIffSYu.js";
|
|
13
14
|
import { c as raceWithTimeout, u as withAbortTimeout } from "./timeouts-B9cy6RvQ.js";
|
|
14
|
-
import { a as getDiscordExecApprovalApprovers, n as formatDiscordApprovalDisplayValue, r as
|
|
15
|
-
import { t as resolveDiscordChannelAllowlist } from "./resolve-channels-
|
|
16
|
-
import { t as resolveDiscordUserAllowlist } from "./resolve-users-
|
|
17
|
-
import { a as isThreadArchived, c as resolveDiscordChannelInfoSafe,
|
|
18
|
-
import { a as probeDiscordApplicationId, r as parseApplicationIdFromToken } from "./probe-
|
|
15
|
+
import { a as resolveDiscordBoundConversationRoute, f as getDiscordExecApprovalApprovers, l as resolveDiscordConversationIdentity, m as isDiscordExecApprovalClientEnabled, n as formatDiscordApprovalDisplayValue, r as buildDiscordConversationRouteContext, s as resolveDiscordEffectiveRoute, t as DISCORD_APPROVAL_ALLOWED_MENTIONS } from "./approval-message-safety-XGFPbDoI.js";
|
|
16
|
+
import { t as resolveDiscordChannelAllowlist } from "./resolve-channels-CGeUoIqb.js";
|
|
17
|
+
import { t as resolveDiscordUserAllowlist } from "./resolve-users-BtKxLUZv.js";
|
|
18
|
+
import { a as isThreadArchived, c as resolveDiscordChannelInfoSafe, f as resolveDiscordChannelTopicSafe, h as formatThreadBindingDurationLabel, l as resolveDiscordChannelNameSafe, r as getThreadBindingManager, s as resolveDiscordChannelIdSafe, u as resolveDiscordChannelParentIdSafe } from "./thread-bindings.manager-CngsgErq.js";
|
|
19
|
+
import { a as probeDiscordApplicationId, r as parseApplicationIdFromToken } from "./probe-BTdtVRwU.js";
|
|
19
20
|
import { i as sanitizeRecentModels, n as normalizeModelRef, r as preferenceTimestampMs, t as buildPreferenceModelKey } from "./model-picker-preference-primitives-BHT1LkR_.js";
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import { buildAgentSessionKey, deriveLastRoutePolicy, isAcpSessionKey, isSubagentSessionKey, parseAgentSessionKey, resolveAgentIdFromSessionKey, resolveAgentRoute } from "openclaw/plugin-sdk/routing";
|
|
24
|
-
import { asFiniteNumber, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeOptionalStringifiedId, normalizeStringEntries, parseFiniteNumber, parseStrictNonNegativeInteger, summarizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
25
|
-
import { getRuntimeConfig, getRuntimeConfigSnapshot } from "openclaw/plugin-sdk/runtime-config-snapshot";
|
|
21
|
+
import { d as resolveDiscordMessageStickers, f as resolveDiscordChannelInfo } from "./message-utils-BXLLnFl6.js";
|
|
22
|
+
import { i as resolveDiscordThreadParentInfo } from "./threading-DU6pgeGm.js";
|
|
23
|
+
import { t as resolveDiscordSenderIdentity } from "./sender-identity-BJtfyise.js";
|
|
26
24
|
import { logDebug, logError } from "openclaw/plugin-sdk/logging-core";
|
|
27
25
|
import { ApplicationCommandOptionType, ButtonStyle, ChannelType, ComponentType, GatewayCloseCodes, GatewayCloseCodes as GatewayCloseCodes$1, GatewayDispatchEvents, GatewayIntentBits, GatewayOpcodes } from "discord-api-types/v10";
|
|
28
26
|
import { createHash, randomUUID } from "node:crypto";
|
|
29
|
-
import { MAX_DATE_TIMESTAMP_MS, asDateTimestampMs,
|
|
27
|
+
import { MAX_DATE_TIMESTAMP_MS, MAX_TIMER_TIMEOUT_MS, asDateTimestampMs, asSafeIntegerInRange, parseFiniteNumber, parseStrictInteger, parseStrictPositiveInteger, resolveDateTimestampMs, resolveTimestampMsToIsoString } from "openclaw/plugin-sdk/number-runtime";
|
|
30
28
|
import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
|
|
31
29
|
import { Type } from "typebox";
|
|
32
30
|
import { Check, Errors } from "typebox/value";
|
|
@@ -34,6 +32,10 @@ import { inspect } from "node:util";
|
|
|
34
32
|
import { readResponseWithLimit } from "openclaw/plugin-sdk/response-limit-runtime";
|
|
35
33
|
import { PlatformMessageNotDispatchedError, formatErrorMessage, toErrorObject } from "openclaw/plugin-sdk/error-runtime";
|
|
36
34
|
import { fetchWithSsrFGuard, formatErrorMessage as formatErrorMessage$1 } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
35
|
+
import { normalizeAccountId } from "openclaw/plugin-sdk/account-id";
|
|
36
|
+
import { resolveAgentRoute } from "openclaw/plugin-sdk/routing";
|
|
37
|
+
import { asFiniteNumber, asOptionalRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries, parseFiniteNumber as parseFiniteNumber$1, parseStrictNonNegativeInteger as parseStrictNonNegativeInteger$1, summarizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
38
|
+
import { getRuntimeConfig, getRuntimeConfigSnapshot } from "openclaw/plugin-sdk/runtime-config-snapshot";
|
|
37
39
|
import { createHttp1EnvHttpProxyAgent, createHttp1ProxyAgent, createNodeProxyAgent, resolveEnvHttpProxyAgentOptions, wrapFetchWithAbortSignal } from "openclaw/plugin-sdk/fetch-runtime";
|
|
38
40
|
import { createNonExitingRuntime, createSubsystemLogger, danger, formatDurationSeconds, isVerbose, logVerbose, shouldLogVerbose, sleepWithAbort, warn } from "openclaw/plugin-sdk/runtime-env";
|
|
39
41
|
import { sliceUtf16Safe, truncateUtf16Safe, withTimeout } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
@@ -41,33 +43,31 @@ import { addAllowlistUserEntriesFromConfigEntry, buildAllowlistResolutionSummary
|
|
|
41
43
|
import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
|
|
42
44
|
import { resolveChunkMode, resolveTextChunkLimit } from "openclaw/plugin-sdk/reply-chunking";
|
|
43
45
|
import { chunkItems, findCodeRegions, sanitizeAssistantVisibleText, sanitizeAssistantVisibleTextWithProfile } from "openclaw/plugin-sdk/text-chunking";
|
|
44
|
-
import { createReplyReferencePlanner } from "openclaw/plugin-sdk/reply-reference";
|
|
45
46
|
import { buildOutboundSessionContext, listMessageReceiptPlatformIds, resolveChannelStreamingBlockEnabled, sendDurableMessageBatch } from "openclaw/plugin-sdk/channel-outbound";
|
|
46
47
|
import { getAgentScopedMediaLocalRoots } from "openclaw/plugin-sdk/media-runtime";
|
|
47
48
|
import { resolveSendableOutboundReplyParts, resolveTextChunksWithFallback } from "openclaw/plugin-sdk/reply-payload";
|
|
48
49
|
import { loadWebMedia } from "openclaw/plugin-sdk/web-media";
|
|
49
50
|
import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
|
|
50
|
-
import {
|
|
51
|
+
import { buildCommandTextFromArgs, findCommandByNativeName, formatCommandArgMenuTitle, listChatCommands, listNativeCommandSpecsForConfig, listSkillCommandsForAgents, resolveCommandAuthorizedFromAuthorizers, resolveEffectiveAgentRuntime, resolveNativeCommandSessionTargets, resolveStoredModelOverride, serializeCommandArgs } from "openclaw/plugin-sdk/command-auth-native";
|
|
51
52
|
import { GROUP_POLICY_BLOCKED_LABEL, resolveDefaultGroupPolicy, resolveOpenProviderRuntimeGroupPolicy, warnMissingProviderGroupPolicyFallbackOnce } from "openclaw/plugin-sdk/runtime-group-policy";
|
|
53
|
+
import { resolvePinnedMainDmOwnerFromAllowlist as resolvePinnedMainDmOwnerFromAllowlist$1 } from "openclaw/plugin-sdk/security-runtime";
|
|
52
54
|
import { createChannelPairingChallengeIssuer } from "openclaw/plugin-sdk/channel-pairing";
|
|
53
55
|
import { CHANNEL_APPROVAL_NATIVE_RUNTIME_CONTEXT_CAPABILITY } from "openclaw/plugin-sdk/approval-handler-adapter-runtime";
|
|
54
|
-
import { questionGatewayRuntime } from "openclaw/plugin-sdk/question-gateway-runtime";
|
|
55
56
|
import { buildPairingReply, upsertChannelPairingRequest, upsertChannelPairingRequest as upsertChannelPairingRequest$1 } from "openclaw/plugin-sdk/conversation-runtime";
|
|
57
|
+
import * as conversationRuntime from "openclaw/plugin-sdk/conversation-binding-runtime";
|
|
58
|
+
import { questionGatewayRuntime } from "openclaw/plugin-sdk/question-gateway-runtime";
|
|
56
59
|
import { clearExpiredCooldowns, ensureAuthProfileStore, formatReasoningMessage, getPreparedModelCatalogSnapshot, isProfileInCooldown, listAgentIds, loadPreparedModelCatalog, resolveAgentAvatar, resolveAgentDir, resolveDefaultModelForAgent, resolveHumanDelayConfig, resolveProfilesUnavailableReason } from "openclaw/plugin-sdk/agent-runtime";
|
|
57
60
|
import { isDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/dangerous-name-runtime";
|
|
58
61
|
import { resolveNativeCommandsEnabled, resolveNativeSkillsEnabled } from "openclaw/plugin-sdk/native-command-config-runtime";
|
|
59
62
|
import { requestHeartbeat } from "openclaw/plugin-sdk/heartbeat-runtime";
|
|
60
63
|
import { enqueueRoutedSystemEvent, enqueueRoutedSystemEvent as enqueueRoutedSystemEvent$1 } from "openclaw/plugin-sdk/system-event-runtime";
|
|
64
|
+
import { deleteSessionEntry, getSessionEntry, listSessionEntries, readSessionUpdatedAt as readSessionUpdatedAt$1, resolveStorePath, resolveStorePath as resolveStorePath$1 } from "openclaw/plugin-sdk/session-store-runtime";
|
|
61
65
|
import { createChannelIngressResolver, defineStableChannelIngressIdentity, readChannelIngressStoreAllowFromForDmPolicy } from "openclaw/plugin-sdk/channel-ingress-runtime";
|
|
62
66
|
import { createChannelPartialDeliveryError, dispatchChannelInboundTurn, formatInboundEnvelope, hasVisibleInboundReplyDispatch, isChannelPartialDeliveryError, resolveEnvelopeFormatOptions, resolveInboundSupplementalSenderAllowed, runChannelInboundEvent } from "openclaw/plugin-sdk/channel-inbound";
|
|
63
|
-
import {
|
|
64
|
-
import { finalizeInboundContext, generateConversationLabel } from "openclaw/plugin-sdk/reply-dispatch-runtime";
|
|
65
|
-
import { deleteSessionEntry, getSessionEntry, listSessionEntries, readSessionUpdatedAt as readSessionUpdatedAt$1, resolveStorePath, resolveStorePath as resolveStorePath$1 } from "openclaw/plugin-sdk/session-store-runtime";
|
|
66
|
-
import { buildCommandTextFromArgs, findCommandByNativeName, formatCommandArgMenuTitle, listChatCommands, listNativeCommandSpecsForConfig, listSkillCommandsForAgents, resolveCommandAuthorizedFromAuthorizers, resolveEffectiveAgentRuntime, resolveNativeCommandSessionTargets, resolveStoredModelOverride, serializeCommandArgs } from "openclaw/plugin-sdk/command-auth-native";
|
|
67
|
+
import { finalizeInboundContext } from "openclaw/plugin-sdk/reply-dispatch-runtime";
|
|
67
68
|
import { buildCommandTextFromArgs as buildCommandTextFromArgs$1, findCommandByNativeName as findCommandByNativeName$1, mergeNativeCommandSpecs, parseCommandArgs, resolveCommandArgChoices, resolveCommandArgMenu, serializeCommandArgs as serializeCommandArgs$1 } from "openclaw/plugin-sdk/native-command-registry";
|
|
68
69
|
import { PLUGIN_COMMAND_DISPATCH } from "openclaw/plugin-sdk/plugin-command-runtime";
|
|
69
70
|
import { resolveDirectStatusReplyForSession } from "openclaw/plugin-sdk/command-status-runtime";
|
|
70
|
-
import * as conversationRuntime from "openclaw/plugin-sdk/conversation-binding-runtime";
|
|
71
71
|
import { normalizeProviderId } from "openclaw/plugin-sdk/provider-model-shared";
|
|
72
72
|
import { EventEmitter } from "node:events";
|
|
73
73
|
import * as ws from "ws";
|
|
@@ -140,6 +140,205 @@ async function runDiscordListenerWithSlowLog(params) {
|
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
142
|
//#endregion
|
|
143
|
+
//#region extensions/discord/src/monitor/presence-events.ts
|
|
144
|
+
const DISCORD_PRESENCE_GREETING_COOLDOWN_MS = 480 * 60 * 1e3;
|
|
145
|
+
function isDiscordOnlineStatus(status) {
|
|
146
|
+
return status === "online" || status === "idle" || status === "dnd";
|
|
147
|
+
}
|
|
148
|
+
function isDiscordOfflineStatus(status) {
|
|
149
|
+
return status === "offline";
|
|
150
|
+
}
|
|
151
|
+
function resolveDiscordOnlinePresenceEvent(params) {
|
|
152
|
+
const config = params.config;
|
|
153
|
+
const userId = params.data.user?.id?.trim();
|
|
154
|
+
if (!config || config.enabled === false || !userId || userId === params.botUserId || params.data.user.bot === true || !isDiscordOnlineStatus(params.data.status) || !params.availabilityKind) return null;
|
|
155
|
+
if (config.users !== void 0 && !config.users.includes(userId)) return null;
|
|
156
|
+
if (params.lastEmittedAtMs !== void 0 && params.nowMs - params.lastEmittedAtMs < 288e5) return null;
|
|
157
|
+
const lines = [
|
|
158
|
+
"Discord online-presence event:",
|
|
159
|
+
params.availabilityKind === "observed-offline" ? `A human member became available online after being observed offline in guild_id=${JSON.stringify(params.data.guild_id)} user_id=${JSON.stringify(userId)} status=${JSON.stringify(params.data.status)}.` : `A human member became newly visible online since the current guild snapshot in guild_id=${JSON.stringify(params.data.guild_id)} user_id=${JSON.stringify(userId)} status=${JSON.stringify(params.data.status)}. They may have come online or joined after the snapshot; do not claim an exact prior status.`,
|
|
160
|
+
`The authorized greeting target is channel_id=${JSON.stringify(config.channelId)}.`,
|
|
161
|
+
"Before greeting, retrieve relevant memory and wiki context for this immutable user_id, including a known timezone when available. Use their local time for the greeting; if their timezone is unknown, do not guess.",
|
|
162
|
+
"Send at most one short, natural greeting to the target channel. Do not reveal private memory. If no greeting is appropriate, stay silent."
|
|
163
|
+
];
|
|
164
|
+
return {
|
|
165
|
+
channelId: config.channelId,
|
|
166
|
+
userId,
|
|
167
|
+
text: lines.join("\n")
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
//#endregion
|
|
171
|
+
//#region extensions/discord/src/monitor/presence-cooldown-store.ts
|
|
172
|
+
const DISCORD_PRESENCE_COOLDOWN_MAX_ENTRIES = 25e3;
|
|
173
|
+
function openDiscordPresenceCooldownStore() {
|
|
174
|
+
return getDiscordRuntime().state.openSyncKeyedStore({
|
|
175
|
+
namespace: "presence-greeting-cooldowns",
|
|
176
|
+
maxEntries: DISCORD_PRESENCE_COOLDOWN_MAX_ENTRIES,
|
|
177
|
+
overflowPolicy: "reject-new",
|
|
178
|
+
defaultTtlMs: DISCORD_PRESENCE_GREETING_COOLDOWN_MS
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
//#endregion
|
|
182
|
+
//#region extensions/discord/src/monitor/presence-emission-gate.ts
|
|
183
|
+
const DISCORD_PRESENCE_RECONNECT_SUPPRESS_MS = 300 * 1e3;
|
|
184
|
+
const DISCORD_PRESENCE_BURST_LIMIT = 8;
|
|
185
|
+
const DISCORD_PRESENCE_BURST_WINDOW_MS = 60 * 1e3;
|
|
186
|
+
function resolveDiscordPresenceGateOptions(config) {
|
|
187
|
+
return {
|
|
188
|
+
reconnectSuppressMs: config?.reconnectSuppressSeconds !== void 0 ? config.reconnectSuppressSeconds * 1e3 : DISCORD_PRESENCE_RECONNECT_SUPPRESS_MS,
|
|
189
|
+
burstLimit: config?.burstLimit ?? DISCORD_PRESENCE_BURST_LIMIT,
|
|
190
|
+
burstWindowMs: config?.burstWindowSeconds !== void 0 ? config.burstWindowSeconds * 1e3 : DISCORD_PRESENCE_BURST_WINDOW_MS
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Per-account lifecycle gate for online-presence events. Reconnect state belongs to the Gateway
|
|
195
|
+
* session, while burst state follows the guild-owned configuration that supplies its limits.
|
|
196
|
+
*/
|
|
197
|
+
var DiscordPresenceEmissionGate = class {
|
|
198
|
+
constructor() {
|
|
199
|
+
this.reconnectLogged = false;
|
|
200
|
+
this.burstByGuild = /* @__PURE__ */ new Map();
|
|
201
|
+
this.nextReservationId = 0;
|
|
202
|
+
}
|
|
203
|
+
noteGatewaySessionReset(nowMs) {
|
|
204
|
+
this.lastSessionResetAtMs = nowMs;
|
|
205
|
+
this.reconnectLogged = false;
|
|
206
|
+
}
|
|
207
|
+
evaluateReconnectWindow(nowMs, options) {
|
|
208
|
+
if (this.lastSessionResetAtMs !== void 0 && options.reconnectSuppressMs > 0 && nowMs - this.lastSessionResetAtMs < options.reconnectSuppressMs) {
|
|
209
|
+
const shouldLog = !this.reconnectLogged;
|
|
210
|
+
this.reconnectLogged = true;
|
|
211
|
+
return {
|
|
212
|
+
allowed: false,
|
|
213
|
+
reason: "reconnect-window",
|
|
214
|
+
shouldLog
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
return { allowed: true };
|
|
218
|
+
}
|
|
219
|
+
reserveBurst(guildId, nowMs, options) {
|
|
220
|
+
const state = this.burstByGuild.get(guildId) ?? {
|
|
221
|
+
reservations: [],
|
|
222
|
+
logged: false
|
|
223
|
+
};
|
|
224
|
+
state.reservations = state.reservations.filter((reservation) => !reservation.committed || nowMs - reservation.atMs < options.burstWindowMs);
|
|
225
|
+
this.burstByGuild.set(guildId, state);
|
|
226
|
+
if (state.reservations.length >= options.burstLimit) {
|
|
227
|
+
const shouldLog = !state.logged;
|
|
228
|
+
state.logged = true;
|
|
229
|
+
return {
|
|
230
|
+
allowed: false,
|
|
231
|
+
reason: state.reservations.some((reservation) => !reservation.committed) ? "burst-pending" : "burst",
|
|
232
|
+
shouldLog
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
state.logged = false;
|
|
236
|
+
const reservation = {
|
|
237
|
+
id: this.nextReservationId++,
|
|
238
|
+
atMs: nowMs,
|
|
239
|
+
committed: false
|
|
240
|
+
};
|
|
241
|
+
state.reservations.push(reservation);
|
|
242
|
+
return {
|
|
243
|
+
allowed: true,
|
|
244
|
+
reservation: reservation.id
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
commitBurst(guildId, reservation, nowMs) {
|
|
248
|
+
const entry = this.burstByGuild.get(guildId)?.reservations.find((candidate) => candidate.id === reservation);
|
|
249
|
+
if (!entry) return;
|
|
250
|
+
entry.atMs = nowMs;
|
|
251
|
+
entry.committed = true;
|
|
252
|
+
}
|
|
253
|
+
releaseBurst(guildId, reservation) {
|
|
254
|
+
const state = this.burstByGuild.get(guildId);
|
|
255
|
+
if (!state) return;
|
|
256
|
+
state.reservations = state.reservations.filter((candidate) => candidate.id !== reservation);
|
|
257
|
+
if (state.reservations.length === 0 && !state.logged) this.burstByGuild.delete(guildId);
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
//#endregion
|
|
261
|
+
//#region extensions/discord/src/monitor/presence-transition-cache.ts
|
|
262
|
+
const DEFAULT_PRESENCE_BASELINE_MAX_ENTRIES = 75e3;
|
|
263
|
+
var DiscordPresenceBaselineCache = class {
|
|
264
|
+
constructor(maxEntries = DEFAULT_PRESENCE_BASELINE_MAX_ENTRIES) {
|
|
265
|
+
this.maxEntries = maxEntries;
|
|
266
|
+
this.offlineByKey = /* @__PURE__ */ new Map();
|
|
267
|
+
this.onlineByKey = /* @__PURE__ */ new Map();
|
|
268
|
+
}
|
|
269
|
+
clear() {
|
|
270
|
+
this.offlineByKey.clear();
|
|
271
|
+
this.onlineByKey.clear();
|
|
272
|
+
}
|
|
273
|
+
clearScope(scope) {
|
|
274
|
+
for (const markers of [this.offlineByKey, this.onlineByKey]) for (const [key, markerScope] of markers) if (markerScope === scope) markers.delete(key);
|
|
275
|
+
}
|
|
276
|
+
isOffline(scope, key) {
|
|
277
|
+
return this.offlineByKey.get(key) === scope;
|
|
278
|
+
}
|
|
279
|
+
isOnline(scope, key) {
|
|
280
|
+
return this.onlineByKey.get(key) === scope;
|
|
281
|
+
}
|
|
282
|
+
observeOffline(scope, key) {
|
|
283
|
+
this.deleteMarker(this.onlineByKey, scope, key);
|
|
284
|
+
return this.observe(this.offlineByKey, scope, key);
|
|
285
|
+
}
|
|
286
|
+
observeOnline(scope, key) {
|
|
287
|
+
this.deleteMarker(this.offlineByKey, scope, key);
|
|
288
|
+
return this.observe(this.onlineByKey, scope, key);
|
|
289
|
+
}
|
|
290
|
+
deleteMarker(markers, scope, key) {
|
|
291
|
+
if (markers.get(key) === scope) markers.delete(key);
|
|
292
|
+
}
|
|
293
|
+
observe(markers, scope, key) {
|
|
294
|
+
markers.delete(key);
|
|
295
|
+
markers.set(key, scope);
|
|
296
|
+
let evictedScope;
|
|
297
|
+
while (markers.size > this.maxEntries) {
|
|
298
|
+
const oldestKey = markers.keys().next().value;
|
|
299
|
+
if (oldestKey === void 0) break;
|
|
300
|
+
evictedScope = markers.get(oldestKey);
|
|
301
|
+
markers.delete(oldestKey);
|
|
302
|
+
}
|
|
303
|
+
return evictedScope;
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
//#endregion
|
|
307
|
+
//#region extensions/discord/src/monitor/thread-session-close.ts
|
|
308
|
+
/**
|
|
309
|
+
* Closes every session entry in the store whose key contains {@link threadId}.
|
|
310
|
+
* The explicit lifecycle deletion archives the old transcript and guarantees
|
|
311
|
+
* that a later inbound message starts a fresh session in every reset mode.
|
|
312
|
+
*/
|
|
313
|
+
async function closeDiscordThreadSessions(params) {
|
|
314
|
+
const { cfg, threadId } = params;
|
|
315
|
+
const normalizedThreadId = normalizeOptionalLowercaseString(threadId) ?? "";
|
|
316
|
+
if (!normalizedThreadId) return 0;
|
|
317
|
+
const segmentRe = new RegExp(`:${normalizedThreadId}(?::|$)`, "i");
|
|
318
|
+
function sessionKeyContainsThreadId(key) {
|
|
319
|
+
return segmentRe.test(key);
|
|
320
|
+
}
|
|
321
|
+
let resetCount = 0;
|
|
322
|
+
for (const agentId of listAgentIds(cfg)) {
|
|
323
|
+
const storePath = resolveStorePath(cfg.session?.store, { agentId });
|
|
324
|
+
for (const { sessionKey, entry } of listSessionEntries({
|
|
325
|
+
agentId,
|
|
326
|
+
storePath,
|
|
327
|
+
readOnly: true
|
|
328
|
+
})) {
|
|
329
|
+
if (!sessionKeyContainsThreadId(sessionKey)) continue;
|
|
330
|
+
if (await deleteSessionEntry({
|
|
331
|
+
archiveTranscript: true,
|
|
332
|
+
expectedSessionId: entry.sessionId ?? null,
|
|
333
|
+
expectedUpdatedAt: entry.updatedAt,
|
|
334
|
+
sessionKey,
|
|
335
|
+
storePath
|
|
336
|
+
})) resetCount += 1;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
return resetCount;
|
|
340
|
+
}
|
|
341
|
+
//#endregion
|
|
143
342
|
//#region extensions/discord/src/monitor/dm-command-auth.ts
|
|
144
343
|
const DISCORD_ALLOW_LIST_PREFIXES = [
|
|
145
344
|
"discord:",
|
|
@@ -305,461 +504,6 @@ async function resolveDiscordTextCommandAccess(params) {
|
|
|
305
504
|
});
|
|
306
505
|
}
|
|
307
506
|
//#endregion
|
|
308
|
-
//#region extensions/discord/src/monitor/thread-title.ts
|
|
309
|
-
const DEFAULT_THREAD_TITLE_TIMEOUT_MS = 6e4;
|
|
310
|
-
const MAX_THREAD_TITLE_SOURCE_CHARS = 600;
|
|
311
|
-
const MAX_THREAD_TITLE_CHANNEL_NAME_CHARS = 120;
|
|
312
|
-
const MAX_THREAD_TITLE_CHANNEL_DESCRIPTION_CHARS = 320;
|
|
313
|
-
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.";
|
|
314
|
-
async function generateThreadTitle(params) {
|
|
315
|
-
const sourceText = params.messageText.trim();
|
|
316
|
-
if (!sourceText) return null;
|
|
317
|
-
try {
|
|
318
|
-
const userMessage = buildThreadTitleCompletionUserMessage({
|
|
319
|
-
sourceText,
|
|
320
|
-
channelName: params.channelName,
|
|
321
|
-
channelDescription: params.channelDescription
|
|
322
|
-
});
|
|
323
|
-
const timeoutMs = resolveThreadTitleTimeoutMs(params.timeoutMs);
|
|
324
|
-
const generated = await generateConversationLabel({
|
|
325
|
-
cfg: params.cfg,
|
|
326
|
-
agentId: params.agentId,
|
|
327
|
-
userMessage,
|
|
328
|
-
prompt: DISCORD_THREAD_TITLE_SYSTEM_PROMPT,
|
|
329
|
-
...params.modelRef ? { modelRef: params.modelRef } : {},
|
|
330
|
-
timeoutMs,
|
|
331
|
-
maxLength: MAX_THREAD_TITLE_SOURCE_CHARS
|
|
332
|
-
});
|
|
333
|
-
return generated ? normalizeGeneratedThreadTitle(generated) : null;
|
|
334
|
-
} catch (err) {
|
|
335
|
-
logVerbose(`thread-title: title generation failed for agent ${params.agentId}: ${String(err)}`);
|
|
336
|
-
return null;
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
function buildThreadTitleCompletionUserMessage(params) {
|
|
340
|
-
const sourceText = truncateThreadTitleSourceText(params.sourceText);
|
|
341
|
-
const channelName = normalizeTitleContextField(params.channelName, MAX_THREAD_TITLE_CHANNEL_NAME_CHARS);
|
|
342
|
-
const channelDescription = normalizeTitleContextField(params.channelDescription, MAX_THREAD_TITLE_CHANNEL_DESCRIPTION_CHARS);
|
|
343
|
-
const messageLines = [];
|
|
344
|
-
if (channelName) messageLines.push(`Channel: ${channelName}`);
|
|
345
|
-
if (channelDescription) messageLines.push(`Channel description: ${channelDescription}`);
|
|
346
|
-
messageLines.push(`Message:\n${sourceText}`);
|
|
347
|
-
return messageLines.join("\n\n");
|
|
348
|
-
}
|
|
349
|
-
function truncateThreadTitleSourceText(sourceText) {
|
|
350
|
-
if (sourceText.length <= MAX_THREAD_TITLE_SOURCE_CHARS) return sourceText;
|
|
351
|
-
return `${truncateUtf16Safe(sourceText, MAX_THREAD_TITLE_SOURCE_CHARS)}...`;
|
|
352
|
-
}
|
|
353
|
-
function resolveThreadTitleTimeoutMs(timeoutMs) {
|
|
354
|
-
return Math.max(100, Math.floor(timeoutMs ?? DEFAULT_THREAD_TITLE_TIMEOUT_MS));
|
|
355
|
-
}
|
|
356
|
-
function normalizeGeneratedThreadTitle(raw) {
|
|
357
|
-
const lines = raw.replace(/\r/g, "").split("\n");
|
|
358
|
-
let firstLine = "";
|
|
359
|
-
for (const line of lines) {
|
|
360
|
-
const trimmed = line.trim();
|
|
361
|
-
if (!trimmed) continue;
|
|
362
|
-
if (!firstLine && trimmed.startsWith("```")) continue;
|
|
363
|
-
firstLine = trimmed;
|
|
364
|
-
break;
|
|
365
|
-
}
|
|
366
|
-
return stripThreadTitleWrappers(firstLine);
|
|
367
|
-
}
|
|
368
|
-
function stripThreadTitleWrappers(raw) {
|
|
369
|
-
let current = raw.trim();
|
|
370
|
-
let previous = "";
|
|
371
|
-
while (current && current !== previous) {
|
|
372
|
-
previous = current;
|
|
373
|
-
current = current.replace(/^["'`]+|["'`]+$/g, "").trim();
|
|
374
|
-
current = stripBalancedWrapper(current, "**");
|
|
375
|
-
current = stripBalancedWrapper(current, "__");
|
|
376
|
-
current = stripBalancedWrapper(current, "*");
|
|
377
|
-
current = stripBalancedWrapper(current, "_");
|
|
378
|
-
current = stripBalancedWrapper(current, "~~");
|
|
379
|
-
}
|
|
380
|
-
return current;
|
|
381
|
-
}
|
|
382
|
-
function stripBalancedWrapper(text, marker) {
|
|
383
|
-
if (text.length < marker.length * 2 + 1) return text;
|
|
384
|
-
if (!text.startsWith(marker) || !text.endsWith(marker)) return text;
|
|
385
|
-
const inner = text.slice(marker.length, text.length - marker.length);
|
|
386
|
-
if (!inner || inner.includes(marker)) return text;
|
|
387
|
-
return inner;
|
|
388
|
-
}
|
|
389
|
-
function normalizeTitleContextField(raw, maxChars) {
|
|
390
|
-
const value = raw?.trim();
|
|
391
|
-
if (!value) return;
|
|
392
|
-
const singleLine = value.replace(/\s+/g, " ");
|
|
393
|
-
if (singleLine.length <= maxChars) return singleLine;
|
|
394
|
-
return `${truncateUtf16Safe(singleLine, maxChars)}...`;
|
|
395
|
-
}
|
|
396
|
-
//#endregion
|
|
397
|
-
//#region extensions/discord/src/monitor/threading.cache.ts
|
|
398
|
-
const DISCORD_THREAD_STARTER_CACHE_TTL_MS = 300 * 1e3;
|
|
399
|
-
const DISCORD_THREAD_STARTER_CACHE_MAX = 500;
|
|
400
|
-
const DISCORD_THREAD_STARTER_CACHE = /* @__PURE__ */ new Map();
|
|
401
|
-
function resetDiscordThreadStarterCacheForTest() {
|
|
402
|
-
DISCORD_THREAD_STARTER_CACHE.clear();
|
|
403
|
-
}
|
|
404
|
-
function getCachedThreadStarter(key, now) {
|
|
405
|
-
const entry = DISCORD_THREAD_STARTER_CACHE.get(key);
|
|
406
|
-
if (!entry) return;
|
|
407
|
-
if (now - entry.updatedAt > DISCORD_THREAD_STARTER_CACHE_TTL_MS) {
|
|
408
|
-
DISCORD_THREAD_STARTER_CACHE.delete(key);
|
|
409
|
-
return;
|
|
410
|
-
}
|
|
411
|
-
DISCORD_THREAD_STARTER_CACHE.delete(key);
|
|
412
|
-
DISCORD_THREAD_STARTER_CACHE.set(key, {
|
|
413
|
-
...entry,
|
|
414
|
-
updatedAt: now
|
|
415
|
-
});
|
|
416
|
-
return entry.value;
|
|
417
|
-
}
|
|
418
|
-
function setCachedThreadStarter(key, value, now) {
|
|
419
|
-
DISCORD_THREAD_STARTER_CACHE.delete(key);
|
|
420
|
-
DISCORD_THREAD_STARTER_CACHE.set(key, {
|
|
421
|
-
value,
|
|
422
|
-
updatedAt: now
|
|
423
|
-
});
|
|
424
|
-
while (DISCORD_THREAD_STARTER_CACHE.size > DISCORD_THREAD_STARTER_CACHE_MAX) {
|
|
425
|
-
const iter = DISCORD_THREAD_STARTER_CACHE.keys().next();
|
|
426
|
-
if (iter.done) break;
|
|
427
|
-
DISCORD_THREAD_STARTER_CACHE.delete(iter.value);
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
//#endregion
|
|
431
|
-
//#region extensions/discord/src/monitor/threading.starter.ts
|
|
432
|
-
function isDiscordThreadType(type) {
|
|
433
|
-
return type === discord_exports.ChannelType.PublicThread || type === discord_exports.ChannelType.PrivateThread || type === discord_exports.ChannelType.AnnouncementThread;
|
|
434
|
-
}
|
|
435
|
-
function isDiscordForumParentType(parentType) {
|
|
436
|
-
return parentType === discord_exports.ChannelType.GuildForum || parentType === discord_exports.ChannelType.GuildMedia;
|
|
437
|
-
}
|
|
438
|
-
function resolveDiscordThreadChannel(params) {
|
|
439
|
-
if (!params.isGuildMessage) return null;
|
|
440
|
-
const { message, channelInfo } = params;
|
|
441
|
-
const channel = "channel" in message ? message.channel : void 0;
|
|
442
|
-
if (channel && typeof channel === "object" && "isThread" in channel && typeof channel.isThread === "function" && channel.isThread()) return channel;
|
|
443
|
-
if (!isDiscordThreadType(channelInfo?.type)) return null;
|
|
444
|
-
const messageChannelId = params.messageChannelId || resolveDiscordMessageChannelId({ message });
|
|
445
|
-
if (!messageChannelId) return null;
|
|
446
|
-
return {
|
|
447
|
-
id: messageChannelId,
|
|
448
|
-
name: channelInfo?.name ?? void 0,
|
|
449
|
-
parentId: channelInfo?.parentId ?? void 0,
|
|
450
|
-
parent: void 0,
|
|
451
|
-
ownerId: channelInfo?.ownerId ?? void 0
|
|
452
|
-
};
|
|
453
|
-
}
|
|
454
|
-
async function resolveDiscordThreadParentInfo(params) {
|
|
455
|
-
const { threadChannel, channelInfo, client } = params;
|
|
456
|
-
const parent = resolveDiscordChannelParentSafe(threadChannel);
|
|
457
|
-
let parentId = resolveDiscordChannelParentIdSafe(threadChannel) ?? resolveDiscordChannelIdSafe(parent) ?? channelInfo?.parentId ?? void 0;
|
|
458
|
-
if (!parentId && threadChannel.id) parentId = (await resolveDiscordChannelInfo(client, threadChannel.id))?.parentId ?? void 0;
|
|
459
|
-
if (!parentId) return {};
|
|
460
|
-
let parentName = resolveDiscordChannelNameSafe(parent);
|
|
461
|
-
const parentInfo = await resolveDiscordChannelInfo(client, parentId);
|
|
462
|
-
parentName = parentName ?? parentInfo?.name;
|
|
463
|
-
const parentType = parentInfo?.type;
|
|
464
|
-
return {
|
|
465
|
-
id: parentId,
|
|
466
|
-
name: parentName,
|
|
467
|
-
type: parentType
|
|
468
|
-
};
|
|
469
|
-
}
|
|
470
|
-
async function resolveDiscordThreadStarter(params) {
|
|
471
|
-
const cacheKey = params.channel.id;
|
|
472
|
-
const cached = getCachedThreadStarter(cacheKey, Date.now());
|
|
473
|
-
if (cached) return cached;
|
|
474
|
-
try {
|
|
475
|
-
const messageChannelId = resolveDiscordThreadStarterMessageChannelId(params);
|
|
476
|
-
if (!messageChannelId) return null;
|
|
477
|
-
const starter = await fetchDiscordThreadStarterMessage({
|
|
478
|
-
client: params.client,
|
|
479
|
-
messageChannelId,
|
|
480
|
-
threadId: params.channel.id
|
|
481
|
-
});
|
|
482
|
-
if (!starter) return null;
|
|
483
|
-
const payload = buildDiscordThreadStarterPayload({
|
|
484
|
-
starter,
|
|
485
|
-
resolveTimestampMs: params.resolveTimestampMs
|
|
486
|
-
});
|
|
487
|
-
if (!payload) return null;
|
|
488
|
-
setCachedThreadStarter(cacheKey, payload, Date.now());
|
|
489
|
-
return payload;
|
|
490
|
-
} catch {
|
|
491
|
-
return null;
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
function resolveDiscordThreadStarterMessageChannelId(params) {
|
|
495
|
-
return isDiscordForumParentType(params.parentType) ? params.channel.id : params.parentId;
|
|
496
|
-
}
|
|
497
|
-
async function fetchDiscordThreadStarterMessage(params) {
|
|
498
|
-
const starter = await getChannelMessage(params.client.rest, params.messageChannelId, params.threadId);
|
|
499
|
-
return starter ? starter : null;
|
|
500
|
-
}
|
|
501
|
-
function buildDiscordThreadStarterPayload(params) {
|
|
502
|
-
const text = resolveDiscordThreadStarterText(params.starter);
|
|
503
|
-
if (!text) return null;
|
|
504
|
-
return {
|
|
505
|
-
text,
|
|
506
|
-
...resolveDiscordThreadStarterIdentity(params.starter),
|
|
507
|
-
timestamp: params.resolveTimestampMs(params.starter.timestamp) ?? void 0
|
|
508
|
-
};
|
|
509
|
-
}
|
|
510
|
-
function resolveDiscordThreadStarterText(starter) {
|
|
511
|
-
const content = normalizeOptionalString(starter.content) ?? "";
|
|
512
|
-
const embedText = resolveDiscordEmbedText(starter.embeds?.[0]);
|
|
513
|
-
const forwardedText = resolveDiscordForwardedMessagesTextFromSnapshots(starter.message_snapshots);
|
|
514
|
-
return [content || embedText || forwardedText, formatDiscordMediaText({
|
|
515
|
-
attachments: starter.attachments ?? void 0,
|
|
516
|
-
stickers: starter.sticker_items ?? void 0
|
|
517
|
-
})].filter(Boolean).join("\n");
|
|
518
|
-
}
|
|
519
|
-
function resolveDiscordThreadStarterIdentity(starter) {
|
|
520
|
-
return {
|
|
521
|
-
author: resolveDiscordThreadStarterAuthor(starter),
|
|
522
|
-
authorId: starter.author?.id ?? void 0,
|
|
523
|
-
authorName: starter.author?.username ?? void 0,
|
|
524
|
-
authorTag: resolveDiscordThreadStarterAuthorTag(starter.author),
|
|
525
|
-
memberRoleIds: resolveDiscordThreadStarterRoleIds(starter.member)
|
|
526
|
-
};
|
|
527
|
-
}
|
|
528
|
-
function resolveDiscordThreadStarterAuthor(starter) {
|
|
529
|
-
return starter.member?.nick ?? starter.member?.displayName ?? resolveDiscordThreadStarterAuthorTag(starter.author) ?? starter.author?.username ?? starter.author?.id ?? "Unknown";
|
|
530
|
-
}
|
|
531
|
-
function resolveDiscordThreadStarterAuthorTag(author) {
|
|
532
|
-
if (!author?.username || !author.discriminator) return;
|
|
533
|
-
if (author.discriminator !== "0") return `${author.username}#${author.discriminator}`;
|
|
534
|
-
return author.username;
|
|
535
|
-
}
|
|
536
|
-
function resolveDiscordThreadStarterRoleIds(member) {
|
|
537
|
-
return Array.isArray(member?.roles) ? member.roles : void 0;
|
|
538
|
-
}
|
|
539
|
-
function resolveDiscordReplyTarget(opts) {
|
|
540
|
-
if (opts.replyToMode === "off") return;
|
|
541
|
-
const replyToId = normalizeOptionalString(opts.replyToId);
|
|
542
|
-
if (!replyToId) return;
|
|
543
|
-
if (opts.replyToMode === "all") return replyToId;
|
|
544
|
-
return opts.hasReplied ? void 0 : replyToId;
|
|
545
|
-
}
|
|
546
|
-
function sanitizeDiscordThreadName(rawName, fallbackId) {
|
|
547
|
-
return truncateUtf16Safe(truncateUtf16Safe(rawName.replace(/<@!?\d+>/g, "").replace(/<@&\d+>/g, "").replace(/<#\d+>/g, "").replace(/\s+/g, " ").trim() || `Thread ${fallbackId}`, 80), 100) || `Thread ${fallbackId}`;
|
|
548
|
-
}
|
|
549
|
-
function resolveDiscordReplyDeliveryPlan(params) {
|
|
550
|
-
const originalReplyTarget = params.replyTarget;
|
|
551
|
-
let deliverTarget = originalReplyTarget;
|
|
552
|
-
let replyTarget = originalReplyTarget;
|
|
553
|
-
if (params.createdThreadId) {
|
|
554
|
-
deliverTarget = `channel:${params.createdThreadId}`;
|
|
555
|
-
replyTarget = deliverTarget;
|
|
556
|
-
}
|
|
557
|
-
const allowReference = deliverTarget === originalReplyTarget;
|
|
558
|
-
const replyReference = createReplyReferencePlanner({
|
|
559
|
-
replyToMode: allowReference ? params.replyToMode : "off",
|
|
560
|
-
existingId: params.threadChannel ? params.messageId : void 0,
|
|
561
|
-
startId: params.messageId,
|
|
562
|
-
allowReference
|
|
563
|
-
});
|
|
564
|
-
return {
|
|
565
|
-
deliverTarget,
|
|
566
|
-
replyTarget,
|
|
567
|
-
replyReference
|
|
568
|
-
};
|
|
569
|
-
}
|
|
570
|
-
//#endregion
|
|
571
|
-
//#region extensions/discord/src/monitor/threading.auto-thread.ts
|
|
572
|
-
function resolveTrimmedDiscordMessageChannelId(params) {
|
|
573
|
-
return (params.messageChannelId || resolveDiscordMessageChannelId({ message: params.message })).trim();
|
|
574
|
-
}
|
|
575
|
-
function resolveDiscordAutoThreadContext(params) {
|
|
576
|
-
const createdThreadId = normalizeOptionalStringifiedId(params.createdThreadId) ?? "";
|
|
577
|
-
if (!createdThreadId) return null;
|
|
578
|
-
const messageChannelId = normalizeOptionalString(params.messageChannelId) ?? "";
|
|
579
|
-
if (!messageChannelId) return null;
|
|
580
|
-
const threadSessionKey = buildAgentSessionKey({
|
|
581
|
-
agentId: params.agentId,
|
|
582
|
-
channel: params.channel,
|
|
583
|
-
peer: {
|
|
584
|
-
kind: "channel",
|
|
585
|
-
id: createdThreadId
|
|
586
|
-
}
|
|
587
|
-
});
|
|
588
|
-
const parentSessionKey = buildAgentSessionKey({
|
|
589
|
-
agentId: params.agentId,
|
|
590
|
-
channel: params.channel,
|
|
591
|
-
peer: {
|
|
592
|
-
kind: "channel",
|
|
593
|
-
id: messageChannelId
|
|
594
|
-
}
|
|
595
|
-
});
|
|
596
|
-
return {
|
|
597
|
-
createdThreadId,
|
|
598
|
-
From: `${params.channel}:channel:${createdThreadId}`,
|
|
599
|
-
To: `channel:${createdThreadId}`,
|
|
600
|
-
OriginatingTo: `channel:${createdThreadId}`,
|
|
601
|
-
SessionKey: threadSessionKey,
|
|
602
|
-
ModelParentSessionKey: parentSessionKey,
|
|
603
|
-
...params.parentInheritanceEnabled === true ? { ParentSessionKey: parentSessionKey } : {}
|
|
604
|
-
};
|
|
605
|
-
}
|
|
606
|
-
async function resolveDiscordAutoThreadReplyPlan(params) {
|
|
607
|
-
const messageChannelId = resolveTrimmedDiscordMessageChannelId(params);
|
|
608
|
-
const originalReplyTarget = `channel:${params.threadChannel?.id ?? (messageChannelId || "unknown")}`;
|
|
609
|
-
const createdThreadId = await maybeCreateDiscordAutoThread({
|
|
610
|
-
client: params.client,
|
|
611
|
-
message: params.message,
|
|
612
|
-
messageChannelId: messageChannelId || void 0,
|
|
613
|
-
channel: params.channel,
|
|
614
|
-
isGuildMessage: params.isGuildMessage,
|
|
615
|
-
channelConfig: params.channelConfig,
|
|
616
|
-
threadChannel: params.threadChannel,
|
|
617
|
-
channelType: params.channelType,
|
|
618
|
-
channelName: params.channelName,
|
|
619
|
-
channelDescription: params.channelDescription,
|
|
620
|
-
baseText: params.baseText,
|
|
621
|
-
combinedBody: params.combinedBody,
|
|
622
|
-
cfg: params.cfg,
|
|
623
|
-
agentId: params.agentId
|
|
624
|
-
});
|
|
625
|
-
const deliveryPlan = resolveDiscordReplyDeliveryPlan({
|
|
626
|
-
replyTarget: originalReplyTarget,
|
|
627
|
-
replyToMode: params.replyToMode,
|
|
628
|
-
messageId: params.message.id,
|
|
629
|
-
threadChannel: params.threadChannel,
|
|
630
|
-
createdThreadId
|
|
631
|
-
});
|
|
632
|
-
const autoThreadContext = params.isGuildMessage ? resolveDiscordAutoThreadContext({
|
|
633
|
-
agentId: params.agentId,
|
|
634
|
-
channel: params.channel,
|
|
635
|
-
messageChannelId,
|
|
636
|
-
createdThreadId,
|
|
637
|
-
parentInheritanceEnabled: params.threadParentInheritanceEnabled
|
|
638
|
-
}) : null;
|
|
639
|
-
return {
|
|
640
|
-
...deliveryPlan,
|
|
641
|
-
createdThreadId,
|
|
642
|
-
autoThreadContext
|
|
643
|
-
};
|
|
644
|
-
}
|
|
645
|
-
async function maybeCreateDiscordAutoThread(params) {
|
|
646
|
-
if (!params.isGuildMessage) return;
|
|
647
|
-
if (!params.channelConfig?.autoThread) return;
|
|
648
|
-
if (params.threadChannel) return;
|
|
649
|
-
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;
|
|
650
|
-
const messageChannelId = resolveTrimmedDiscordMessageChannelId(params);
|
|
651
|
-
if (!messageChannelId) return;
|
|
652
|
-
try {
|
|
653
|
-
try {
|
|
654
|
-
const existingThreadId = (await getChannelMessage(params.client.rest, messageChannelId, params.message.id))?.thread?.id;
|
|
655
|
-
if (existingThreadId) {
|
|
656
|
-
logVerbose(`discord: autoThread reusing existing thread ${existingThreadId} on ${messageChannelId}/${params.message.id}`);
|
|
657
|
-
return existingThreadId;
|
|
658
|
-
}
|
|
659
|
-
} catch {}
|
|
660
|
-
if (params.message.author?.bot) {
|
|
661
|
-
logVerbose(`discord: autoThread skipped for bot-authored message ${messageChannelId}/${params.message.id}`);
|
|
662
|
-
return;
|
|
663
|
-
}
|
|
664
|
-
const rawThreadSource = params.baseText || params.combinedBody || "Thread";
|
|
665
|
-
const threadName = sanitizeDiscordThreadName(rawThreadSource, params.message.id);
|
|
666
|
-
const archiveDuration = params.channelConfig?.autoArchiveDuration ? Number(params.channelConfig.autoArchiveDuration) : 60;
|
|
667
|
-
const createdId = (await createThread(params.client.rest, messageChannelId, { body: {
|
|
668
|
-
name: threadName,
|
|
669
|
-
auto_archive_duration: archiveDuration
|
|
670
|
-
} }, params.message.id))?.id || "";
|
|
671
|
-
if (createdId && params.channelConfig?.autoThreadName === "generated" && params.cfg && params.agentId) {
|
|
672
|
-
const modelRef = resolveDiscordThreadTitleModelRef({
|
|
673
|
-
cfg: params.cfg,
|
|
674
|
-
channel: params.channel,
|
|
675
|
-
agentId: params.agentId,
|
|
676
|
-
threadId: createdId,
|
|
677
|
-
messageChannelId,
|
|
678
|
-
channelName: params.channelName
|
|
679
|
-
});
|
|
680
|
-
maybeRenameDiscordAutoThread({
|
|
681
|
-
client: params.client,
|
|
682
|
-
threadId: createdId,
|
|
683
|
-
currentName: threadName,
|
|
684
|
-
fallbackId: params.message.id,
|
|
685
|
-
sourceText: rawThreadSource,
|
|
686
|
-
modelRef,
|
|
687
|
-
channelName: params.channelName,
|
|
688
|
-
channelDescription: params.channelDescription,
|
|
689
|
-
cfg: params.cfg,
|
|
690
|
-
agentId: params.agentId
|
|
691
|
-
});
|
|
692
|
-
}
|
|
693
|
-
return createdId || void 0;
|
|
694
|
-
} catch (err) {
|
|
695
|
-
logVerbose(`discord: autoThread creation failed for ${messageChannelId}/${params.message.id}: ${String(err)}`);
|
|
696
|
-
try {
|
|
697
|
-
const existingThreadId = (await getChannelMessage(params.client.rest, messageChannelId, params.message.id))?.thread?.id || "";
|
|
698
|
-
if (existingThreadId) {
|
|
699
|
-
logVerbose(`discord: autoThread reusing existing thread ${existingThreadId} on ${messageChannelId}/${params.message.id}`);
|
|
700
|
-
return existingThreadId;
|
|
701
|
-
}
|
|
702
|
-
} catch {}
|
|
703
|
-
return;
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
function resolveDiscordThreadTitleModelRef(params) {
|
|
707
|
-
const channel = params.channel?.trim();
|
|
708
|
-
if (!channel) return;
|
|
709
|
-
const parentSessionKey = buildAgentSessionKey({
|
|
710
|
-
agentId: params.agentId,
|
|
711
|
-
channel,
|
|
712
|
-
peer: {
|
|
713
|
-
kind: "channel",
|
|
714
|
-
id: params.messageChannelId
|
|
715
|
-
}
|
|
716
|
-
});
|
|
717
|
-
const channelLabel = params.channelName?.trim();
|
|
718
|
-
const groupChannel = channelLabel ? `#${channelLabel}` : void 0;
|
|
719
|
-
return resolveChannelModelOverride({
|
|
720
|
-
cfg: params.cfg,
|
|
721
|
-
channel,
|
|
722
|
-
groupId: params.threadId,
|
|
723
|
-
groupChatType: "channel",
|
|
724
|
-
groupChannel,
|
|
725
|
-
groupSubject: groupChannel,
|
|
726
|
-
parentSessionKey
|
|
727
|
-
})?.model;
|
|
728
|
-
}
|
|
729
|
-
async function maybeRenameDiscordAutoThread(params) {
|
|
730
|
-
try {
|
|
731
|
-
const fallbackName = sanitizeDiscordThreadName("", params.fallbackId);
|
|
732
|
-
const generated = await generateThreadTitle({
|
|
733
|
-
cfg: params.cfg,
|
|
734
|
-
agentId: params.agentId,
|
|
735
|
-
messageText: params.sourceText,
|
|
736
|
-
modelRef: params.modelRef,
|
|
737
|
-
channelName: params.channelName,
|
|
738
|
-
channelDescription: params.channelDescription
|
|
739
|
-
});
|
|
740
|
-
if (!generated) return;
|
|
741
|
-
const nextName = sanitizeDiscordThreadName(generated, params.fallbackId);
|
|
742
|
-
if (!nextName || nextName === params.currentName || nextName === fallbackName) return;
|
|
743
|
-
await editChannel(params.client.rest, params.threadId, { body: { name: nextName } });
|
|
744
|
-
} catch (err) {
|
|
745
|
-
logVerbose(`discord: autoThread rename failed for ${params.threadId}: ${String(err)}`);
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
//#endregion
|
|
749
|
-
//#region extensions/discord/src/monitor/threading.ts
|
|
750
|
-
var threading_exports = /* @__PURE__ */ __exportAll({
|
|
751
|
-
maybeCreateDiscordAutoThread: () => maybeCreateDiscordAutoThread,
|
|
752
|
-
resetDiscordThreadStarterCacheForTest: () => resetDiscordThreadStarterCacheForTest,
|
|
753
|
-
resolveDiscordAutoThreadContext: () => resolveDiscordAutoThreadContext,
|
|
754
|
-
resolveDiscordAutoThreadReplyPlan: () => resolveDiscordAutoThreadReplyPlan,
|
|
755
|
-
resolveDiscordReplyDeliveryPlan: () => resolveDiscordReplyDeliveryPlan,
|
|
756
|
-
resolveDiscordReplyTarget: () => resolveDiscordReplyTarget,
|
|
757
|
-
resolveDiscordThreadChannel: () => resolveDiscordThreadChannel,
|
|
758
|
-
resolveDiscordThreadParentInfo: () => resolveDiscordThreadParentInfo,
|
|
759
|
-
resolveDiscordThreadStarter: () => resolveDiscordThreadStarter,
|
|
760
|
-
sanitizeDiscordThreadName: () => sanitizeDiscordThreadName
|
|
761
|
-
});
|
|
762
|
-
//#endregion
|
|
763
507
|
//#region extensions/discord/src/monitor/thread-channel-context.ts
|
|
764
508
|
function isDiscordThreadChannelType(type) {
|
|
765
509
|
return type === discord_exports.ChannelType.PublicThread || type === discord_exports.ChannelType.PrivateThread || type === discord_exports.ChannelType.AnnouncementThread;
|
|
@@ -1131,264 +875,65 @@ async function handleDiscordReactionEvent(params) {
|
|
|
1131
875
|
const text = authorLabel ? `${baseText} from ${authorLabel}` : baseText;
|
|
1132
876
|
emitReaction(text, parentId);
|
|
1133
877
|
};
|
|
1134
|
-
const resolveThreadChannelConfig = () => resolveDiscordChannelConfigWithFallback({
|
|
1135
|
-
guildInfo,
|
|
1136
|
-
channelId: data.channel_id,
|
|
1137
|
-
channelName,
|
|
1138
|
-
channelSlug,
|
|
1139
|
-
parentId,
|
|
1140
|
-
parentName,
|
|
1141
|
-
parentSlug,
|
|
1142
|
-
scope: "thread"
|
|
1143
|
-
});
|
|
1144
|
-
const authorizeReactionIngressForChannel = async (channelConfig) => await authorizeDiscordReactionIngress({
|
|
1145
|
-
...reactionIngressBase,
|
|
1146
|
-
channelConfig
|
|
1147
|
-
});
|
|
1148
|
-
const resolveThreadChannelAccess = async () => {
|
|
1149
|
-
const channelConfig = resolveThreadChannelConfig();
|
|
1150
|
-
return {
|
|
1151
|
-
access: await authorizeReactionIngressForChannel(channelConfig),
|
|
1152
|
-
channelConfig
|
|
1153
|
-
};
|
|
1154
|
-
};
|
|
1155
|
-
if (isThreadChannel) {
|
|
1156
|
-
await handleDiscordThreadReactionNotification({
|
|
1157
|
-
reactionMode,
|
|
1158
|
-
message: data.message,
|
|
1159
|
-
parentId,
|
|
1160
|
-
resolveThreadChannelAccess,
|
|
1161
|
-
shouldNotifyReaction,
|
|
1162
|
-
resolveReactionBase,
|
|
1163
|
-
emitReaction,
|
|
1164
|
-
emitReactionWithAuthor
|
|
1165
|
-
});
|
|
1166
|
-
return;
|
|
1167
|
-
}
|
|
1168
|
-
const channelConfig = resolveDiscordChannelConfigWithFallback({
|
|
1169
|
-
guildInfo,
|
|
1170
|
-
channelId: data.channel_id,
|
|
1171
|
-
channelName,
|
|
1172
|
-
channelSlug,
|
|
1173
|
-
parentId,
|
|
1174
|
-
parentName,
|
|
1175
|
-
parentSlug,
|
|
1176
|
-
scope: "channel"
|
|
1177
|
-
});
|
|
1178
|
-
await handleDiscordChannelReactionNotification({
|
|
1179
|
-
isGuildMessage,
|
|
1180
|
-
reactionMode,
|
|
1181
|
-
message: data.message,
|
|
1182
|
-
channelConfig,
|
|
1183
|
-
parentId,
|
|
1184
|
-
authorizeReactionIngressForChannel,
|
|
1185
|
-
shouldNotifyReaction,
|
|
1186
|
-
resolveReactionBase,
|
|
1187
|
-
emitReaction,
|
|
1188
|
-
emitReactionWithAuthor
|
|
1189
|
-
});
|
|
1190
|
-
} catch (err) {
|
|
1191
|
-
params.logger.error(danger(`discord reaction handler failed: ${String(err)}`));
|
|
1192
|
-
}
|
|
1193
|
-
}
|
|
1194
|
-
//#endregion
|
|
1195
|
-
//#region extensions/discord/src/monitor/presence-events.ts
|
|
1196
|
-
const DISCORD_PRESENCE_GREETING_COOLDOWN_MS = 480 * 60 * 1e3;
|
|
1197
|
-
function isDiscordOnlineStatus(status) {
|
|
1198
|
-
return status === "online" || status === "idle" || status === "dnd";
|
|
1199
|
-
}
|
|
1200
|
-
function isDiscordOfflineStatus(status) {
|
|
1201
|
-
return status === "offline";
|
|
1202
|
-
}
|
|
1203
|
-
function resolveDiscordOnlinePresenceEvent(params) {
|
|
1204
|
-
const config = params.config;
|
|
1205
|
-
const userId = params.data.user?.id?.trim();
|
|
1206
|
-
if (!config || config.enabled === false || !userId || userId === params.botUserId || params.data.user.bot === true || !isDiscordOnlineStatus(params.data.status) || !params.availabilityKind) return null;
|
|
1207
|
-
if (config.users !== void 0 && !config.users.includes(userId)) return null;
|
|
1208
|
-
if (params.lastEmittedAtMs !== void 0 && params.nowMs - params.lastEmittedAtMs < 288e5) return null;
|
|
1209
|
-
const lines = [
|
|
1210
|
-
"Discord online-presence event:",
|
|
1211
|
-
params.availabilityKind === "observed-offline" ? `A human member became available online after being observed offline in guild_id=${JSON.stringify(params.data.guild_id)} user_id=${JSON.stringify(userId)} status=${JSON.stringify(params.data.status)}.` : `A human member became newly visible online since the current guild snapshot in guild_id=${JSON.stringify(params.data.guild_id)} user_id=${JSON.stringify(userId)} status=${JSON.stringify(params.data.status)}. They may have come online or joined after the snapshot; do not claim an exact prior status.`,
|
|
1212
|
-
`The authorized greeting target is channel_id=${JSON.stringify(config.channelId)}.`,
|
|
1213
|
-
"Before greeting, retrieve relevant memory and wiki context for this immutable user_id, including a known timezone when available. Use their local time for the greeting; if their timezone is unknown, do not guess.",
|
|
1214
|
-
"Send at most one short, natural greeting to the target channel. Do not reveal private memory. If no greeting is appropriate, stay silent."
|
|
1215
|
-
];
|
|
1216
|
-
return {
|
|
1217
|
-
channelId: config.channelId,
|
|
1218
|
-
userId,
|
|
1219
|
-
text: lines.join("\n")
|
|
1220
|
-
};
|
|
1221
|
-
}
|
|
1222
|
-
//#endregion
|
|
1223
|
-
//#region extensions/discord/src/monitor/presence-cooldown-store.ts
|
|
1224
|
-
const DISCORD_PRESENCE_COOLDOWN_MAX_ENTRIES = 25e3;
|
|
1225
|
-
function openDiscordPresenceCooldownStore() {
|
|
1226
|
-
return getDiscordRuntime().state.openSyncKeyedStore({
|
|
1227
|
-
namespace: "presence-greeting-cooldowns",
|
|
1228
|
-
maxEntries: DISCORD_PRESENCE_COOLDOWN_MAX_ENTRIES,
|
|
1229
|
-
overflowPolicy: "reject-new",
|
|
1230
|
-
defaultTtlMs: DISCORD_PRESENCE_GREETING_COOLDOWN_MS
|
|
1231
|
-
});
|
|
1232
|
-
}
|
|
1233
|
-
//#endregion
|
|
1234
|
-
//#region extensions/discord/src/monitor/presence-emission-gate.ts
|
|
1235
|
-
const DISCORD_PRESENCE_RECONNECT_SUPPRESS_MS = 300 * 1e3;
|
|
1236
|
-
const DISCORD_PRESENCE_BURST_LIMIT = 8;
|
|
1237
|
-
const DISCORD_PRESENCE_BURST_WINDOW_MS = 60 * 1e3;
|
|
1238
|
-
function resolveDiscordPresenceGateOptions(config) {
|
|
1239
|
-
return {
|
|
1240
|
-
reconnectSuppressMs: config?.reconnectSuppressSeconds !== void 0 ? config.reconnectSuppressSeconds * 1e3 : DISCORD_PRESENCE_RECONNECT_SUPPRESS_MS,
|
|
1241
|
-
burstLimit: config?.burstLimit ?? DISCORD_PRESENCE_BURST_LIMIT,
|
|
1242
|
-
burstWindowMs: config?.burstWindowSeconds !== void 0 ? config.burstWindowSeconds * 1e3 : DISCORD_PRESENCE_BURST_WINDOW_MS
|
|
1243
|
-
};
|
|
1244
|
-
}
|
|
1245
|
-
/**
|
|
1246
|
-
* Per-account lifecycle gate for online-presence events. Reconnect state belongs to the Gateway
|
|
1247
|
-
* session, while burst state follows the guild-owned configuration that supplies its limits.
|
|
1248
|
-
*/
|
|
1249
|
-
var DiscordPresenceEmissionGate = class {
|
|
1250
|
-
constructor() {
|
|
1251
|
-
this.reconnectLogged = false;
|
|
1252
|
-
this.burstByGuild = /* @__PURE__ */ new Map();
|
|
1253
|
-
this.nextReservationId = 0;
|
|
1254
|
-
}
|
|
1255
|
-
noteGatewaySessionReset(nowMs) {
|
|
1256
|
-
this.lastSessionResetAtMs = nowMs;
|
|
1257
|
-
this.reconnectLogged = false;
|
|
1258
|
-
}
|
|
1259
|
-
evaluateReconnectWindow(nowMs, options) {
|
|
1260
|
-
if (this.lastSessionResetAtMs !== void 0 && options.reconnectSuppressMs > 0 && nowMs - this.lastSessionResetAtMs < options.reconnectSuppressMs) {
|
|
1261
|
-
const shouldLog = !this.reconnectLogged;
|
|
1262
|
-
this.reconnectLogged = true;
|
|
1263
|
-
return {
|
|
1264
|
-
allowed: false,
|
|
1265
|
-
reason: "reconnect-window",
|
|
1266
|
-
shouldLog
|
|
1267
|
-
};
|
|
1268
|
-
}
|
|
1269
|
-
return { allowed: true };
|
|
1270
|
-
}
|
|
1271
|
-
reserveBurst(guildId, nowMs, options) {
|
|
1272
|
-
const state = this.burstByGuild.get(guildId) ?? {
|
|
1273
|
-
reservations: [],
|
|
1274
|
-
logged: false
|
|
1275
|
-
};
|
|
1276
|
-
state.reservations = state.reservations.filter((reservation) => !reservation.committed || nowMs - reservation.atMs < options.burstWindowMs);
|
|
1277
|
-
this.burstByGuild.set(guildId, state);
|
|
1278
|
-
if (state.reservations.length >= options.burstLimit) {
|
|
1279
|
-
const shouldLog = !state.logged;
|
|
1280
|
-
state.logged = true;
|
|
878
|
+
const resolveThreadChannelConfig = () => resolveDiscordChannelConfigWithFallback({
|
|
879
|
+
guildInfo,
|
|
880
|
+
channelId: data.channel_id,
|
|
881
|
+
channelName,
|
|
882
|
+
channelSlug,
|
|
883
|
+
parentId,
|
|
884
|
+
parentName,
|
|
885
|
+
parentSlug,
|
|
886
|
+
scope: "thread"
|
|
887
|
+
});
|
|
888
|
+
const authorizeReactionIngressForChannel = async (channelConfig) => await authorizeDiscordReactionIngress({
|
|
889
|
+
...reactionIngressBase,
|
|
890
|
+
channelConfig
|
|
891
|
+
});
|
|
892
|
+
const resolveThreadChannelAccess = async () => {
|
|
893
|
+
const channelConfig = resolveThreadChannelConfig();
|
|
1281
894
|
return {
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
shouldLog
|
|
895
|
+
access: await authorizeReactionIngressForChannel(channelConfig),
|
|
896
|
+
channelConfig
|
|
1285
897
|
};
|
|
1286
|
-
}
|
|
1287
|
-
state.logged = false;
|
|
1288
|
-
const reservation = {
|
|
1289
|
-
id: this.nextReservationId++,
|
|
1290
|
-
atMs: nowMs,
|
|
1291
|
-
committed: false
|
|
1292
|
-
};
|
|
1293
|
-
state.reservations.push(reservation);
|
|
1294
|
-
return {
|
|
1295
|
-
allowed: true,
|
|
1296
|
-
reservation: reservation.id
|
|
1297
898
|
};
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
}
|
|
1311
|
-
};
|
|
1312
|
-
//#endregion
|
|
1313
|
-
//#region extensions/discord/src/monitor/presence-transition-cache.ts
|
|
1314
|
-
const DEFAULT_PRESENCE_BASELINE_MAX_ENTRIES = 75e3;
|
|
1315
|
-
var DiscordPresenceBaselineCache = class {
|
|
1316
|
-
constructor(maxEntries = DEFAULT_PRESENCE_BASELINE_MAX_ENTRIES) {
|
|
1317
|
-
this.maxEntries = maxEntries;
|
|
1318
|
-
this.offlineByKey = /* @__PURE__ */ new Map();
|
|
1319
|
-
this.onlineByKey = /* @__PURE__ */ new Map();
|
|
1320
|
-
}
|
|
1321
|
-
clear() {
|
|
1322
|
-
this.offlineByKey.clear();
|
|
1323
|
-
this.onlineByKey.clear();
|
|
1324
|
-
}
|
|
1325
|
-
clearScope(scope) {
|
|
1326
|
-
for (const markers of [this.offlineByKey, this.onlineByKey]) for (const [key, markerScope] of markers) if (markerScope === scope) markers.delete(key);
|
|
1327
|
-
}
|
|
1328
|
-
isOffline(scope, key) {
|
|
1329
|
-
return this.offlineByKey.get(key) === scope;
|
|
1330
|
-
}
|
|
1331
|
-
isOnline(scope, key) {
|
|
1332
|
-
return this.onlineByKey.get(key) === scope;
|
|
1333
|
-
}
|
|
1334
|
-
observeOffline(scope, key) {
|
|
1335
|
-
this.deleteMarker(this.onlineByKey, scope, key);
|
|
1336
|
-
return this.observe(this.offlineByKey, scope, key);
|
|
1337
|
-
}
|
|
1338
|
-
observeOnline(scope, key) {
|
|
1339
|
-
this.deleteMarker(this.offlineByKey, scope, key);
|
|
1340
|
-
return this.observe(this.onlineByKey, scope, key);
|
|
1341
|
-
}
|
|
1342
|
-
deleteMarker(markers, scope, key) {
|
|
1343
|
-
if (markers.get(key) === scope) markers.delete(key);
|
|
1344
|
-
}
|
|
1345
|
-
observe(markers, scope, key) {
|
|
1346
|
-
markers.delete(key);
|
|
1347
|
-
markers.set(key, scope);
|
|
1348
|
-
let evictedScope;
|
|
1349
|
-
while (markers.size > this.maxEntries) {
|
|
1350
|
-
const oldestKey = markers.keys().next().value;
|
|
1351
|
-
if (oldestKey === void 0) break;
|
|
1352
|
-
evictedScope = markers.get(oldestKey);
|
|
1353
|
-
markers.delete(oldestKey);
|
|
1354
|
-
}
|
|
1355
|
-
return evictedScope;
|
|
1356
|
-
}
|
|
1357
|
-
};
|
|
1358
|
-
//#endregion
|
|
1359
|
-
//#region extensions/discord/src/monitor/thread-session-close.ts
|
|
1360
|
-
/**
|
|
1361
|
-
* Closes every session entry in the store whose key contains {@link threadId}.
|
|
1362
|
-
* The explicit lifecycle deletion archives the old transcript and guarantees
|
|
1363
|
-
* that a later inbound message starts a fresh session in every reset mode.
|
|
1364
|
-
*/
|
|
1365
|
-
async function closeDiscordThreadSessions(params) {
|
|
1366
|
-
const { cfg, threadId } = params;
|
|
1367
|
-
const normalizedThreadId = normalizeOptionalLowercaseString(threadId) ?? "";
|
|
1368
|
-
if (!normalizedThreadId) return 0;
|
|
1369
|
-
const segmentRe = new RegExp(`:${normalizedThreadId}(?::|$)`, "i");
|
|
1370
|
-
function sessionKeyContainsThreadId(key) {
|
|
1371
|
-
return segmentRe.test(key);
|
|
1372
|
-
}
|
|
1373
|
-
let resetCount = 0;
|
|
1374
|
-
for (const agentId of listAgentIds(cfg)) {
|
|
1375
|
-
const storePath = resolveStorePath(cfg.session?.store, { agentId });
|
|
1376
|
-
for (const { sessionKey, entry } of listSessionEntries({
|
|
1377
|
-
agentId,
|
|
1378
|
-
storePath,
|
|
1379
|
-
readOnly: true
|
|
1380
|
-
})) {
|
|
1381
|
-
if (!sessionKeyContainsThreadId(sessionKey)) continue;
|
|
1382
|
-
if (await deleteSessionEntry({
|
|
1383
|
-
archiveTranscript: true,
|
|
1384
|
-
expectedSessionId: entry.sessionId ?? null,
|
|
1385
|
-
expectedUpdatedAt: entry.updatedAt,
|
|
1386
|
-
sessionKey,
|
|
1387
|
-
storePath
|
|
1388
|
-
})) resetCount += 1;
|
|
899
|
+
if (isThreadChannel) {
|
|
900
|
+
await handleDiscordThreadReactionNotification({
|
|
901
|
+
reactionMode,
|
|
902
|
+
message: data.message,
|
|
903
|
+
parentId,
|
|
904
|
+
resolveThreadChannelAccess,
|
|
905
|
+
shouldNotifyReaction,
|
|
906
|
+
resolveReactionBase,
|
|
907
|
+
emitReaction,
|
|
908
|
+
emitReactionWithAuthor
|
|
909
|
+
});
|
|
910
|
+
return;
|
|
1389
911
|
}
|
|
912
|
+
const channelConfig = resolveDiscordChannelConfigWithFallback({
|
|
913
|
+
guildInfo,
|
|
914
|
+
channelId: data.channel_id,
|
|
915
|
+
channelName,
|
|
916
|
+
channelSlug,
|
|
917
|
+
parentId,
|
|
918
|
+
parentName,
|
|
919
|
+
parentSlug,
|
|
920
|
+
scope: "channel"
|
|
921
|
+
});
|
|
922
|
+
await handleDiscordChannelReactionNotification({
|
|
923
|
+
isGuildMessage,
|
|
924
|
+
reactionMode,
|
|
925
|
+
message: data.message,
|
|
926
|
+
channelConfig,
|
|
927
|
+
parentId,
|
|
928
|
+
authorizeReactionIngressForChannel,
|
|
929
|
+
shouldNotifyReaction,
|
|
930
|
+
resolveReactionBase,
|
|
931
|
+
emitReaction,
|
|
932
|
+
emitReactionWithAuthor
|
|
933
|
+
});
|
|
934
|
+
} catch (err) {
|
|
935
|
+
params.logger.error(danger(`discord reaction handler failed: ${String(err)}`));
|
|
1390
936
|
}
|
|
1391
|
-
return resetCount;
|
|
1392
937
|
}
|
|
1393
938
|
//#endregion
|
|
1394
939
|
//#region extensions/discord/src/monitor/listeners.ts
|
|
@@ -1815,11 +1360,16 @@ function isDiscordUnknownInteraction(error) {
|
|
|
1815
1360
|
if (/Unknown interaction/i.test(err.rawBody?.message ?? "")) return true;
|
|
1816
1361
|
return false;
|
|
1817
1362
|
}
|
|
1363
|
+
function resolveDiscordInteractionMessageParts(payload) {
|
|
1364
|
+
const { components, embeds } = payload.channelData?.discord ?? {};
|
|
1365
|
+
return {
|
|
1366
|
+
components: Array.isArray(components) && components.length > 0 ? components : void 0,
|
|
1367
|
+
embeds: Array.isArray(embeds) && embeds.length > 0 ? embeds : void 0
|
|
1368
|
+
};
|
|
1369
|
+
}
|
|
1818
1370
|
function hasRenderableReplyPayload(payload) {
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
if (Array.isArray(discordData?.components) && discordData.components.length > 0) return true;
|
|
1822
|
-
return false;
|
|
1371
|
+
const { components, embeds } = resolveDiscordInteractionMessageParts(payload);
|
|
1372
|
+
return resolveSendableOutboundReplyParts(payload).hasContent || Boolean(components || embeds);
|
|
1823
1373
|
}
|
|
1824
1374
|
async function safeDiscordInteractionCall(label, fn) {
|
|
1825
1375
|
try {
|
|
@@ -1839,33 +1389,25 @@ async function settleDiscordInteractionWithoutVisibleReply(interaction) {
|
|
|
1839
1389
|
async function deliverDiscordInteractionReply(params) {
|
|
1840
1390
|
const { interaction, payload, textLimit, maxLinesPerMessage, preferFollowUp, chunkMode } = params;
|
|
1841
1391
|
const reply = resolveSendableOutboundReplyParts(payload);
|
|
1842
|
-
|
|
1843
|
-
let firstMessageComponents = Array.isArray(discordData?.components) && discordData.components.length > 0 ? discordData.components : void 0;
|
|
1392
|
+
let { components: firstMessageComponents, embeds: firstMessageEmbeds } = resolveDiscordInteractionMessageParts(payload);
|
|
1844
1393
|
let payloadDelivered = false;
|
|
1845
|
-
const sendMessage = async (content, files, components) => {
|
|
1846
|
-
const
|
|
1847
|
-
const payloadLocal =
|
|
1848
|
-
...
|
|
1394
|
+
const sendMessage = async (content, files, components, embeds) => {
|
|
1395
|
+
const hasV2 = hasDiscordV2Components(components);
|
|
1396
|
+
const payloadLocal = {
|
|
1397
|
+
...content && !hasV2 ? { content } : {},
|
|
1849
1398
|
...components ? { components } : {},
|
|
1399
|
+
...embeds && !hasV2 ? { embeds } : {},
|
|
1850
1400
|
...params.responseEphemeral !== void 0 ? { ephemeral: params.responseEphemeral } : {},
|
|
1851
|
-
files
|
|
1852
|
-
} : {
|
|
1853
|
-
...contentPayload,
|
|
1854
|
-
...components ? { components } : {},
|
|
1855
|
-
...params.responseEphemeral !== void 0 ? { ephemeral: params.responseEphemeral } : {}
|
|
1401
|
+
...files?.length ? { files } : {}
|
|
1856
1402
|
};
|
|
1857
1403
|
let result;
|
|
1858
1404
|
try {
|
|
1859
1405
|
result = await safeDiscordInteractionCall("interaction send", async () => {
|
|
1860
|
-
if (!preferFollowUp && !payloadDelivered)
|
|
1861
|
-
|
|
1862
|
-
payloadDelivered = true;
|
|
1863
|
-
firstMessageComponents = void 0;
|
|
1864
|
-
return;
|
|
1865
|
-
}
|
|
1866
|
-
await interaction.followUp(payloadLocal);
|
|
1406
|
+
if (!preferFollowUp && !payloadDelivered) await interaction.reply(payloadLocal);
|
|
1407
|
+
else await interaction.followUp(payloadLocal);
|
|
1867
1408
|
payloadDelivered = true;
|
|
1868
1409
|
firstMessageComponents = void 0;
|
|
1410
|
+
firstMessageEmbeds = void 0;
|
|
1869
1411
|
});
|
|
1870
1412
|
} catch (error) {
|
|
1871
1413
|
if (!payloadDelivered) throw error;
|
|
@@ -1890,99 +1432,27 @@ async function deliverDiscordInteractionReply(params) {
|
|
|
1890
1432
|
maxLines: maxLinesPerMessage,
|
|
1891
1433
|
chunkMode
|
|
1892
1434
|
}));
|
|
1893
|
-
await sendMessage(chunks[0] ?? "", media, firstMessageComponents);
|
|
1435
|
+
await sendMessage(chunks[0] ?? "", media, firstMessageComponents, firstMessageEmbeds);
|
|
1894
1436
|
for (const chunk of chunks.slice(1)) {
|
|
1895
1437
|
if (!chunk.trim()) continue;
|
|
1896
1438
|
await sendMessage(chunk);
|
|
1897
1439
|
}
|
|
1898
1440
|
return payloadDelivered;
|
|
1899
1441
|
}
|
|
1900
|
-
if (!reply.hasText && !firstMessageComponents) return false;
|
|
1901
|
-
|
|
1442
|
+
if (!reply.hasText && !firstMessageComponents && !firstMessageEmbeds) return false;
|
|
1443
|
+
const chunks = resolveTextChunksWithFallback(reply.text, chunkDiscordTextWithMode(reply.text, {
|
|
1902
1444
|
maxChars: textLimit,
|
|
1903
1445
|
maxLines: maxLinesPerMessage,
|
|
1904
1446
|
chunkMode
|
|
1905
|
-
}))
|
|
1906
|
-
if (chunks.length === 0
|
|
1447
|
+
}));
|
|
1448
|
+
if (chunks.length === 0) chunks.push("");
|
|
1907
1449
|
for (const chunk of chunks) {
|
|
1908
|
-
if (!chunk.trim() && !firstMessageComponents) continue;
|
|
1909
|
-
await sendMessage(chunk, void 0, firstMessageComponents);
|
|
1450
|
+
if (!chunk.trim() && !firstMessageComponents && !firstMessageEmbeds) continue;
|
|
1451
|
+
await sendMessage(chunk, void 0, firstMessageComponents, firstMessageEmbeds);
|
|
1910
1452
|
}
|
|
1911
1453
|
return payloadDelivered;
|
|
1912
1454
|
}
|
|
1913
1455
|
//#endregion
|
|
1914
|
-
//#region extensions/discord/src/monitor/route-resolution.ts
|
|
1915
|
-
function buildDiscordRoutePeer(params) {
|
|
1916
|
-
return {
|
|
1917
|
-
kind: params.isDirectMessage ? "direct" : params.isGroupDm ? "group" : "channel",
|
|
1918
|
-
id: params.isDirectMessage ? params.directUserId?.trim() || params.conversationId : params.conversationId
|
|
1919
|
-
};
|
|
1920
|
-
}
|
|
1921
|
-
function resolveDiscordConversationRoute(params) {
|
|
1922
|
-
return resolveAgentRoute({
|
|
1923
|
-
cfg: params.cfg,
|
|
1924
|
-
channel: "discord",
|
|
1925
|
-
accountId: params.accountId,
|
|
1926
|
-
guildId: params.guildId ?? void 0,
|
|
1927
|
-
memberRoleIds: params.memberRoleIds,
|
|
1928
|
-
peer: params.peer,
|
|
1929
|
-
parentPeer: params.parentConversationId ? {
|
|
1930
|
-
kind: "channel",
|
|
1931
|
-
id: params.parentConversationId
|
|
1932
|
-
} : void 0
|
|
1933
|
-
});
|
|
1934
|
-
}
|
|
1935
|
-
function resolveDiscordBoundConversationRoute(params) {
|
|
1936
|
-
return resolveDiscordEffectiveRoute({
|
|
1937
|
-
route: resolveDiscordConversationRoute({
|
|
1938
|
-
cfg: params.cfg,
|
|
1939
|
-
accountId: params.accountId,
|
|
1940
|
-
guildId: params.guildId,
|
|
1941
|
-
memberRoleIds: params.memberRoleIds,
|
|
1942
|
-
peer: buildDiscordRoutePeer({
|
|
1943
|
-
isDirectMessage: params.isDirectMessage,
|
|
1944
|
-
isGroupDm: params.isGroupDm,
|
|
1945
|
-
directUserId: params.directUserId,
|
|
1946
|
-
conversationId: params.conversationId
|
|
1947
|
-
}),
|
|
1948
|
-
parentConversationId: params.parentConversationId
|
|
1949
|
-
}),
|
|
1950
|
-
boundSessionKey: params.boundSessionKey,
|
|
1951
|
-
configuredRoute: params.configuredRoute,
|
|
1952
|
-
matchedBy: params.matchedBy
|
|
1953
|
-
});
|
|
1954
|
-
}
|
|
1955
|
-
function resolveDiscordEffectiveRoute(params) {
|
|
1956
|
-
const boundSessionKey = params.boundSessionKey?.trim();
|
|
1957
|
-
if (!boundSessionKey) return params.configuredRoute?.route ?? params.route;
|
|
1958
|
-
return {
|
|
1959
|
-
...params.route,
|
|
1960
|
-
sessionKey: boundSessionKey,
|
|
1961
|
-
agentId: resolveAgentIdFromSessionKey(boundSessionKey),
|
|
1962
|
-
lastRoutePolicy: deriveLastRoutePolicy({
|
|
1963
|
-
sessionKey: boundSessionKey,
|
|
1964
|
-
mainSessionKey: params.route.mainSessionKey
|
|
1965
|
-
}),
|
|
1966
|
-
...params.matchedBy ? { matchedBy: params.matchedBy } : {}
|
|
1967
|
-
};
|
|
1968
|
-
}
|
|
1969
|
-
function hasExplicitRuntimeBindingIntent(record) {
|
|
1970
|
-
if (record.targetKind === "subagent") return true;
|
|
1971
|
-
if (isAcpSessionKey(record.targetSessionKey) || isSubagentSessionKey(record.targetSessionKey)) return true;
|
|
1972
|
-
const metadata = record.metadata;
|
|
1973
|
-
if (!metadata || typeof metadata !== "object") return false;
|
|
1974
|
-
return typeof metadata.boundBy === "string" || typeof metadata.label === "string" || typeof metadata.threadName === "string" || metadata.pluginBindingOwner === "plugin";
|
|
1975
|
-
}
|
|
1976
|
-
function shouldIgnoreStaleDiscordRouteBinding(params) {
|
|
1977
|
-
const bindingRecord = params.bindingRecord;
|
|
1978
|
-
const boundSessionKey = bindingRecord?.targetSessionKey?.trim();
|
|
1979
|
-
if (!bindingRecord || !boundSessionKey || hasExplicitRuntimeBindingIntent(bindingRecord)) return false;
|
|
1980
|
-
const bound = parseAgentSessionKey(boundSessionKey);
|
|
1981
|
-
const routed = parseAgentSessionKey(params.route.sessionKey);
|
|
1982
|
-
if (!bound || !routed || bound.rest !== routed.rest) return false;
|
|
1983
|
-
return bound.agentId !== params.route.agentId;
|
|
1984
|
-
}
|
|
1985
|
-
//#endregion
|
|
1986
1456
|
//#region extensions/discord/src/monitor/native-command-route.ts
|
|
1987
1457
|
async function resolveDiscordNativeInteractionRouteState(params) {
|
|
1988
1458
|
const route = resolveDiscordBoundConversationRoute({
|
|
@@ -2398,11 +1868,11 @@ async function resolveDiscordNativeAutocompleteAuthorized(params) {
|
|
|
2398
1868
|
//#endregion
|
|
2399
1869
|
//#region extensions/discord/src/monitor/native-command-bypass.ts
|
|
2400
1870
|
function shouldBypassConfiguredAcpEnsure(commandName) {
|
|
2401
|
-
return
|
|
1871
|
+
return commandName.trim().toLowerCase() === "acp";
|
|
2402
1872
|
}
|
|
2403
1873
|
function shouldBypassConfiguredAcpGuildGuards(commandName) {
|
|
2404
|
-
const
|
|
2405
|
-
return
|
|
1874
|
+
const command = commandName.trim().toLowerCase();
|
|
1875
|
+
return command === "new" || command === "reset";
|
|
2406
1876
|
}
|
|
2407
1877
|
//#endregion
|
|
2408
1878
|
//#region extensions/discord/src/monitor/inbound-context.ts
|
|
@@ -2481,6 +1951,14 @@ function buildDiscordNativeCommandContext(params) {
|
|
|
2481
1951
|
CommandTargetSessionKey: params.commandTargetSessionKey,
|
|
2482
1952
|
AccountId: params.accountId ?? void 0,
|
|
2483
1953
|
ChatType: params.isDirectMessage ? "direct" : params.isGroupDm ? "group" : "channel",
|
|
1954
|
+
...buildDiscordConversationRouteContext({
|
|
1955
|
+
isDirectMessage: params.isDirectMessage,
|
|
1956
|
+
isGroupDm: params.isGroupDm,
|
|
1957
|
+
directUserId: params.user.id,
|
|
1958
|
+
conversationId: params.channelId,
|
|
1959
|
+
isThread: params.isThreadChannel,
|
|
1960
|
+
parentConversationId: params.threadParentId
|
|
1961
|
+
}),
|
|
2484
1962
|
ConversationLabel: conversationLabel,
|
|
2485
1963
|
GroupSubject: params.isGuild ? params.guildName : void 0,
|
|
2486
1964
|
GroupSpace: params.isGuild ? params.guildInfo?.id ?? params.guildInfo?.slug ?? params.guildId : void 0,
|
|
@@ -2496,7 +1974,6 @@ function buildDiscordNativeCommandContext(params) {
|
|
|
2496
1974
|
Surface: "discord",
|
|
2497
1975
|
WasMentioned: true,
|
|
2498
1976
|
MessageSid: params.interactionId,
|
|
2499
|
-
MessageThreadId: params.isThreadChannel ? params.channelId : void 0,
|
|
2500
1977
|
Timestamp: params.timestampMs ?? Date.now(),
|
|
2501
1978
|
CommandAuthorized: params.commandAuthorized,
|
|
2502
1979
|
CommandTurn: {
|
|
@@ -2511,8 +1988,7 @@ function buildDiscordNativeCommandContext(params) {
|
|
|
2511
1988
|
isDirectMessage: params.isDirectMessage,
|
|
2512
1989
|
userId: params.user.id,
|
|
2513
1990
|
channelId: params.channelId
|
|
2514
|
-
}) ?? (params.isDirectMessage ? `user:${params.user.id}` : `channel:${params.channelId}`)
|
|
2515
|
-
ThreadParentId: params.isThreadChannel ? params.threadParentId : void 0
|
|
1991
|
+
}) ?? (params.isDirectMessage ? `user:${params.user.id}` : `channel:${params.channelId}`)
|
|
2516
1992
|
});
|
|
2517
1993
|
}
|
|
2518
1994
|
//#endregion
|
|
@@ -4446,7 +3922,7 @@ const DISCORD_COMMAND_DESCRIPTION_MAX = 100;
|
|
|
4446
3922
|
function truncateDiscordCommandDescription(params) {
|
|
4447
3923
|
const { value, label } = params;
|
|
4448
3924
|
if (value.length <= DISCORD_COMMAND_DESCRIPTION_MAX) return value;
|
|
4449
|
-
log$1.
|
|
3925
|
+
log$1.debug(`discord: truncating native command description (${label}) from ${value.length} to ${DISCORD_COMMAND_DESCRIPTION_MAX}: ${JSON.stringify(value)}`);
|
|
4450
3926
|
return truncateUtf16Safe(value, DISCORD_COMMAND_DESCRIPTION_MAX);
|
|
4451
3927
|
}
|
|
4452
3928
|
function truncateDiscordCommandDescriptionLocalizations(params) {
|
|
@@ -5097,7 +4573,7 @@ function canResumeAfterGatewayClose(code) {
|
|
|
5097
4573
|
//#region extensions/discord/src/internal/gateway-identify-limiter.ts
|
|
5098
4574
|
const IDENTIFY_WINDOW_MS = 5e3;
|
|
5099
4575
|
function normalizeMaxConcurrency(value) {
|
|
5100
|
-
const parsed = parseFiniteNumber
|
|
4576
|
+
const parsed = parseFiniteNumber(value);
|
|
5101
4577
|
return parsed === void 0 ? 1 : Math.max(1, Math.floor(parsed));
|
|
5102
4578
|
}
|
|
5103
4579
|
var GatewayIdentifyLimiter = class {
|
|
@@ -5305,7 +4781,7 @@ var DiscordGatewayVoiceStateCache = class {
|
|
|
5305
4781
|
}
|
|
5306
4782
|
listVoiceChannelStates(guildId, channelId) {
|
|
5307
4783
|
const states = this.statesByGuild.get(guildId);
|
|
5308
|
-
if (!states) return
|
|
4784
|
+
if (!states) return null;
|
|
5309
4785
|
const result = [];
|
|
5310
4786
|
for (const state of states.values()) if (state.channel_id === channelId) result.push({ ...state });
|
|
5311
4787
|
return result;
|
|
@@ -5518,7 +4994,10 @@ var GatewayPlugin = class extends Plugin {
|
|
|
5518
4994
|
if (payload.s !== null && payload.s !== void 0) this.sequence = payload.s;
|
|
5519
4995
|
switch (payload.op) {
|
|
5520
4996
|
case GatewayOpcodes.Hello: {
|
|
5521
|
-
this.startHeartbeat(payload.d
|
|
4997
|
+
this.startHeartbeat(asSafeIntegerInRange(asOptionalRecord(payload.d)?.heartbeat_interval, {
|
|
4998
|
+
min: 1,
|
|
4999
|
+
max: MAX_TIMER_TIMEOUT_MS
|
|
5000
|
+
}) ?? 45e3);
|
|
5522
5001
|
const resumeState = resume ? this.getResumeState() : null;
|
|
5523
5002
|
if (resumeState) this.send({
|
|
5524
5003
|
op: GatewayOpcodes.Resume,
|
|
@@ -5721,12 +5200,6 @@ var GatewayPlugin = class extends Plugin {
|
|
|
5721
5200
|
}
|
|
5722
5201
|
};
|
|
5723
5202
|
//#endregion
|
|
5724
|
-
//#region extensions/discord/src/voice/config.ts
|
|
5725
|
-
function resolveDiscordVoiceEnabled(voice) {
|
|
5726
|
-
if (voice?.enabled !== void 0) return voice.enabled;
|
|
5727
|
-
return voice !== void 0;
|
|
5728
|
-
}
|
|
5729
|
-
//#endregion
|
|
5730
5203
|
//#region extensions/discord/src/monitor/presence.ts
|
|
5731
5204
|
const DEFAULT_CUSTOM_ACTIVITY_TYPE$1 = 4;
|
|
5732
5205
|
const CUSTOM_STATUS_NAME$1 = "Custom Status";
|
|
@@ -7045,7 +6518,7 @@ async function runDiscordGatewayLifecycle(params) {
|
|
|
7045
6518
|
gatewayEmitter?.removeListener(DISCORD_GATEWAY_TRANSPORT_ACTIVITY_EVENT, onGatewayTransportActivity);
|
|
7046
6519
|
if (params.voiceManager) {
|
|
7047
6520
|
await params.voiceManager.destroy();
|
|
7048
|
-
const { setDiscordTranscriptsVoiceManager } = await import("./transcripts-source-
|
|
6521
|
+
const { setDiscordTranscriptsVoiceManager } = await import("./transcripts-source-DeIMNbRh.js").then((n) => n.n);
|
|
7049
6522
|
setDiscordTranscriptsVoiceManager({
|
|
7050
6523
|
accountId: params.accountId,
|
|
7051
6524
|
manager: null
|
|
@@ -7060,7 +6533,7 @@ async function runDiscordGatewayLifecycle(params) {
|
|
|
7060
6533
|
let discordVoiceRuntimePromise;
|
|
7061
6534
|
let discordProviderSessionRuntimePromise;
|
|
7062
6535
|
async function loadDiscordVoiceRuntime() {
|
|
7063
|
-
const promise = discordVoiceRuntimePromise ?? import("./voice-runtime-
|
|
6536
|
+
const promise = discordVoiceRuntimePromise ?? import("./voice-runtime-CjNFaynA.js");
|
|
7064
6537
|
discordVoiceRuntimePromise = promise;
|
|
7065
6538
|
try {
|
|
7066
6539
|
return await promise;
|
|
@@ -7070,7 +6543,7 @@ async function loadDiscordVoiceRuntime() {
|
|
|
7070
6543
|
}
|
|
7071
6544
|
}
|
|
7072
6545
|
async function loadDiscordProviderSessionRuntime() {
|
|
7073
|
-
const promise = discordProviderSessionRuntimePromise ?? import("./provider-session.runtime-
|
|
6546
|
+
const promise = discordProviderSessionRuntimePromise ?? import("./provider-session.runtime-CvvphHvs.js");
|
|
7074
6547
|
discordProviderSessionRuntimePromise = promise;
|
|
7075
6548
|
try {
|
|
7076
6549
|
return await promise;
|
|
@@ -7431,102 +6904,6 @@ async function cleanupDiscordProviderStartup(params) {
|
|
|
7431
6904
|
if (!params.lifecycleStarted) params.threadBindings.stop();
|
|
7432
6905
|
}
|
|
7433
6906
|
//#endregion
|
|
7434
|
-
//#region extensions/discord/src/voice/access.ts
|
|
7435
|
-
async function authorizeDiscordVoiceIngress(params) {
|
|
7436
|
-
const groupPolicy = params.groupPolicy ?? resolveOpenProviderRuntimeGroupPolicy({
|
|
7437
|
-
providerConfigPresent: params.cfg.channels?.discord !== void 0,
|
|
7438
|
-
groupPolicy: params.discordConfig.groupPolicy,
|
|
7439
|
-
defaultGroupPolicy: params.cfg.channels?.defaults?.groupPolicy
|
|
7440
|
-
}).groupPolicy;
|
|
7441
|
-
const guildInfo = resolveDiscordGuildEntry({
|
|
7442
|
-
guild: params.guild ?? {
|
|
7443
|
-
id: params.guildId,
|
|
7444
|
-
...params.guildName ? { name: params.guildName } : {}
|
|
7445
|
-
},
|
|
7446
|
-
guildId: params.guildId,
|
|
7447
|
-
guildEntries: params.discordConfig.guilds
|
|
7448
|
-
});
|
|
7449
|
-
const channelConfig = params.channelId ? resolveDiscordChannelConfigWithFallback({
|
|
7450
|
-
guildInfo,
|
|
7451
|
-
channelId: params.channelId,
|
|
7452
|
-
channelName: params.channelName,
|
|
7453
|
-
channelSlug: params.channelSlug,
|
|
7454
|
-
parentId: params.parentId,
|
|
7455
|
-
parentName: params.parentName,
|
|
7456
|
-
parentSlug: params.parentSlug,
|
|
7457
|
-
scope: params.scope
|
|
7458
|
-
}) : null;
|
|
7459
|
-
if (channelConfig?.enabled === false) return {
|
|
7460
|
-
ok: false,
|
|
7461
|
-
message: "This channel is disabled."
|
|
7462
|
-
};
|
|
7463
|
-
const channelAllowlistConfigured = Boolean(guildInfo?.channels) && Object.keys(guildInfo?.channels ?? {}).length > 0;
|
|
7464
|
-
if (!params.channelId && groupPolicy === "allowlist" && channelAllowlistConfigured) return {
|
|
7465
|
-
ok: false,
|
|
7466
|
-
message: `${params.channelLabel ?? "This channel"} is not allowlisted for voice commands.`
|
|
7467
|
-
};
|
|
7468
|
-
const channelAllowed = channelConfig ? channelConfig.allowed : !channelAllowlistConfigured;
|
|
7469
|
-
if (!isDiscordGroupAllowedByPolicy({
|
|
7470
|
-
groupPolicy,
|
|
7471
|
-
guildAllowlisted: Boolean(guildInfo),
|
|
7472
|
-
channelAllowlistConfigured,
|
|
7473
|
-
channelAllowed
|
|
7474
|
-
}) || channelConfig?.allowed === false) return {
|
|
7475
|
-
ok: false,
|
|
7476
|
-
message: `${params.channelLabel ?? "This channel"} is not allowlisted for voice commands.`
|
|
7477
|
-
};
|
|
7478
|
-
const { hasAccessRestrictions, memberAllowed } = resolveDiscordMemberAccessState({
|
|
7479
|
-
channelConfig,
|
|
7480
|
-
guildInfo,
|
|
7481
|
-
memberRoleIds: params.memberRoleIds,
|
|
7482
|
-
sender: params.sender,
|
|
7483
|
-
allowNameMatching: false
|
|
7484
|
-
});
|
|
7485
|
-
const admissionAllowList = normalizeDiscordAllowList(params.admissionAllowFrom ?? params.discordConfig.allowFrom ?? params.discordConfig.allowFrom, [
|
|
7486
|
-
"discord:",
|
|
7487
|
-
"user:",
|
|
7488
|
-
"pk:"
|
|
7489
|
-
]);
|
|
7490
|
-
const admissionAllowed = admissionAllowList ? allowListMatches(admissionAllowList, params.sender, { allowNameMatching: false }) : false;
|
|
7491
|
-
const useAccessGroups = params.useAccessGroups ?? true;
|
|
7492
|
-
return resolveCommandAuthorizedFromAuthorizers({
|
|
7493
|
-
useAccessGroups,
|
|
7494
|
-
authorizers: useAccessGroups ? [{
|
|
7495
|
-
configured: admissionAllowList != null,
|
|
7496
|
-
allowed: admissionAllowed
|
|
7497
|
-
}, {
|
|
7498
|
-
configured: hasAccessRestrictions,
|
|
7499
|
-
allowed: memberAllowed
|
|
7500
|
-
}] : [{
|
|
7501
|
-
configured: hasAccessRestrictions,
|
|
7502
|
-
allowed: memberAllowed
|
|
7503
|
-
}],
|
|
7504
|
-
modeWhenAccessGroupsOff: "configured"
|
|
7505
|
-
}) ? {
|
|
7506
|
-
ok: true,
|
|
7507
|
-
channelConfig
|
|
7508
|
-
} : {
|
|
7509
|
-
ok: false,
|
|
7510
|
-
message: "You are not authorized to use this command."
|
|
7511
|
-
};
|
|
7512
|
-
}
|
|
7513
|
-
//#endregion
|
|
7514
|
-
//#region extensions/discord/src/voice/owner-access.ts
|
|
7515
|
-
function resolveDiscordVoiceAccess(params) {
|
|
7516
|
-
const commandOwnerAllowFrom = resolveDiscordCommandOwnerAllowFrom(params.cfg);
|
|
7517
|
-
if (commandOwnerAllowFrom) return {
|
|
7518
|
-
admissionAllowFrom: commandOwnerAllowFrom,
|
|
7519
|
-
ownerAllowFrom: commandOwnerAllowFrom
|
|
7520
|
-
};
|
|
7521
|
-
return {
|
|
7522
|
-
admissionAllowFrom: resolveDiscordAccountAllowFrom({
|
|
7523
|
-
cfg: params.cfg,
|
|
7524
|
-
accountId: params.accountId
|
|
7525
|
-
}) ?? params.discordConfig.allowFrom ?? [],
|
|
7526
|
-
ownerAllowFrom: []
|
|
7527
|
-
};
|
|
7528
|
-
}
|
|
7529
|
-
//#endregion
|
|
7530
6907
|
//#region extensions/discord/src/voice/command.ts
|
|
7531
6908
|
const VOICE_CHANNEL_TYPES = [ChannelType.GuildVoice, ChannelType.GuildStageVoice];
|
|
7532
6909
|
const DISCORD_VOICE_COMMAND_SPEC = {
|
|
@@ -7890,8 +7267,8 @@ function formatDiscordDeployRestOperation(err) {
|
|
|
7890
7267
|
function formatDiscordDeployErrorMessage(err) {
|
|
7891
7268
|
if (!isAbortLikeError(err)) return formatErrorMessage$1(err);
|
|
7892
7269
|
const deployErr = err && typeof err === "object" ? err : {};
|
|
7893
|
-
const requestMs = parseFiniteNumber(deployErr.deployRequestMs);
|
|
7894
|
-
const timeoutMs = parseFiniteNumber(deployErr.deployTimeoutMs);
|
|
7270
|
+
const requestMs = parseFiniteNumber$1(deployErr.deployRequestMs);
|
|
7271
|
+
const timeoutMs = parseFiniteNumber$1(deployErr.deployTimeoutMs);
|
|
7895
7272
|
const operation = formatDiscordDeployRestOperation(deployErr);
|
|
7896
7273
|
if (!(requestMs !== void 0 || timeoutMs !== void 0 || deployErr.deployRestMethod !== void 0 || deployErr.deployRestPath !== void 0)) return "Discord REST request was aborted";
|
|
7897
7274
|
const timing = [];
|
|
@@ -7904,8 +7281,8 @@ function formatDiscordDeployErrorMessage(err) {
|
|
|
7904
7281
|
function resolveDiscordDeployRateLimitDetails(err) {
|
|
7905
7282
|
if (!err || typeof err !== "object") return;
|
|
7906
7283
|
const deployErr = err;
|
|
7907
|
-
const status = parseStrictNonNegativeInteger(deployErr.status) ?? parseStrictNonNegativeInteger(deployErr.statusCode);
|
|
7908
|
-
const retryAfterSeconds = parseFiniteNumber(deployErr.retryAfter) ?? parseFiniteNumber(readDiscordDeployObjectField(deployErr.rawBody, "retry_after"));
|
|
7284
|
+
const status = parseStrictNonNegativeInteger$1(deployErr.status) ?? parseStrictNonNegativeInteger$1(deployErr.statusCode);
|
|
7285
|
+
const retryAfterSeconds = parseFiniteNumber$1(deployErr.retryAfter) ?? parseFiniteNumber$1(readDiscordDeployObjectField(deployErr.rawBody, "retry_after"));
|
|
7909
7286
|
if (!(err instanceof RateLimitError || status === 429 || retryAfterSeconds !== void 0)) return;
|
|
7910
7287
|
const rawGlobal = readDiscordDeployObjectField(deployErr.rawBody, "global");
|
|
7911
7288
|
const scope = typeof deployErr.scope === "string" && deployErr.scope.trim().length > 0 ? deployErr.scope : rawGlobal === true ? "global" : rawGlobal === false ? "route" : void 0;
|
|
@@ -7995,8 +7372,8 @@ function formatDiscordDeployErrorDetails(err) {
|
|
|
7995
7372
|
function isDiscordDeployDailyCreateLimit(err) {
|
|
7996
7373
|
if (!err || typeof err !== "object") return false;
|
|
7997
7374
|
const deployErr = err;
|
|
7998
|
-
const discordCode = parseStrictNonNegativeInteger(deployErr.discordCode);
|
|
7999
|
-
const rawCode = parseStrictNonNegativeInteger(readDiscordDeployObjectField(deployErr.rawBody, "code"));
|
|
7375
|
+
const discordCode = parseStrictNonNegativeInteger$1(deployErr.discordCode);
|
|
7376
|
+
const rawCode = parseStrictNonNegativeInteger$1(readDiscordDeployObjectField(deployErr.rawBody, "code"));
|
|
8000
7377
|
return (discordCode === 30034 || rawCode === 30034) && /daily application command creates/i.test(formatErrorMessage$1(err));
|
|
8001
7378
|
}
|
|
8002
7379
|
//#endregion
|
|
@@ -8757,7 +8134,8 @@ function resolveReplyContext(message, resolveDiscordMessageText) {
|
|
|
8757
8134
|
const referenced = message.referencedMessage;
|
|
8758
8135
|
if (!referenced?.author) return null;
|
|
8759
8136
|
const referencedText = resolveDiscordMessageText(referenced, { includeForwarded: true });
|
|
8760
|
-
|
|
8137
|
+
const hasVisibleMedia = referenced.attachments.length > 0 || !referencedText && resolveDiscordMessageStickers(referenced).length > 0;
|
|
8138
|
+
if (!referencedText && !hasVisibleMedia) return null;
|
|
8761
8139
|
const sender = resolveDiscordSenderIdentity({
|
|
8762
8140
|
author: referenced.author,
|
|
8763
8141
|
pluralkitInfo: null
|
|
@@ -8773,7 +8151,7 @@ function resolveReplyContext(message, resolveDiscordMessageText) {
|
|
|
8773
8151
|
const roles = referenced.member?.roles;
|
|
8774
8152
|
return Array.isArray(roles) ? roles.map((roleId) => roleId) : void 0;
|
|
8775
8153
|
})(),
|
|
8776
|
-
body: referencedText,
|
|
8154
|
+
...referencedText ? { body: referencedText } : {},
|
|
8777
8155
|
timestamp: resolveTimestampMs(referenced.timestamp)
|
|
8778
8156
|
};
|
|
8779
8157
|
}
|
|
@@ -8971,7 +8349,7 @@ async function deliverDiscordReply(params) {
|
|
|
8971
8349
|
//#endregion
|
|
8972
8350
|
//#region extensions/discord/src/monitor/agent-components.dispatch.ts
|
|
8973
8351
|
const loadConversationRuntime$1 = createLazyRuntimeModule(() => import("./agent-components.runtime-CEPrf2SY.js"));
|
|
8974
|
-
const loadTypingRuntime = createLazyRuntimeModule(() => import("./typing-
|
|
8352
|
+
const loadTypingRuntime = createLazyRuntimeModule(() => import("./typing-oLiS5Z13.js").then((n) => n.n));
|
|
8975
8353
|
function buildDiscordComponentConversationLabel(params) {
|
|
8976
8354
|
if (params.interactionCtx.isDirectMessage) return buildDirectLabel(params.interactionCtx.user);
|
|
8977
8355
|
if (params.interactionCtx.isGroupDm) return `Group DM #${params.channelCtx.channelName ?? params.interactionCtx.channelId} channel id:${params.interactionCtx.channelId}`;
|
|
@@ -9093,6 +8471,14 @@ async function dispatchDiscordComponentEvent(params) {
|
|
|
9093
8471
|
SessionKey: sessionKey,
|
|
9094
8472
|
AccountId: accountId,
|
|
9095
8473
|
ChatType: chatType,
|
|
8474
|
+
...buildDiscordConversationRouteContext({
|
|
8475
|
+
isDirectMessage: interactionCtx.isDirectMessage,
|
|
8476
|
+
isGroupDm: interactionCtx.isGroupDm,
|
|
8477
|
+
directUserId: interactionCtx.userId,
|
|
8478
|
+
conversationId: interactionCtx.channelId,
|
|
8479
|
+
isThread: channelCtx.isThread,
|
|
8480
|
+
parentConversationId: channelCtx.parentId
|
|
8481
|
+
}),
|
|
9096
8482
|
ConversationLabel: fromLabel,
|
|
9097
8483
|
SenderName: senderName,
|
|
9098
8484
|
SenderId: interactionCtx.userId,
|
|
@@ -9161,6 +8547,7 @@ async function dispatchDiscordComponentEvent(params) {
|
|
|
9161
8547
|
sessionKey
|
|
9162
8548
|
},
|
|
9163
8549
|
ctxPayload,
|
|
8550
|
+
dispatchReplyFromConfig: ctx.channelRuntime?.reply?.dispatchReplyFromConfig,
|
|
9164
8551
|
record: {
|
|
9165
8552
|
updateLastRoute: interactionCtx.isDirectMessage ? {
|
|
9166
8553
|
sessionKey: inboundLastRouteSessionKey,
|
|
@@ -9367,7 +8754,7 @@ async function dispatchPluginDiscordInteractiveEvent(params) {
|
|
|
9367
8754
|
}
|
|
9368
8755
|
//#endregion
|
|
9369
8756
|
//#region extensions/discord/src/monitor/agent-components.handlers.ts
|
|
9370
|
-
const loadComponentsRuntime = createLazyRuntimeModule(() => import("./
|
|
8757
|
+
const loadComponentsRuntime = createLazyRuntimeModule(() => import("./components-ezGKo_Yh.js").then((n) => n.t));
|
|
9371
8758
|
async function handleDiscordComponentEvent(params) {
|
|
9372
8759
|
const parsed = parseDiscordComponentData(params.data, resolveInteractionCustomId(params.interaction));
|
|
9373
8760
|
if (!parsed) {
|
|
@@ -10149,6 +9536,7 @@ function createDiscordProviderInteractionSurface(params) {
|
|
|
10149
9536
|
allowFrom: params.allowFrom,
|
|
10150
9537
|
dmPolicy: params.dmPolicy,
|
|
10151
9538
|
runtime: params.runtime,
|
|
9539
|
+
channelRuntime: params.channelRuntime,
|
|
10152
9540
|
token: params.token
|
|
10153
9541
|
}, params.applicationId);
|
|
10154
9542
|
if (activityButton) components.push(activityButton);
|
|
@@ -10641,6 +10029,7 @@ async function monitorDiscordProvider(opts = {}) {
|
|
|
10641
10029
|
let earlyGatewayEmitter = gatewaySupervisor?.emitter;
|
|
10642
10030
|
let onEarlyGatewayDebug;
|
|
10643
10031
|
try {
|
|
10032
|
+
const pluginChannelRuntime = opts.channelRuntime;
|
|
10644
10033
|
const { commands, components, modals } = createDiscordProviderInteractionSurface({
|
|
10645
10034
|
cfg,
|
|
10646
10035
|
discordConfig: discordCfg,
|
|
@@ -10660,7 +10049,7 @@ async function monitorDiscordProvider(opts = {}) {
|
|
|
10660
10049
|
allowFrom,
|
|
10661
10050
|
dmPolicy,
|
|
10662
10051
|
runtime,
|
|
10663
|
-
channelRuntime:
|
|
10052
|
+
channelRuntime: pluginChannelRuntime,
|
|
10664
10053
|
abortSignal: opts.abortSignal,
|
|
10665
10054
|
createNativeCommand: discordProviderRuntime.createDiscordNativeCommand
|
|
10666
10055
|
});
|
|
@@ -10734,7 +10123,7 @@ async function monitorDiscordProvider(opts = {}) {
|
|
|
10734
10123
|
runtime,
|
|
10735
10124
|
botUserId
|
|
10736
10125
|
});
|
|
10737
|
-
const { setDiscordTranscriptsVoiceManager } = await import("./transcripts-source-
|
|
10126
|
+
const { setDiscordTranscriptsVoiceManager } = await import("./transcripts-source-DeIMNbRh.js").then((n) => n.n);
|
|
10738
10127
|
setDiscordTranscriptsVoiceManager({
|
|
10739
10128
|
accountId: account.accountId,
|
|
10740
10129
|
manager: voiceManager
|
|
@@ -10752,7 +10141,7 @@ async function monitorDiscordProvider(opts = {}) {
|
|
|
10752
10141
|
accountId: account.accountId,
|
|
10753
10142
|
token,
|
|
10754
10143
|
runtime,
|
|
10755
|
-
buildContext:
|
|
10144
|
+
buildContext: pluginChannelRuntime?.inbound.buildContext,
|
|
10756
10145
|
setStatus: opts.setStatus,
|
|
10757
10146
|
abortSignal: opts.abortSignal,
|
|
10758
10147
|
botUserId,
|
|
@@ -10840,4 +10229,4 @@ async function monitorDiscordProvider(opts = {}) {
|
|
|
10840
10229
|
}
|
|
10841
10230
|
}
|
|
10842
10231
|
//#endregion
|
|
10843
|
-
export {
|
|
10232
|
+
export { mapGatewayDispatchData as _, sanitizeDiscordFrontChannelReplyPayloads as a, resolveDiscordDmCommandAccess as b, resolveReplyContext as c, waitForDiscordGatewayPluginRegistration as d, createDiscordNativeCommand as f, handleDiscordDmCommandDecision as g, createDiscordSupplementalContextAccessChecker as h, formatDiscordReplySkip as i, createDiscordGatewayPlugin as l, buildDiscordInboundAccessContext as m, deliverDiscordReply as n, buildDirectLabel as o, buildDiscordGroupSystemPrompt as p, formatDiscordReplyDeliveryFailure as r, buildGuildLabel as s, monitorDiscordProvider as t, resolveDiscordGatewayIntents as u, registerDiscordListener as v, resolveDiscordTextCommandAccess as x, resolveFetchedDiscordThreadLikeChannelContext as y };
|