@gguf/claw
Version:
Multi-channel AI gateway with extensible messaging integrations
924 lines (910 loc) • 2.67 MB
JavaScript
import { t as __exportAll } from "./rolldown-runtime-Cbj13DAv.js";
import { _ as isSubagentSessionKey, c as normalizeAccountId$3, d as resolveAgentIdFromSessionKey, f as resolveThreadSessionKeys, g as isCronSessionKey, h as isAcpSessionKey, i as buildAgentMainSessionKey, l as normalizeAgentId, m as getSubagentDepth, n as DEFAULT_AGENT_ID, p as sanitizeAgentId, s as classifySessionKeyShape, t as DEFAULT_ACCOUNT_ID$1, u as normalizeMainKey, v as parseAgentSessionKey, y as resolveThreadParentSessionKey } from "./session-key-9yEYlIQe.js";
import { c as logoutWeb, f as readWebSelfId, g as webAuthExists, o as getWebAuthAgeMs, r as resolveWhatsAppAccount, s as logWebSelfId } from "./accounts-Dy3mxoHH.js";
import { B as danger, C as formatTerminalLink, D as normalizeE164, F as sleep$1, G as setVerbose, I as sliceUtf16Safe, J as warn, K as shouldLogVerbose, N as shortenHomeInString, P as shortenHomePath, Q as getChildLogger, R as truncateUtf16Safe, S as escapeRegExp, U as logVerbose, X as isRich, Y as colorize, Z as theme, _ as CONFIG_DIR, a as normalizeAnyChannelId, at as normalizeLogLevel, ct as createInternalHookEvent, d as createPluginRegistry, f as clearPluginCommands, g as matchPluginCommand, h as listPluginCommands, j as resolveUserPath, l as requireActivePluginRegistry, lt as triggerInternalHook, m as getPluginCommandSpecs, n as CHAT_CHANNEL_ORDER, o as normalizeChannelId, p as executePluginCommand, r as DEFAULT_CHAT_CHANNEL, st as resolvePreferredOpenClawTmpDir, u as setActivePluginRegistry, ut as normalizePluginHttpPath, w as isRecord$1, x as ensureDir$3, y as clampInt, z as isPlainObject } from "./registry-C8pj8ctW.js";
import { c as expandHomePrefix, i as resolveGatewayPort, n as resolveConfigPath, s as resolveStateDir, t as STATE_DIR, u as resolveRequiredHomeDir } from "./paths-DJmOcr7Q.js";
import { A as getSoonestCooldownExpiry, B as resolveOpenClawAgentDir, C as getCustomProviderApiKey, D as resolveModelAuthMode, E as resolveEnvApiKey, F as dedupeProfileIds, G as DEFAULT_PROVIDER, H as resolveAuthProfileDisplayLabel, I as listProfilesForProvider, J as resolveShellEnvFallbackTimeoutMs, K as getShellPathFromLoginShell, L as markAuthProfileGood, M as markAuthProfileFailure, N as markAuthProfileUsed, P as resolveApiKeyForProfile, Q as withFileLock, R as ensureAuthProfileStore, S as getApiKeyForModel, T as resolveApiKeyForProvider, U as DEFAULT_CONTEXT_TOKENS, V as normalizeSecretInput, W as DEFAULT_MODEL, a as isCliProvider, b as OLLAMA_NATIVE_BASE_URL, c as normalizeProviderId, d as resolveDefaultModelForAgent, f as resolveModelRefFromString, i as findNormalizedProviderValue, j as isProfileInCooldown, k as resolveAuthProfileOrder, m as resolveThinkingDefault, n as buildConfiguredAllowlistKeys, o as modelKey, p as resolveSubagentSpawnModelSelection, r as buildModelAliasIndex, s as normalizeModelRef$2, t as buildAllowedModelSet, u as resolveConfiguredModelRef, w as requireApiKey, x as createOllamaStreamFn, z as resolveAuthStorePathForDisplay } from "./model-selection-DQIwoYb8.js";
import { B as isSafeExecutableValue, H as TELEGRAM_COMMAND_NAME_PATTERN, J as resolveIMessageAttachmentRoots, K as isInboundPathAllowed, U as normalizeTelegramCommandName, V as parseDurationMs, W as resolveTelegramCustomCommands, X as normalizeScpRemoteHost, Y as resolveIMessageRemoteAttachmentRoots, _ as resolveAgentMaxConcurrent, a as writeConfigFile, c as validateJsonSchemaValue, d as setConfigOverride, f as unsetConfigOverride, g as unsetConfigValueAtPath, h as setConfigValueAtPath, i as resolveConfigSnapshotHash, l as getConfigOverrides, m as parseConfigPath, n as loadConfig, o as validateConfigObjectWithPlugins, p as getConfigValueAtPath, r as readConfigFileSnapshot, u as resetConfigOverrides, v as VERSION } from "./config-DA0pxYcO.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-BEpJBywc.js";
import { d as detectMime, f as extensionForMime, g as isGifMedia, h as isAudioFileName, m as imageMimeFromFormat, s as getImageMetadata, u as resizeToJpeg, x as mediaKindFromMime, y as MAX_IMAGE_BYTES } from "./fs-safe-CGcLaY9D.js";
import { a as clearActiveProgressLine, i as defaultRuntime, o as registerActiveProgressLine, r as createNonExitingRuntime, s as unregisterActiveProgressLine, t as createSubsystemLogger } from "./subsystem-BfLMZ8kW.js";
import { A as logError, C as resolveOpenClawPackageRoot, D as runExec, E as runCommandWithTimeout, M as logWarn, O as spawnWithFallback, S as loadWorkspaceBootstrapFiles, a as resolveAgentModelPrimary, b as ensureAgentWorkspace, c as resolveDefaultAgentId, d as resolveSessionAgentIds, i as resolveAgentModelFallbacksOverride, j as logInfo, k as logDebug, l as resolveEffectiveModelFallbacks, m as DEFAULT_BOOTSTRAP_FILENAME, n as resolveAgentConfig, o as resolveAgentSkillsFilter, p as DEFAULT_AGENT_WORKSPACE_DIR, r as resolveAgentDir, s as resolveAgentWorkspaceDir, t as listAgentIds, u as resolveSessionAgentId, x as filterBootstrapFilesForSession } from "./agent-scope-OWMdRegz.js";
import { a as parseAvailableTags, c as readStringArrayParam, h as resolveImageSanitizationLimits, i as jsonResult, l as readStringOrNumberParam, m as sanitizeToolResultImages, n as imageResult, o as readNumberParam, p as sanitizeImageBlocks, r as imageResultFromFile, s as readReactionParams, t as createActionGate, u as readStringParam } from "./common-CCPGi5xr.js";
import { a as createSlackWebClient, c as validateSlackBlocksArray, i as buildSlackBlocksFallbackText, o as resolveSlackWebClientOptions, s as parseSlackBlocksInput, t as sendMessageSlack } from "./send-DyFx4sCR.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-C9J4kyVw.js";
import { $ as parseTelegramTarget, A as hasBotMention, B as resolveSenderAllowMatch, C as buildTelegramGroupPeerId, D as describeReplyTarget, E as buildTypingThreadParams, F as resolveTelegramReplyId, G as readChannelAllowFromStore, H as isSenderIdAllowed, I as resolveTelegramStreamMode, J as upsertChannelPairingRequest, L as resolveTelegramThreadSpec, M as resolveTelegramForumThreadId, N as resolveTelegramGroupAllowFromContext, O as expandTextLinks, P as resolveTelegramMediaPlaceholder, Q as isVoiceCompatibleAudio, R as isSenderAllowed$1, S as buildTelegramGroupFrom, T as buildTelegramThreadParams, U as mergeAllowFromSources, V as firstDefined$1, W as addChannelAllowFromStoreEntry, X as listPairingChannels, Y as getPairingAdapter, Z as withTelegramApiErrorLogging, _ as resolveTelegramFetch, a as reactMessageTelegram, b as buildSenderLabel, c as sendStickerTelegram, d as wasSentByBot, et as resolveTelegramTargetChatType, f as isRecoverableTelegramNetworkError, g as wrapFileReferencesInHtml, h as renderTelegramHtmlText, i as editMessageTelegram, j as normalizeForwardedContext, k as extractTelegramLocation, m as markdownToTelegramHtml, n as createForumTopicTelegram, nt as toLocationContext, o as sendMessageTelegram, p as markdownToTelegramChunks, q as removeChannelAllowFromStoreEntry, r as deleteMessageTelegram, s as sendPollTelegram, t as buildInlineKeyboard, tt as formatLocationText, u as resolveTelegramVoiceSend, v as splitTelegramCaption, w as buildTelegramParentPeer, x as buildSenderName, y as buildGroupLabel, z as normalizeAllowFromWithStore$1 } from "./send-CxkhX9l7.js";
import { _ as CLI_OUTPUT_MAX_BUFFER, a as resolveMediaAttachmentLocalRoots, c as loadModelCatalog, d as resolveAttachmentKind, f as registerUnhandledRejectionHandler, g as resolveMediaUnderstandingScope, h as normalizeMediaUnderstandingChatType, i as resolveAutoImageModel, l as modelSupportsVision, m as resolveTimeoutMs$1, n as createMediaAttachmentCache, o as runCapability, p as resolveConcurrency, r as normalizeMediaAttachments, s as findModelInCatalog, t as buildProviderRegistry, v as applyTemplate, y as buildRandomTempFilePath } from "./runner-DIcTJgbP.js";
import { a as resolveAckReaction, i as resolveResponsePrefixTemplate, n as createReplyPrefixOptions, o as resolveEffectiveMessagesConfig, s as resolveHumanDelayConfig } from "./reply-prefix-YUOHz1rF.js";
import { n as SILENT_REPLY_TOKEN, r as isSilentReplyText, t as HEARTBEAT_TOKEN } from "./tokens-D1LxPszt.js";
import { c as getSkillsSnapshotVersion, d as resolvePairingPaths, f as createAsyncLock, i as resolveSkillCommandInvocation, l as generatePairingToken, m as writeJsonAtomic, n as listSkillCommandsForAgents, o as getRemoteSkillEligibility, p as readJsonFile, r as listSkillCommandsForWorkspace, s as ensureSkillsWatcher, t as listReservedChatSlashCommandNames, u as pruneExpiredPending } from "./skill-commands-BpaH_zzk.js";
import { c as assertSandboxPath, d as resolveSandboxedMediaSource, f as applySkillEnvOverrides, i as resolveSkillsPromptForRun, l as resolveSandboxInputPath, n as buildWorkspaceSkillSnapshot, p as applySkillEnvOverridesFromSnapshot, r as loadWorkspaceSkillEntries, s as assertMediaNotDataUrl } from "./skills-OZUqNHBX.js";
import { n as formatErrorMessage, r as formatUncaughtError } from "./errors-Bv8oZiTO.js";
import { n as fetchWithTimeout, t as bindAbortRelay } from "./fetch-timeout-BKZjgek-.js";
import { a as isBlockedHostnameOrIp, c as normalizeHostname, t as SsrFBlockedError } from "./ssrf-DxmqkHJJ.js";
import { a as readResponseWithLimit, i as fetchRemoteMedia, n as getDefaultMediaLocalRoots, o as fetchWithSsrFGuard, t as getAgentScopedMediaLocalRoots } from "./local-roots-jpNoUngc.js";
import { M as isSecureWebSocketUrl, N as rawDataToString, T as DEFAULT_AI_SNAPSHOT_MAX_CHARS, x as ensureChromeExtensionRelayServer } from "./chrome-32CP7Tm2.js";
import { i as parseBooleanValue$1, n as resolveCliName, r as isTruthyEnvValue, t as formatCliCommand } from "./command-format-sreXrOOr.js";
import { A as normalizeHyphenSlug, F as resolveChannelGroupRequireMention, I as resolveChannelGroupToolsPolicy, M as normalizeStringEntriesLower, P as resolveChannelGroupPolicy, a as normalizeReasoningLevel, c as normalizeVerboseLevel, d as getChannelDock, f as listChannelDocks, i as normalizeElevatedLevel, j as normalizeStringEntries, k as normalizeAtHashSlug, l as resolveResponseUsageMode, m as normalizeSignalMessagingTarget, n as formatXHighModelHint, o as normalizeThinkLevel, s as normalizeUsageDisplay, t as formatThinkingLevels, u as supportsXHighThinking } from "./thinking-DFXDZFyu.js";
import { a as listTelegramAccountIds, b as resolveDiscordAccount, c as resolveTelegramToken, f as resolveSlackAccount, g as createDiscordActionGate, h as resolveSlackBotToken, i as listEnabledTelegramAccounts, m as resolveSlackAppToken, n as normalizeWhatsAppTarget, r as createTelegramActionGate, s as resolveTelegramAccount, t as isWhatsAppGroupJid, v as listEnabledDiscordAccounts, x as normalizeDiscordToken } from "./normalize-D9b0GOOm.js";
import { r as resolveIMessageAccount } from "./accounts-mzh94Dc2.js";
import { i as resolveSignalAccount, t as listEnabledSignalAccounts } from "./accounts-Bkix50Fs.js";
import { t as normalizeChatType } from "./chat-type-B5__aQIT.js";
import { h as resolveSlackChannelId, m as parseSlackTarget, n as listChannelPlugins, r as normalizeChannelId$1, t as getChannelPlugin } from "./plugins-BpKonLQ1.js";
import { $ as resolveDiscordChannelId, A as addRoleDiscord, B as removeRoleDiscord, C as fetchMessageDiscord, Ct as applyChannelMatchMeta, D as readMessagesDiscord, Dt as resolveChannelEntryMatchWithFallback, E as pinMessageDiscord, 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 parseDiscordTarget, R as listGuildChannelsDiscord, S as editMessageDiscord, St as chunkDiscordTextWithMode, 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 resolveTimestampMs, a as removeReactionDiscord, at as normalizeDiscordSlug, b as createThreadDiscord, bt as hasAnyGuildPermissionDiscord, c as formatDiscordComponentEventText, ct as resolveDiscordGuildEntry, d as parseDiscordModalCustomId, dt as resolveDiscordShouldRequireMention, et as listDiscordDirectoryGroupsLive, f as parseDiscordModalCustomIdForCarbon, ft as resolveGroupDmAllow, g as sendMessageDiscord, gt as resolveDiscordSystemLocation, h as resolveDiscordModalEntry, ht as formatDiscordUserTag, i as removeOwnReactionsDiscord, it as normalizeDiscordAllowList, j as banMemberDiscord, k as unpinMessageDiscord, l as parseDiscordComponentCustomId, lt as resolveDiscordMemberAccessState, m as resolveDiscordComponentEntry, mt as formatDiscordReactionEmoji, n as fetchReactionsDiscord, nt as allowListMatches$1, o as sendDiscordComponentMessage, ot as resolveDiscordAllowListMatch, p as readDiscordComponentSpec, pt as shouldEmitDiscordReactionNotification, q as editChannelDiscord, r as reactMessageDiscord, rt as isDiscordGroupAllowedByPolicy, s as createDiscordFormModal, st as resolveDiscordChannelConfigWithFallback, tt as listDiscordDirectoryPeersLive, u as parseDiscordComponentCustomIdForCarbon, ut as resolveDiscordOwnerAllowFrom, v as sendStickerDiscord, vt as fetchDiscord, w as listPinsDiscord, wt as buildChannelKeyCandidates, x as deleteMessageDiscord, xt as createDiscordClient, y as sendVoiceMessageDiscord, yt as fetchChannelPermissionsDiscord, z as listScheduledEventsDiscord } from "./send-DwpvvHgk.js";
import { C as getGlobalHookRunner, S as throwIfAborted, _ as normalizeTargetForProvider, a as normalizeOutboundPayloadsForJson, b as splitMediaFromOutput, 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 parseReplyDirectives, w as initializeGlobalHookRunner, x as parseInlineDirectives$1, y as MEDIA_TOKEN_RE } from "./deliver-Dn83X5NP.js";
import { a as isMarkdownCapableMessageChannel, c as resolveGatewayMessageChannel, d as GATEWAY_CLIENT_MODES, f as GATEWAY_CLIENT_NAMES, i as isInternalMessageChannel, l as resolveMessageChannel, n as isDeliverableMessageChannel, o as listDeliverableMessageChannels, r as isGatewayMessageChannel, s as normalizeMessageChannel, t as INTERNAL_MESSAGE_CHANNEL, u as GATEWAY_CLIENT_IDS } from "./message-channel-C3OrO29D.js";
import { $ as normalizeToolName, A as isTransientHttpError, At as INPUT_PROVENANCE_KIND_VALUES, B as resolveProfile, Bt as resolveSessionResetType, C as isContextOverflowError, Ct as normalizeDeliveryContext, D as isRateLimitAssistantError, Dt as capArrayByJsonBytes, E as isLikelyContextOverflowError, Et as archiveSessionTranscripts, F as resolveSandboxContext, Ft as resolveSessionLockMaxHoldFromTimeout, G as resolveBrowserControlAuth, Gt as resolveExplicitAgentSessionKey, H as resolveExistingPathsWithinRoot, Ht as DEFAULT_RESET_TRIGGERS, I as resolveSandboxRuntimeStatus, It as resolveSessionKey, J as buildPluginToolGroups, Jt as resolveGroupSessionKey, K as resolveSandboxConfigForAgent, Kt as resolveMainSessionKey, L as createBrowserRouteContext, Lt as evaluateSessionFreshness, M as parseImageSizeError, Mt as hasInterSessionUserProvenance, N as sanitizeUserFacingText, Nt as normalizeInputProvenance, O as isRawApiErrorPayload, Ot as countToolResults, P as ensureSandboxWorkspaceForSession, Pt as acquireSessionWriteLock, Q as mergeAlsoAllowPolicy, R as registerBrowserRoutes, Rt as resolveChannelResetConfig, S as isCompactionFailureError, St as mergeDeliveryContext, T as isFailoverErrorMessage, Tt as normalizeAccountId$4, U as getBridgeAuthForPort, Ut as resolveFreshSessionTotalTokens, V as DEFAULT_UPLOAD_DIR, Vt as resolveThreadFlag, W as ensureBrowserControlAuth, Wt as canonicalizeMainSessionAlias, X as expandPolicyWithPluginGroups, Y as collectExplicitAllowlist, Z as expandToolGroups, _ as formatRawAssistantErrorForUi, _t as updateSessionStoreEntry, a as isMessagingToolDuplicateNormalized, at as ensureSessionHeader, b as isBillingAssistantError, bt as deliveryContextFromSession, c as extractToolCallsFromAssistant, ct as sanitizeGoogleTurnOrdering, d as isAntigravityClaude, et as resolveToolProfilePolicy, f as isGoogleModelApi, ft as loadSessionStore, g as formatBillingErrorMessage, gt as updateSessionStore, h as formatAssistantErrorText, ht as updateLastRoute, it as buildBootstrapContextFiles, j as parseImageDimensionError, jt as applyInputProvenanceToUserMessage, k as isTimeoutErrorMessage, kt as extractToolCallNames, l as extractToolResultId, lt as extractDeliveryInfo, m as classifyFailoverReason, mt as recordSessionMetaFromInbound, n as validateGeminiTurns, nt as compileGlobPatterns, o as normalizeTextForComparison, ot as resolveBootstrapMaxChars, p as BILLING_ERROR_USER_MESSAGE, pt as readSessionUpdatedAt, q as applyOwnerOnlyToolPolicy, qt as deriveSessionMetaPatch, r as pickFallbackThinkingLevel, rt as matchesAnyGlobPattern, s as sanitizeSessionMessagesImages, st as resolveBootstrapTotalMaxChars, t as validateAnthropicTurns, tt as stripPluginOnlyAllowlist, u as downgradeOpenAIReasoningBlocks, ut as appendAssistantMessageToSessionTranscript, v as getApiErrorPayloadFingerprint, vt as isCacheEnabled, w as isFailoverAssistantError, wt as normalizeSessionDeliveryFields, x as isCloudCodeAssistFormatError, xt as deliveryContextKey, y as isAuthAssistantError, yt as resolveCacheTtlMs$1, z as resolveBrowserConfig, zt as resolveSessionResetPolicy } from "./pi-embedded-helpers-Caj23g0W.js";
import { n as resolveConversationLabel } from "./conversation-label-2FLz1ei_.js";
import { a as saveJsonFile, i as loadJsonFile } from "./github-copilot-token-etmIcdko.js";
import { c as normalizePluginsConfig, f as isPathInsideWithRealpath, i as safeStatSync, l as resolveEnableState, n as discoverOpenClawPlugins, r as isPathInside, s as applyTestPluginDefaults, t as loadPluginManifestRegistry, u as resolveMemorySlotDecision } from "./manifest-registry-Lzj-fZNH.js";
import { i as resolveSessionTranscriptPath, n as resolveSessionFilePath, o as resolveSessionTranscriptsDirForAgent, r as resolveSessionFilePathOptions, s as resolveStorePath, t as resolveDefaultSessionStorePath } from "./paths-a1ZEI8nz.js";
import { t as emitSessionTranscriptUpdate } from "./transcript-events-Cj85Mq0h.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-oBxO5N68.js";
import { i as saveMediaBuffer, r as getMediaDir } from "./store-BJRhX9Bi.js";
import { n as normalizePollInput } from "./polls-dTqdfZ_K.js";
import { a as loadWebMedia, i as getDefaultLocalRoots } from "./ir-JSGKj1e6.js";
import { n as retryAsync } from "./retry-B8Oq5mgi.js";
import { n as recordChannelActivity, r as createDiscordRetryRunner, t as getChannelActivity } from "./channel-activity-DHI8R5Xg.js";
import { n as wrapFetchWithAbortSignal, t as resolveFetch } from "./fetch-B79-NBmS.js";
import { n as resolveMarkdownTableMode } from "./markdown-tables-Cf5RtnFi.js";
import { t as convertMarkdownTables } from "./tables-D5aPNTF6.js";
import { r as normalizeInboundTextNewlines, t as finalizeInboundContext } from "./inbound-context-hgCIam0H.js";
import { S as minimaxUnderstandImage, _ as stripThinkingTagsFromText, a as decodeDataUrl, b as extractTextFromChatContent, c as extractAssistantThinking, d as formatReasoningMessage, f as inferToolMetaFromArgs, g as stripMinimaxToolCallXml, h as stripDowngradedToolCallText, i as coerceImageModelConfig, l as extractThinkingFromTaggedStream, m as promoteThinkingTagsToBlocks, o as resolveProviderVisionModelFromConfig, p as isAssistantMessage, r as coerceImageAssistantText, s as extractAssistantText$1, u as extractThinkingFromTaggedText, v as resolveToolDisplay, x as ensureOpenClawModelsJson, y as stripReasoningTagsFromText } from "./image-B6uzdadC.js";
import { n as discoverModels, t as discoverAuthStorage } from "./pi-model-discovery-3Y4hcIsw.js";
import { d as listMemoryFiles, f as normalizeExtraMemoryPaths, v as runTasksWithConcurrency } from "./sqlite-Yn48izJ_.js";
import { r as getDiagnosticSessionState } from "./diagnostic-session-state-BW5KRYN1.js";
import { n as resolveMemorySearchConfig } from "./manager-iI-4K8tc.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-zf_cMU77.js";
import { c as signalRpcRequest, l as streamSignalEvents, n as sendReadReceiptSignal, o as resolveSignalRpcContext, r as sendTypingSignal, s as signalCheck, t as sendMessageSignal } from "./send-BqnSueAq.js";
import { t as makeProxyFetch } from "./proxy-BwzmpJWq.js";
import { n as resolveAgentRoute, t as buildAgentSessionKey } from "./resolve-route-DudlMKs4.js";
import { a as createReplyReferencePlanner, i as resolveSlackThreadTs, n as deliverReplies$3, t as createSlackReplyDeliveryPlan } from "./replies-CH9sggoc.js";
import { t as getActiveWebListener } from "./active-listener-RPIOZo7v.js";
import { n as recordCommandPoll, r as resetCommandPollCount } from "./command-poll-backoff-NAePk3eL.js";
import { createRequire } from "node:module";
import * as path$1 from "node:path";
import path from "node:path";
import fs, { existsSync, mkdirSync, mkdtempSync, readFileSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync } from "node:fs";
import os, { homedir } from "node:os";
import JSON5 from "json5";
import * as fs$2 from "node:fs/promises";
import fs$1 from "node:fs/promises";
import { inspect, promisify } from "node:util";
import { execFile, execFileSync, spawn, spawnSync } from "node:child_process";
import crypto, { X509Certificate, randomBytes, randomUUID } from "node:crypto";
import { fileURLToPath } from "node:url";
import { ProxyAgent, fetch as fetch$1 } from "undici";
import { Buffer as Buffer$1 } from "node:buffer";
import { complete, completeSimple, streamSimple } from "@mariozechner/pi-ai";
import AjvPkg from "ajv";
import { CURRENT_SESSION_VERSION, DefaultResourceLoader, SessionManager, SettingsManager, codingTools, createAgentSession, createEditTool, createReadTool, createWriteTool, estimateTokens, generateSummary, readTool } from "@mariozechner/pi-coding-agent";
import { Type } from "@sinclair/typebox";
import { createServer } from "node:http";
import { ApplicationCommandOptionType, ButtonStyle, ChannelType, PermissionFlagsBits, Routes, StickerFormatType } from "discord-api-types/v10";
import { Button, ChannelSelectMenu, ChannelType as ChannelType$1, Client, Command, CommandWithSubcommands, Container, MentionableSelectMenu, MessageCreateListener, MessageReactionAddListener, MessageReactionRemoveListener, MessageType, Modal, PresenceUpdateListener, ReadyListener, RoleSelectMenu, Row, Separator, StringSelectMenu, TextDisplay, UserSelectMenu, serializePayload } from "@buape/carbon";
import { spinner } from "@clack/prompts";
import WebSocket, { WebSocket as WebSocket$1 } from "ws";
import { EdgeTTS } from "node-edge-tts";
import { createJiti } from "jiti";
import readline from "node:readline";
import { API_CONSTANTS, Bot, GrammyError, InputFile, webhookCallback } from "grammy";
import { createOscProgressController, supportsOscProgress } from "osc-progress";
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/channels/plugins/message-action-names.ts
const CHANNEL_MESSAGE_ACTION_NAMES = [
"send",
"broadcast",
"poll",
"react",
"reactions",
"read",
"edit",
"unsend",
"reply",
"sendWithEffect",
"renameGroup",
"setGroupIcon",
"addParticipant",
"removeParticipant",
"leaveGroup",
"sendAttachment",
"delete",
"pin",
"unpin",
"list-pins",
"permissions",
"thread-create",
"thread-list",
"thread-reply",
"search",
"sticker",
"sticker-search",
"member-info",
"role-info",
"emoji-list",
"emoji-upload",
"sticker-upload",
"role-add",
"role-remove",
"channel-info",
"channel-list",
"channel-create",
"channel-edit",
"channel-delete",
"channel-move",
"category-create",
"category-edit",
"category-delete",
"topic-create",
"voice-status",
"event-list",
"event-create",
"timeout",
"kick",
"ban",
"set-presence"
];
//#endregion
//#region src/channels/plugins/bluebubbles-actions.ts
const BLUEBUBBLES_ACTIONS = {
react: { gate: "reactions" },
edit: {
gate: "edit",
unsupportedOnMacOS26: true
},
unsend: { gate: "unsend" },
reply: { gate: "reply" },
sendWithEffect: { gate: "sendWithEffect" },
renameGroup: {
gate: "renameGroup",
groupOnly: true
},
setGroupIcon: {
gate: "setGroupIcon",
groupOnly: true
},
addParticipant: {
gate: "addParticipant",
groupOnly: true
},
removeParticipant: {
gate: "removeParticipant",
groupOnly: true
},
leaveGroup: {
gate: "leaveGroup",
groupOnly: true
},
sendAttachment: { gate: "sendAttachment" }
};
const BLUEBUBBLES_ACTION_SPECS = BLUEBUBBLES_ACTIONS;
const BLUEBUBBLES_ACTION_NAMES = Object.keys(BLUEBUBBLES_ACTIONS);
const BLUEBUBBLES_GROUP_ACTIONS = new Set(BLUEBUBBLES_ACTION_NAMES.filter((action) => BLUEBUBBLES_ACTION_SPECS[action]?.groupOnly));
//#endregion
//#region src/plugins/http-registry.ts
function registerPluginHttpRoute(params) {
const registry = params.registry ?? requireActivePluginRegistry();
const routes = registry.httpRoutes ?? [];
registry.httpRoutes = routes;
const normalizedPath = normalizePluginHttpPath(params.path, params.fallbackPath);
const suffix = params.accountId ? ` for account "${params.accountId}"` : "";
if (!normalizedPath) {
params.log?.(`plugin: webhook path missing${suffix}`);
return () => {};
}
if (routes.some((entry) => entry.path === normalizedPath)) {
const pluginHint = params.pluginId ? ` (${params.pluginId})` : "";
params.log?.(`plugin: webhook path ${normalizedPath} already registered${suffix}${pluginHint}`);
return () => {};
}
const entry = {
path: normalizedPath,
handler: params.handler,
pluginId: params.pluginId,
source: params.source
};
routes.push(entry);
return () => {
const index = routes.indexOf(entry);
if (index >= 0) routes.splice(index, 1);
};
}
//#endregion
//#region src/plugin-sdk/tool-send.ts
function extractToolSend(args, expectedAction = "sendMessage") {
if ((typeof args.action === "string" ? args.action.trim() : "") !== expectedAction) return null;
const to = typeof args.to === "string" ? args.to : void 0;
if (!to) return null;
return {
to,
accountId: typeof args.accountId === "string" ? args.accountId.trim() : void 0
};
}
//#endregion
//#region src/shared/device-auth.ts
function normalizeDeviceAuthRole(role) {
return role.trim();
}
function normalizeDeviceAuthScopes(scopes) {
if (!Array.isArray(scopes)) return [];
const out = /* @__PURE__ */ new Set();
for (const scope of scopes) {
const trimmed = scope.trim();
if (trimmed) out.add(trimmed);
}
return [...out].toSorted();
}
//#endregion
//#region src/infra/device-pairing.ts
const PENDING_TTL_MS = 300 * 1e3;
const withLock = createAsyncLock();
async function loadState(baseDir) {
const { pendingPath, pairedPath } = resolvePairingPaths(baseDir, "devices");
const [pending, paired] = await Promise.all([readJsonFile(pendingPath), readJsonFile(pairedPath)]);
const state = {
pendingById: pending ?? {},
pairedByDeviceId: paired ?? {}
};
pruneExpiredPending(state.pendingById, Date.now(), PENDING_TTL_MS);
return state;
}
async function persistState(state, baseDir) {
const { pendingPath, pairedPath } = resolvePairingPaths(baseDir, "devices");
await Promise.all([writeJsonAtomic(pendingPath, state.pendingById), writeJsonAtomic(pairedPath, state.pairedByDeviceId)]);
}
function normalizeDeviceId(deviceId) {
return deviceId.trim();
}
function normalizeRole(role) {
const trimmed = role?.trim();
return trimmed ? trimmed : null;
}
function mergeRoles(...items) {
const roles = /* @__PURE__ */ new Set();
for (const item of items) {
if (!item) continue;
if (Array.isArray(item)) for (const role of item) {
const trimmed = role.trim();
if (trimmed) roles.add(trimmed);
}
else {
const trimmed = item.trim();
if (trimmed) roles.add(trimmed);
}
}
if (roles.size === 0) return;
return [...roles];
}
function mergeScopes(...items) {
const scopes = /* @__PURE__ */ new Set();
for (const item of items) {
if (!item) continue;
for (const scope of item) {
const trimmed = scope.trim();
if (trimmed) scopes.add(trimmed);
}
}
if (scopes.size === 0) return;
return [...scopes];
}
function newToken() {
return generatePairingToken();
}
async function listDevicePairing(baseDir) {
const state = await loadState(baseDir);
return {
pending: Object.values(state.pendingById).toSorted((a, b) => b.ts - a.ts),
paired: Object.values(state.pairedByDeviceId).toSorted((a, b) => b.approvedAtMs - a.approvedAtMs)
};
}
async function approveDevicePairing(requestId, baseDir) {
return await withLock(async () => {
const state = await loadState(baseDir);
const pending = state.pendingById[requestId];
if (!pending) return null;
const now = Date.now();
const existing = state.pairedByDeviceId[pending.deviceId];
const roles = mergeRoles(existing?.roles, existing?.role, pending.roles, pending.role);
const approvedScopes = mergeScopes(existing?.approvedScopes ?? existing?.scopes, pending.scopes);
const tokens = existing?.tokens ? { ...existing.tokens } : {};
const roleForToken = normalizeRole(pending.role);
if (roleForToken) {
const nextScopes = normalizeDeviceAuthScopes(pending.scopes);
const existingToken = tokens[roleForToken];
const now = Date.now();
tokens[roleForToken] = {
token: newToken(),
role: roleForToken,
scopes: nextScopes,
createdAtMs: existingToken?.createdAtMs ?? now,
rotatedAtMs: existingToken ? now : void 0,
revokedAtMs: void 0,
lastUsedAtMs: existingToken?.lastUsedAtMs
};
}
const device = {
deviceId: pending.deviceId,
publicKey: pending.publicKey,
displayName: pending.displayName,
platform: pending.platform,
clientId: pending.clientId,
clientMode: pending.clientMode,
role: pending.role,
roles,
scopes: approvedScopes,
approvedScopes,
remoteIp: pending.remoteIp,
tokens,
createdAtMs: existing?.createdAtMs ?? now,
approvedAtMs: now
};
delete state.pendingById[requestId];
state.pairedByDeviceId[device.deviceId] = device;
await persistState(state, baseDir);
return {
requestId,
device
};
});
}
async function rejectDevicePairing(requestId, baseDir) {
return await withLock(async () => {
const state = await loadState(baseDir);
const pending = state.pendingById[requestId];
if (!pending) return null;
delete state.pendingById[requestId];
await persistState(state, baseDir);
return {
requestId,
deviceId: pending.deviceId
};
});
}
async function clearDevicePairing(deviceId, baseDir) {
return await withLock(async () => {
const state = await loadState(baseDir);
const normalizedId = normalizeDeviceId(deviceId);
if (!state.pairedByDeviceId[normalizedId]) return false;
delete state.pairedByDeviceId[normalizedId];
await persistState(state, baseDir);
return true;
});
}
//#endregion
//#region src/infra/map-size.ts
function pruneMapToMaxSize(map, maxSize) {
const limit = Math.max(0, Math.floor(maxSize));
if (limit <= 0) {
map.clear();
return;
}
while (map.size > limit) {
const oldest = map.keys().next();
if (oldest.done) break;
map.delete(oldest.value);
}
}
//#endregion
//#region src/infra/dedupe.ts
function createDedupeCache(options) {
const ttlMs = Math.max(0, options.ttlMs);
const maxSize = Math.max(0, Math.floor(options.maxSize));
const cache = /* @__PURE__ */ new Map();
const touch = (key, now) => {
cache.delete(key);
cache.set(key, now);
};
const prune = (now) => {
const cutoff = ttlMs > 0 ? now - ttlMs : void 0;
if (cutoff !== void 0) {
for (const [entryKey, entryTs] of cache) if (entryTs < cutoff) cache.delete(entryKey);
}
if (maxSize <= 0) {
cache.clear();
return;
}
pruneMapToMaxSize(cache, maxSize);
};
return {
check: (key, now = Date.now()) => {
if (!key) return false;
const existing = cache.get(key);
if (existing !== void 0 && (ttlMs <= 0 || now - existing < ttlMs)) {
touch(key, now);
return true;
}
touch(key, now);
prune(now);
return false;
},
clear: () => {
cache.clear();
},
size: () => cache.size
};
}
//#endregion
//#region src/infra/http-body.ts
const DEFAULT_WEBHOOK_MAX_BODY_BYTES = 1024 * 1024;
const DEFAULT_WEBHOOK_BODY_TIMEOUT_MS = 3e4;
const DEFAULT_ERROR_MESSAGE = {
PAYLOAD_TOO_LARGE: "PayloadTooLarge",
REQUEST_BODY_TIMEOUT: "RequestBodyTimeout",
CONNECTION_CLOSED: "RequestBodyConnectionClosed"
};
const DEFAULT_ERROR_STATUS_CODE = {
PAYLOAD_TOO_LARGE: 413,
REQUEST_BODY_TIMEOUT: 408,
CONNECTION_CLOSED: 400
};
const DEFAULT_RESPONSE_MESSAGE = {
PAYLOAD_TOO_LARGE: "Payload too large",
REQUEST_BODY_TIMEOUT: "Request body timeout",
CONNECTION_CLOSED: "Connection closed"
};
var RequestBodyLimitError = class extends Error {
constructor(init) {
super(init.message ?? DEFAULT_ERROR_MESSAGE[init.code]);
this.name = "RequestBodyLimitError";
this.code = init.code;
this.statusCode = DEFAULT_ERROR_STATUS_CODE[init.code];
}
};
function isRequestBodyLimitError(error, code) {
if (!(error instanceof RequestBodyLimitError)) return false;
if (!code) return true;
return error.code === code;
}
function requestBodyErrorToText(code) {
return DEFAULT_RESPONSE_MESSAGE[code];
}
function parseContentLengthHeader(req) {
const header = req.headers["content-length"];
const raw = Array.isArray(header) ? header[0] : header;
if (typeof raw !== "string") return null;
const parsed = Number.parseInt(raw, 10);
if (!Number.isFinite(parsed) || parsed < 0) return null;
return parsed;
}
async function readRequestBodyWithLimit(req, options) {
const maxBytes = Number.isFinite(options.maxBytes) ? Math.max(1, Math.floor(options.maxBytes)) : 1;
const timeoutMs = typeof options.timeoutMs === "number" && Number.isFinite(options.timeoutMs) ? Math.max(1, Math.floor(options.timeoutMs)) : DEFAULT_WEBHOOK_BODY_TIMEOUT_MS;
const encoding = options.encoding ?? "utf-8";
const declaredLength = parseContentLengthHeader(req);
if (declaredLength !== null && declaredLength > maxBytes) {
const error = new RequestBodyLimitError({ code: "PAYLOAD_TOO_LARGE" });
if (!req.destroyed) req.destroy();
throw error;
}
return await new Promise((resolve, reject) => {
let done = false;
let ended = false;
let totalBytes = 0;
const chunks = [];
const cleanup = () => {
req.removeListener("data", onData);
req.removeListener("end", onEnd);
req.removeListener("error", onError);
req.removeListener("close", onClose);
clearTimeout(timer);
};
const finish = (cb) => {
if (done) return;
done = true;
cleanup();
cb();
};
const fail = (error) => {
finish(() => reject(error));
};
const timer = setTimeout(() => {
const error = new RequestBodyLimitError({ code: "REQUEST_BODY_TIMEOUT" });
if (!req.destroyed) req.destroy();
fail(error);
}, timeoutMs);
const onData = (chunk) => {
if (done) return;
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
totalBytes += buffer.length;
if (totalBytes > maxBytes) {
const error = new RequestBodyLimitError({ code: "PAYLOAD_TOO_LARGE" });
if (!req.destroyed) req.destroy();
fail(error);
return;
}
chunks.push(buffer);
};
const onEnd = () => {
ended = true;
finish(() => resolve(Buffer.concat(chunks).toString(encoding)));
};
const onError = (error) => {
if (done) return;
fail(error);
};
const onClose = () => {
if (done || ended) return;
fail(new RequestBodyLimitError({ code: "CONNECTION_CLOSED" }));
};
req.on("data", onData);
req.on("end", onEnd);
req.on("error", onError);
req.on("close", onClose);
});
}
async function readJsonBodyWithLimit(req, options) {
try {
const trimmed = (await readRequestBodyWithLimit(req, options)).trim();
if (!trimmed) {
if (options.emptyObjectOnEmpty === false) return {
ok: false,
code: "INVALID_JSON",
error: "empty payload"
};
return {
ok: true,
value: {}
};
}
try {
return {
ok: true,
value: JSON.parse(trimmed)
};
} catch (error) {
return {
ok: false,
code: "INVALID_JSON",
error: error instanceof Error ? error.message : String(error)
};
}
} catch (error) {
if (isRequestBodyLimitError(error)) return {
ok: false,
code: error.code,
error: requestBodyErrorToText(error.code)
};
return {
ok: false,
code: "INVALID_JSON",
error: error instanceof Error ? error.message : String(error)
};
}
}
function installRequestBodyLimitGuard(req, res, options) {
const maxBytes = Number.isFinite(options.maxBytes) ? Math.max(1, Math.floor(options.maxBytes)) : 1;
const timeoutMs = typeof options.timeoutMs === "number" && Number.isFinite(options.timeoutMs) ? Math.max(1, Math.floor(options.timeoutMs)) : DEFAULT_WEBHOOK_BODY_TIMEOUT_MS;
const responseFormat = options.responseFormat ?? "json";
const customText = options.responseText ?? {};
let tripped = false;
let reason = null;
let done = false;
let ended = false;
let totalBytes = 0;
const cleanup = () => {
req.removeListener("data", onData);
req.removeListener("end", onEnd);
req.removeListener("close", onClose);
req.removeListener("error", onError);
clearTimeout(timer);
};
const finish = () => {
if (done) return;
done = true;
cleanup();
};
const respond = (error) => {
const text = customText[error.code] ?? requestBodyErrorToText(error.code);
if (!res.headersSent) {
res.statusCode = error.statusCode;
if (responseFormat === "text") {
res.setHeader("Content-Type", "text/plain; charset=utf-8");
res.end(text);
} else {
res.setHeader("Content-Type", "application/json; charset=utf-8");
res.end(JSON.stringify({ error: text }));
}
}
};
const trip = (error) => {
if (tripped) return;
tripped = true;
reason = error.code;
finish();
respond(error);
if (!req.destroyed) req.destroy();
};
const onData = (chunk) => {
if (done) return;
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
totalBytes += buffer.length;
if (totalBytes > maxBytes) trip(new RequestBodyLimitError({ code: "PAYLOAD_TOO_LARGE" }));
};
const onEnd = () => {
ended = true;
finish();
};
const onClose = () => {
if (done || ended) return;
finish();
};
const onError = () => {
finish();
};
const timer = setTimeout(() => {
trip(new RequestBodyLimitError({ code: "REQUEST_BODY_TIMEOUT" }));
}, timeoutMs);
req.on("data", onData);
req.on("end", onEnd);
req.on("close", onClose);
req.on("error", onError);
const declaredLength = parseContentLengthHeader(req);
if (declaredLength !== null && declaredLength > maxBytes) trip(new RequestBodyLimitError({ code: "PAYLOAD_TOO_LARGE" }));
return {
dispose: finish,
isTripped: () => tripped,
code: () => reason
};
}
//#endregion
//#region src/infra/wsl.ts
function isWSLEnv() {
if (process.env.WSL_INTEROP || process.env.WSL_DISTRO_NAME || process.env.WSLENV) return true;
return false;
}
/**
* Synchronously check if running in WSL.
* Checks env vars first, then /proc/version.
*/
function isWSLSync() {
if (process.platform !== "linux") return false;
if (isWSLEnv()) return true;
try {
const release = readFileSync("/proc/version", "utf8").toLowerCase();
return release.includes("microsoft") || release.includes("wsl");
} catch {
return false;
}
}
/**
* Synchronously check if running in WSL2.
*/
function isWSL2Sync() {
if (!isWSLSync()) return false;
try {
const version = readFileSync("/proc/version", "utf8").toLowerCase();
return version.includes("wsl2") || version.includes("microsoft-standard");
} catch {
return false;
}
}
//#endregion
//#region src/channels/allowlist-match.ts
function formatAllowlistMatchMeta(match) {
return `matchKey=${match?.matchKey ?? "none"} matchSource=${match?.matchSource ?? "none"}`;
}
function resolveAllowlistMatchSimple(params) {
const allowFrom = params.allowFrom.map((entry) => String(entry).trim().toLowerCase()).filter(Boolean);
if (allowFrom.length === 0) return { allowed: false };
if (allowFrom.includes("*")) return {
allowed: true,
matchKey: "*",
matchSource: "wildcard"
};
const senderId = params.senderId.toLowerCase();
if (allowFrom.includes(senderId)) return {
allowed: true,
matchKey: senderId,
matchSource: "id"
};
const senderName = params.senderName?.toLowerCase();
if (senderName && allowFrom.includes(senderName)) return {
allowed: true,
matchKey: senderName,
matchSource: "name"
};
return { allowed: false };
}
//#endregion
//#region src/auto-reply/reply/mentions.ts
function deriveMentionPatterns(identity) {
const patterns = [];
const name = identity?.name?.trim();
if (name) {
const parts = name.split(/\s+/).filter(Boolean).map(escapeRegExp);
const re = parts.length ? parts.join(String.raw`\s+`) : escapeRegExp(name);
patterns.push(String.raw`\b@?${re}\b`);
}
const emoji = identity?.emoji?.trim();
if (emoji) patterns.push(escapeRegExp(emoji));
return patterns;
}
const BACKSPACE_CHAR = "\b";
const CURRENT_MESSAGE_MARKER = "[Current message - respond to this]";
function normalizeMentionPattern(pattern) {
if (!pattern.includes(BACKSPACE_CHAR)) return pattern;
return pattern.split(BACKSPACE_CHAR).join("\\b");
}
function normalizeMentionPatterns(patterns) {
return patterns.map(normalizeMentionPattern);
}
function resolveMentionPatterns(cfg, agentId) {
if (!cfg) return [];
const agentConfig = agentId ? resolveAgentConfig(cfg, agentId) : void 0;
const agentGroupChat = agentConfig?.groupChat;
if (agentGroupChat && Object.hasOwn(agentGroupChat, "mentionPatterns")) return agentGroupChat.mentionPatterns ?? [];
const globalGroupChat = cfg.messages?.groupChat;
if (globalGroupChat && Object.hasOwn(globalGroupChat, "mentionPatterns")) return globalGroupChat.mentionPatterns ?? [];
const derived = deriveMentionPatterns(agentConfig?.identity);
return derived.length > 0 ? derived : [];
}
function buildMentionRegexes(cfg, agentId) {
return normalizeMentionPatterns(resolveMentionPatterns(cfg, agentId)).map((pattern) => {
try {
return new RegExp(pattern, "i");
} catch {
return null;
}
}).filter((value) => Boolean(value));
}
function normalizeMentionText(text) {
return (text ?? "").replace(/[\u200b-\u200f\u202a-\u202e\u2060-\u206f]/g, "").toLowerCase();
}
function matchesMentionPatterns(text, mentionRegexes) {
if (mentionRegexes.length === 0) return false;
const cleaned = normalizeMentionText(text ?? "");
if (!cleaned) return false;
return mentionRegexes.some((re) => re.test(cleaned));
}
function matchesMentionWithExplicit(params) {
const cleaned = normalizeMentionText(params.text ?? "");
const explicit = params.explicit?.isExplicitlyMentioned === true;
const explicitAvailable = params.explicit?.canResolveExplicit === true;
const hasAnyMention = params.explicit?.hasAnyMention === true;
const transcriptCleaned = params.transcript ? normalizeMentionText(params.transcript) : "";
const textToCheck = cleaned || transcriptCleaned;
if (hasAnyMention && explicitAvailable) return explicit || params.mentionRegexes.some((re) => re.test(textToCheck));
if (!textToCheck) return explicit;
return explicit || params.mentionRegexes.some((re) => re.test(textToCheck));
}
function stripStructuralPrefixes(text) {
return (text.includes(CURRENT_MESSAGE_MARKER) ? text.slice(text.indexOf(CURRENT_MESSAGE_MARKER) + 35).trimStart() : text).replace(/\[[^\]]+\]\s*/g, "").replace(/^[ \t]*[A-Za-z0-9+()\-_. ]+:\s*/gm, "").replace(/\\n/g, " ").replace(/\s+/g, " ").trim();
}
function stripMentions(text, ctx, cfg, agentId) {
let result = text;
const providerId = ctx.Provider ? normalizeChannelId$1(ctx.Provider) : null;
const providerMentions = providerId ? getChannelDock(providerId)?.mentions : void 0;
const patterns = normalizeMentionPatterns([...resolveMentionPatterns(cfg, agentId), ...providerMentions?.stripPatterns?.({
ctx,
cfg,
agentId
}) ?? []]);
for (const p of patterns) try {
const re = new RegExp(p, "gi");
result = result.replace(re, " ");
} catch {}
if (providerMentions?.stripMentions) result = providerMentions.stripMentions({
text: result,
ctx,
cfg,
agentId
});
result = result.replace(/@[0-9+]{5,}/g, " ");
return result.replace(/\s+/g, " ").trim();
}
//#endregion
//#region src/auto-reply/reply/history.ts
const HISTORY_CONTEXT_MARKER = "[Chat messages since your last reply - for context]";
const DEFAULT_GROUP_HISTORY_LIMIT = 50;
/** Maximum number of group history keys to retain (LRU eviction when exceeded). */
const MAX_HISTORY_KEYS = 1e3;
/**
* Evict oldest keys from a history map when it exceeds MAX_HISTORY_KEYS.
* Uses Map's insertion order for LRU-like behavior.
*/
function evictOldHistoryKeys(historyMap, maxKeys = MAX_HISTORY_KEYS) {
if (historyMap.size <= maxKeys) return;
const keysToDelete = historyMap.size - maxKeys;
const iterator = historyMap.keys();
for (let i = 0; i < keysToDelete; i++) {
const key = iterator.next().value;
if (key !== void 0) historyMap.delete(key);
}
}
function buildHistoryContext(params) {
const { historyText, currentMessage } = params;
const lineBreak = params.lineBreak ?? "\n";
if (!historyText.trim()) return currentMessage;
return [
HISTORY_CONTEXT_MARKER,
historyText,
"",
CURRENT_MESSAGE_MARKER,
currentMessage
].join(lineBreak);
}
function appendHistoryEntry(params) {
const { historyMap, historyKey, entry } = params;
if (params.limit <= 0) return [];
const history = historyMap.get(historyKey) ?? [];
history.push(entry);
while (history.length > params.limit) history.shift();
if (historyMap.has(historyKey)) historyMap.delete(historyKey);
historyMap.set(historyKey, history);
evictOldHistoryKeys(historyMap);
return history;
}
function recordPendingHistoryEntry(params) {
return appendHistoryEntry(params);
}
function recordPendingHistoryEntryIfEnabled(params) {
if (!params.entry) return [];
if (params.limit <= 0) return [];
return recordPendingHistoryEntry({
historyMap: params.historyMap,
historyKey: params.historyKey,
entry: params.entry,
limit: params.limit
});
}
function buildPendingHistoryContextFromMap(params) {
if (params.limit <= 0) return params.currentMessage;
return buildHistoryContextFromEntries({
entries: params.historyMap.get(params.historyKey) ?? [],
currentMessage: params.currentMessage,
formatEntry: params.formatEntry,
lineBreak: params.lineBreak,
excludeLast: false
});
}
function clearHistoryEntries(params) {
params.historyMap.set(params.historyKey, []);
}
function clearHistoryEntriesIfEnabled(params) {
if (params.limit <= 0) return;
clearHistoryEntries({
historyMap: params.historyMap,
historyKey: params.historyKey
});
}
function buildHistoryContextFromEntries(params) {
const lineBreak = params.lineBreak ?? "\n";
const entries = params.excludeLast === false ? params.entries : params.entries.slice(0, -1);
if (entries.length === 0) return params.currentMessage;
return buildHistoryContext({
historyText: entries.map(params.formatEntry).join(lineBreak),
currentMessage: params.currentMessage,
lineBreak
});
}
//#endregion
//#region src/channels/allowlists/resolve-utils.ts
function mergeAllowlist(params) {
const seen = /* @__PURE__ */ new Set();
const merged = [];
const push = (value) => {
const normalized = value.trim();
if (!normalized) return;
const key = normalized.toLowerCase();
if (seen.has(key)) return;
seen.add(key);
merged.push(normalized);
};
for (const entry of params.existing ?? []) push(String(entry));
for (const entry of params.additions) push(entry);
return merged;
}
function buildAllowlistResolutionSummary(resolvedUsers, opts) {
const resolvedMap = new Map(resolvedUsers.map((entry) => [entry.input, entry]));
const resolvedOk = (entry) => Boolean(entry.resolved && entry.id);
const formatResolved = opts?.formatResolved ?? ((entry) => `${entry.input}→${entry.id}`);
const mapping = resolvedUsers.filter(resolvedOk).map(formatRe