UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

210 lines (209 loc) 8.55 kB
import { t as isFastTestRuntimeEnv } from "./test-runtime-env-DQDRzsLt.js"; import "./env-M3R40TOb.js"; import { xt as updateSessionEntry } from "./session-accessor-YsytfDtG.js"; import { d as patchSessionEntryCore } from "./session-accessor.sqlite-entry-CWk3jL7s.js"; import { c as projectCanonicalSessionEntryShape } from "./store-writer-state-C4OG_EQ4.js"; import { t as clearAllCliSessions } from "./cli-session-binding-Aa6nlDa8.js"; import "./sessions-9nxpeTwt.js"; import "./cli-session-pAa_-y_N.js"; import { n as resolveNodeExecEligibility } from "./exec-defaults-CET-_UfH.js"; import { t as getRemoteSkillEligibility } from "./remote-D-j1AEXQ.js"; import { t as resolveReusableWorkspaceSkillSnapshot } from "./session-snapshot-CnGGVFJ3.js"; import crypto from "node:crypto"; //#region src/auto-reply/reply/session-updates.ts /** Session update helpers for skill snapshots and completed compaction accounting. */ async function persistSessionEntryUpdate(params) { if (!params.sessionEntryHandle && (!params.sessionStore || !params.sessionKey)) return; if (!params.storePath || !params.sessionKey) { if (params.sessionEntryHandle) params.sessionEntryHandle.replaceCurrent(params.nextEntry); else if (params.sessionStore && params.sessionKey) params.sessionStore[params.sessionKey] = { ...params.sessionStore[params.sessionKey], ...params.nextEntry }; return params.nextEntry; } const persistedEntry = await updateSessionEntry({ storePath: params.storePath, sessionKey: params.sessionKey }, (entry) => entry.sessionId === params.expectedSessionId ? params.updates : null); if (persistedEntry) { if (params.sessionEntryHandle) params.sessionEntryHandle.replaceCurrent(persistedEntry); else if (params.sessionStore && params.sessionKey) params.sessionStore[params.sessionKey] = persistedEntry; return persistedEntry; } params.sessionEntryHandle?.clearCurrent(); if (params.sessionStore && params.sessionKey) delete params.sessionStore[params.sessionKey]; } function resolveNonNegativeTokenCount(value) { return typeof value === "number" && Number.isFinite(value) && value >= 0 ? Math.floor(value) : void 0; } /** Ensures a session entry has the reusable skill snapshot needed for reply runs. */ async function ensureSkillSnapshot(params) { if (isFastTestRuntimeEnv()) return { sessionEntry: params.sessionEntry, skillsSnapshot: params.sessionEntry?.skillsSnapshot, systemSent: params.sessionEntry?.systemSent ?? false }; const { agentId, sessionEntry, sessionEntryHandle, sessionStore, sessionKey, storePath, sessionId, isFirstTurnInSession, workspaceDir, cfg, skillFilter, skillOverrides } = params; let nextEntry = sessionEntryHandle?.getCurrent() ?? sessionEntry; let systemSent = sessionEntry?.systemSent ?? false; const nodeSkillsEligibility = resolveNodeExecEligibility({ cfg, sessionEntry, sessionKey, agentId, execOverrides: params.execOverrides }); const remoteEligibility = getRemoteSkillEligibility({ advertiseExecNode: nodeSkillsEligibility.canExec }); const existingSnapshot = nextEntry?.skillsSnapshot; const resolveSnapshot = (snapshot) => resolveReusableWorkspaceSkillSnapshot({ workspaceDir, ...params.executionSkillsDir ? { executionSkillsDir: params.executionSkillsDir } : {}, config: cfg, agentId, skillFilter, skillOverrides, eligibility: { nodeSkills: nodeSkillsEligibility, remote: remoteEligibility }, existingSnapshot: snapshot, librarySelections: nextEntry?.skillLibrarySelections }); const initialSnapshotState = resolveSnapshot(existingSnapshot); const shouldRefreshSnapshot = initialSnapshotState.shouldRefresh; if (isFirstTurnInSession && (sessionEntryHandle || sessionStore) && sessionKey) { const current = nextEntry ?? sessionEntryHandle?.get(sessionKey) ?? sessionStore?.[sessionKey] ?? { sessionId: sessionId ?? crypto.randomUUID(), updatedAt: Date.now() }; const skillSnapshot = !current.skillsSnapshot || shouldRefreshSnapshot ? initialSnapshotState.snapshot : resolveSnapshot(current.skillsSnapshot).snapshot; nextEntry = { ...current, sessionId: sessionId ?? current.sessionId ?? crypto.randomUUID(), updatedAt: Date.now(), systemSent: true, skillsSnapshot: skillSnapshot }; const persistedEntry = await persistSessionEntryUpdate({ expectedSessionId: current.sessionId, sessionEntryHandle, sessionStore, sessionKey, storePath, nextEntry, updates: { sessionId: nextEntry.sessionId, updatedAt: nextEntry.updatedAt, systemSent: nextEntry.systemSent, skillsSnapshot: nextEntry.skillsSnapshot } }); nextEntry = persistedEntry; systemSent = persistedEntry?.systemSent ?? systemSent; } const skillsSnapshot = Boolean(nextEntry?.skillsSnapshot) && (nextEntry?.skillsSnapshot !== existingSnapshot || !shouldRefreshSnapshot) && nextEntry?.skillsSnapshot ? resolveSnapshot(nextEntry.skillsSnapshot).snapshot : shouldRefreshSnapshot || !nextEntry?.skillsSnapshot ? initialSnapshotState.snapshot : resolveSnapshot(nextEntry.skillsSnapshot).snapshot; if (skillsSnapshot && (sessionEntryHandle || sessionStore) && sessionKey && !isFirstTurnInSession && (!nextEntry?.skillsSnapshot || shouldRefreshSnapshot)) { const current = nextEntry ?? { sessionId: sessionId ?? crypto.randomUUID(), updatedAt: Date.now() }; nextEntry = { ...current, sessionId: sessionId ?? current.sessionId ?? crypto.randomUUID(), updatedAt: Date.now(), skillsSnapshot }; nextEntry = await persistSessionEntryUpdate({ expectedSessionId: current.sessionId, sessionEntryHandle, sessionStore, sessionKey, storePath, nextEntry, updates: { sessionId: nextEntry.sessionId, updatedAt: nextEntry.updatedAt, skillsSnapshot: nextEntry.skillsSnapshot } }); } return { sessionEntry: nextEntry, skillsSnapshot, systemSent }; } /** Accounts completed compaction without creating or changing session ownership. */ async function incrementCompactionCount(params) { const { sessionStore, sessionKey, storePath, authorize } = params; if (!sessionKey || !storePath && !sessionStore) return; const cachedEntry = sessionStore?.[sessionKey] ?? params.sessionEntry; const initial = params.expectedSession ?? cachedEntry; if (!initial) return; const expected = { sessionId: initial.sessionId, lifecycleRevision: initial.lifecycleRevision, activeWriterRunId: initial.activeWriterRunId }; const incrementBy = Math.max(0, params.amount ?? 1); const tokensAfter = resolveNonNegativeTokenCount(params.tokensAfter); const update = (current) => { if (!(authorize?.() ?? true) || current.sessionId !== expected.sessionId || current.lifecycleRevision !== expected.lifecycleRevision || current.activeWriterRunId !== expected.activeWriterRunId) return null; const patch = { compactionCount: (current.compactionCount ?? 0) + incrementBy, transcriptByteCompactionLatch: params.transcriptByteCompactionLatch, updatedAt: params.now ?? Date.now(), ...incrementBy > 0 ? { contextBudgetStatus: void 0 } : {} }; if (params.compactionKind === "context-engine") clearAllCliSessions(patch); if (tokensAfter !== void 0) { patch.totalTokens = tokensAfter; patch.totalTokensFresh = true; patch.totalTokensVersion = 1; patch.inputTokens = void 0; patch.outputTokens = void 0; patch.cacheRead = void 0; patch.cacheWrite = void 0; } else if (incrementBy > 0) { patch.totalTokensFresh = false; patch.totalTokensVersion = void 0; } return patch; }; if (storePath) { let committed = false; const authorityRevoked = /* @__PURE__ */ new Error("compaction accounting authority revoked"); let persisted; try { persisted = await patchSessionEntryCore({ agentId: params.agentId, storePath, sessionKey }, update, { onCommitted: (entry) => { committed = true; if (sessionStore) sessionStore[sessionKey] = entry; }, ...authorize ? { assertCommitAllowed: () => { if (!authorize()) throw authorityRevoked; } } : {} }); } catch (error) { if (error === authorityRevoked) return; throw error; } if (!committed || !persisted) return; return persisted.compactionCount; } const patch = cachedEntry && update(cachedEntry); if (!sessionStore || !cachedEntry || !patch) return; const nextEntry = projectCanonicalSessionEntryShape({ ...cachedEntry, ...patch }); sessionStore[sessionKey] = nextEntry; return nextEntry.compactionCount; } //#endregion export { incrementCompactionCount as n, ensureSkillSnapshot as t };