UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

130 lines (129 loc) • 6.19 kB
import { a as resolveGlobalSingleton } from "./global-singleton-0m-JziJW.mjs"; import { c as registerNodeSqliteDisposeCallback } from "./kysely-sync-cache-state-DbAMR_DD.mjs"; import { m as registerSqliteSchemaMutationListener } from "./sqlite-schema-facts-BVf0E_0z.mjs"; import { d as readDatabasePathIdentitySync, r as assertExistingDatabaseIdentity } from "./sqlite-worker-identity-BRNRpRyc.mjs"; import { a as resolveExistingSqliteFileUri, r as openNodeSqliteDatabase } from "./node-sqlite-DyeJqxPf.mjs"; import { p as withSqliteNativeOpen } from "./sqlite-error-diagnostics-CWRyv4lz.mjs"; import { o as stageSqliteTransactionState } from "./sqlite-post-commit-DENvzR6w.mjs"; import { i as assertStateDatabaseAccessAllowed } from "./gateway-state-owner-eDtEELE9.mjs"; import { n as assertSqliteIntegrity } from "./sqlite-integrity-D3yHPOet.mjs"; //#region src/state/openclaw-state-db-handle.ts const identities = resolveGlobalSingleton(Symbol.for("openclaw.stateNativeIdentities"), () => /* @__PURE__ */ new WeakMap()); /** Physical identity admitted by the native opener, never a later pathname observation. */ function readTrackedStateDatabaseIdentity(database) { return identities.get(database); } function openTrackedStateDatabase(pathname, options) { const result = openTrackedStateDatabaseResult(pathname, options); if (result.status === "unavailable") throw result.error; return result.database; } /** Native open failure is an ordinary read failure; admitted handles retain their own cleanup. */ function openTrackedStateDatabaseResult(pathname, options) { assertStateDatabaseAccessAllowed(pathname); try { if (options?.expectedIdentity !== void 0) assertExistingDatabaseIdentity(pathname, options.expectedIdentity); const location = options?.existingOnly || options?.expectedIdentity !== void 0 ? resolveExistingSqliteFileUri(pathname) : pathname; const nativeOptions = options?.readOnly ? { readOnly: true, timeout: options.timeout } : { enableForeignKeyConstraints: options?.enableForeignKeyConstraints }; const openingIdentity = readDatabasePathIdentitySync(pathname); const database = withSqliteNativeOpen(() => openNodeSqliteDatabase(location, nativeOptions)); try { assertStateDatabaseAccessAllowed(pathname); if (openingIdentity.key.startsWith("file:")) assertExistingDatabaseIdentity(pathname, openingIdentity.key, openingIdentity.birthtime); const identity = openingIdentity.key.startsWith("file:") ? openingIdentity : readDatabasePathIdentitySync(pathname); if (identity.key.startsWith("file:")) { identities.set(database, identity); const unregister = registerNodeSqliteDisposeCallback(database, () => { identities.delete(database); unregister(); }); } } catch (error) { database.close(); throw error; } return { status: "available", database }; } catch (error) { return { status: "unavailable", error }; } } function closeTrackedStateDatabase(database) { if (database.isOpen) database.close(); } //#endregion //#region src/state/openclaw-state-db-integrity-admission.ts const bindings = resolveGlobalSingleton(Symbol.for("openclaw.stateIntegrityBindings"), () => /* @__PURE__ */ new WeakMap()); function invalidate(revision) { let previous = Atomics.load(revision, 0); while (previous >= 0n) { const observed = Atomics.compareExchange(revision, 0, previous, previous + 1n); if (observed === previous) return; previous = observed; } } /** Corruption observed in an isolate revokes the exact host proof borrowed by its native handle. */ function invalidateOpenClawStateRuntimeIntegrity(database) { const bound = bindings.get(database); if (bound) invalidate(new BigInt64Array(bound.revision)); } /** Native bindings revoke borrowed proof; the host generation alone owns its lifetime. */ function bind(database, admission) { if (bindings.get(database)?.revision === admission.revision) return; bindings.get(database)?.release(); const revision = new BigInt64Array(admission.revision); const unobserve = registerSqliteSchemaMutationListener(database, () => invalidate(revision)); const release = () => { unobserve(); unregister(); }; const unregister = registerNodeSqliteDisposeCallback(database, (reason) => { if (reason === "replace") invalidate(revision); release(); }); bindings.set(database, { revision: admission.revision, release }); } /** Reuse only completed integrity proof; shape and mutable metadata retain their admission owners. */ function assertOpenClawStateRuntimeIntegrity(database, pathname, schema, admission, policy = "verify") { const identity = admission && readTrackedStateDatabaseIdentity(database); if (!admission || !identity || !identity.key.startsWith("file:") || identity.key !== admission.identity.key || identity.birthtime !== admission.identity.birthtime) { if (policy === "require-proof") throw new Error("Shared-state reader requires current worker integrity proof"); assertSqliteIntegrity(database, pathname); return; } bind(database, admission); const revision = new BigInt64Array(admission.revision); const proof = new BigInt64Array(admission.proof); const metadata = BigInt.asIntN(64, BigInt(schema.userVersion >>> 0) << 32n | BigInt(schema.schemaVersion >>> 0)); const observed = Atomics.load(proof, 0); if (Atomics.load(revision, 0) === admission.epoch && observed !== -1n) { if (observed === metadata && Atomics.load(revision, 0) === admission.epoch) return; invalidate(revision); } if (policy === "require-proof") throw new Error("Shared-state reader requires current worker integrity proof"); assertSqliteIntegrity(database, pathname); const publish = () => { if (Atomics.load(revision, 0) === admission.epoch) Atomics.store(proof, 0, metadata); }; return () => { if (database.isTransaction) stageSqliteTransactionState(database, { stage() {}, rollback() {}, commit: publish }); else publish(); }; } //#endregion export { openTrackedStateDatabaseResult as a, openTrackedStateDatabase as i, invalidateOpenClawStateRuntimeIntegrity as n, readTrackedStateDatabaseIdentity as o, closeTrackedStateDatabase as r, assertOpenClawStateRuntimeIntegrity as t };