@gguf/claw
Version:
Multi-channel AI gateway with extensible messaging integrations
839 lines (828 loc) • 2.46 MB
JavaScript
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(/ /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: () =