UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

244 lines (243 loc) 10.8 kB
import { l as asNonNegativeFiniteNumber } from "./number-coercion-CLj0HTDM.js"; import { l as normalizeOptionalString } from "./string-coerce-CIXf7egm.js"; import { n as createLazyPromise } from "./lazy-promise-DGqyc4Y4.js"; import "./defaults-CdX9UGcX.js"; import { a as hasNonzeroUsage, i as hasBillableUsage, r as deriveSessionTotalTokens } from "./usage-CtmV8Xxq.js"; import "./session-accessor-YsytfDtG.js"; import { d as patchSessionEntryCore } from "./session-accessor.sqlite-entry-CWk3jL7s.js"; import { _ as resolveMaintenanceConfigFromInput } from "./disk-budget-BsDSCUGD.js"; import { u as setSessionRuntimeModel } from "./types-BHV0IaPK.js"; import { t as clearAllCliSessions } from "./cli-session-binding-Aa6nlDa8.js"; import "./sessions-9nxpeTwt.js"; import { c as setCliSessionBinding } from "./cli-session-pAa_-y_N.js"; import { r as clearMainSessionRecoveryAfterAgentRun } from "./main-session-recovery-clear-H7IP1700.js"; import { i as projectSessionSnapshotChanges } from "./session-snapshot-merge-Cf1TdJBp.js"; //#region src/agents/command/session-store.ts /** * Updates persisted session metadata after agent command runs. */ const getUsageFormatModule = createLazyPromise(() => import("./usage-format-Bh6k2SRY.js")); const getContextModule = createLazyPromise(() => import("./context-M2p7wU0f.js")); function normalizeSessionTokenCount(value) { if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) return; return Math.floor(value); } /** Applies run result metadata and usage to a session entry. */ async function updateSessionStoreAfterAgentRun(params) { const { cfg, sessionId, sessionKey, storePath, sessionStore, defaultProvider, defaultModel, fallbackProvider, fallbackModel, result } = params; const now = Date.now(); const touchInteraction = params.touchInteraction !== false; const touchActivity = params.touchActivity !== false; const usage = result.meta.agentMeta?.usage; const promptTokens = result.meta.agentMeta?.promptTokens; const lastCallUsage = result.meta.agentMeta?.lastCallUsage; const modelUsed = result.meta.agentMeta?.model ?? fallbackModel ?? defaultModel; const providerUsed = result.meta.agentMeta?.provider ?? fallbackProvider ?? defaultProvider; const agentHarnessId = normalizeOptionalString(result.meta.agentMeta?.agentHarnessId); const runtimeContextTokens = normalizeSessionTokenCount(result.meta.agentMeta?.contextTokens); const contextBudgetStatus = result.meta.agentMeta?.contextBudgetStatus; const contextTokens = runtimeContextTokens !== void 0 ? runtimeContextTokens : (await getContextModule()).resolveContextTokensForModel({ cfg, provider: providerUsed, model: modelUsed, fallbackContextTokens: 2e5, allowAsyncLoad: false }) ?? 2e5; const contextTokensSource = result.meta.agentMeta?.contextTokensSource ?? "resolved"; const preserveUserFacingRunState = params.preserveUserFacingSessionModelState === true; const preserveRuntimeModel = params.preserveRuntimeModel === true || preserveUserFacingRunState; const hadPreExistingEntry = sessionStore[sessionKey] !== void 0; const entry = sessionStore[sessionKey] ?? { sessionId, updatedAt: now, sessionStartedAt: now }; const expectedSession = params.compactionAccounting?.target ?? entry; if (!preserveUserFacingRunState && expectedSession.sessionId !== sessionId) return; const next = { ...entry, updatedAt: now, sessionStartedAt: entry.sessionStartedAt ?? now, lastInteractionAt: touchInteraction ? now : entry.lastInteractionAt, lastActivityAt: touchActivity ? now : entry.lastActivityAt, ...preserveRuntimeModel ? {} : { contextTokens, contextTokensSource } }; if (preserveRuntimeModel) { if (entry.model) { next.contextTokens = entry.contextTokens; if (entry.modelProvider) setSessionRuntimeModel(next, { provider: entry.modelProvider, model: entry.model }); else next.model = entry.model; } } else setSessionRuntimeModel(next, { provider: providerUsed, model: modelUsed }); if (!preserveUserFacingRunState) { if (!preserveRuntimeModel) next.agentHarnessId = agentHarnessId; next.abortedLastRun = result.meta.aborted ?? false; clearMainSessionRecoveryAfterAgentRun(next, params.clearRestartRecoveryForceSafeTools); if (result.meta.systemPromptReport) next.systemPromptReport = result.meta.systemPromptReport; if (!preserveRuntimeModel) next.contextBudgetStatus = contextBudgetStatus; } const hasUsage = hasNonzeroUsage(usage); if (hasBillableUsage(usage) && !preserveUserFacingRunState) { const { estimateAggregateUsageCost } = await getUsageFormatModule(); const runEstimatedCostUsd = asNonNegativeFiniteNumber(estimateAggregateUsageCost({ usage, provider: providerUsed, model: modelUsed, config: cfg, agentDir: params.agentDir })); if (hasUsage) { next.inputTokens = usage.input ?? 0; next.outputTokens = usage.output ?? 0; next.cacheRead = usage.cacheRead ?? 0; next.cacheWrite = usage.cacheWrite ?? 0; } next.estimatedCostUsd = runEstimatedCostUsd; } if (!preserveUserFacingRunState) { const currentContextSnapshot = params.compactionAccounting?.currentContextSnapshot; if (currentContextSnapshot || hasUsage) { const totalTokens = currentContextSnapshot ? currentContextSnapshot.tokens : deriveSessionTotalTokens({ lastCallUsage, contextTokens, promptTokens }); next.totalTokens = totalTokens; next.totalTokensFresh = totalTokens !== void 0; next.totalTokensVersion = totalTokens !== void 0 ? 1 : void 0; } else { next.totalTokensFresh = false; next.totalTokensVersion = void 0; } } const metadataPatch = preserveUserFacingRunState ? { updatedAt: next.updatedAt, ...touchInteraction ? { lastInteractionAt: next.lastInteractionAt } : {} } : next; const maintenanceConfig = resolveMaintenanceConfigFromInput(cfg.session?.maintenance); await patchSessionEntryCore({ storePath, sessionKey }, (currentEntry, context) => { if (!context.existingEntry && hadPreExistingEntry || !preserveUserFacingRunState && context.existingEntry && (context.existingEntry.sessionId !== expectedSession.sessionId || context.existingEntry.lifecycleRevision !== expectedSession.lifecycleRevision || context.existingEntry.activeWriterRunId !== expectedSession.activeWriterRunId)) return null; return preserveUserFacingRunState ? metadataPatch : projectSessionSnapshotChanges({ initial: entry, next, current: currentEntry, reassertAbortedLastRun: result.meta.aborted === true }); }, { ...preserveUserFacingRunState || params.compactionAccounting ? {} : { fallbackEntry: entry }, maintenanceConfig, onCommitted: (committed) => { sessionStore[sessionKey] = committed; } }); } function isSameSessionLifecycleOwner(current, expected) { return current.sessionId === expected.sessionId && current.lifecycleRevision === expected.lifecycleRevision && current.activeWriterRunId === expected.activeWriterRunId; } async function patchCliSessionForkBinding(params, updateBinding) { const { provider, sessionKey, sessionStore, storePath, expectedCliSessionId } = params; const entry = sessionStore[sessionKey]; if (!entry || entry.cliSessionBindings?.[provider]?.sessionId !== expectedCliSessionId) return; let committed; await patchSessionEntryCore({ storePath, sessionKey }, (currentEntry) => { const currentBinding = currentEntry.cliSessionBindings?.[provider]; if (!isSameSessionLifecycleOwner(currentEntry, entry) || currentBinding?.sessionId !== expectedCliSessionId) return null; const nextBinding = updateBinding(currentBinding); if (!nextBinding) return null; const next = { ...currentEntry }; setCliSessionBinding(next, provider, nextBinding); return next; }, { assertCommitAllowed: params.assertCommitAllowed, onCommitted: (current) => { committed = current; sessionStore[sessionKey] = current; } }); return committed; } /** Clears the one-shot fork marker before the resumed CLI process starts. */ async function consumeCliSessionForkInStore(params) { return await patchCliSessionForkBinding(params, (binding) => { if (binding.forkNextResume !== true) return; const { forkNextResume: _forkNextResume, ...consumedBinding } = binding; return consumedBinding; }); } /** Arms a fork marker for recovery, or re-arms one after a failed CLI turn. */ async function restoreCliSessionForkInStore(params) { return await patchCliSessionForkBinding(params, (binding) => binding.forkNextResume === true ? void 0 : { ...binding, forkNextResume: true }); } /** Rebinds a claimed fork to its successor before the rest of the CLI turn can fail. */ async function persistCliSessionForkSuccessorInStore(params) { if (params.successorCliSessionId === params.expectedCliSessionId) return; return await patchCliSessionForkBinding(params, (binding) => binding.forkNextResume === true ? void 0 : { ...binding, sessionId: params.successorCliSessionId, forceReuse: true }); } /** Records CLI compaction metadata on the persisted session entry. */ async function recordCliCompactionInStore(params) { const { compactionKind, sessionKey, sessionStore, storePath, expectedSession } = params; const entry = sessionStore[sessionKey]; if (!entry) return; const next = { ...entry }; if (compactionKind === "context-engine") clearAllCliSessions(next); next.compactionCount = (entry.compactionCount ?? 0) + 1; next.updatedAt = Date.now(); const tokensAfterCompaction = asNonNegativeFiniteNumber(params.tokensAfter); next.contextBudgetStatus = void 0; next.inputTokens = void 0; next.outputTokens = void 0; next.cacheRead = void 0; next.cacheWrite = void 0; if (tokensAfterCompaction !== void 0) { next.totalTokens = Math.floor(tokensAfterCompaction); next.totalTokensFresh = true; next.totalTokensVersion = 1; } else { next.totalTokensFresh = false; next.totalTokensVersion = void 0; } let committedEntry; await patchSessionEntryCore({ storePath, sessionKey }, (currentEntry, context) => { if (!context.existingEntry || currentEntry.sessionId !== expectedSession.sessionId || currentEntry.lifecycleRevision !== expectedSession.lifecycleRevision || currentEntry.activeWriterRunId !== expectedSession.activeWriterRunId) return null; return { ...currentEntry, ...projectSessionSnapshotChanges({ initial: entry, next, current: currentEntry }), compactionCount: (currentEntry.compactionCount ?? 0) + 1 }; }, { onCommitted: (committed) => { committedEntry = committed; sessionStore[sessionKey] = committed; } }); return committedEntry; } //#endregion export { restoreCliSessionForkInStore as a, recordCliCompactionInStore as i, normalizeSessionTokenCount as n, updateSessionStoreAfterAgentRun as o, persistCliSessionForkSuccessorInStore as r, consumeCliSessionForkInStore as t };