UNPKG

@gguf/claw

Version:

Multi-channel AI gateway with extensible messaging integrations

838 lines (825 loc) 2.48 MB
import { t as __exportAll } from "./rolldown-runtime-Cbj13DAv.js"; import { g as resolveStateDir, r as STATE_DIR, u as resolveGatewayPort, y as resolveRequiredHomeDir } from "./paths-B4BZAPZh.js"; import { B as theme, C as sleep$1, D as isPlainObject, E as truncateUtf16Safe, F as shouldLogVerbose, J as normalizeLogLevel, L as warn, M as logVerbose, O as danger, S as shortenHomePath, V as getChildLogger, X as resolvePreferredOpenClawTmpDir, d as isRecord$1, i as clampInt, l as escapeRegExp, m as normalizeE164, t as CONFIG_DIR, w as sliceUtf16Safe, x as shortenHomeInString, y as resolveUserPath } from "./utils-CP9YLh6M.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-EAliFiVK.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, v as isCronRunSessionKey, x as parseAgentSessionKey, y as isCronSessionKey } from "./session-key-CZ6OwgSB.js"; import { t as resolveOpenClawPackageRoot } from "./openclaw-root-BM-yQZH6.js"; import { C as createInternalHookEvent, T as triggerInternalHook, _ as clearPluginCommands, b as listPluginCommands, c as normalizeAnyChannelId, f as requireActivePluginRegistry, g as normalizePluginHttpPath, h as createPluginRegistry, l as normalizeChannelId, n as CHAT_CHANNEL_ORDER, p as setActivePluginRegistry, r as DEFAULT_CHAT_CHANNEL, v as executePluginCommand, x as matchPluginCommand, y as getPluginCommandSpecs } from "./registry-B-j4DRfe.js"; import { d as createNonExitingRuntime, f as defaultRuntime, t as createSubsystemLogger } from "./subsystem-BCQGGxdd.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-DYqRzFbo.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-BnZW9Gh2.js"; import { $ as resolveShellEnvFallbackTimeoutMs, Bt as resolveAuthProfileDisplayLabel, Ct as dedupeProfileIds, Ft as withFileLock, G as requireApiKey, Gt as DEFAULT_PROVIDER, H as createOllamaStreamFn, J as resolveEnvApiKey, K as resolveApiKeyForProvider, Nt as resolveAuthStorePathForDisplay, Pt as resolveOpenClawAgentDir, Tt as markAuthProfileGood, U as getApiKeyForModel, Ut as DEFAULT_CONTEXT_TOKENS, V as OLLAMA_NATIVE_BASE_URL, W as getCustomProviderApiKey, Wt as DEFAULT_MODEL, Y as resolveModelAuthMode, Z as getShellPathFromLoginShell, _t as resolveApiKeyForProfile, c as normalizeModelRef$2, dt as resolveAuthProfileOrder, ft as getSoonestCooldownExpiry, g as resolveModelRefFromString, ht as markAuthProfileUsed, i as findNormalizedProviderValue, kt as ensureAuthProfileStore, l as normalizeProviderId, m as resolveDefaultModelForAgent, mt as markAuthProfileFailure, n as buildConfiguredAllowlistKeys, o as isCliProvider, p as resolveConfiguredModelRef, pt as isProfileInCooldown, r as buildModelAliasIndex, s as modelKey, t as buildAllowedModelSet, u as parseModelRef, v as resolveSubagentSpawnModelSelection, wt as listProfilesForProvider, y as resolveThinkingDefault, zt as normalizeSecretInput } from "./model-selection-CqaTAlhy.js"; import { a as saveJsonFile, i as loadJsonFile } from "./github-copilot-token-D2zp6kMZ.js"; import { t as formatCliCommand } from "./command-format-DEKzLnLg.js"; import { t as parseBooleanValue$1 } from "./boolean-BsqeuxE6.js"; import { t as isTruthyEnvValue } from "./env-VriqyjXT.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-Bena1Tzd.js"; import { $ as resolveDiscordChannelId, 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 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-CsyONLnQ.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-PQiujvsf.js"; import { a as isPathInsideWithRealpath } from "./legacy-names-DyDKpCnk.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-4k4vkhPS.js"; import { t as normalizeChatType } from "./chat-type-DyovJwCt.js"; import { n as resolveConversationLabel } from "./conversation-label-Bn5j3lUT.js"; import { r as normalizeInboundTextNewlines, t as finalizeInboundContext } from "./inbound-context-CmmmT8IP.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-U04aiHHC.js"; import { _ as stripThinkingTagsFromText, a as decodeDataUrl, b as minimaxUnderstandImage, 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 stripReasoningTagsFromText, y as extractTextFromChatContent } from "./image-DxEpBZim.js"; import { t as ensureOpenClawModelsJson } from "./models-config-B459BnCS.js"; import { n as discoverModels, t as discoverAuthStorage } from "./pi-model-discovery-4uUnLc3n.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-BdscQhyS.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-UAzvS0V6.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-CI1VknD1.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-a25M2Kvi.js"; import { T as DEFAULT_AI_SNAPSHOT_MAX_CHARS } from "./chrome-Dd5zBIFu.js"; import { i as resolveBrowserConfig, m as resolveBrowserControlAuth } from "./server-context-DAWsUNUs.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-CLmzWt48.js"; import { n as formatErrorMessage, r as formatUncaughtError } from "./errors-kfGqPQ4b.js"; import { i as resolveExistingPathsWithinRoot, r as DEFAULT_UPLOAD_DIR } from "./paths-D1WZUYry.js"; import { i as isBlockedHostnameOrIp, o as normalizeHostname, t as SsrFBlockedError } from "./ssrf-6f5m2MMA.js"; import { n as getMediaDir, r as saveMediaBuffer } from "./store-DSGYY-H9.js"; import { A as resolveSessionKey, B as resolveExplicitAgentSessionKey, F as resolveThreadFlag, G as buildGroupDisplayName, I as DEFAULT_RESET_TRIGGERS, K as resolveGroupSessionKey, L as resolveFreshSessionTotalTokens, M as resolveChannelResetConfig, N as resolveSessionResetPolicy, P as resolveSessionResetType, R as canonicalizeMainSessionAlias, S as capArrayByJsonBytes, T as readSessionTitleFieldsFromTranscript, U as deriveSessionMetaPatch, V as resolveMainSessionKey, Y as resolveSessionLockMaxHoldFromTimeout, _ as normalizeDeliveryContext, a as loadSessionStore, d as updateSessionStoreEntry, f as isCacheEnabled, g as mergeDeliveryContext, h as deliveryContextKey, j as evaluateSessionFreshness, l as updateLastRoute, m as deliveryContextFromSession, o as readSessionUpdatedAt, p as resolveCacheTtlMs$1, q as acquireSessionWriteLock, r as appendAssistantMessageToSessionTranscript, s as recordSessionMetaFromInbound, t as extractDeliveryInfo, u as updateSessionStore, v as normalizeSessionDeliveryFields, x as archiveSessionTranscripts, y as normalizeAccountId$4, z as resolveAgentMainSessionKey } from "./sessions-Z1BZU3xh.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-7F-MiPtF.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-Ci8UyR3Z.js"; import { a as logWebSelfId, i as getWebAuthAgeMs, m as webAuthExists, n as resolveWhatsAppAccount, o as logoutWeb, u as readWebSelfId } from "./accounts-Bj1dJ-fd.js"; import { t as resolveIMessageAccount } from "./accounts-DOl1Wkxo.js"; import { n as resolveSignalAccount, t as listEnabledSignalAccounts } from "./accounts-t6R5_PzC.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-uu2Jc-Js.js"; import { n as listChannelPlugins, r as normalizeChannelId$1, t as getChannelPlugin } from "./plugins-CKbXkuXd.js"; import { c as resolveStorePath, i as resolveSessionTranscriptPath, n as resolveSessionFilePath, r as resolveSessionFilePathOptions, t as resolveDefaultSessionStorePath } from "./paths-C2NfoGZE.js"; import { i as normalizeInputProvenance, n as applyInputProvenanceToUserMessage, r as hasInterSessionUserProvenance } from "./input-provenance-DkoU-lPU.js"; import { t as emitSessionTranscriptUpdate } from "./transcript-events-BwQWL-Af.js"; import { n as resolveToolDisplay } from "./tool-display-Bx4M6uNT.js"; import { n as fetchWithTimeout, t as bindAbortRelay } from "./fetch-timeout-DoySHqfO.js"; import { t as fetchWithSsrFGuard } from "./fetch-guard-C1sYsWgl.js"; import { a as readResponseWithLimit, i as fetchRemoteMedia, n as getDefaultMediaLocalRoots, t as getAgentScopedMediaLocalRoots } from "./local-roots-DiDvXIIo.js"; import { v as runTasksWithConcurrency } from "./sqlite-JcMMx8Z5.js"; import { n as loadModelCatalog, r as modelSupportsVision, t as findModelInCatalog } from "./model-catalog-CIixTnGt.js"; import { n as SILENT_REPLY_TOKEN, r as isSilentReplyText, t as HEARTBEAT_TOKEN } from "./tokens-D4lZk7-h.js"; import { n as createBrowserRouteDispatcher, r as getMachineDisplayName, t as withTimeout$4 } from "./with-timeout-DijiQjw6.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-DgvS3uCz.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-UUwku4RV.js"; import { r as getDiagnosticSessionState } from "./diagnostic-session-state-ByqoIyGn.js"; import { A as hasBotMention, B as resolveSenderAllowMatch, C as buildTelegramGroupPeerId, D as describeReplyTarget, E as buildTypingThreadParams, F as resolveTelegramReplyId, G as toLocationContext, H as isSenderIdAllowed, I as resolveTelegramStreamMode, J as parseTelegramTarget, K as withTelegramApiErrorLogging, L as resolveTelegramThreadSpec, M as resolveTelegramForumThreadId, N as resolveTelegramGroupAllowFromContext, O as expandTextLinks, P as resolveTelegramMediaPlaceholder, R as isSenderAllowed$1, S as buildTelegramGroupFrom, T as buildTelegramThreadParams, U as mergeAllowFromSources, V as firstDefined$1, W as formatLocationText, Y as resolveTelegramTargetChatType, _ as resolveTelegramFetch, a as reactMessageTelegram, b as buildSenderLabel, c as sendStickerTelegram, d as wasSentByBot, f as isRecoverableTelegramNetworkError, g as wrapFileReferencesInHtml, h as renderTelegramHtmlText, i as editMessageTelegram, j as normalizeForwardedContext, k as extractTelegramLocation, 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 buildTelegramParentPeer, x as buildSenderName, y as buildGroupLabel, z as normalizeAllowFromWithStore$1 } from "./send-DbwyyQAv.js"; import { a as buildModelAliasLines, n as resolveModel } from "./model-VbWjwqaW.js"; import { i as resolveAckReaction, o as resolveEffectiveMessagesConfig, r as resolveResponsePrefixTemplate, s as resolveHumanDelayConfig, t as createReplyPrefixOptions } from "./reply-prefix-DAK7-zK4.js"; import { i as resolveMemoryBackendConfig, n as registerMemoryCli, r as getMemorySearchManager } from "./memory-cli-DxmtLhh_.js"; import { n as resolveMemorySearchConfig } from "./manager-C0teWocQ.js"; import { n as retryAsync } from "./retry-rUEdE6zT.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-CMylpCPi.js"; import { n as resolveMarkdownTableMode } from "./markdown-tables-B9VGUdDc.js"; import { a as loadWebMedia, i as getDefaultLocalRoots } from "./ir-24qCLTKH.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-bb_U-3FM.js"; import { Mt as SESSION_LABEL_MAX_LENGTH, t as GatewayClient } from "./client-BdSkEtCd.js"; import { a as randomIdempotencyKey, d as resolveLeastPrivilegeOperatorScopesForMethod, n as callGateway, r as callGatewayLeastPrivilege, t as buildGatewayConnectionDetails } from "./call-BCz_8mqq.js"; import { n as formatTimeAgo } from "./format-relative-DdvuDKIv.js"; import { n as normalizePollInput } from "./polls-CdvQ578Y.js"; import { n as recordChannelActivity, r as createDiscordRetryRunner, t as getChannelActivity } from "./channel-activity-DynIQUB_.js"; import { n as wrapFetchWithAbortSignal, t as resolveFetch } from "./fetch-Bu5zBCce.js"; import { t as convertMarkdownTables } from "./tables-C70h_80U.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-CAfFUUkm.js"; import { i as readChannelAllowFromStore, l as listPairingChannels, o as removeChannelAllowFromStoreEntry, s as upsertChannelPairingRequest, t as addChannelAllowFromStoreEntry } from "./pairing-store-T5DpOfoL.js"; import { t as makeProxyFetch } from "./proxy-BiOWrea2.js"; import { i as formatDurationSeconds, r as formatDurationPrecise, t as formatDurationCompact$1 } from "./format-duration-pIcWg99c.js"; import { n as resolveAgentRoute, t as buildAgentSessionKey } from "./resolve-route-2TU_aaLs.js"; import { a as createReplyReferencePlanner, i as resolveSlackThreadTs, n as deliverReplies$3, t as createSlackReplyDeliveryPlan } from "./replies-NhrZJ3yf.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-N8Sho46-.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-DTy1DnPK.js"; import { c as hasNonzeroUsage, l as normalizeUsage, n as loadCostUsageSummary, o as derivePromptTokens, r as loadSessionCostSummary, s as deriveSessionTotalTokens } from "./session-cost-usage-BlUDaylg.js"; import { a as normalizeIMessageHandle, c as DEFAULT_IMESSAGE_PROBE_TIMEOUT_MS, i as isAllowedIMessageSender, o as parseIMessageTarget, r as formatIMessageChatTarget, s as createIMessageRpcClient, t as sendMessageIMessage } from "./send-4LoRaltQ.js"; import { r as detectBinary } from "./onboard-helpers-DbjfBSMX.js"; import { t as resolvePairingIdLabel } from "./pairing-labels-DaESq9ML.js"; import { i as resolveModelCostConfig, n as formatTokenCount$2, r as formatUsd, t as estimateUsageCost } from "./usage-format-BzKEDn0q.js"; import { t as getActiveWebListener } from "./active-listener-CQFe2moz.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-q0C8VDMT.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-5fMfTT2n.js"; import { n as parseNodeList, r as parsePairingList, t as resolveNodeIdFromCandidates } from "./node-match-CN8o4Vi3.js"; import { n as recordCommandPoll, r as resetCommandPollCount } from "./command-poll-backoff-BiwOFDEK.js"; import { n as createBrowserControlContext, r as startBrowserControlServiceFromConfig } from "./control-service-BoO2TGOx.js"; import { i as parseAbsoluteTimeMs, r as resolveDefaultCronStaggerMs, t as normalizeCronStaggerMs } from "./stagger-B6VQyn1F.js"; import { c as resolveGatewayLaunchAgentLabel, d as resolveGatewaySystemdServiceName } from "./constants-CEbQvI8z.js"; import { n as resolveMessageChannelSelection, t as listConfiguredMessageChannels } from "./channel-selection-DuDSoVSC.js"; import { t as parseTimeoutMs } from "./parse-timeout-UOA56UND.js"; import { createRequire } from "node:module"; import { fileURLToPath } from "node:url"; import fs, { existsSync, mkdirSync, mkdtempSync, readFileSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync } from "node:fs"; import os, { homedir } from "node:os"; import path from "node:path"; import JSON5 from "json5"; import fs$1 from "node:fs/promises"; import { execFileSync, spawn, spawnSync } from "node:child_process"; import { inspect } from "node:util"; import crypto, { randomBytes, randomUUID } from "node:crypto"; import { complete, completeSimple, streamSimple } from "@mariozechner/pi-ai"; import { CURRENT_SESSION_VERSION, DefaultResourceLoader, SessionManager, SettingsManager, codingTools, createAgentSession, createEditTool, createReadTool, createWriteTool, estimateTokens, generateSummary, readTool } from "@mariozechner/pi-coding-agent"; import { createServer } from "node:http"; import { ProxyAgent, fetch as fetch$1 } from "undici"; import WebSocket from "ws"; import { Buffer as Buffer$1 } from "node:buffer"; import { EdgeTTS } from "node-edge-tts"; import { createJiti } from "jiti"; import { Type } from "@sinclair/typebox"; 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 { 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/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/exec/directive.ts function normalizeExecHost$1(value) { const normalized = value?.trim().toLowerCase(); if (normalized === "sandbox" || normalized === "gateway" || normalized === "node") return normalized; } function normalizeExecSecurity$1(value) { const normalized = value?.trim().toLowerCase(); if (normalized === "deny" || normalized === "allowlist" || normalized === "full") return normalized; } function normalizeExecAsk$1(value) { const normalized = value?.trim().toLowerCase(); if (normalized === "off" || normalized === "on-miss" || normalized === "always") return normalized; } function parseExecDirectiveArgs(raw) { const len = raw.length; let i = skipDirectiveArgPrefix(raw); let consumed = i; let execHost; let execSecurity; let execAsk; let execNode; let rawExecHost; let rawExecSecurity; let rawExecAsk; let rawExecNode; let hasExecOptions = false; let invalidHost = false; let invalidSecurity = false; let invalidAsk = false; let invalidNode = false; const takeToken = () => { const res = takeDirectiveToken(raw, i); i = res.nextIndex; return res.token; }; const splitToken = (token) => { const eq = token.indexOf("="); const colon = token.indexOf(":"); const idx = eq === -1 ? colon : colon === -1 ? eq : Math.min(eq, colon); if (idx === -1) return null; const key = token.slice(0, idx).trim().toLowerCase(); const value = token.slice(idx + 1).trim(); if (!key) return null; return { key, value }; }; while (i < len) { const token = takeToken(); if (!token) break; const parsed = splitToken(token); if (!parsed) break; const { key, value } = parsed; if (key === "host") { rawExecHost = value; execHost = normalizeExecHost$1(value); if (!execHost) invalidHost = true; hasExecOptions = true; consumed = i; continue; } if (key === "security") { rawExecSecurity = value; execSecurity = normalizeExecSecurity$1(value); if (!execSecurity) invalidSecurity = true; hasExecOptions = true; consumed = i; continue; } if (key === "ask") { rawExecAsk = value; execAsk = normalizeExecAsk$1(value); if (!execAsk) invalidAsk = true; hasExecOptions = true; consumed = i; continue; } if (key === "node") { rawExecNode = value; const trimmed = value.trim(); if (!trimmed) invalidNode = true; else execNode = trimmed; hasExecOptions = true; consumed = i; continue; } break; } return { consumed, execHost, execSecurity, execAsk, execNode, rawExecHost, rawExecSecurity, rawExecAsk, rawExecNode, hasExecOptions, invalidHost, invalidSecurity, invalidAsk, invalidNode }; } function extractExecDirective(body) { if (!body) return { cleaned: "", hasDirective: false, hasExecOptions: false, invalidHost: false, invalidSecurity: false, invalidAsk: false, invalidNode: false }; const match = /(?:^|\s)\/exec(?=$|\s|:)/i.exec(body); if (!match) return { cleaned: body.trim(), hasDirective: false, hasExecOptions: false, invalidHost: false, invalidSecurity: false, invalidAsk: false, invalidNode: false }; const start = match.index + match[0].indexOf("/exec"); const argsStart = start + 5; const parsed = parseExecDirectiveArgs(body.slice(argsStart)); return { cleaned: `${body.slice(0, start)} ${body.slice(argsStart + parsed.consumed)}`.replace(/\s+/g, " ").trim(), hasDirective: true, execHost: parsed.execHost, execSecurity: parsed.execSecurity, execAsk: parsed.execAsk, execNode: parsed.execNode, rawExecHost: parsed.rawExecHost, rawExecSecurity: parsed.rawExecSecurity, rawExecAsk: parsed.rawExecAsk, rawExecNode: parsed.rawExecNode, hasExecOptions: parsed.hasExecOptions, invalidHost: parsed.invalidHost, invalidSecurity: parsed.invalidSecurity, invalidAsk: parsed.invalidAsk, invalidNode: parsed.invalidNode }; } //#endregion //#region src/auto-reply/reply/directives.ts const matchLevelDirective = (body, names) => { const namePattern = names.map(escapeRegExp).join("|"); const match = body.match(new RegExp(`(?:^|\\s)\\/(?:${namePattern})(?=$|\\s|:)`, "i")); if (!match || match.index === void 0) return null; const start = match.index; let end = match.index + match[0].length; let i = end; while (i < body.length && /\s/.test(body[i])) i += 1; if (body[i] === ":") { i += 1; while (i < body.length && /\s/.test(body[i])) i += 1; } const argStart = i; while (i < body.length && /[A-Za-z-]/.test(body[i])) i += 1; const rawLevel = i > argStart ? body.slice(argStart, i) : void 0; end = i; return { start, end, rawLevel }; }; const extractLevelDirective = (body, names, normalize) => { const match = matchLevelDirective(body, names); if (!match) return { cleaned: body.trim(), hasDirective: false }; const rawLevel = match.rawLevel; const level = normalize(rawLevel); return { cleaned: body.slice(0, match.start).concat(" ").concat(body.slice(match.end)).replace(/\s+/g, " ").trim(), level, rawLevel, hasDirective: true }; }; const extractSimpleDirective = (body, names) => { const namePattern = names.map(escapeRegExp).join("|"); const match = body.match(new RegExp(`(?:^|\\s)\\/(?:${namePattern})(?=$|\\s|:)(?:\\s*:\\s*)?`, "i")); return { cleaned: match ? body.replace(match[0], " ").replace(/\s+/g, " ").trim() : body.trim(), hasDirective: Boolean(match) }; }; function extractThinkDirective(body) { if (!body) return { cleaned: "", hasDirective: false }; const extracted = extractLevelDirective(body, [ "thinking", "think", "t" ], normalizeThinkLevel); return { cleaned: extracted.cleaned, thinkLevel: extracted.level, rawLevel: extracted.rawLevel, hasDirective: extracted.hasDirective }; } function extractVerboseDirective(body) { if (!body) return { cleaned: "", hasDirective: false }; const extracted = extractLevelDirective(body, ["verbose", "v"], normalizeVerboseLevel); return { cleaned: extracted.cleaned, verboseLevel: extracted.level, rawLevel: extracted.rawLevel, hasDirective: extracted.hasDirective }; } function extractElevatedDirective(body) { if (!body) return { cleaned: "", hasDirective: false }; const extracted = extractLevelDirective(body, ["elevated", "elev"], normalizeElevatedLevel); return { cleaned: extracted.cleaned, elevatedLevel: extracted.level, rawLevel: extracted.rawLevel, hasDirective: extracted.hasDirective }; } function extractReasoningDirective(body) { if (!body) return { cleaned: "", hasDirective: false }; const extracted = extractLevelDirective(body, ["reasoning", "reason"], normalizeReasoningLevel); return { cleaned: extracted.cleaned, reasoningLevel: extracted.level, rawLevel: extracted.rawLevel, hasDirective: extracted.hasDirective }; } function extractStatusDirective(body) { if (!body) return { cleaned: "", hasDirective: false }; return extractSimpleDirective(body, ["status"]); } //#endregion //#region src/agents/timeout.ts const DEFAULT_AGENT_TIMEOUT_SECONDS = 600; const MAX_SAFE_TIMEOUT_MS = 2147e6; const normalizeNumber = (value) => typeof value === "number" && Number.isFinite(value) ? Math.floor(value) : void 0; function resolveAgentTimeoutSeconds(cfg) { const seconds = normalizeNumber(cfg?.agents?.defaults?.timeoutSeconds) ?? DEFAULT_AGENT_TIMEOUT_SECONDS; return Math.max(seconds, 1); } function resolveAgentTimeoutMs(opts) { const minMs = Math.max(normalizeNumber(opts.minMs) ?? 1, 1); const clampTimeoutMs = (valueMs) => Math.min(Math.max(valueMs, minMs), MAX_SAFE_TIMEOUT_MS); const defaultMs = clampTimeoutMs(resolveAgentTimeoutSeconds(opts.cfg) * 1e3); const NO_TIMEOUT_MS = MAX_SAFE_TIMEOUT_MS; const overrideMs = normalizeNumber(opts.overrideMs); if (overrideMs !== void 0) { if (overrideMs === 0) return NO_TIMEOUT_MS; if (overrideMs < 0) return defaultMs; return clampTimeoutMs(overrideMs); } const overrideSeconds = normalizeNumber(opts.overrideSeconds); if (overrideSeconds !== void 0) { if (overrideSeconds === 0) return NO_TIMEOUT_MS; if (overrideSeconds < 0) return defaultMs; return clampTimeoutMs(overrideSeconds * 1e3); } return defaultMs; } //#endregion //#region src/channels/model-overrides.ts const THREAD_SUFFIX_REGEX$1 = /:(?:thread|topic):[^:]+$/i; function resolveProviderEntry(modelByChannel, channel) { const normalized = normalizeMessageChannel(channel) ?? channel.trim().toLowerCase(); return modelByChannel?.[normalized] ?? modelByChannel?.[Object.keys(modelByChannel ?? {}).find((key) => { return (normalizeMessageChannel(key) ?? key.trim().toLowerCase()) === normalized; }) ?? ""]; } function resolveParentGroupId(groupId) { const raw = groupId?.trim(); if (!raw || !THREAD_SUFFIX_REGEX$1.test(raw)) return; const parent = raw.replace(THREAD_SUFFIX_REGEX$1, "").trim(); return parent && parent !== raw ? parent : void 0; } function resolveGroupIdFromSessionKey(sessionKey) { const raw = sessionKey?.trim(); if (!raw) return; return (parseAgentSessionKey(raw)?.rest ?? raw).match(/(?:^|:)(?:group|channel):([^:]+)(?::|$)/i)?.[1]?.trim() || void 0; } function buildChannelCandidates(params) { const groupId = params.groupId?.trim(); const parentGroupId = resolveParentGroupId(groupId); const parentGroupIdFromSession = resolveGroupIdFromSessionKey(params.parentSessionKey); const parentGroupIdResolved = resolveParentGroupId(parentGroupIdFromSession) ?? parentGroupIdFromSession; const groupChannel = params.groupChannel?.trim(); const groupSubject = params.groupSubject?.trim(); const channelBare = groupChannel ? groupChannel.replace(/^#/, "") : void 0; const subjectBare = groupSubject ? groupSubject.replace(/^#/, "") : void 0; return buildChannelKeyCandidates(groupId, parentGroupId, parentGroupIdResolved, groupChannel, channelBare, channelBare ? normalizeChannelSlug(channelBare) : void 0, groupSubject, subjectBare, subjectBare ? normalizeChannelSlug(subjectBare) : void 0); } function resolveChannelModelOverride(params) { const channel = params.channel?.trim(); if (!channel) return null; const modelByChannel = params.cfg.channels?.modelByChannel; if (!modelByChannel) return null; const providerEntries = resolveProviderEntry(modelByChannel, channel); if (!providerEntries) return null; const candidates = buildChannelCandidates(params); if (candidates.length === 0) return null; const match = resolveChannelEntryMatchWithFallback({ entries: providerEntries, keys: candidates, wildcardKey: "*", normalizeKey: (value) => value.trim().toLowerCase() }); const raw = match.entry ?? match.wildcardEntry; if (typeof raw !== "string") return null; const model = raw.trim(); if (!model) return null; return { channel: normalizeMessageChannel(channel) ?? channel.trim().toLowerCase(), model, matchKey: match.matchKey, matchSource: match.matchSource }; } //#endregion //#region src/link-understanding/format.ts function formatLinkUnderstandingBody(params) { const outputs = params.outputs.map((output) => output.trim()).filter(Boolean); if (outputs.length === 0) return params.body ?? ""; const base = (params.body ?? "").trim(); if (!base) return outputs.join("\n"); return `${base}\n\n${outputs.join("\n")}`; } //#endregion //#region src/channels/allowlist-match.ts function formatAllowlistMatchMeta(match) { return `matchKey=${match?.matchKey ?? "none"} matchSource=${match?.matchSource ?? "none"}`; } //#endregion //#region src/link-understanding/defaults.ts const DEFAULT_LINK_TIMEOUT_SECONDS = 30; const DEFAULT_MAX_LINKS = 3; //#endregion //#region src/link-understanding/detect.ts const MARKDOWN_LINK_RE = /\[[^\]]*]\((https?:\/\/\S+?)\)/gi; const BARE_LINK_RE = /https?:\/\/\S+/gi; function stripMarkdownLinks(message) { return message.replace(MARKDOWN_LINK_RE, " "); } function resolveMaxLinks(value) { if (typeof value === "number" && Number.isFinite(value) && value > 0) return Math.floor(value); return DEFAULT_MAX_LINKS; } function isAllowedUrl(raw) { try { const parsed = new URL(raw); if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return false; if (isBlockedHostnameOrIp(parsed.hostname)) return false; return true; } catch { return false; } } function extractLinksFromMessage(message, opts) { const source = message?.trim(); if (!source) return []; const maxLinks = resolveMaxLinks(opts?.maxLinks); const sanitized = stripMarkdownLinks(source); const seen = /* @__PURE__ */ new Set(); const results = []; for (const match of sanitized.matchAll(BARE_LINK_RE)) { const raw = match[0]?.trim(); if (!raw) continue; if (!isAllowedUrl(raw)) continue; if (seen.has(raw)) continue; seen.add(raw); results.push(raw); if (results.length >= maxLinks) break; } return results; } //#endregion //#region src/link-understanding/runner.ts function resolveScopeDecision(params) { return resolveMediaUnderstandingScope({ scope: params.config?.scope, sessionKey: params.ctx.SessionKey, channel: params.ctx.Surface ?? params.ctx.Provider, chatType: normalizeMediaUnderstandingChatType(params.ctx.ChatType) }); } function resolveTimeoutMsFromConfig(params) { return resolveTimeoutMs(params.entry.timeoutSeconds ?? params.config?.timeoutSeconds, DEFAULT_LINK_TIMEOUT_SECONDS); } async function runCliEntry(params) { if ((params.entry.type ?? "cli") !== "cli") return null; const command = params.entry.command.trim(); if (!command) return null; const args = params.entry.args ?? []; const timeoutMs = resolveTimeoutMsFromConfig({ config: params.config, entry: params.entry }); const templCtx = { ...params.ctx, LinkUrl: params.url }; const argv = [command, ...args].map((part, index) => index === 0 ? part : applyTemplate(part, templCtx)); if (shouldLogVerbose()) logVerbose(`Link understanding via CLI: ${argv.join(" ")}`); const { stdout } = await runExec(argv[0], argv.slice(1), { timeoutMs, maxBuffer: CLI_OUTPUT_MAX_BUFFER }); return stdout.trim() || null; } async function runLinkEntries(params) { let lastError; for (const entry of params.entries) try { const output = await runCliEntry({ entry, ctx: params.ctx, url: params.url, config: params.config }); if (output) return output; } catch (err) { lastError = err; if (shouldLogVerbose()) logVerbose(`Link understanding failed for ${params.url}: ${String(err)}`); } if (lastError && shouldLogVerbose()) logVerbose(`Link understanding exhausted for ${params.url}`); return null; } async function runLinkUnderstanding(params) { const config = params.cfg.tools?.links; if (!config || config.enabled === false) return { urls: [], outputs: [] }; if (resolveScopeDecision({ config, ctx: params.ctx }) === "deny") { if (shouldLogVerbose()) logVerbose("Link understanding disabled by scope policy."); return { urls: [], outputs: [] }; } const links = extractLinksFromMessage(params.message ?? params.ctx.CommandBody ?? params.ctx.RawBody ?? params.ctx.Body ?? "", { maxLinks: config?.maxLinks }); if (links.length === 0) return { urls: [], outputs: [] }; const entries = config?.models ?? []; if (entries.length === 0) return { urls: links, outputs: [] }; const outputs = []; for (const url of links) { const output = await runLinkEntries({ entries, ctx: params.ctx, url, config }); if (output) outputs.push(output); } return { urls: links, outputs }; } //#endregion //#region src/link-understanding/apply.ts async function applyLinkUnderstanding(params) { const result = await runLinkUnderstanding({ cfg: params.cfg, ctx: params.ctx }); if (result.outputs.length === 0) return result; params.ctx.LinkUnderstanding = [...params.ctx.LinkUnderstanding ?? [], ...result.outputs]; params.ctx.Body = formatLinkUnderstandingBody({ body: params.ctx.Body, outputs: result.outputs }); finalizeInboundContext(params.ctx, { forceBodyForAgent: true, forceBodyForCommands: true }); return result; } //#endregion //#region src/media/base64.ts function estimateBase64DecodedBytes(base64) { let effectiveLen = 0; for (let i = 0; i < base64.length; i += 1) { if (base64.charCodeAt(i) <= 32) continue; effectiveLen += 1; } if (effectiveLen === 0) return 0; let padding = 0; let end = base64.length - 1; while (end >= 0 && base64.charCodeAt(end) <= 32) end -= 1; if (end >= 0 && base64[end] === "=") { padding = 1; end -= 1; while (end >= 0 && base64.charCodeAt(end) <= 32) end -= 1; if (end >= 0 && base64[end] === "=") padding = 2; } const estimated = Math.floor(effectiveLen * 3 / 4) - padding; return Math.max(0, estimated); } //#endregion //#region src/media/input-files.ts let canvasModulePromise = null; let pdfJsModulePromise = null; async function loadCanvasModule() { if (!canvasModulePromise) canvasModulePromise = import("@napi-rs/canvas").catch((err) => { canvasModulePromise = null; throw new Error(`Optional dependency @napi-rs/canvas is required for PDF image extraction: ${String(err)}`); }); return canvasModulePromise; } async function loadPdfJsModule() { if (!pdfJsModulePromise) pdfJsModulePromise = import("pdfjs-dist/legacy/build/pdf.mjs").catch((err) => { pdfJsModulePromise = null; throw new Error(`Optional dependency pdfjs-dist is required for PDF extraction: ${String(err)}`); }); return pdfJsModulePromise; } const DEFAULT_INPUT_IMAGE_MIMES = [ "image/jpeg", "image/png", "image/gif", "image/webp" ]; const DEFAULT_INPUT_FILE_MIMES = [ "text/plain", "text/markdown", "text/html", "text/csv", "application/json", "application/pdf" ]; const DEFAULT_INPUT_IMAGE_MAX_BYTES = 10 * 1024 * 1024; const DEFAULT_INPUT_FILE_MAX_BYTES = 5 * 1024 * 1024; const DEFAULT_INPUT_FILE_MAX_CHARS = 2e5; const DEFAULT_INPUT_MAX_REDIRECTS = 3; const DEFAULT_INPUT_TIMEOUT_MS = 1e4; const DEFAULT_INPUT_PDF_MAX_PAGES = 4; const DEFAULT_INPUT_PDF_MAX_PIXELS = 4e6; const DEFAULT_INPUT_PDF_MIN_TEXT_CHARS = 200; function rejectOversizedBase64Payload(params) { const estimated = estimateBase64DecodedBytes(params.data); if (estimated > params.maxBytes) throw new Error(`${params.label} too large: ${estimated} bytes (limit: ${params.maxBytes} bytes)`); } function normalizeMimeType(value) { if (!value) return; const [raw] = value.split(";"); return raw?.trim().toLowerCase() || void 0; } function parseContentType(value) { if (!value) return {}; const parts = value.split(";").map((part) => part.trim()); return { mimeType: normalizeMimeType(parts[0]), charset: parts.map((part) => part.match(/^charset=(.+)$/i)?.[1]?.trim()).find((part) => part && part.length > 0) }; } function normalizeMimeList(values, fallback) { const input = values && values.length > 0 ? values : fallback; return new Set(input.map((value) => normalizeMimeType(value)).filter(Boolean)); } function resolveInputFileLimits(config) { return { allowUrl: config?.allowUrl ?? true, allowedMimes: normalizeMimeList(config?.allowedMimes, DEFAULT_INPUT_FILE_MIMES), maxBytes: config?.maxBytes ?? DEFAULT_INPUT_FILE_MAX_BYTES, maxChars: config?.maxChars ?? DEFAULT_INPUT_FILE_MAX_CHARS, maxRedirects: config?.maxRedirects ?? DEFAULT_INPUT_MAX_REDIRECTS, timeoutMs: config?.timeoutMs ?? DEFAULT_INPUT_TIMEOUT_MS, pdf: { maxPages: config?.pdf?.maxPages ?? DEFAULT_INPUT_PDF_MAX_PAGES, maxPixels: config?.pdf?.maxPixels ?? DEFAULT_INPUT_PDF_MAX_PIXELS, minTextChars: config?.pdf?.minTextChars ?? DEFAULT_INPUT_PDF_MIN_TEXT_CHARS } }; } async function fetchWithGuard(params) { const { response, release } = await fetchWithSsrFGuard({ url: params.url, maxRedirects: params.maxRedirects, timeoutMs: params.timeoutMs, policy: params.policy, auditContext: params.auditContext, init: { headers: { "User-Agent": "OpenClaw-Gateway/1.0" } } }); try { if (!response.ok) throw new Error(`Failed to fetch: ${response.status} ${response.statusText}`); const contentLength = response.headers.get("content-length"); if (contentLength) { const size = Number(contentLength); if (Number.isFinite(size) && size > params.maxBytes) throw new Error(`Content too large: ${size} bytes (limit: ${params.maxBytes} bytes)`); } const buffer = await readResponseWithLimit(response, params.maxBytes); const contentType = response.headers.get("content-type") || void 0; return { buffer, mimeType: parseContentType(contentType).mimeType ?? "application/octet-stream", contentType }; } finally { await release(); } } function decodeTextContent(buffer, charset) { const encoding = charset?.trim().toLowerCase() || "utf-8"; try { return new TextDecoder(encoding).decode(buffer); } catch { return new TextDecoder("utf-8").decode(buffer); } } function clampText(text, maxChars) { if (text.length <= maxChars) return text; return text.slice(0, maxChars); } async function extractPdfContent(params) { const { buffer, limits } = params; const { getDocument } = await loadPdfJsModule(); const pdf = await getDocument({ data: new Uint8Array(buffer), disableWorker: true }).promise; const maxPages = Math.min(pdf.numPages, limits.pdf.maxPages); const textParts = []; for (let pageNum = 1; pageNum <= maxPages; pageNum += 1) { const pageText = (await (await pdf.getPage(pageNum)).getTextContent()).items.map((item) => "str" in item ? String(item.str) : "").filter(Boolean).join(" "); if (pageText) textParts.push(pageText); } const text = tex