UNPKG

@gguf/claw

Version:

Multi-channel AI gateway with extensible messaging integrations

839 lines (828 loc) 2.46 MB
import { t as __exportAll } from "./rolldown-runtime-Cbj13DAv.js"; import { $t as triggerInternalHook, A as normalizeChannelId, B as getPluginCommandSpecs, C as CHAT_CHANNEL_ORDER, Dt as theme, G as clampInt, H as matchPluginCommand, I as createPluginRegistry, It as STATE_DIR, L as normalizePluginHttpPath, Mt as normalizeLogLevel, N as requireActivePluginRegistry, Nt as resolvePreferredOpenClawTmpDir, Ot as getChildLogger, P as setActivePluginRegistry, Q as isRecord$1, R as clearPluginCommands, St as shouldLogVerbose, U as CONFIG_DIR, Ut as resolveGatewayPort, V as listPluginCommands, X as escapeRegExp, Yt as resolveStateDir, Zt as createInternalHookEvent, _ as defaultRuntime, a as parseBooleanValue$1, ct as shortenHomeInString, dt as sliceUtf16Safe, g as createNonExitingRuntime, ht as danger, k as normalizeAnyChannelId, lt as shortenHomePath, mt as isPlainObject, n as isTruthyEnvValue, o as createSubsystemLogger, ot as resolveUserPath, pn as resolveRequiredHomeDir, pt as truncateUtf16Safe, tt as normalizeE164, ut as sleep$1, w as DEFAULT_CHAT_CHANNEL, wt as warn, yt as logVerbose, z as executePluginCommand } from "./entry.js"; import { A as buildConfiguredAllowlistKeys, Bt as DEFAULT_CONTEXT_TOKENS, Ct as resolveModelAuthMode, Dt as getShellPathFromLoginShell, E as withFileLock, F as modelKey, H as resolveDefaultModelForAgent, Ht as DEFAULT_PROVIDER, I as normalizeModelRef$2, K as resolveSubagentSpawnModelSelection, L as normalizeProviderId, M as findNormalizedProviderValue, P as isCliProvider, St as resolveEnvApiKey, T as resolveOpenClawAgentDir, Tt as normalizeSecretInput, Ut as resolveAuthProfileDisplayLabel, V as resolveConfiguredModelRef, Vt as DEFAULT_MODEL, W as resolveModelRefFromString, _t as getApiKeyForModel, a as markAuthProfileFailure, b as ensureAuthProfileStore, bt as resolveApiKeyForProvider, c as resolveApiKeyForProfile, g as markAuthProfileGood, gt as createOllamaStreamFn, h as listProfilesForProvider, ht as OLLAMA_NATIVE_BASE_URL, i as isProfileInCooldown, j as buildModelAliasIndex, k as buildAllowedModelSet, kt as resolveShellEnvFallbackTimeoutMs, m as dedupeProfileIds, n as resolveAuthProfileOrder, o as markAuthProfileUsed, q as resolveThinkingDefault, r as getSoonestCooldownExpiry, vt as getCustomProviderApiKey, w as resolveAuthStorePathForDisplay, yt as requireApiKey } from "./auth-profiles-DFa1zzNy.js"; import { t as formatCliCommand } from "./command-format-D3syQOZg.js"; import { S as resolveThreadParentSessionKey, _ as isAcpSessionKey, b as isSubagentSessionKey, c as normalizeAccountId$3, d as resolveAgentIdFromSessionKey, f as resolveThreadSessionKeys, g as getSubagentDepth, i as buildAgentMainSessionKey, l as normalizeAgentId, n as DEFAULT_AGENT_ID, p as sanitizeAgentId, s as classifySessionKeyShape, t as DEFAULT_ACCOUNT_ID$1, u as normalizeMainKey, x as parseAgentSessionKey, y as isCronSessionKey } from "./session-key-BGiG_JcT.js"; import { t as resolveOpenClawPackageRoot } from "./openclaw-root-B5pKN_cp.js"; import { a as logError, i as logDebug, n as runExec, o as logInfo, r as spawnWithFallback, s as logWarn, t as runCommandWithTimeout } from "./exec-CBKBIMpA.js"; import { C as ensureAgentWorkspace, E as loadWorkspaceBootstrapFiles, a as resolveAgentModelFallbacksOverride, c as resolveAgentWorkspaceDir, d as resolveSessionAgentId, f as resolveSessionAgentIds, h as DEFAULT_BOOTSTRAP_FILENAME, i as resolveAgentDir, l as resolveDefaultAgentId, m as DEFAULT_AGENT_WORKSPACE_DIR, n as listAgentIds, o as resolveAgentModelPrimary, r as resolveAgentConfig, s as resolveAgentSkillsFilter, u as resolveEffectiveModelFallbacks, w as filterBootstrapFilesForSession } from "./agent-scope-RzK9Zcks.js"; import { a as saveJsonFile, i as loadJsonFile } from "./github-copilot-token-DuFIqfeC.js"; import { n as recordCommandPoll, r as resetCommandPollCount } from "./command-poll-backoff-anX686I1.js"; import { a as buildModelAliasLines, n as resolveModel } from "./model-DY9t1aT6.js"; import { n as discoverModels, t as discoverAuthStorage } from "./pi-model-discovery-Do3xMEtM.js"; import { r as isPathInsideWithRealpath } from "./scan-paths-B22E7-Cg.js"; import { a as resolveSkillsPromptForRun, d as resolveSandboxInputPath, h as applySkillEnvOverridesFromSnapshot, i as loadWorkspaceSkillEntries, l as assertMediaNotDataUrl, m as applySkillEnvOverrides, p as resolveSandboxedMediaSource, r as buildWorkspaceSkillSnapshot, u as assertSandboxPath } from "./skills-DJmGZazd.js"; import { a as safeStatSync, c as applyTestPluginDefaults, d as resolveEnableState, f as resolveMemorySlotDecision, i as isPathInside, n as loadPluginManifestRegistry, r as discoverOpenClawPlugins, u as normalizePluginsConfig } from "./manifest-registry-DS2iK5AZ.js"; import { A as parseConfigPath, C as parseDurationMs, D as setConfigOverride, E as resetConfigOverrides, M as unsetConfigValueAtPath, O as unsetConfigOverride, T as getConfigOverrides, V as VERSION, _ as isInboundPathAllowed, b as resolveIMessageRemoteAttachmentRoots, c as resolveConfigSnapshotHash, h as resolveTelegramCustomCommands, i as loadConfig, j as setConfigValueAtPath, k as getConfigValueAtPath, l as writeConfigFile, m as normalizeTelegramCommandName, o as readConfigFileSnapshot, p as TELEGRAM_COMMAND_NAME_PATTERN, u as validateConfigObjectWithPlugins, w as validateJsonSchemaValue, x as normalizeScpRemoteHost, y as resolveIMessageAttachmentRoots, z as resolveAgentMaxConcurrent } from "./config-B2kL1ciP.js"; import { Mt as SESSION_LABEL_MAX_LENGTH, t as GatewayClient } from "./client-CDjZdZtI.js"; import { a as randomIdempotencyKey, d as resolveLeastPrivilegeOperatorScopesForMethod, n as callGateway, r as callGatewayLeastPrivilege, t as buildGatewayConnectionDetails } from "./call-DXhJGwEy.js"; import { a as isInternalMessageChannel, c as listDeliverableMessageChannels, d as resolveMessageChannel, h as GATEWAY_CLIENT_NAMES, i as isGatewayMessageChannel, l as normalizeMessageChannel, m as GATEWAY_CLIENT_MODES, n as isDeliverableMessageChannel, o as isMarkdownCapableMessageChannel, p as GATEWAY_CLIENT_IDS, t as INTERNAL_MESSAGE_CHANNEL, u as resolveGatewayMessageChannel } from "./message-channel-CVHJDItx.js"; import { i as normalizeInputProvenance, n as applyInputProvenanceToUserMessage, r as hasInterSessionUserProvenance } from "./input-provenance-D0lNkCf6.js"; import { A as resolveFreshSessionTotalTokens, B as acquireSessionWriteLock, C as resolveSessionKey, D as resolveSessionResetType, E as resolveSessionResetPolicy, G as mergeDeliveryContext, H as resolveSessionLockMaxHoldFromTimeout, I as deriveSessionMetaPatch, J as normalizeAccountId$4, K as normalizeDeliveryContext, N as resolveExplicitAgentSessionKey, O as resolveThreadFlag, P as resolveMainSessionKey, T as resolveChannelResetConfig, U as deliveryContextFromSession, W as deliveryContextKey, a as loadSessionStore, d as updateSessionStoreEntry, f as isCacheEnabled, g as capArrayByJsonBytes, h as archiveSessionTranscripts, k as DEFAULT_RESET_TRIGGERS, l as updateLastRoute, o as readSessionUpdatedAt, p as resolveCacheTtlMs$1, q as normalizeSessionDeliveryFields, r as appendAssistantMessageToSessionTranscript, s as recordSessionMetaFromInbound, t as extractDeliveryInfo, u as updateSessionStore, w as evaluateSessionFreshness, z as resolveGroupSessionKey } from "./sessions-BD5dyLxb.js"; import { n as SILENT_REPLY_TOKEN, r as isSilentReplyText, t as HEARTBEAT_TOKEN } from "./tokens-D5RzuaYP.js"; import { a as listTelegramAccountIds, c as resolveSlackAccount, d as resolveSlackBotToken, f as createDiscordActionGate, h as normalizeDiscordToken, i as listEnabledTelegramAccounts, m as resolveDiscordAccount, n as normalizeWhatsAppTarget, o as resolveTelegramAccount, p as listEnabledDiscordAccounts, r as createTelegramActionGate, s as resolveTelegramToken, t as isWhatsAppGroupJid, u as resolveSlackAppToken } from "./normalize-Db7Xtx2v.js"; import { a as logWebSelfId, i as getWebAuthAgeMs, m as webAuthExists, n as resolveWhatsAppAccount, o as logoutWeb, u as readWebSelfId } from "./accounts-BpzwDfBB.js"; import { t as normalizeChatType } from "./chat-type-CeFzWU-6.js"; import { a as resolveSlackWebClientOptions, c as buildSlackBlocksFallbackText, i as createSlackWebClient, l as parseSlackTarget, o as parseSlackBlocksInput, s as validateSlackBlocksArray, t as sendMessageSlack, u as resolveSlackChannelId } from "./send-BFiRlO6V.js"; import { n as listChannelPlugins, r as normalizeChannelId$1, t as getChannelPlugin } from "./plugins-RqhjLCb6.js"; import { $ as hasAnyGuildPermissionDiscord, A as addRoleDiscord, B as removeRoleDiscord, C as fetchMessageDiscord, Ct as applyChannelMatchMeta, D as readMessagesDiscord, E as pinMessageDiscord, Et as resolveChannelEntryMatchWithFallback, F as fetchRoleInfoDiscord, G as createChannelDiscord, H as listGuildEmojisDiscord, I as fetchVoiceStatusDiscord, J as moveChannelDiscord, K as deleteChannelDiscord, L as kickMemberDiscord, M as createScheduledEventDiscord, N as fetchChannelInfoDiscord, O as searchMessagesDiscord, P as fetchMemberInfoDiscord, Q as fetchChannelPermissionsDiscord, R as listGuildChannelsDiscord, S as editMessageDiscord, St as fetchDiscord, T as listThreadsDiscord, Tt as normalizeChannelSlug, U as uploadEmojiDiscord, V as timeoutMemberDiscord, W as uploadStickerDiscord, X as setChannelPermissionDiscord, Y as removeChannelPermissionDiscord, Z as stripUndefinedFields, _ as sendPollDiscord, _t as shouldEmitDiscordReactionNotification, a as removeReactionDiscord, at as listDiscordDirectoryPeersLive, b as createThreadDiscord, bt as resolveDiscordSystemLocation, c as formatDiscordComponentEventText, ct as normalizeDiscordAllowList, d as parseDiscordModalCustomId, dt as resolveDiscordChannelConfigWithFallback, et as createDiscordClient, f as parseDiscordModalCustomIdForCarbon, ft as resolveDiscordGuildEntry, g as sendMessageDiscord, gt as resolveGroupDmAllow, h as resolveDiscordModalEntry, ht as resolveDiscordShouldRequireMention, i as removeOwnReactionsDiscord, it as listDiscordDirectoryGroupsLive, j as banMemberDiscord, k as unpinMessageDiscord, l as parseDiscordComponentCustomId, lt as normalizeDiscordSlug, m as resolveDiscordComponentEntry, mt as resolveDiscordOwnerAllowFrom, n as fetchReactionsDiscord, nt as parseDiscordTarget, o as sendDiscordComponentMessage, ot as allowListMatches$1, p as readDiscordComponentSpec, pt as resolveDiscordMemberAccessState, q as editChannelDiscord, r as reactMessageDiscord, rt as resolveDiscordChannelId, s as createDiscordFormModal, st as isDiscordGroupAllowedByPolicy, tt as chunkDiscordTextWithMode, u as parseDiscordComponentCustomIdForCarbon, ut as resolveDiscordAllowListMatch, v as sendStickerDiscord, vt as formatDiscordReactionEmoji, w as listPinsDiscord, wt as buildChannelKeyCandidates, x as deleteMessageDiscord, xt as resolveTimestampMs, y as sendVoiceMessageDiscord, yt as formatDiscordUserTag, z as listScheduledEventsDiscord } from "./send-CWDtU8Gi.js"; import { n as createBrowserRouteDispatcher, r as getMachineDisplayName, t as withTimeout$4 } from "./with-timeout-nVWy7PWz.js"; import { C as getGlobalHookRunner, S as parseInlineDirectives$1, _ as normalizeTargetForProvider, a as normalizeOutboundPayloadsForJson, b as MEDIA_TOKEN_RE, c as applyReplyThreading, d as isRenderablePayload, f as shouldSuppressMessagingToolReplies, g as normalizeChannelTargetInput, h as buildTargetResolverSignature, i as normalizeOutboundPayloads, l as filterMessagingToolDuplicates, m as resolveReplyToMode, o as normalizeReplyPayloadsForDelivery, p as createReplyToModeFilterForChannel, r as formatOutboundPayloadLog, s as applyReplyTagsToPayload, t as deliverOutboundPayloads, u as filterMessagingToolMediaDuplicates, v as throwIfAborted, w as initializeGlobalHookRunner, x as splitMediaFromOutput, y as parseReplyDirectives } from "./deliver-CeVE1Jh-.js"; import { a as logMessageProcessed, c as logWebhookError, d as startDiagnosticHeartbeat, f as stopDiagnosticHeartbeat, i as logLaneEnqueue, l as logWebhookProcessed, m as isDiagnosticsEnabled, o as logMessageQueued, p as emitDiagnosticEvent, r as logLaneDequeue, s as logSessionStateChange, t as diag, u as logWebhookReceived } from "./diagnostic-774btyou.js"; import { r as getDiagnosticSessionState } from "./diagnostic-session-state-HO94DMou.js"; import { n as resolveSignalAccount, t as listEnabledSignalAccounts } from "./accounts-B3D4iWUP.js"; import { A as extractTelegramLocation, B as normalizeAllowFromWithStore$1, C as buildTelegramGroupFrom, D as buildTypingThreadParams, E as buildTelegramThreadParams, F as resolveTelegramMediaPlaceholder, G as formatLocationText, H as firstDefined$1, I as resolveTelegramReplyId, J as parseTelegramTarget, K as toLocationContext, L as resolveTelegramStreamMode, M as normalizeForwardedContext, N as resolveTelegramForumThreadId, O as describeReplyTarget, P as resolveTelegramGroupAllowFromContext, R as resolveTelegramThreadSpec, S as buildSenderName, T as buildTelegramParentPeer, U as isSenderIdAllowed, V as resolveSenderAllowMatch, W as mergeAllowFromSources, Y as resolveTelegramTargetChatType, _ as resolveTelegramFetch, a as reactMessageTelegram, b as buildGroupLabel, c as sendStickerTelegram, d as wasSentByBot, f as isRecoverableTelegramNetworkError, g as wrapFileReferencesInHtml, h as renderTelegramHtmlText, i as editMessageTelegram, j as hasBotMention, k as expandTextLinks, m as markdownToTelegramHtml, n as createForumTopicTelegram, o as sendMessageTelegram, p as markdownToTelegramChunks, q as isVoiceCompatibleAudio, r as deleteMessageTelegram, s as sendPollTelegram, t as buildInlineKeyboard, u as resolveTelegramVoiceSend, v as splitTelegramCaption, w as buildTelegramGroupPeerId, x as buildSenderLabel, y as withTelegramApiErrorLogging, z as isSenderAllowed$1 } from "./send-DCCBUsNn.js"; import { c as detectMime, d as imageMimeFromFormat, f as isAudioFileName, g as MAX_IMAGE_BYTES, i as getImageMetadata, l as extensionForMime, p as isGifMedia, s as resizeToJpeg, v as mediaKindFromMime } from "./image-ops-lDlFpoR2.js"; import { A as isTransientHttpError, C as isContextOverflowError, D as isRateLimitAssistantError, E as isLikelyContextOverflowError, F as ensureSessionHeader, I as resolveBootstrapMaxChars, L as resolveBootstrapTotalMaxChars, M as parseImageSizeError, N as sanitizeUserFacingText, O as isRawApiErrorPayload, P as buildBootstrapContextFiles, R as sanitizeGoogleTurnOrdering, S as isCompactionFailureError, T as isFailoverErrorMessage, _ as formatRawAssistantErrorForUi, a as isMessagingToolDuplicateNormalized, b as isBillingAssistantError, c as extractToolCallsFromAssistant, d as isAntigravityClaude, f as isGoogleModelApi, g as formatBillingErrorMessage, h as formatAssistantErrorText, j as parseImageDimensionError, k as isTimeoutErrorMessage, l as extractToolResultId, m as classifyFailoverReason, n as validateGeminiTurns, o as normalizeTextForComparison, p as BILLING_ERROR_USER_MESSAGE, r as pickFallbackThinkingLevel, s as sanitizeSessionMessagesImages, t as validateAnthropicTurns, u as downgradeOpenAIReasoningBlocks, v as getApiErrorPayloadFingerprint, w as isFailoverAssistantError, x as isCloudCodeAssistFormatError, y as isAuthAssistantError } from "./pi-embedded-helpers-NVEtaJwl.js"; import { C as compileGlobPatterns, S as stripPluginOnlyAllowlist, _ as expandPolicyWithPluginGroups, a as ensureSandboxWorkspaceForSession, b as normalizeToolName, c as resolveSandboxRuntimeStatus, d as resolveSandboxConfigForAgent, g as collectExplicitAllowlist, h as buildPluginToolGroups, m as applyOwnerOnlyToolPolicy, o as resolveSandboxContext, u as getBridgeAuthForPort, w as matchesAnyGlobPattern, x as resolveToolProfilePolicy, y as mergeAlsoAllowPolicy } from "./sandbox-CO-R8v6J.js"; import { a as jsonResult, c as readReactionParams, d as readStringParam, g as resolveImageSanitizationLimits, h as sanitizeToolResultImages, i as imageResultFromFile, l as readStringArrayParam, m as sanitizeImageBlocks, n as createActionGate, o as parseAvailableTags, r as imageResult, s as readNumberParam, u as readStringOrNumberParam } from "./common-DcSh1hZE.js"; import { T as DEFAULT_AI_SNAPSHOT_MAX_CHARS } from "./chrome-52ZF7gmE.js"; import { i as resolveBrowserConfig, m as resolveBrowserControlAuth } from "./server-context-C1f7cijA.js"; import { n as formatErrorMessage, r as formatUncaughtError } from "./errors-CFEPAPWc.js"; import { i as resolveExistingPathsWithinRoot, r as DEFAULT_UPLOAD_DIR } from "./paths-CXKNzNjU.js"; import { i as isBlockedHostnameOrIp, o as normalizeHostname, t as SsrFBlockedError } from "./ssrf-Cv2DiHsm.js"; import { n as getMediaDir, r as saveMediaBuffer } from "./store-e6fIrP17.js"; import { a as resolveChannelGroupRequireMention, c as normalizeHyphenSlug, i as resolveChannelGroupPolicy, l as normalizeStringEntries, n as listChannelDocks, r as normalizeSignalMessagingTarget, s as normalizeAtHashSlug, t as getChannelDock, u as normalizeStringEntriesLower } from "./dock-BZuwgj1O.js"; import { n as resolveConversationLabel } from "./conversation-label-B7Ya7NPL.js"; import { t as resolveIMessageAccount } from "./accounts-Jg3_1Y-r.js"; import { c as resolveStorePath, i as resolveSessionTranscriptPath, n as resolveSessionFilePath, r as resolveSessionFilePathOptions, t as resolveDefaultSessionStorePath } from "./paths-CXpciDEv.js"; import { t as emitSessionTranscriptUpdate } from "./transcript-events-CMT5U7Om.js"; import { a as normalizeElevatedLevel, c as normalizeUsageDisplay, d as supportsXHighThinking, l as normalizeVerboseLevel, n as formatXHighModelHint, o as normalizeReasoningLevel, s as normalizeThinkLevel, t as formatThinkingLevels, u as resolveResponseUsageMode } from "./thinking-CJPPUYWd.js"; import { t as ensureOpenClawModelsJson } from "./models-config-5zJ39mUb.js"; import { i as resolveAckReaction, o as resolveEffectiveMessagesConfig, r as resolveResponsePrefixTemplate, s as resolveHumanDelayConfig, t as createReplyPrefixOptions } from "./reply-prefix-DJOqzjBt.js"; import { i as resolveMemoryBackendConfig, n as registerMemoryCli, r as getMemorySearchManager } from "./memory-cli-C3uas9sI.js"; import { n as resolveMemorySearchConfig } from "./manager-D3ZmOwqt.js"; import { g as runTasksWithConcurrency } from "./sqlite-1-TCahE6.js"; import { n as retryAsync } from "./retry-BcjnIuo-.js"; import { a as chunkText, c as resolveChunkMode, d as isSafeFenceBreak, f as parseFenceSpans, i as chunkMarkdownTextWithMode, l as resolveTextChunkLimit, o as chunkTextWithMode, r as chunkMarkdownText, t as chunkByNewline, u as findFenceSpanAt } from "./chunk-Z2NYDchs.js"; import { n as resolveMarkdownTableMode } from "./markdown-tables-GCHx-nGT.js"; import { n as fetchWithTimeout, t as bindAbortRelay } from "./fetch-timeout-L2NTusph.js"; import { t as fetchWithSsrFGuard } from "./fetch-guard-B5BAqVyD.js"; import { a as readResponseWithLimit, i as fetchRemoteMedia, n as getDefaultMediaLocalRoots, t as getAgentScopedMediaLocalRoots } from "./local-roots-SkDT1Wv8.js"; import { a as loadWebMedia, i as getDefaultLocalRoots } from "./ir-DAwVi0a7.js"; import { a as listChatCommandsForConfig, c as normalizeCommandBody, d as resolveCommandArgMenu, f as serializeCommandArgs, i as listChatCommands, l as parseCommandArgs, o as listNativeCommandSpecs, p as shouldHandleTextCommands, r as findCommandByNativeName, s as listNativeCommandSpecsForConfig, t as buildCommandTextFromArgs, u as resolveCommandArgChoices } from "./commands-registry-CRmMPJQ9.js"; import { _ as stripMinimaxToolCallXml, a as decodeDataUrl, b as extractTextFromChatContent, c as extractAssistantText$1, d as extractThinkingFromTaggedText, f as formatReasoningMessage, g as stripDowngradedToolCallText, h as promoteThinkingTagsToBlocks, i as coerceImageModelConfig, l as extractAssistantThinking, m as isAssistantMessage, o as resolveProviderVisionModelFromConfig, p as inferToolMetaFromArgs, r as coerceImageAssistantText, s as minimaxUnderstandImage, u as extractThinkingFromTaggedStream, v as stripThinkingTagsFromText, y as stripReasoningTagsFromText } from "./image-QGUQCdGh.js"; import { n as resolveToolDisplay } from "./tool-display-Cs1uRaRV.js"; import { n as formatTimeAgo } from "./format-relative-TyajjYxu.js"; import { r as normalizeInboundTextNewlines, t as finalizeInboundContext } from "./inbound-context-DzPbh5jG.js"; import { _ as applyTemplate, a as resolveMediaAttachmentLocalRoots, c as resolveAttachmentKind, d as registerUnhandledRejectionHandler, f as resolveConcurrency, g as CLI_OUTPUT_MAX_BUFFER, h as resolveMediaUnderstandingScope, i as resolveAutoImageModel, l as buildRandomTempFilePath, m as normalizeMediaUnderstandingChatType, n as createMediaAttachmentCache, o as runCapability, p as resolveTimeoutMs, r as normalizeMediaAttachments, t as buildProviderRegistry } from "./runner-D81xREgc.js"; import { n as loadModelCatalog, r as modelSupportsVision, t as findModelInCatalog } from "./model-catalog-DLoDxnxL.js"; import { a as loadCombinedSessionStoreForGateway, u as lookupContextTokens } from "./session-utils-C3Oi9cXA.js"; import { b as ensureSkillsWatcher, i as resolveSkillCommandInvocation, n as listSkillCommandsForAgents, o as getRemoteSkillEligibility, r as listSkillCommandsForWorkspace, t as listReservedChatSlashCommandNames, x as getSkillsSnapshotVersion } from "./skill-commands-D2rmj6w8.js"; import { i as readChannelAllowFromStore, l as listPairingChannels, o as removeChannelAllowFromStoreEntry, s as upsertChannelPairingRequest, t as addChannelAllowFromStoreEntry } from "./pairing-store-CruPwgBw.js"; import { n as wrapFetchWithAbortSignal, t as resolveFetch } from "./fetch-vg2oFVIH.js"; import { _ as getTrustedSafeBinDirs, b as buildSafeShellCommand, d as resolveExecApprovals, f as resolveExecApprovalsFromFile, g as resolveSafeBins, h as evaluateShellAllowlist, i as maxAsk, l as recordAllowlistUse, n as addAllowlistEntry, o as minSecurity, u as requiresExecApproval, y as buildSafeBinsShellCommand } from "./exec-approvals-BZA6z4HM.js"; import { a as canvasSnapshotTempPath, c as parseCameraClipPayload, d as writeCameraClipPayloadToFile, f as writeUrlToFile, g as normalizePathPrepend, h as mergePathPrepend, i as parseEnvPairs, l as parseCameraSnapPayload, m as applyPathPrepend, n as screenRecordTempPath, o as parseCanvasSnapshotPayload, p as buildNodeShellCommand, r as writeScreenRecordToFile, s as cameraTempPath, t as parseScreenRecordPayload, u as writeBase64ToFile } from "./nodes-screen-x7YKy8Ay.js"; import { n as parseNodeList, r as parsePairingList, t as resolveNodeIdFromCandidates } from "./node-match-CsjUSOO_.js"; import { i as formatDurationSeconds, r as formatDurationPrecise, t as formatDurationCompact$1 } from "./format-duration-BUgR8KSB.js"; import { c as hasNonzeroUsage, l as normalizeUsage, n as loadCostUsageSummary, o as derivePromptTokens, r as loadSessionCostSummary, s as deriveSessionTotalTokens } from "./session-cost-usage-CpxG9Mup.js"; import { i as resolveModelCostConfig, n as formatTokenCount$2, r as formatUsd, t as estimateUsageCost } from "./usage-format-8m-0w7RC.js"; import { a as resolveSubagentToolPolicy, c as isRestartEnabled, i as resolveGroupToolPolicy, l as resolveNativeCommandsEnabled, n as isToolAllowedByPolicies, r as resolveEffectiveToolPolicy, s as isNativeCommandsExplicitlyDisabled, t as filterToolsByPolicy, u as resolveNativeSkillsEnabled } from "./pi-tools.policy-DeRwGLEO.js"; import { c as resolveGatewayLaunchAgentLabel, d as resolveGatewaySystemdServiceName } from "./constants-ClfJ_wF3.js"; import { n as createBrowserControlContext, r as startBrowserControlServiceFromConfig } from "./control-service-DGleRjGJ.js"; import { i as parseAbsoluteTimeMs, r as resolveDefaultCronStaggerMs, t as normalizeCronStaggerMs } from "./stagger-CArN2YVJ.js"; import { n as resolveMessageChannelSelection, t as listConfiguredMessageChannels } from "./channel-selection-DoXlsBhe.js"; import { n as normalizePollInput } from "./polls-BmLZB1uH.js"; import { a as resolveSignalRpcContext, c as streamSignalEvents, n as sendReadReceiptSignal, o as signalCheck, r as sendTypingSignal, s as signalRpcRequest, t as sendMessageSignal } from "./send-C3RIrBTr.js"; import { a as formatIMessageChatTarget, c as parseIMessageTarget, i as DEFAULT_IMESSAGE_PROBE_TIMEOUT_MS, o as isAllowedIMessageSender, r as createIMessageRpcClient, s as normalizeIMessageHandle, t as sendMessageIMessage } from "./send-0Nz3O9Jc.js"; import { n as resolveAgentRoute, t as buildAgentSessionKey } from "./resolve-route-BONxzeyg.js"; import { t as parseTimeoutMs } from "./parse-timeout-ntOahNdf.js"; import { n as recordChannelActivity, r as createDiscordRetryRunner, t as getChannelActivity } from "./channel-activity-BYGpAtHP.js"; import { t as convertMarkdownTables } from "./tables-BrqD0SUa.js"; import { t as makeProxyFetch } from "./proxy-DL3MD6-P.js"; import { a as createReplyReferencePlanner, i as resolveSlackThreadTs, n as deliverReplies$3, t as createSlackReplyDeliveryPlan } from "./replies-CuUAAFF2.js"; import { r as detectBinary } from "./onboard-helpers-CEx2tGVB.js"; import { t as resolvePairingIdLabel } from "./pairing-labels-DtxjElSq.js"; import { t as getActiveWebListener } from "./active-listener-DJAL1z1W.js"; import { createRequire } from "node:module"; import { execFileSync, spawn, spawnSync } from "node:child_process"; import os, { homedir } from "node:os"; import path from "node:path"; import fs, { existsSync, mkdirSync, mkdtempSync, readFileSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync } from "node:fs"; import JSON5 from "json5"; import { inspect } from "node:util"; import fs$1 from "node:fs/promises"; import { fileURLToPath } from "node:url"; import { complete, completeSimple, streamSimple } from "@mariozechner/pi-ai"; import crypto, { randomBytes, randomUUID } from "node:crypto"; import { CURRENT_SESSION_VERSION, DefaultResourceLoader, SessionManager, SettingsManager, codingTools, createAgentSession, createEditTool, createReadTool, createWriteTool, estimateTokens, generateSummary, readTool } from "@mariozechner/pi-coding-agent"; import WebSocket from "ws"; import { Buffer as Buffer$1 } from "node:buffer"; import { Type } from "@sinclair/typebox"; import { EdgeTTS } from "node-edge-tts"; import { createServer } from "node:http"; import { ProxyAgent, fetch as fetch$1 } from "undici"; import { createJiti } from "jiti"; import { Button, ChannelSelectMenu, ChannelType, Client, Command, CommandWithSubcommands, Container, MentionableSelectMenu, MessageCreateListener, MessageReactionAddListener, MessageReactionRemoveListener, MessageType, Modal, PresenceUpdateListener, ReadyListener, RoleSelectMenu, Row, Separator, StringSelectMenu, TextDisplay, UserSelectMenu, serializePayload } from "@buape/carbon"; import { ApplicationCommandOptionType, ButtonStyle, ChannelType as ChannelType$1, PermissionFlagsBits, Routes, StickerFormatType } from "discord-api-types/v10"; import { API_CONSTANTS, Bot, GrammyError, InputFile, webhookCallback } from "grammy"; import { GatewayCloseCodes, GatewayIntents, GatewayPlugin } from "@buape/carbon/gateway"; import { VoicePlugin } from "@buape/carbon/voice"; import { AudioPlayerStatus, EndBehaviorType, VoiceConnectionStatus, createAudioPlayer, createAudioResource, entersState, joinVoiceChannel } from "@discordjs/voice"; import { HttpsProxyAgent } from "https-proxy-agent"; import { setTimeout as setTimeout$1 } from "node:timers/promises"; import { messagingApi } from "@line/bot-sdk"; import SlackBolt from "@slack/bolt"; import { run, sequentialize } from "@grammyjs/runner"; import { apiThrottler } from "@grammyjs/transformer-throttler"; import { EventEmitter } from "node:events"; //#region src/infra/agent-events.ts const seqByRun = /* @__PURE__ */ new Map(); const listeners = /* @__PURE__ */ new Set(); const runContextById = /* @__PURE__ */ new Map(); function registerAgentRunContext(runId, context) { if (!runId) return; const existing = runContextById.get(runId); if (!existing) { runContextById.set(runId, { ...context }); return; } if (context.sessionKey && existing.sessionKey !== context.sessionKey) existing.sessionKey = context.sessionKey; if (context.verboseLevel && existing.verboseLevel !== context.verboseLevel) existing.verboseLevel = context.verboseLevel; if (context.isHeartbeat !== void 0 && existing.isHeartbeat !== context.isHeartbeat) existing.isHeartbeat = context.isHeartbeat; } function getAgentRunContext(runId) { return runContextById.get(runId); } function clearAgentRunContext(runId) { runContextById.delete(runId); } function emitAgentEvent(event) { const nextSeq = (seqByRun.get(event.runId) ?? 0) + 1; seqByRun.set(event.runId, nextSeq); const context = runContextById.get(event.runId); const sessionKey = typeof event.sessionKey === "string" && event.sessionKey.trim() ? event.sessionKey : context?.sessionKey; const enriched = { ...event, sessionKey, seq: nextSeq, ts: Date.now() }; for (const listener of listeners) try { listener(enriched); } catch {} } function onAgentEvent(listener) { listeners.add(listener); return () => listeners.delete(listener); } //#endregion //#region src/utils/queue-helpers.ts function clearQueueSummaryState(state) { state.droppedCount = 0; state.summaryLines = []; } function previewQueueSummaryPrompt(params) { return buildQueueSummaryPrompt({ state: { dropPolicy: params.state.dropPolicy, droppedCount: params.state.droppedCount, summaryLines: [...params.state.summaryLines] }, noun: params.noun, title: params.title }); } function applyQueueRuntimeSettings(params) { params.target.mode = params.settings.mode; params.target.debounceMs = typeof params.settings.debounceMs === "number" ? Math.max(0, params.settings.debounceMs) : params.target.debounceMs; params.target.cap = typeof params.settings.cap === "number" && params.settings.cap > 0 ? Math.floor(params.settings.cap) : params.target.cap; params.target.dropPolicy = params.settings.dropPolicy ?? params.target.dropPolicy; } function elideQueueText(text, limit = 140) { if (text.length <= limit) return text; return `${text.slice(0, Math.max(0, limit - 1)).trimEnd()}…`; } function buildQueueSummaryLine(text, limit = 160) { return elideQueueText(text.replace(/\s+/g, " ").trim(), limit); } function shouldSkipQueueItem(params) { if (!params.dedupe) return false; return params.dedupe(params.item, params.items); } function applyQueueDropPolicy(params) { const cap = params.queue.cap; if (cap <= 0 || params.queue.items.length < cap) return true; if (params.queue.dropPolicy === "new") return false; const dropCount = params.queue.items.length - cap + 1; const dropped = params.queue.items.splice(0, dropCount); if (params.queue.dropPolicy === "summarize") { for (const item of dropped) { params.queue.droppedCount += 1; params.queue.summaryLines.push(buildQueueSummaryLine(params.summarize(item))); } const limit = Math.max(0, params.summaryLimit ?? cap); while (params.queue.summaryLines.length > limit) params.queue.summaryLines.shift(); } return true; } function waitForQueueDebounce(queue) { const debounceMs = Math.max(0, queue.debounceMs); if (debounceMs <= 0) return Promise.resolve(); return new Promise((resolve) => { const check = () => { const since = Date.now() - queue.lastEnqueuedAt; if (since >= debounceMs) { resolve(); return; } setTimeout(check, debounceMs - since); }; check(); }); } async function drainNextQueueItem(items, run) { const next = items[0]; if (!next) return false; await run(next); items.shift(); return true; } async function drainCollectItemIfNeeded(params) { if (!params.forceIndividualCollect && !params.isCrossChannel) return "skipped"; if (params.isCrossChannel) params.setForceIndividualCollect?.(true); return await drainNextQueueItem(params.items, params.run) ? "drained" : "empty"; } function buildQueueSummaryPrompt(params) { if (params.state.dropPolicy !== "summarize" || params.state.droppedCount <= 0) return; const noun = params.noun; const lines = [params.title ?? `[Queue overflow] Dropped ${params.state.droppedCount} ${noun}${params.state.droppedCount === 1 ? "" : "s"} due to cap.`]; if (params.state.summaryLines.length > 0) { lines.push("Summary:"); for (const line of params.state.summaryLines) lines.push(`- ${line}`); } clearQueueSummaryState(params.state); return lines.join("\n"); } function buildCollectPrompt(params) { const blocks = [params.title]; if (params.summary) blocks.push(params.summary); params.items.forEach((item, idx) => { blocks.push(params.renderItem(item, idx)); }); return blocks.join("\n\n"); } function hasCrossChannelItems(items, resolveKey) { const keys = /* @__PURE__ */ new Set(); let hasUnkeyed = false; for (const item of items) { const resolved = resolveKey(item); if (resolved.cross) return true; if (!resolved.key) { hasUnkeyed = true; continue; } keys.add(resolved.key); } if (keys.size === 0) return false; if (hasUnkeyed) return true; return keys.size > 1; } //#endregion //#region src/agents/subagent-announce-queue.ts const ANNOUNCE_QUEUES = /* @__PURE__ */ new Map(); function getAnnounceQueue(key, settings, send) { const existing = ANNOUNCE_QUEUES.get(key); if (existing) { applyQueueRuntimeSettings({ target: existing, settings }); existing.send = send; return existing; } const created = { items: [], draining: false, lastEnqueuedAt: 0, mode: settings.mode, debounceMs: typeof settings.debounceMs === "number" ? Math.max(0, settings.debounceMs) : 1e3, cap: typeof settings.cap === "number" && settings.cap > 0 ? Math.floor(settings.cap) : 20, dropPolicy: settings.dropPolicy ?? "summarize", droppedCount: 0, summaryLines: [], send }; applyQueueRuntimeSettings({ target: created, settings }); ANNOUNCE_QUEUES.set(key, created); return created; } function scheduleAnnounceDrain(key) { const queue = ANNOUNCE_QUEUES.get(key); if (!queue || queue.draining) return; queue.draining = true; (async () => { try { let forceIndividualCollect = false; while (queue.items.length > 0 || queue.droppedCount > 0) { await waitForQueueDebounce(queue); if (queue.mode === "collect") { const isCrossChannel = hasCrossChannelItems(queue.items, (item) => { if (!item.origin) return {}; if (!item.originKey) return { cross: true }; return { key: item.originKey }; }); const collectDrainResult = await drainCollectItemIfNeeded({ forceIndividualCollect, isCrossChannel, setForceIndividualCollect: (next) => { forceIndividualCollect = next; }, items: queue.items, run: async (item) => await queue.send(item) }); if (collectDrainResult === "empty") break; if (collectDrainResult === "drained") continue; const items = queue.items.slice(); const summary = previewQueueSummaryPrompt({ state: queue, noun: "announce" }); const prompt = buildCollectPrompt({ title: "[Queued announce messages while agent was busy]", items, summary, renderItem: (item, idx) => `---\nQueued #${idx + 1}\n${item.prompt}`.trim() }); const last = items.at(-1); if (!last) break; await queue.send({ ...last, prompt }); queue.items.splice(0, items.length); if (summary) clearQueueSummaryState(queue); continue; } const summaryPrompt = previewQueueSummaryPrompt({ state: queue, noun: "announce" }); if (summaryPrompt) { if (!await drainNextQueueItem(queue.items, async (item) => await queue.send({ ...item, prompt: summaryPrompt }))) break; clearQueueSummaryState(queue); continue; } if (!await drainNextQueueItem(queue.items, async (item) => await queue.send(item))) break; } } catch (err) { queue.lastEnqueuedAt = Date.now(); defaultRuntime.error?.(`announce queue drain failed for ${key}: ${String(err)}`); } finally { queue.draining = false; if (queue.items.length === 0 && queue.droppedCount === 0) ANNOUNCE_QUEUES.delete(key); else scheduleAnnounceDrain(key); } })(); } function enqueueAnnounce(params) { const queue = getAnnounceQueue(params.key, params.settings, params.send); queue.lastEnqueuedAt = Date.now(); if (!applyQueueDropPolicy({ queue, summarize: (item) => item.summaryLine?.trim() || item.prompt.trim() })) { if (queue.dropPolicy === "new") scheduleAnnounceDrain(params.key); return false; } const origin = normalizeDeliveryContext(params.item.origin); const originKey = deliveryContextKey(origin); queue.items.push({ ...params.item, origin, originKey }); scheduleAnnounceDrain(params.key); return true; } //#endregion //#region src/auto-reply/reply/directive-parsing.ts function skipDirectiveArgPrefix(raw) { let i = 0; const len = raw.length; while (i < len && /\s/.test(raw[i])) i += 1; if (raw[i] === ":") { i += 1; while (i < len && /\s/.test(raw[i])) i += 1; } return i; } function takeDirectiveToken(raw, startIndex) { let i = startIndex; const len = raw.length; while (i < len && /\s/.test(raw[i])) i += 1; if (i >= len) return { token: null, nextIndex: i }; const start = i; while (i < len && !/\s/.test(raw[i])) i += 1; if (start === i) return { token: null, nextIndex: i }; const token = raw.slice(start, i); while (i < len && /\s/.test(raw[i])) i += 1; return { token, nextIndex: i }; } //#endregion //#region src/auto-reply/reply/queue/normalize.ts function normalizeQueueMode(raw) { if (!raw) return; const cleaned = raw.trim().toLowerCase(); if (cleaned === "queue" || cleaned === "queued") return "steer"; if (cleaned === "interrupt" || cleaned === "interrupts" || cleaned === "abort") return "interrupt"; if (cleaned === "steer" || cleaned === "steering") return "steer"; if (cleaned === "followup" || cleaned === "follow-ups" || cleaned === "followups") return "followup"; if (cleaned === "collect" || cleaned === "coalesce") return "collect"; if (cleaned === "steer+backlog" || cleaned === "steer-backlog" || cleaned === "steer_backlog") return "steer-backlog"; } function normalizeQueueDropPolicy(raw) { if (!raw) return; const cleaned = raw.trim().toLowerCase(); if (cleaned === "old" || cleaned === "oldest") return "old"; if (cleaned === "new" || cleaned === "newest") return "new"; if (cleaned === "summarize" || cleaned === "summary") return "summarize"; } //#endregion //#region src/auto-reply/reply/queue/directive.ts function parseQueueDebounce(raw) { if (!raw) return; try { const parsed = parseDurationMs(raw.trim(), { defaultUnit: "ms" }); if (!parsed || parsed < 0) return; return Math.round(parsed); } catch { return; } } function parseQueueCap(raw) { if (!raw) return; const num = Number(raw); if (!Number.isFinite(num)) return; const cap = Math.floor(num); if (cap < 1) return; return cap; } function parseQueueDirectiveArgs(raw) { const len = raw.length; let i = skipDirectiveArgPrefix(raw); let consumed = i; let queueMode; let queueReset = false; let rawMode; let debounceMs; let cap; let dropPolicy; let rawDebounce; let rawCap; let rawDrop; let hasOptions = false; const takeToken = () => { const res = takeDirectiveToken(raw, i); i = res.nextIndex; return res.token; }; while (i < len) { const token = takeToken(); if (!token) break; const lowered = token.trim().toLowerCase(); if (lowered === "default" || lowered === "reset" || lowered === "clear") { queueReset = true; consumed = i; break; } if (lowered.startsWith("debounce:") || lowered.startsWith("debounce=")) { rawDebounce = token.split(/[:=]/)[1] ?? ""; debounceMs = parseQueueDebounce(rawDebounce); hasOptions = true; consumed = i; continue; } if (lowered.startsWith("cap:") || lowered.startsWith("cap=")) { rawCap = token.split(/[:=]/)[1] ?? ""; cap = parseQueueCap(rawCap); hasOptions = true; consumed = i; continue; } if (lowered.startsWith("drop:") || lowered.startsWith("drop=")) { rawDrop = token.split(/[:=]/)[1] ?? ""; dropPolicy = normalizeQueueDropPolicy(rawDrop); hasOptions = true; consumed = i; continue; } const mode = normalizeQueueMode(token); if (mode) { queueMode = mode; rawMode = token; consumed = i; continue; } break; } return { consumed, queueMode, queueReset, rawMode, debounceMs, cap, dropPolicy, rawDebounce, rawCap, rawDrop, hasOptions }; } function extractQueueDirective(body) { if (!body) return { cleaned: "", hasDirective: false, queueReset: false, hasOptions: false }; const match = /(?:^|\s)\/queue(?=$|\s|:)/i.exec(body); if (!match) return { cleaned: body.trim(), hasDirective: false, queueReset: false, hasOptions: false }; const start = match.index + match[0].indexOf("/queue"); const argsStart = start + 6; const parsed = parseQueueDirectiveArgs(body.slice(argsStart)); return { cleaned: `${body.slice(0, start)} ${body.slice(argsStart + parsed.consumed)}`.replace(/\s+/g, " ").trim(), queueMode: parsed.queueMode, queueReset: parsed.queueReset, rawMode: parsed.rawMode, debounceMs: parsed.debounceMs, cap: parsed.cap, dropPolicy: parsed.dropPolicy, rawDebounce: parsed.rawDebounce, rawCap: parsed.rawCap, rawDrop: parsed.rawDrop, hasDirective: true, hasOptions: parsed.hasOptions }; } //#endregion //#region src/auto-reply/heartbeat.ts const HEARTBEAT_PROMPT = "Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK."; const DEFAULT_HEARTBEAT_EVERY = "30m"; const DEFAULT_HEARTBEAT_ACK_MAX_CHARS = 300; /** * Check if HEARTBEAT.md content is "effectively empty" - meaning it has no actionable tasks. * This allows skipping heartbeat API calls when no tasks are configured. * * A file is considered effectively empty if it contains only: * - Whitespace * - Comment lines (lines starting with #) * - Empty lines * * Note: A missing file returns false (not effectively empty) so the LLM can still * decide what to do. This function is only for when the file exists but has no content. */ function isHeartbeatContentEffectivelyEmpty(content) { if (content === void 0 || content === null) return false; if (typeof content !== "string") return false; const lines = content.split("\n"); for (const line of lines) { const trimmed = line.trim(); if (!trimmed) continue; if (/^#+(\s|$)/.test(trimmed)) continue; if (/^[-*+]\s*(\[[\sXx]?\]\s*)?$/.test(trimmed)) continue; return false; } return true; } function resolveHeartbeatPrompt(raw) { return (typeof raw === "string" ? raw.trim() : "") || HEARTBEAT_PROMPT; } function stripTokenAtEdges(raw) { let text = raw.trim(); if (!text) return { text: "", didStrip: false }; const token = HEARTBEAT_TOKEN; const tokenAtEndWithOptionalTrailingPunctuation = new RegExp(`${escapeRegExp(token)}[^\\w]{0,4}$`); if (!text.includes(token)) return { text, didStrip: false }; let didStrip = false; let changed = true; while (changed) { changed = false; const next = text.trim(); if (next.startsWith(token)) { text = next.slice(token.length).trimStart(); didStrip = true; changed = true; continue; } if (tokenAtEndWithOptionalTrailingPunctuation.test(next)) { const idx = next.lastIndexOf(token); const before = next.slice(0, idx).trimEnd(); if (!before) text = ""; else text = `${before}${next.slice(idx + token.length).trimStart()}`.trimEnd(); didStrip = true; changed = true; } } return { text: text.replace(/\s+/g, " ").trim(), didStrip }; } function stripHeartbeatToken(raw, opts = {}) { if (!raw) return { shouldSkip: true, text: "", didStrip: false }; const trimmed = raw.trim(); if (!trimmed) return { shouldSkip: true, text: "", didStrip: false }; const mode = opts.mode ?? "message"; const maxAckCharsRaw = opts.maxAckChars; const parsedAckChars = typeof maxAckCharsRaw === "string" ? Number(maxAckCharsRaw) : maxAckCharsRaw; const maxAckChars = Math.max(0, typeof parsedAckChars === "number" && Number.isFinite(parsedAckChars) ? parsedAckChars : DEFAULT_HEARTBEAT_ACK_MAX_CHARS); const stripMarkup = (text) => text.replace(/<[^>]*>/g, " ").replace(/&nbsp;/gi, " ").replace(/^[*`~_]+/, "").replace(/[*`~_]+$/, ""); const trimmedNormalized = stripMarkup(trimmed); if (!(trimmed.includes(HEARTBEAT_TOKEN) || trimmedNormalized.includes(HEARTBEAT_TOKEN))) return { shouldSkip: false, text: trimmed, didStrip: false }; const strippedOriginal = stripTokenAtEdges(trimmed); const strippedNormalized = stripTokenAtEdges(trimmedNormalized); const picked = strippedOriginal.didStrip && strippedOriginal.text ? strippedOriginal : strippedNormalized; if (!picked.didStrip) return { shouldSkip: false, text: trimmed, didStrip: false }; if (!picked.text) return { shouldSkip: true, text: "", didStrip: true }; const rest = picked.text.trim(); if (mode === "heartbeat") { if (rest.length <= maxAckChars) return { shouldSkip: true, text: "", didStrip: true }; } return { shouldSkip: false, text: rest, didStrip: true }; } //#endregion //#region src/channels/allowlist-match.ts function formatAllowlistMatchMeta(match) { return `matchKey=${match?.matchKey ?? "none"} matchSource=${match?.matchSource ?? "none"}`; } //#endregion //#region src/config/channel-capabilities.ts const isStringArray = (value) => Array.isArray(value) && value.every((entry) => typeof entry === "string"); function normalizeCapabilities(capabilities) { if (!isStringArray(capabilities)) return; const normalized = capabilities.map((entry) => entry.trim()).filter(Boolean); return normalized.length > 0 ? normalized : void 0; } function resolveAccountCapabilities(params) { const cfg = params.cfg; if (!cfg) return; const normalizedAccountId = normalizeAccountId$3(params.accountId); const accounts = cfg.accounts; if (accounts && typeof accounts === "object") { const direct = accounts[normalizedAccountId]; if (direct) return normalizeCapabilities(direct.capabilities) ?? normalizeCapabilities(cfg.capabilities); const matchKey = Object.keys(accounts).find((key) => key.toLowerCase() === normalizedAccountId.toLowerCase()); const match = matchKey ? accounts[matchKey] : void 0; if (match) return normalizeCapabilities(match.capabilities) ?? normalizeCapabilities(cfg.capabilities); } return normalizeCapabilities(cfg.capabilities); } function resolveChannelCapabilities(params) { const cfg = params.cfg; const channel = normalizeChannelId$1(params.channel); if (!cfg || !channel) return; return resolveAccountCapabilities({ cfg: cfg.channels?.[channel] ?? cfg[channel], accountId: params.accountId }); } //#endregion //#region src/process/lanes.ts let CommandLane = /* @__PURE__ */ function(CommandLane) { CommandLane["Main"] = "main"; CommandLane["Cron"] = "cron"; CommandLane["Subagent"] = "subagent"; CommandLane["Nested"] = "nested"; return CommandLane; }({}); //#endregion //#region src/process/command-queue.ts /** * Dedicated error type thrown when a queued command is rejected because * its lane was cleared. Callers that fire-and-forget enqueued tasks can * catch (or ignore) this specific type to avoid unhandled-rejection noise. */ var CommandLaneClearedError = class extends Error { constructor(lane) { super(lane ? `Command lane "${lane}" cleared` : "Command lane cleared"); this.name = "CommandLaneClearedError"; } }; const lanes = /* @__PURE__ */ new Map(); let nextTaskId = 1; function getLaneState(lane) { const existing = lanes.get(lane); if (existing) return existing; const created = { lane, queue: [], activeTaskIds: /* @__PURE__ */ new Set(), maxConcurrent: 1, draining: false, generation: 0 }; lanes.set(lane, created); return created; } function completeTask(state, taskId, taskGeneration) { if (taskGeneration !== state.generation) return false; state.activeTaskIds.delete(taskId); return true; } function drainLane(lane) { const state = getLaneState(lane); if (state.draining) return; state.draining = true; const pump = () => { while (state.activeTaskIds.size < state.maxConcurrent && state.queue.length > 0) { const entry = state.queue.shift(); const waitedMs = Date.now() - entry.enqueuedAt; if (waitedMs >= entry.warnAfterMs) { entry.onWait?.(waitedMs, state.queue.length); diag.warn(`lane wait exceeded: lane=${lane} waitedMs=${waitedMs} queueAhead=${state.queue.length}`); } logLaneDequeue(lane, waitedMs, state.queue.length); const taskId = nextTaskId++; const taskGeneration = state.generation; state.activeTaskIds.add(taskId); (async () => { const startTime = Date.now(); try { const result = await entry.task(); if (completeTask(state, taskId, taskGeneration)) { diag.debug(`lane task done: lane=${lane} durationMs=${Date.now() - startTime} active=${state.activeTaskIds.size} queued=${state.queue.length}`); pump(); } entry.resolve(result); } catch (err) { const completedCurrentGeneration = completeTask(state, taskId, taskGeneration); if (!(lane.startsWith("auth-probe:") || lane.startsWith("session:probe-"))) diag.error(`lane task error: lane=${lane} durationMs=${Date.now() - startTime} error="${String(err)}"`); if (completedCurrentGeneration) pump(); entry.reject(err); } })(); } state.draining = false; }; pump(); } function setCommandLaneConcurrency(lane, maxConcurrent) { const cleaned = lane.trim() || CommandLane.Main; const state = getLaneState(cleaned); state.maxConcurrent = Math.max(1, Math.floor(maxConcurrent)); drainLane(cleaned); } function enqueueCommandInLane(lane, task, opts) { const cleaned = lane.trim() || CommandLane.Main; const warnAfterMs = opts?.warnAfterMs ?? 2e3; const state = getLaneState(cleaned); return new Promise((resolve, reject) => { state.queue.push({ task: () =