UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

605 lines (604 loc) 29.4 kB
import { l as normalizeOptionalString } from "./string-coerce-CIXf7egm.js"; import { i as truncateWithMarker, r as truncateUtf16Safe } from "./utf16-slice-D_ngcYKd.js"; import "./utils-P__uGsPB.js"; import { t as pruneMapToMaxSize } from "./map-size-CNcWiFKu.js"; import { T as isSubagentSessionKey, w as isCronSessionKey } from "./session-key-BnWWjqNc.js"; import { a as normalizeOptionalAgentRuntimeId, r as isDefaultAgentRuntimeId } from "./agent-runtime-id-BpfvnoN1.js"; import { c as inferUniqueProviderFromConfiguredModels, i as buildModelAliasIndex, u as listModelAliasCandidates } from "./model-selection-shared-BlLyx1r2.js"; import "./defaults-CdX9UGcX.js"; import { t as splitTrailingAuthProfile } from "./model-ref-profile-BIKs-96s.js"; import { d as resolveSelectedOpenAIRuntimeProvider } from "./openai-routing-Ex_3E9TF.js"; import { t as buildPluginAgentTurnPrepareContext } from "./host-hooks-sVMn958c.js"; import { v as joinPresentTextSegments } from "./hook-runner-global-0kfmMG4T.js"; import { t as deriveContextPromptTokens } from "./usage-CtmV8Xxq.js"; import { f as shouldPreserveUserFacingSessionStateForInputProvenance } from "./input-provenance-DiG-Cwnd.js"; import { a as resolveCandidateThinkingLevel } from "./thinking-runtime-BiFbTVdI.js"; import { n as resolveBoundAgentIdForSession } from "./plugin-command-execution-BiIlm39K.js"; import { E as deriveSessionName, a as compareProcessSessionStartOrder, m as listRunningSessions } from "./bash-process-registry-DvUU9bL3.js"; import { n as resolveEffectiveToolFsWorkspaceOnly } from "./tool-fs-policy-BciYLPcO.js"; import { t as drainPluginNextTurnInjectionContext } from "./host-hook-state-Bk6oeu0I.js"; import { t as log } from "./logger-C3TD2wdV.js"; import { r as normalizeContextTokenBudget } from "./utils-CefVZRZM.js"; import { t as resolveProcessToolScopeKey } from "./bash-process-scope-Bmw8_ghL.js"; import { a as buildActiveMusicGenerationTaskPromptContextForSession, i as buildActiveImageGenerationTaskPromptContextForSession, o as buildActiveVideoGenerationTaskPromptContextForSession } from "./media-generation-task-status-DWy1n9Ka.js"; import { a as resolveContextWindowInfo } from "./context-window-guard-DHDMEGvr.js"; import { t as agentRuntimeAuthPlanMatchesTarget } from "./prepare-auth-Ci9igqt8.js"; import { t as readAgentModelContextTokens } from "./model-context-tokens-Cy1KpVE9.js"; import { normalizeStructuredPromptSection, prependSystemPromptAdditionAfterCacheBoundary } from "@openclaw/ai/internal/shared"; //#region src/agents/bash-process-references.ts /** * Compact references for active background bash sessions. * These references are surfaced in agent context so follow-up turns can * reconnect to prior long-running work. */ const DEFAULT_ACTIVE_PROCESS_LIMIT = 8; const MAX_COMMAND_LABEL_CHARS = 140; function truncate(value, maxChars) { if (value.length <= maxChars) return value; if (maxChars <= 1) return truncateUtf16Safe(value, maxChars); return truncateWithMarker(value, maxChars, { marker: "...", reserve: 3, trimEnd: false }); } /** List active background process sessions for one scope key, newest first. */ function listActiveProcessSessionReferences(params) { const scopeKey = params.scopeKey?.trim(); if (!scopeKey) return []; const now = params.now ?? Date.now(); const limit = typeof params.limit === "number" && Number.isFinite(params.limit) && params.limit > 0 ? Math.floor(params.limit) : DEFAULT_ACTIVE_PROCESS_LIMIT; return listRunningSessions().filter((session) => session.scopeKey === scopeKey).toSorted(compareProcessSessionStartOrder).slice(0, limit).map((session) => ({ sessionId: session.id, status: "running", pid: session.pid, startedAt: session.startedAt, runtimeMs: Math.max(0, now - session.startedAt), cwd: session.cwd, command: session.command, name: truncate(deriveSessionName(session.command) || session.command, MAX_COMMAND_LABEL_CHARS), tail: session.tail, truncated: session.truncated })); } //#endregion //#region src/agents/hook-system-context-boundary.ts /** * Wraps plugin-provided system context in stable prompt-cache boundaries. */ const HOOK_SYSTEM_CONTEXT_HEADER = "OpenClaw plugin-injected system context. This block is not workspace file content."; /** Normalizes and fences plugin-injected system context before it enters prompts. */ function wrapPluginSystemContextSection(value) { if (typeof value !== "string") return; const normalized = normalizeStructuredPromptSection(value); if (!normalized) return; return `---\n\n${HOOK_SYSTEM_CONTEXT_HEADER}\n\n${normalized}\n\n---`; } //#endregion //#region src/agents/embedded-agent-runner/compaction-runtime-context.ts /** Resolve the configured compaction override against the actual model/runtime candidate. */ function resolveEmbeddedCompactionThinkingLevel(params) { const configuredLevel = params.config?.agents?.defaults?.compaction?.thinkingLevel; const requestedLevel = configuredLevel === "inherit" ? params.inheritedLevel : configuredLevel ?? "low"; if (!requestedLevel) return "off"; return resolveCandidateThinkingLevel({ cfg: params.config, provider: params.provider, modelId: params.modelId, level: requestedLevel, catalog: params.catalog, agentId: params.agentId, sessionKey: params.sessionKey, agentRuntime: params.agentRuntime }) ?? "off"; } /** * Resolve the effective compaction target from config, falling back to the * caller-supplied provider/model and optionally applying runtime defaults. */ function resolveEmbeddedCompactionTarget(params) { const provider = params.provider?.trim() || params.defaultProvider; const model = params.modelId?.trim() || params.defaultModel; const override = params.modelSelectionLocked ? void 0 : params.config?.agents?.defaults?.compaction?.model?.trim(); const resolveTargetProviders = (targetProvider, authProfileId) => { if (!targetProvider) return {}; const selectedHarnessRuntime = normalizeOptionalAgentRuntimeId(params.harnessRuntime); const useNativeHarnessRuntime = selectedHarnessRuntime !== void 0 && selectedHarnessRuntime !== "openclaw" && !isDefaultAgentRuntimeId(selectedHarnessRuntime); const runtimeProvider = resolveSelectedOpenAIRuntimeProvider({ provider: targetProvider, harnessRuntime: (useNativeHarnessRuntime ? selectedHarnessRuntime : "openclaw") ?? void 0, authProfileId, config: params.config }); const routedRuntimeProvider = runtimeProvider === targetProvider ? void 0 : runtimeProvider; return { runtimeProvider: routedRuntimeProvider, contextProvider: useNativeHarnessRuntime ? routedRuntimeProvider : void 0, ...useNativeHarnessRuntime ? { nativeHarnessCompaction: true } : {} }; }; const assembleTarget = (targetProvider, targetModel) => { const authProfileId = targetProvider !== provider ? void 0 : params.authProfileId ?? void 0; return { provider: targetProvider, ...resolveTargetProviders(targetProvider, authProfileId), model: targetModel, authProfileId }; }; if (!override) return assembleTarget(provider, model); const slashIdx = override.indexOf("/"); if (slashIdx > 0) return assembleTarget(override.slice(0, slashIdx).trim(), override.slice(slashIdx + 1).trim() || params.defaultModel); const config = params.config ?? {}; const currentProvider = provider?.trim(); if (currentProvider && hasBareConfiguredModelForProvider({ cfg: config, provider: currentProvider, model: override })) return assembleTarget(currentProvider, override); const inferredLiteralProvider = inferUniqueProviderFromConfiguredModels({ cfg: config, model: override, allowManifestNormalization: false }); if (inferredLiteralProvider) return assembleTarget(inferredLiteralProvider, override); const defaultProvider = provider || "openai"; const aliasKey = normalizeCompactionConfigKey(splitTrailingAuthProfile(override).model); const alias = listModelAliasCandidates(config).some(({ alias: candidate }) => normalizeCompactionConfigKey(candidate) === aliasKey) ? buildModelAliasIndex({ cfg: config, defaultProvider }).byAlias.get(aliasKey) : void 0; if (alias) return assembleTarget(alias.ref.provider, alias.ref.model); return assembleTarget(provider, override); } function normalizeCompactionConfigKey(value) { return value.trim().toLowerCase(); } function hasBareConfiguredModelForProvider(params) { const providerKey = normalizeCompactionConfigKey(params.provider); const modelKey = normalizeCompactionConfigKey(params.model); if (!providerKey || !modelKey || params.model.includes("/")) return false; for (const rawRef of Object.keys(params.cfg.agents?.defaults?.models ?? {})) { const slashIdx = rawRef.indexOf("/"); if (slashIdx <= 0 || rawRef.endsWith("/*")) continue; const rawProvider = rawRef.slice(0, slashIdx); const rawModel = rawRef.slice(slashIdx + 1); if (normalizeCompactionConfigKey(rawProvider) === providerKey && normalizeCompactionConfigKey(rawModel) === modelKey) return true; } return ((Object.entries(params.cfg.models?.providers ?? {}).find(([key]) => { return normalizeCompactionConfigKey(key) === providerKey; })?.[1])?.models ?? []).some((entry) => { return normalizeCompactionConfigKey(entry?.id ?? "") === modelKey; }); } /** Resolves the concrete harness already bound to this exact compaction target. */ function resolveCompactionHarnessRuntime(params) { const boundHarnessRuntime = normalizeOptionalAgentRuntimeId(params.boundHarnessRuntime); if (boundHarnessRuntime) return boundHarnessRuntime; const preparedRuntimePlan = params.preparedRuntimePlan; if (preparedRuntimePlan && agentRuntimeAuthPlanMatchesTarget(preparedRuntimePlan.auth, { provider: params.provider, modelId: params.modelId })) { const preparedHarnessRuntime = normalizeOptionalAgentRuntimeId(preparedRuntimePlan.resolvedRef.harnessId); if (preparedHarnessRuntime) return preparedHarnessRuntime; } return normalizeOptionalAgentRuntimeId(params.configuredHarnessRuntime); } /** Resolves the shared policy, target, and harness ownership for either compaction entry point. */ function resolveCompactionContextTokenBudget(params) { const resolvedBudget = normalizeContextTokenBudget(resolveContextWindowInfo({ cfg: params.config, provider: params.provider, modelId: params.modelId, modelContextTokens: readAgentModelContextTokens(params.model), modelContextWindow: params.model?.contextWindow, defaultTokens: 2e5 }).tokens) ?? 2e5; return Math.min(normalizeContextTokenBudget(params.requestedTokenBudget) ?? normalizeContextTokenBudget(params.fallbackTokenBudget) ?? resolvedBudget, resolvedBudget); } function buildEmbeddedCompactionRuntimeContext(params) { const resolved = resolveEmbeddedCompactionTarget({ config: params.config, provider: params.provider, modelId: params.modelId, authProfileId: params.authProfileId, harnessRuntime: params.harnessRuntime, modelSelectionLocked: params.modelSelectionLocked }); const agentHarnessId = params.harnessRuntime?.trim() || void 0; const runtimeAuthPlan = params.runtimeAuthPlan && resolved.provider && resolved.model && agentRuntimeAuthPlanMatchesTarget(params.runtimeAuthPlan, { provider: resolved.provider, modelId: resolved.model }) ? params.runtimeAuthPlan : void 0; const processScopeKey = params.sessionKey?.trim(); const activeProcessSessions = params.activeProcessSessions ?? listActiveProcessSessionReferences({ scopeKey: processScopeKey }); return { sessionKey: params.sessionKey ?? void 0, sandboxSessionKey: params.sandboxSessionKey, sandboxAgentId: params.sandboxAgentId, messageChannel: params.messageChannel ?? void 0, messageProvider: params.messageProvider ?? void 0, clientCaps: params.clientCaps, chatType: params.chatType ?? void 0, agentAccountId: params.agentAccountId ?? void 0, conversationRoutePeerId: params.conversationRoutePeerId, currentChannelId: params.currentChannelId ?? void 0, currentThreadTs: params.currentThreadTs ?? void 0, currentMessageId: params.currentMessageId ?? void 0, authProfileId: resolved.authProfileId, authProfileIdSource: params.authProfileIdSource, runtimeAuthPlan, agentHarnessId, modelSelectionLocked: params.modelSelectionLocked, workspaceDir: params.workspaceDir, cwd: params.cwd ?? void 0, permissionMode: params.permissionMode, sessionRoot: params.sessionRoot, agentDir: params.agentDir, config: params.config, toolOverrides: params.toolOverrides, toolsAllow: params.toolsAllow, skillsSnapshot: params.skillsSnapshot, senderIsOwner: params.senderIsOwner, senderId: params.senderId ?? void 0, provider: resolved.provider, runtimeProvider: resolved.runtimeProvider, model: resolved.model, modelFallbacksOverride: params.modelFallbacksOverride, thinkLevel: params.thinkLevel, reasoningLevel: params.reasoningLevel, execOverrides: params.execOverrides, bashElevated: params.bashElevated, extraSystemPrompt: params.extraSystemPrompt, sourceReplyDeliveryMode: params.sourceReplyDeliveryMode, ownerNumbers: params.ownerNumbers, ...activeProcessSessions.length > 0 ? { activeProcessSessions } : {} }; } //#endregion //#region src/agents/embedded-agent-runner/context-engine-capabilities.ts /** * Builds host capabilities passed into context-engine runtime calls. */ /** * Build host-owned capabilities that are bound to one context-engine runtime call. */ function resolveContextEngineCapabilities(params) { const sessionKey = normalizeOptionalString(params.sessionKey); const agentId = resolveBoundAgentIdForSession({ config: params.config, sessionKey, agentId: params.explicitAgentId }); const contextEnginePluginId = normalizeOptionalString(params.contextEnginePluginId); return { llm: { complete: async (request) => { const { createRuntimeLlm } = await import("./runtime-llm.runtime.js"); return await createRuntimeLlm({ getConfig: () => params.config, authority: { caller: { kind: "context-engine", id: params.purpose }, requiresBoundAgent: true, ...sessionKey ? { sessionKey } : {}, ...agentId ? { agentId } : {}, ...params.authProfileId ? { preferredProfile: params.authProfileId } : {}, ...contextEnginePluginId ? { pluginIdForPolicy: contextEnginePluginId } : {}, allowAgentIdOverride: false, allowModelOverride: false, allowComplete: true } }).complete(request); } } }; } //#endregion //#region src/agents/embedded-agent-runner/run/attempt-prompt-helpers.ts const PROMPT_BUILD_DRAIN_CACHE_MAX = 256; const promptBuildDrainCache = /* @__PURE__ */ new Map(); function rememberDrainedInjections(runId, injections) { if (promptBuildDrainCache.has(runId)) promptBuildDrainCache.delete(runId); else if (promptBuildDrainCache.size >= PROMPT_BUILD_DRAIN_CACHE_MAX) pruneMapToMaxSize(promptBuildDrainCache, 255); promptBuildDrainCache.set(runId, injections); } /** * Releases the per-run drained-injection cache. Call when a run terminates so * the cap stays headroom for active runs. */ function forgetPromptBuildDrainCacheForRun(runId) { if (runId) promptBuildDrainCache.delete(runId); } /** * Resolves prompt-build hook contributions for one attempt. Next-turn * injections are drained once per run and cached for retries so destructive * session-store reads do not lose plugin context after a failed first attempt. */ async function resolvePromptBuildHookResult(params) { const runId = params.hookCtx.runId; const cachedInjections = runId ? promptBuildDrainCache.get(runId) : void 0; const queuedContext = cachedInjections ? { queuedInjections: cachedInjections, ...buildPluginAgentTurnPrepareContext({ queuedInjections: cachedInjections }) } : await drainPluginNextTurnInjectionContext({ cfg: params.config, sessionKey: params.hookCtx.sessionKey, agentId: params.hookCtx.agentId }); if (runId && !cachedInjections) rememberDrainedInjections(runId, queuedContext.queuedInjections); const turnPrepareResult = params.hookRunner?.runAgentTurnPrepare && params.hookRunner.hasHooks("agent_turn_prepare") ? await params.hookRunner.runAgentTurnPrepare({ prompt: params.prompt, messages: params.messages, queuedInjections: queuedContext.queuedInjections }, params.hookCtx).catch((hookErr) => { log.warn(`agent_turn_prepare hook failed: ${String(hookErr)}`); }) : void 0; const heartbeatContribution = params.hookCtx.trigger === "heartbeat" && params.hookRunner?.runHeartbeatPromptContribution && params.hookRunner.hasHooks("heartbeat_prompt_contribution") ? await params.hookRunner.runHeartbeatPromptContribution({ sessionKey: params.hookCtx.sessionKey, agentId: params.hookCtx.agentId, heartbeatName: "heartbeat" }, params.hookCtx).catch((hookErr) => { log.warn(`heartbeat_prompt_contribution hook failed: ${String(hookErr)}`); }) : void 0; const promptBuildResult = params.hookRunner?.hasHooks("before_prompt_build") ? await params.hookRunner.runBeforePromptBuild({ prompt: params.prompt, messages: params.messages }, params.hookCtx).catch((hookErr) => { log.warn(`before_prompt_build hook failed: ${String(hookErr)}`); }) : void 0; return { systemPrompt: promptBuildResult?.systemPrompt, ...promptBuildResult?.toolsAllow !== void 0 ? { toolsAllow: promptBuildResult.toolsAllow } : {}, prependContext: joinPresentTextSegments([ queuedContext.prependContext, turnPrepareResult?.prependContext, heartbeatContribution?.prependContext, promptBuildResult?.prependContext ]), appendContext: joinPresentTextSegments([ queuedContext.appendContext, turnPrepareResult?.appendContext, heartbeatContribution?.appendContext, promptBuildResult?.appendContext ]), prependSystemContext: wrapPluginSystemContextSection(promptBuildResult?.prependSystemContext), appendSystemContext: wrapPluginSystemContextSection(promptBuildResult?.appendSystemContext) }; } function resolvePromptModeForSession(sessionKey) { if (!sessionKey) return "full"; return isSubagentSessionKey(sessionKey) || isCronSessionKey(sessionKey) ? "minimal" : "full"; } /** User-visible runs warn when transcript repair had to merge an orphaned user turn. */ function shouldWarnOnOrphanedUserRepair(trigger) { return trigger === "user" || trigger === "manual"; } const QUEUED_USER_MESSAGE_MARKER = "[Queued user message from a previous active turn; preserved as context only. Continue with the active prompt below.]"; const MAX_STRUCTURED_MEDIA_REF_CHARS = 300; const MAX_STRUCTURED_JSON_STRING_CHARS = 300; const MAX_STRUCTURED_JSON_DEPTH = 4; const MAX_STRUCTURED_JSON_ARRAY_ITEMS = 16; const MAX_STRUCTURED_JSON_OBJECT_KEYS = 32; function summarizeStructuredMediaRef(label, value) { if (typeof value !== "string") return; const trimmed = value.trim(); if (!trimmed) return; const dataUriMatch = trimmed.match(/^data:([^;,]+)?(?:;[^,]*)?,/i); if (dataUriMatch) return `[${label}] inline data URI (${dataUriMatch[1]?.trim() || "unknown"}, ${trimmed.length} chars)`; if (trimmed.length > MAX_STRUCTURED_MEDIA_REF_CHARS) return `[${label}] ${truncateUtf16Safe(trimmed, MAX_STRUCTURED_MEDIA_REF_CHARS)}... (${trimmed.length} chars)`; return `[${label}] ${trimmed}`; } function summarizeStructuredJsonString(value) { const mediaSummary = summarizeStructuredMediaRef("value", value); if (mediaSummary?.includes("inline data URI")) return mediaSummary; const trimmed = value.trim(); if (trimmed.length > MAX_STRUCTURED_JSON_STRING_CHARS) return `${truncateUtf16Safe(trimmed, MAX_STRUCTURED_JSON_STRING_CHARS)}... (${trimmed.length} chars)`; return value; } function sanitizeStructuredJsonValue(value, depth = 0, seen = /* @__PURE__ */ new WeakSet()) { if (typeof value === "string") return summarizeStructuredJsonString(value); if (!value || typeof value !== "object") return value; if (seen.has(value)) return "[circular]"; if (depth >= MAX_STRUCTURED_JSON_DEPTH) return "[max depth]"; seen.add(value); if (Array.isArray(value)) { const limited = value.slice(0, MAX_STRUCTURED_JSON_ARRAY_ITEMS).map((item) => sanitizeStructuredJsonValue(item, depth + 1, seen)); if (value.length > MAX_STRUCTURED_JSON_ARRAY_ITEMS) limited.push(`[${value.length - MAX_STRUCTURED_JSON_ARRAY_ITEMS} more items]`); seen.delete(value); return limited; } const output = {}; let copied = 0; let skipped = 0; for (const key in value) { if (!Object.hasOwn(value, key)) continue; if (copied >= MAX_STRUCTURED_JSON_OBJECT_KEYS) { skipped += 1; continue; } output[key] = sanitizeStructuredJsonValue(value[key], depth + 1, seen); copied += 1; } if (skipped > 0) output["__truncated"] = `${skipped} more keys`; seen.delete(value); return output; } function stringifyStructuredJsonFallback(part) { try { const serialized = JSON.stringify(sanitizeStructuredJsonValue(part)); if (!serialized || serialized === "{}") return; const withoutInlineData = serialized.replace(/data:[^"'\\\s]+/gi, (match) => `[inline data URI: ${match.length} chars]`); return withoutInlineData.length > 1e3 ? `${truncateUtf16Safe(withoutInlineData, 1e3)}... (${withoutInlineData.length} chars)` : withoutInlineData; } catch { return; } } function stringifyStructuredContentPart(part) { if (!part || typeof part !== "object") return; const record = part; if (record.type === "text") return (typeof record.text === "string" ? record.text.trim() : "") || void 0; if (record.type === "image_url") { const imageUrl = record.image_url; return summarizeStructuredMediaRef("image_url", typeof imageUrl === "string" ? imageUrl : imageUrl && typeof imageUrl === "object" ? imageUrl.url : void 0); } if (record.type === "image" || record.type === "input_image") return summarizeStructuredMediaRef(record.type, record.url) ?? summarizeStructuredMediaRef(record.type, record.source); if (typeof record.type === "string") { const typedRef = summarizeStructuredMediaRef(record.type, record.audio_url) ?? summarizeStructuredMediaRef(record.type, record.media_url) ?? summarizeStructuredMediaRef(record.type, record.url) ?? summarizeStructuredMediaRef(record.type, record.source); if (typedRef) return typedRef; } return stringifyStructuredJsonFallback(part); } function extractUserMessagePromptText(content) { if (typeof content === "string") return content.trim() || void 0; if (!Array.isArray(content)) return; return content.flatMap((part) => { const textLocal = stringifyStructuredContentPart(part); return textLocal ? [textLocal] : []; }).join("\n").trim() || void 0; } function promptAlreadyIncludesQueuedUserMessage(prompt, orphanText) { const normalizedPrompt = prompt.replace(/\r\n/g, "\n"); const normalizedOrphanText = orphanText.replace(/\r\n/g, "\n").trim(); if (!normalizedOrphanText) return false; const queuedBlockPrefix = `${QUEUED_USER_MESSAGE_MARKER}\n${normalizedOrphanText}`; return normalizedPrompt === queuedBlockPrefix || normalizedPrompt.startsWith(`${queuedBlockPrefix}\n`) || normalizedPrompt.includes(`\n${queuedBlockPrefix}\n`) || `\n${normalizedPrompt}\n`.includes(`\n${normalizedOrphanText}\n`); } function shouldDropStaleInternalOrphanedUserPrompt(params) { return params.prompt.trim().length > 0 && shouldPreserveUserFacingSessionStateForInputProvenance(params.leafMessage.provenance); } /** * Merges a trailing user message that was queued in transcript history but not * present in the active prompt. * * External user leaves are eligible to remain canonical (`removeLeaf: false`). * Session repair preserves them only for producer-tagged main-session restart * recovery; ordinary repair replaces them with the merged prompt. Empty or stale * internal leaves are always detached. */ function mergeOrphanedTrailingUserPrompt(params) { const orphanText = extractUserMessagePromptText(params.leafMessage.content); if (!orphanText) return { prompt: params.prompt, merged: false, removeLeaf: true }; if (shouldDropStaleInternalOrphanedUserPrompt({ prompt: params.prompt, leafMessage: params.leafMessage })) return { prompt: params.prompt, merged: false, removeLeaf: true }; if (promptAlreadyIncludesQueuedUserMessage(params.prompt, orphanText)) return { prompt: params.prompt, merged: false, removeLeaf: false }; return { prompt: [ QUEUED_USER_MESSAGE_MARKER, orphanText, "", params.prompt ].join("\n"), merged: true, removeLeaf: false }; } function resolveAttemptFsWorkspaceOnly(params) { return resolveEffectiveToolFsWorkspaceOnly({ cfg: params.config, agentId: params.sessionAgentId }); } function prependSystemPromptAddition(params) { return prependSystemPromptAdditionAfterCacheBoundary(params); } function resolveAttemptMediaTaskSystemPromptAddition(params) { if (params.trigger !== "user" && params.trigger !== "manual") return; return joinPresentTextSegments([ buildActiveImageGenerationTaskPromptContextForSession(params.sessionKey, params.agentId), buildActiveVideoGenerationTaskPromptContextForSession(params.sessionKey, params.agentId), buildActiveMusicGenerationTaskPromptContextForSession(params.sessionKey, params.agentId) ]); } function resolveRuntimeContextSessionTarget(params) { const sessionTarget = params.attempt.sessionTarget; const agentId = sessionTarget?.agentId ?? params.activeAgentId; const sessionId = sessionTarget?.sessionId ?? params.attempt.sessionId; const sessionKey = sessionTarget?.sessionKey ?? params.attempt.sessionKey; if (!agentId && !sessionId && !sessionKey && !sessionTarget?.storePath && sessionTarget?.threadId === void 0) return; return { ...agentId ? { agentId } : {}, ...sessionId ? { sessionId } : {}, ...sessionKey ? { sessionKey } : {}, ...sessionTarget?.storePath ? { storePath: sessionTarget.storePath } : {}, ...sessionTarget?.threadId !== void 0 ? { threadId: sessionTarget.threadId } : {} }; } /** Build runtime context passed into context-engine afterTurn hooks. */ function buildAfterTurnRuntimeContext(params) { const sessionTarget = resolveRuntimeContextSessionTarget({ attempt: params.attempt, activeAgentId: params.activeAgentId }); return { ...buildEmbeddedCompactionRuntimeContext({ sessionKey: params.attempt.sessionKey, sandboxSessionKey: params.attempt.sandboxSessionKey, sandboxAgentId: params.attempt.sandboxAgentId, messageChannel: params.attempt.messageChannel, messageProvider: params.attempt.messageProvider, agentAccountId: params.attempt.agentAccountId, currentChannelId: params.attempt.currentChannelId, currentThreadTs: params.attempt.currentThreadTs, currentMessageId: params.attempt.currentMessageId, authProfileId: params.attempt.authProfileId, authProfileIdSource: params.attempt.authProfileIdSource, runtimeAuthPlan: params.attempt.runtimePlan?.auth, workspaceDir: params.workspaceDir, cwd: params.cwd, agentDir: params.agentDir, config: params.attempt.config, toolsAllow: params.attempt.toolsAllow, skillsSnapshot: params.attempt.skillsSnapshot, senderId: params.attempt.senderId, provider: params.attempt.provider, modelId: params.attempt.modelId, harnessRuntime: params.attempt.agentHarnessId, modelSelectionLocked: params.attempt.modelSelectionLocked, thinkLevel: params.attempt.thinkLevel, reasoningLevel: params.attempt.reasoningLevel, bashElevated: params.attempt.bashElevated, extraSystemPrompt: params.attempt.extraSystemPrompt, ownerNumbers: params.attempt.ownerNumbers, activeProcessSessions: listActiveProcessSessionReferences({ scopeKey: resolveProcessToolScopeKey({ sessionKey: params.attempt.sandboxSessionKey?.trim() || params.attempt.sessionKey, sessionId: params.attempt.sessionId, agentId: params.activeAgentId }) }) }), ...resolveContextEngineCapabilities({ config: params.attempt.config, sessionKey: params.attempt.sessionKey, explicitAgentId: params.attempt.contextEngineAgentId, authProfileId: params.attempt.authProfileId, contextEnginePluginId: params.contextEnginePluginId, purpose: "context-engine.after-turn" }), ...typeof params.tokenBudget === "number" && Number.isFinite(params.tokenBudget) && params.tokenBudget > 0 ? { tokenBudget: Math.floor(params.tokenBudget) } : {}, ...typeof params.currentTokenCount === "number" && Number.isFinite(params.currentTokenCount) && params.currentTokenCount > 0 ? { currentTokenCount: Math.floor(params.currentTokenCount) } : {}, ...params.promptCache ? { promptCache: params.promptCache } : {}, transcriptStorage: { kind: "sqlite" }, ...sessionTarget ? { sessionTarget } : {} }; } function buildAfterTurnRuntimeContextFromUsage(params) { return buildAfterTurnRuntimeContext({ ...params, currentTokenCount: deriveContextPromptTokens({ lastCallUsage: params.lastCallUsage }) }); } //#endregion export { wrapPluginSystemContextSection as _, prependSystemPromptAddition as a, resolvePromptBuildHookResult as c, resolveContextEngineCapabilities as d, buildEmbeddedCompactionRuntimeContext as f, resolveEmbeddedCompactionThinkingLevel as g, resolveEmbeddedCompactionTarget as h, mergeOrphanedTrailingUserPrompt as i, resolvePromptModeForSession as l, resolveCompactionHarnessRuntime as m, buildAfterTurnRuntimeContextFromUsage as n, resolveAttemptFsWorkspaceOnly as o, resolveCompactionContextTokenBudget as p, forgetPromptBuildDrainCacheForRun as r, resolveAttemptMediaTaskSystemPromptAddition as s, buildAfterTurnRuntimeContext as t, shouldWarnOnOrphanedUserRepair as u, listActiveProcessSessionReferences as v };