UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

201 lines (200 loc) • 9.1 kB
import { n as readGlobalSingleton } from "./global-singleton-0m-JziJW.mjs"; import { i as resolveRuntimeWorkerUrl, n as resolveRuntimeWorkerArgv } from "./runtime-worker-url-CFqA9Dvi.mjs"; import { r as enableNodeSqliteKyselyStatementCache } from "./kysely-sync-cache-state-DbAMR_DD.mjs"; import { h as runSqliteReadOperationSync, i as getAdmittedSqliteSchemaFacts, o as getSqliteReadScopeRevision, t as admitSqliteSchema } from "./sqlite-schema-facts-BVf0E_0z.mjs"; import { n as isArtifactPreservingStateRead } from "./artifact-preserving-state-reads-BQnQLAJR.mjs"; import { f as readExistingAgentSchemaMeta } from "./sqlite-readonly-location-DEj0l7LR.mjs"; import { d as sqlitePrimaryResultCode } from "./sqlite-error-diagnostics-CWRyv4lz.mjs"; import { t as SqliteSchemaMismatchError } from "./sqlite-schema-issues-BnRd2KGO.mjs"; import { s as OPENCLAW_SQLITE_BUSY_TIMEOUT_MS } from "./openclaw-state-db-contract-BYv0nUQr.mjs"; import { r as runSqliteDeferredTransactionSync } from "./sqlite-transaction-DBRLvCDM.mjs"; import { n as runtimeProcessEntrypoints } from "./runtime-process-entrypoints-De68tE_W.mjs"; import { t as openSqliteReadOnlyDatabase } from "./sqlite-snapshot-source-ChTpAJ4b.mjs"; import { i as readSqliteInspectionBudget } from "./sqlite-readonly-worker-RO6waSGe.mjs"; import { s as isDeletedAgentDatabasePath } from "./agent-database-readers-m64TtGjG.mjs"; import { n as normalizeAgentId } from "./agent-id-D1-Q6vR4.mjs"; import { l as recordOpenClawAgentDatabaseReadOpenFailure, r as assertCanonicalSessionValidationSchema, s as classifyOpenClawAgentDatabaseReadError } from "./openclaw-agent-canonical-validation-schema-4dL3LLg2.mjs"; import { o as registerOpenClawAgentDatabaseIdentity } from "./openclaw-agent-db-identity-BlmER9-X.mjs"; import { i as assertSupportedAgentSchemaVersion, r as assertExistingAgentSchemaOwner, t as assertCanonicalAgentPersistenceVersion } from "./openclaw-agent-db-schema-read-y-s2h2dU.mjs"; import { t as assertSqliteIntegrityInWorker } from "./sqlite-integrity-worker-B-14oZqk.mjs"; import { u as hasOpenClawAgentCanonicalValidation } from "./openclaw-agent-db-validation-cache-CHrtutWN.mjs"; import { i as isIncognitoOpenClawAgentSqlitePath, l as resolveOpenClawAgentSqlitePath } from "./openclaw-agent-db.paths-BbmZlEP5.mjs"; import { o as readOpenClawDatabaseQuarantineFailure } from "./openclaw-quarantine-store-CUJxC7wy.mjs"; import fs from "node:fs"; import { spawnSync } from "node:child_process"; import { isMainThread } from "node:worker_threads"; //#region src/state/openclaw-agent-db-terminal.ts function terminalLatch() { return readGlobalSingleton(Symbol.for("openclaw.agentDatabaseLifecycle"))?.terminal; } /** Read the existing damage latch without acquiring the writable database lifecycle. */ function assertAgentDatabaseTerminalOpenAllowed(pathname) { const failure = terminalLatch()?.get(pathname); if (failure) throw failure; } /** Only latched integrity failures need a fresh native check after external repair. */ function revalidateAgentDatabaseTerminalOpen(pathname) { const latch = terminalLatch(); const failure = latch?.peek(pathname); if (latch && failure?.name === "SqliteIntegrityError") { const workerUrl = resolveRuntimeWorkerUrl(runtimeProcessEntrypoints.databaseVerify); const child = spawnSync(process.execPath, [ ...resolveRuntimeWorkerArgv(workerUrl), "--openclaw-database-verify-sync", pathname ], { timeout: readSqliteInspectionBudget("integrity check", pathname).timeoutMs, killSignal: "SIGKILL", stdio: "ignore" }); if (child.error || child.status !== 0) throw failure; latch.clear(pathname); } assertAgentDatabaseTerminalOpenAllowed(pathname); } async function revalidateAgentDatabaseTerminalOpenAsync(pathname, assertCurrent, signal = new AbortController().signal) { const latch = terminalLatch(); const failure = latch?.peek(pathname); if (latch && failure?.name === "SqliteIntegrityError") { await assertSqliteIntegrityInWorker(pathname, OPENCLAW_SQLITE_BUSY_TIMEOUT_MS, signal); assertCurrent?.(); if (latch.peek(pathname) === failure) latch.clear(pathname); } assertCurrent?.(); assertAgentDatabaseTerminalOpenAllowed(pathname); } //#endregion //#region src/state/openclaw-agent-db-readonly-open.ts function readOpenClawAgentDatabase(database, operation) { try { return { found: true, value: operation(database) }; } catch (error) { throw sqlitePrimaryResultCode(error) === 1 ? classifyOpenClawAgentDatabaseReadError(database.db, error) : error; } } function hasAdmittedAgentReadOnlySchema(database) { const userVersion = assertSupportedAgentSchemaVersion(database.db, database.path); assertCanonicalAgentPersistenceVersion(database.db, database.path, userVersion); const schemaMeta = readExistingAgentSchemaMeta(database.db); if (!schemaMeta) return false; assertExistingAgentSchemaOwner(schemaMeta, database.agentId, database.path); assertCanonicalSessionValidationSchema(database.db); return true; } /** Retained grants reuse their fresh read scope without re-admitting changed schema under a lock. */ function captureOpenClawAgentReadOnlyAdmission(database) { const changed = () => new SqliteSchemaMismatchError(`OpenClaw agent database ${database.path} schema admission changed; retry the request.`); const schema = getAdmittedSqliteSchemaFacts(database.db); if (!schema) throw changed(); return () => { if (getSqliteReadScopeRevision(database.db)?.schema !== schema || !hasAdmittedAgentReadOnlySchema(database)) throw changed(); }; } /** Recheck admission and consume retained rows in the same fresh synchronous scope. */ function hasOpenClawAgentReadOnlySchema(database, onAdmitted) { return runSqliteReadOperationSync(database.db, () => { if (!hasAdmittedAgentReadOnlySchema(database)) return false; onAdmitted?.(); return true; }, "fresh"); } /** Admit ownership and consume its rows in the same freshly pinned snapshot. */ function readOpenClawAgentDatabaseSnapshot(database, operation) { let result = { found: false, reason: "schema-missing" }; runSqliteDeferredTransactionSync(database.db, () => { if (hasAdmittedAgentReadOnlySchema(database)) { result = readOpenClawAgentDatabase(database, operation); return result.value; } }); return result; } /** Fresh-only callers do not need the writable runtime's process-held connection cache. */ function withFreshOpenClawAgentDatabaseReadOnly(operation, options, behavior = {}) { const opened = openOpenClawAgentDatabaseReadOnly(options, behavior); if (!opened.found) return opened; try { return behavior.snapshot ? readOpenClawAgentDatabaseSnapshot(opened.database, operation) : readOpenClawAgentDatabase(opened.database, operation); } finally { opened.database.close(); } } /** Open one existing agent database without creating, registering, migrating, or adopting it. */ function openOpenClawAgentDatabaseReadOnly(options, behavior = {}) { const agentId = normalizeAgentId(options.agentId); const pathname = resolveOpenClawAgentSqlitePath({ ...options, agentId }); if (isIncognitoOpenClawAgentSqlitePath(pathname, { agentId, env: options.env })) return { found: false, reason: "database-missing" }; if (isDeletedAgentDatabasePath(pathname) || !fs.existsSync(pathname)) return { found: false, reason: "database-missing" }; revalidateAgentDatabaseTerminalOpen(pathname); const persistedQuarantine = readOpenClawDatabaseQuarantineFailure("agent", pathname, { env: options.env }); if (persistedQuarantine) { recordOpenClawAgentDatabaseReadOpenFailure(persistedQuarantine); throw persistedQuarantine; } let db; try { db = openSqliteReadOnlyDatabase(pathname, { timeout: OPENCLAW_SQLITE_BUSY_TIMEOUT_MS, ...behavior.allowExtension ? { allowExtension: true } : {} }); } catch (error) { recordOpenClawAgentDatabaseReadOpenFailure(error); throw error; } let closed = false; const close = () => { if (closed) return; if (db.isOpen) db.close(); closed = true; }; try { enableNodeSqliteKyselyStatementCache(db); registerOpenClawAgentDatabaseIdentity(db); const privatePath = isArtifactPreservingStateRead("agent", pathname) ? db.location() : void 0; const database = { agentId, db, path: privatePath ?? pathname, close }; if (!runSqliteReadOperationSync(db, () => { admitSqliteSchema(db); return hasAdmittedAgentReadOnlySchema(database); })) { close(); return { found: false, reason: "schema-missing" }; } if (!isMainThread) hasOpenClawAgentCanonicalValidation(database); return { found: true, database }; } catch (error) { close(); recordOpenClawAgentDatabaseReadOpenFailure(error); throw error; } } //#endregion export { readOpenClawAgentDatabaseSnapshot as a, revalidateAgentDatabaseTerminalOpen as c, readOpenClawAgentDatabase as i, revalidateAgentDatabaseTerminalOpenAsync as l, hasOpenClawAgentReadOnlySchema as n, withFreshOpenClawAgentDatabaseReadOnly as o, openOpenClawAgentDatabaseReadOnly as r, assertAgentDatabaseTerminalOpenAllowed as s, captureOpenClawAgentReadOnlyAdmission as t };