openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
201 lines (200 loc) • 9.1 kB
JavaScript
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 };