UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

514 lines (513 loc) 26.4 kB
import { i as resolveGlobalSingleton } from "./global-singleton-Dc_stLtU.js"; import { r as isPathInside } from "./path-guards-Cp-mGr3-.js"; import { n as ok, t as err } from "./result-BQGgYouL.js"; import { n as normalizeAgentId } from "./agent-id-CeT3w4ap.js"; import "./session-key-BnWWjqNc.js"; import { n as normalizeAgentDirRegistryPath } from "./agent-dir-registry-Dkh28921.js"; import { a as getNodeSqliteKysely, i as executeSqliteQueryTakeFirstSync, r as executeSqliteQuerySync } from "./kysely-sync-COmh4HWh.js"; import { i as resolveOpenClawRegisteredAgentDatabasePath, o as resolveOpenClawStateSqliteDir, s as resolveOpenClawStateSqlitePath } from "./openclaw-state-db-schema-version-c1ZL6JGz.js"; import { S as ensureAgentDeletionJournalSchema, dt as resolveSqliteDatabaseFilePaths, i as openOpenClawStateDatabase, s as runOpenClawStateWriteTransaction, x as ensureAgentDatabaseLeaseSchema } from "./openclaw-state-db-BRTnL-D8.js"; import { i as isPidDefinitelyDead, t as getFileLockProcessStartTime } from "./pid-alive-XuW58Ofz.js"; import { n as ensureAgentProvenanceSchema, t as deleteAgentProvenanceForAgent } from "./agent-provenance-Cp8HmAX0.js"; import { existsSync } from "node:fs"; import path from "node:path"; import { AsyncLocalStorage } from "node:async_hooks"; import crypto from "node:crypto"; //#region src/state/openclaw-agent-db.paths.ts const INCOGNITO_AGENT_SQLITE_BASENAME = "incognito-openclaw-agent.sqlite"; /** Resolve the SQLite file for one normalized agent id. */ function resolveOpenClawAgentSqlitePath(options) { const agentId = normalizeAgentId(options.agentId); return path.resolve(options.path ?? path.join(path.dirname(resolveOpenClawStateSqliteDir(options.env ?? process.env)), "agents", agentId, "agent", "openclaw-agent.sqlite")); } /** Resolve the lexical sentinel path that keys one agent's process-held incognito database. */ function resolveIncognitoOpenClawAgentSqlitePath(options) { return path.join(path.dirname(resolveOpenClawAgentSqlitePath(options)), INCOGNITO_AGENT_SQLITE_BASENAME); } /** Identify the reserved incognito sentinel without touching its filesystem path. */ function isIncognitoOpenClawAgentSqlitePath(pathname, options) { return path.resolve(pathname) === resolveIncognitoOpenClawAgentSqlitePath(options); } //#endregion //#region src/state/agent-deletion-cleanup.ts const databaseCleanup = resolveGlobalSingleton(Symbol.for("openclaw.agentDeletionDatabaseCleanup"), () => new AsyncLocalStorage()); const cleanupHandles = resolveGlobalSingleton(Symbol.for("openclaw.agentDeletionDatabaseCleanupHandles"), () => /* @__PURE__ */ new Map()); /** The lifecycle owner supplies live closures, never a transferable operation id. */ function createAgentDeletionDatabaseCleanup(owner) { return async (target, run) => { let active = true; const closers = []; const assertActive = () => { if (!active) throw new Error("Agent deletion database cleanup is no longer active."); }; const scope = { agentId: normalizeAgentId(target.agentId), path: path.resolve(target.path), statePath: path.resolve(owner.statePath), assertCurrent: () => { assertActive(); owner.assertCurrent(); }, assertJournal: (statePath, entries) => { assertActive(); return owner.assertJournal(statePath, entries); }, registerClose: (close) => { assertActive(); closers.push(close); } }; return await databaseCleanup.run(scope, async () => { let outcome; const closeErrors = []; try { scope.assertCurrent(); owner.assertAdmission(); outcome = ok(await run()); } catch (error) { outcome = err(error); } finally { for (const close of closers.toReversed()) try { close(); } catch (error) { closeErrors.push(error); } active = false; closers.length = 0; } if (!outcome.ok) throw closeErrors.length > 0 ? new AggregateError([outcome.error, ...closeErrors], "Agent deletion database cleanup failed.") : outcome.error; if (closeErrors.length > 0) throw closeErrors.length === 1 ? closeErrors[0] : new AggregateError(closeErrors, "Agent deletion database cleanup failed."); return outcome.value; }); }; } function getAgentDeletionDatabaseCleanup(params) { const scope = databaseCleanup.getStore(); if (!scope || scope.agentId !== normalizeAgentId(params.agentId) || scope.path !== resolveOpenClawAgentSqlitePath(params)) return; const statePath = params.statePath ?? resolveOpenClawStateSqlitePath(params.env ?? process.env); if (scope.statePath !== path.resolve(statePath)) throw new Error("Agent deletion database cleanup belongs to another state database."); return scope; } function assertAgentDeletionDatabaseCleanupAccess(database, options) { const scope = getAgentDeletionDatabaseCleanup(options); const owner = cleanupHandles.get(database); if (owner && owner !== scope) throw new Error("Agent database belongs to an active deletion cleanup."); scope?.assertCurrent(); } function assertAgentDeletionCleanupAliases(options, isSamePath) { const pathname = resolveOpenClawAgentSqlitePath(options); for (const owned of cleanupHandles.keys()) if (isSamePath(owned.path, pathname)) assertAgentDeletionDatabaseCleanupAccess(owned, options); } function registerAgentDeletionDatabaseCleanup(database, options) { const scope = getAgentDeletionDatabaseCleanup(options); scope?.assertCurrent(); if (scope) cleanupHandles.set(database, scope); return scope; } /** Release the tag only after the native owner has closed and released its lease. */ function releaseAgentDeletionDatabaseCleanup(database) { cleanupHandles.delete(database); } //#endregion //#region src/state/agent-deletion-journal.ts function assertAgentDeletionIdentityClaimAllowed(claimAgentId, deletedAgentId) { if (deletedAgentId && normalizeAgentId(claimAgentId) === normalizeAgentId(deletedAgentId)) throw new Error(`OpenClaw agent database is unavailable while agent ${normalizeAgentId(deletedAgentId)} is deleted.`); } function prepareAgentDeletionPathFence(claim, options = {}) { let rows = []; runOpenClawStateWriteTransaction((database) => { ensureAgentDeletionJournalSchema(database.db); const db = getNodeSqliteKysely(database.db); rows = executeSqliteQuerySync(database.db, db.selectFrom("agent_deletion_journal").select([ "agent_id", "operation_id", "agent_dir", "workspace_dir", "sessions_dir", "database_paths_json", "cleanup_paths_json", "cleanup_completed" ])).rows; }, options); const env = options.env ?? process.env; return { claimAgentId: normalizeAgentId(claim.agentId), claimPath: path.resolve(claim.path), ...claim.fenceAgentId ? { fenceAgentId: normalizeAgentId(claim.fenceAgentId) } : {}, targetPaths: resolveSqliteDatabaseFilePaths(claim.path).map((filePath) => normalizeAgentDirRegistryPath(filePath, env)), entries: rows.map((row) => ({ agentId: row.agent_id, operationId: row.operation_id, agentDir: row.agent_dir, workspaceDir: row.workspace_dir, sessionsDir: row.sessions_dir, cleanupCompleted: row.cleanup_completed === 1, canonicalPaths: [ row.agent_dir, row.workspace_dir, row.sessions_dir ].map((entryPath) => normalizeAgentDirRegistryPath(entryPath, env)), databasePaths: parseDatabasePaths(row.database_paths_json).map((databasePath) => ({ path: databasePath, canonicalPath: normalizeAgentDirRegistryPath(databasePath, env) })), cleanupPaths: parseCleanupPaths(row.cleanup_paths_json).map((cleanupPath) => Object.assign({}, cleanupPath, { fencePath: normalizeAgentDirRegistryPath(cleanupPath.canonicalPath, env) })) })) }; } /** Refuse database claims beneath paths still owned by an unfinished deletion. */ function assertAgentDeletionPathFence(state, snapshot) { const database = state.db; ensureAgentDeletionJournalSchema(database); const db = getNodeSqliteKysely(database); const journalRows = executeSqliteQuerySync(database, db.selectFrom("agent_deletion_journal").select([ "agent_id", "operation_id", "agent_dir", "workspace_dir", "sessions_dir", "database_paths_json", "cleanup_paths_json", "cleanup_completed" ])).rows; const snapshotJournal = snapshot.entries.map((entry) => [ entry.agentId, entry.operationId, entry.agentDir, entry.workspaceDir, entry.sessionsDir, JSON.stringify(entry.databasePaths.map((candidate) => candidate.path)), JSON.stringify(entry.cleanupPaths.map(({ fencePath: _fencePath, ...candidate }) => ({ ...candidate }))), entry.cleanupCompleted ? 1 : 0 ].join("\0")).toSorted(); const currentJournal = journalRows.map((row) => [ row.agent_id, row.operation_id, row.agent_dir, row.workspace_dir, row.sessions_dir, row.database_paths_json, row.cleanup_paths_json, row.cleanup_completed ].join("\0")).toSorted(); if (snapshotJournal.join("\n") !== currentJournal.join("\n")) throw new Error("Agent deletion journal changed while preparing a database claim."); const cleanupAgentId = (snapshot.fenceAgentId ? void 0 : getAgentDeletionDatabaseCleanup({ agentId: snapshot.claimAgentId, path: snapshot.claimPath, statePath: state.path }))?.assertJournal(state.path, journalRows.map((row) => ({ agentId: row.agent_id, operationId: row.operation_id, cleanupCompleted: row.cleanup_completed === 1 }))); for (const row of journalRows) { if (snapshot.fenceAgentId && snapshot.fenceAgentId !== row.agent_id) continue; if (row.agent_id === cleanupAgentId) continue; assertAgentDeletionIdentityClaimAllowed(snapshot.claimAgentId, row.agent_id); if (row.cleanup_completed === 1) continue; const entry = snapshot.entries.find((candidate) => candidate.agentId === row.agent_id && candidate.operationId === row.operation_id && candidate.agentDir === row.agent_dir && candidate.workspaceDir === row.workspace_dir && candidate.sessionsDir === row.sessions_dir && JSON.stringify(candidate.databasePaths.map((databasePath) => databasePath.path)) === row.database_paths_json && JSON.stringify(candidate.cleanupPaths.map(({ fencePath: _fencePath, ...cleanupPath }) => ({ ...cleanupPath }))) === row.cleanup_paths_json); if (!entry) throw new Error("Agent deletion journal changed while preparing a database claim."); const fences = [ ...entry.canonicalPaths.map((canonicalPath, index) => ({ canonicalPath, path: [ entry.agentDir, entry.workspaceDir, entry.sessionsDir ][index] })), ...entry.databasePaths, ...entry.cleanupPaths.map((cleanupPath) => ({ path: cleanupPath.path, canonicalPath: cleanupPath.fencePath })) ]; for (const fence of fences) { const blockedPath = snapshot.targetPaths.find((targetPath) => targetPath === fence.canonicalPath || isPathInside(fence.canonicalPath, targetPath)); if (blockedPath) throw new Error(`OpenClaw agent database ${blockedPath} is unavailable while agent ${row.agent_id} deletion owns ${fence.path}.`); } } } function fromRow(row) { return { agentId: row.agent_id, operationId: row.operation_id, agentDir: row.agent_dir, workspaceDir: row.workspace_dir, sessionsDir: row.sessions_dir, databasePaths: parseDatabasePaths(row.database_paths_json), cleanupPaths: parseCleanupPaths(row.cleanup_paths_json), createdAt: row.created_at, cleanupCompleted: row.cleanup_completed === 1, deleteFiles: row.delete_files === 1 }; } function parseDatabasePaths(value) { const parsed = JSON.parse(value); if (!Array.isArray(parsed) || !parsed.every((entry) => typeof entry === "string")) throw new Error("Invalid agent deletion database path journal."); return parsed; } function parseCleanupPaths(value) { const parsed = JSON.parse(value); if (!Array.isArray(parsed) || !parsed.every((entry) => typeof entry === "object" && entry !== null && typeof entry.path === "string" && typeof entry.canonicalPath === "string" && typeof entry.parentPath === "string" && (entry.kind === "target" || entry.kind === "symlink") && (entry.dev === null || typeof entry.dev === "number") && (entry.ino === null || typeof entry.ino === "number") && typeof entry.coversDescendants === "boolean" && typeof entry.done === "boolean" && (entry.note === void 0 || typeof entry.note === "string") && Array.isArray(entry.sourcePaths) && entry.sourcePaths.every((sourcePath) => typeof sourcePath === "string"))) throw new Error("Invalid agent deletion cleanup path journal."); return parsed; } function readAgentDeletionJournal(agentId, options = {}) { const id = normalizeAgentId(agentId); const databasePath = path.resolve(options.path ?? resolveOpenClawStateSqlitePath(options.env ?? process.env)); if (!existsSync(databasePath)) return; let entry; runOpenClawStateWriteTransaction((database) => { ensureAgentDeletionJournalSchema(database.db); const db = getNodeSqliteKysely(database.db); const row = executeSqliteQueryTakeFirstSync(database.db, db.selectFrom("agent_deletion_journal").selectAll().where("agent_id", "=", id)); entry = row ? fromRow(row) : void 0; }, options); return entry; } function beginAgentDeletionJournal(entry, options = {}) { const normalized = { ...entry, agentId: normalizeAgentId(entry.agentId), databasePaths: [...new Set((entry.databasePaths ?? []).map((entryPath) => path.resolve(entryPath)))], cleanupPaths: entry.cleanupPaths ?? [] }; let persisted; ensureAgentProvenanceSchema(options); runOpenClawStateWriteTransaction((database) => { ensureAgentDeletionJournalSchema(database.db); const db = getNodeSqliteKysely(database.db); const existing = executeSqliteQueryTakeFirstSync(database.db, db.selectFrom("agent_deletion_journal").selectAll().where("agent_id", "=", normalized.agentId)); const registeredDatabasePaths = executeSqliteQuerySync(database.db, db.selectFrom("agent_databases").select("path").where("agent_id", "=", normalized.agentId)).rows.flatMap((row) => resolveSqliteDatabaseFilePaths(resolveOpenClawRegisteredAgentDatabasePath(database.path, row.path))); const databasePaths = [...new Set([ ...existing ? fromRow(existing).databasePaths : [], ...normalized.databasePaths, ...registeredDatabasePaths ].map((entryPath) => path.resolve(entryPath)))]; const cleanupPaths = existing ? fromRow(existing).cleanupPaths : normalized.cleanupPaths; if (existing) { executeSqliteQuerySync(database.db, db.updateTable("agent_deletion_journal").set({ operation_id: normalized.operationId, database_paths_json: JSON.stringify(databasePaths), cleanup_paths_json: JSON.stringify(cleanupPaths), cleanup_completed: 0, delete_files: normalized.deleteFiles ? 1 : 0 }).where("agent_id", "=", normalized.agentId)); persisted = { ...fromRow(existing), operationId: normalized.operationId, databasePaths, cleanupPaths, cleanupCompleted: false, deleteFiles: normalized.deleteFiles }; return; } const createdAt = Date.now(); executeSqliteQuerySync(database.db, db.insertInto("agent_deletion_journal").values({ agent_id: normalized.agentId, operation_id: normalized.operationId, agent_dir: normalized.agentDir, workspace_dir: normalized.workspaceDir, sessions_dir: normalized.sessionsDir, database_paths_json: JSON.stringify(databasePaths), cleanup_paths_json: JSON.stringify(cleanupPaths), created_at: createdAt, cleanup_completed: 0, delete_files: normalized.deleteFiles ? 1 : 0 })); persisted = { ...normalized, databasePaths, cleanupPaths, createdAt, cleanupCompleted: false }; }, options); if (!persisted) throw new Error(`Failed to record deletion journal for agent ${normalized.agentId}.`); return persisted; } function updateAgentDeletionJournalCleanupPaths(agentId, operationId, cleanupPaths, options = {}) { const id = normalizeAgentId(agentId); let updated = false; runOpenClawStateWriteTransaction((database) => { ensureAgentDeletionJournalSchema(database.db); const db = getNodeSqliteKysely(database.db); const result = executeSqliteQuerySync(database.db, db.updateTable("agent_deletion_journal").set({ cleanup_paths_json: JSON.stringify(cleanupPaths) }).where("agent_id", "=", id).where("operation_id", "=", operationId).where("cleanup_completed", "=", 0)); updated = Number(result.numAffectedRows ?? 0) > 0; }, options); return updated; } function updateAgentDeletionJournalDatabasePaths(agentId, operationId, databasePaths, options = {}) { const id = normalizeAgentId(agentId); const normalizedPaths = [...new Set(databasePaths.map((entryPath) => path.resolve(entryPath)))]; let updated = false; runOpenClawStateWriteTransaction((database) => { ensureAgentDeletionJournalSchema(database.db); const db = getNodeSqliteKysely(database.db); const result = executeSqliteQuerySync(database.db, db.updateTable("agent_deletion_journal").set({ database_paths_json: JSON.stringify(normalizedPaths) }).where("agent_id", "=", id).where("operation_id", "=", operationId).where("cleanup_completed", "=", 0)); updated = Number(result.numAffectedRows ?? 0) > 0; }, options); return updated; } function completeAgentDeletionJournal(agentId, operationId, options = {}) { return runOpenClawStateWriteTransaction((database) => completeAgentDeletionJournalInDatabase(database, agentId, operationId), options); } /** Complete a deletion journal inside a caller-owned shared-state transaction. */ function completeAgentDeletionJournalInDatabase(database, agentId, operationId) { const id = normalizeAgentId(agentId); ensureAgentDeletionJournalSchema(database.db); const db = getNodeSqliteKysely(database.db); const result = executeSqliteQuerySync(database.db, db.updateTable("agent_deletion_journal").set({ cleanup_completed: 1 }).where("agent_id", "=", id).where("operation_id", "=", operationId)); const completed = Number(result.numAffectedRows ?? 0) > 0; if (completed) deleteAgentProvenanceForAgent(database.db, id); return completed; } function removeAgentDeletionJournal(agentId, operationId, options = {}) { const id = normalizeAgentId(agentId); let removed = false; runOpenClawStateWriteTransaction((database) => { ensureAgentDeletionJournalSchema(database.db); const db = getNodeSqliteKysely(database.db); const result = executeSqliteQuerySync(database.db, db.deleteFrom("agent_deletion_journal").where("agent_id", "=", id).where("operation_id", "=", operationId)); removed = Number(result.numAffectedRows ?? 0) > 0; }, options); return removed; } function claimCompletedAgentDeletionJournal(agentId, operationId, options = {}) { const id = normalizeAgentId(agentId); let removed = false; runOpenClawStateWriteTransaction((database) => { ensureAgentDeletionJournalSchema(database.db); const db = getNodeSqliteKysely(database.db); const result = executeSqliteQuerySync(database.db, db.deleteFrom("agent_deletion_journal").where("agent_id", "=", id).where("operation_id", "=", operationId).where("cleanup_completed", "=", 1)); removed = Number(result.numAffectedRows ?? 0) > 0; }, options); return removed; } //#endregion //#region src/state/openclaw-agent-db-lease.ts const AGENT_DATABASE_MAINTENANCE_LEASE = { scope: "core:agent-database-maintenance", key: "global" }; var OpenClawAgentDatabaseLeaseActiveError = class extends Error { constructor(message) { super(message); this.name = "OpenClawAgentDatabaseLeaseActiveError"; } }; const maintenanceAuthority = new AsyncLocalStorage(); function runWithAgentDatabaseMaintenanceAuthority(authority, run) { return maintenanceAuthority.run(authority, run); } /** Revalidate the held lease, including immediately before committing a versioned rebuild. */ function assertAgentDatabaseMaintenanceAuthority() { const authority = maintenanceAuthority.getStore(); if (!authority) throw new Error("Agent identity migration requires stopped-writer maintenance; stop active agents and run openclaw doctor --fix."); authority.assertOwned(); } /** Revalidate a maintenance owner when present, without requiring ordinary opens to hold one. */ function assertAgentDatabaseMaintenanceAuthorityIfPresent() { maintenanceAuthority.getStore()?.assertOwned(); } /** Verify the maintenance owner and its independent heartbeat before a synchronous phase. */ function renewAgentDatabaseMaintenanceAuthorityIfPresent() { const authority = maintenanceAuthority.getStore(); if (!authority) return; if (!authority.renew) throw new Error("Agent database maintenance authority cannot renew its lease."); authority.renew(); } function claimOpenClawAgentDatabaseLease(params, leaseId = crypto.randomUUID()) { const agentId = normalizeAgentId(params.agentId); const deletionFence = prepareAgentDeletionPathFence({ agentId, path: params.path }, { env: params.env }); const ownerStartTime = getFileLockProcessStartTime(process.pid); runOpenClawStateWriteTransaction((database) => { ensureAgentDatabaseLeaseSchema(database.db); const db = getNodeSqliteKysely(database.db); if (executeSqliteQueryTakeFirstSync(database.db, db.selectFrom("state_leases").select("owner").where("scope", "=", AGENT_DATABASE_MAINTENANCE_LEASE.scope).where("lease_key", "=", AGENT_DATABASE_MAINTENANCE_LEASE.key).where("expires_at", ">", Date.now()))) throw new Error("Agent database maintenance is in progress; retry after openclaw doctor --fix completes."); assertAgentDeletionPathFence(database, deletionFence); executeSqliteQuerySync(database.db, db.insertInto("agent_database_leases").values({ lease_id: leaseId, agent_id: agentId, path: params.path, owner_pid: process.pid, owner_start_time: ownerStartTime, opened_at: Date.now() })); }, { env: params.env }); return leaseId; } function releaseOpenClawAgentDatabaseLease(leaseId, options = {}) { runOpenClawStateWriteTransaction((database) => { ensureAgentDatabaseLeaseSchema(database.db); const db = getNodeSqliteKysely(database.db); executeSqliteQuerySync(database.db, db.deleteFrom("agent_database_leases").where("lease_id", "=", leaseId)); }, options); } /** An awaited open may consume its scan only while its original runtime claim survives. */ function assertOpenClawAgentDatabaseLease(leaseId, params) { const ownerStartTime = getFileLockProcessStartTime(process.pid); const database = openOpenClawStateDatabase({ env: params.env }); const db = getNodeSqliteKysely(database.db); const held = executeSqliteQueryTakeFirstSync(database.db, db.selectFrom("agent_database_leases").select([ "agent_id", "path", "owner_pid", "owner_start_time" ]).where("lease_id", "=", leaseId)); if (!held || held.agent_id !== params.agentId || held.path !== params.path || held.owner_pid !== process.pid || held.owner_start_time !== null && ownerStartTime !== null && held.owner_start_time !== ownerStartTime) throw new Error(`Agent database open lost its runtime lease: ${params.path}`); } function assertNoOpenClawAgentDatabaseLeases(agentIdRaw, options = {}) { const maintenance = typeof agentIdRaw === "string" ? void 0 : agentIdRaw; const agentId = typeof agentIdRaw === "string" ? normalizeAgentId(agentIdRaw) : void 0; const rows = runOpenClawStateWriteTransaction((database) => { maintenance?.assertOwnedInTransaction(database.db); ensureAgentDatabaseLeaseSchema(database.db); const db = getNodeSqliteKysely(database.db); return executeSqliteQuerySync(database.db, db.selectFrom("agent_database_leases").select([ "agent_id", "lease_id", "owner_pid", "owner_start_time", "path" ])).rows; }, options); const staleLeaseIds = rows.filter((row) => { if (isPidDefinitelyDead(row.owner_pid)) return true; const currentStartTime = getFileLockProcessStartTime(row.owner_pid); return row.owner_start_time !== null && currentStartTime !== null && row.owner_start_time !== currentStartTime; }).map((row) => row.lease_id); if (staleLeaseIds.length > 0) runOpenClawStateWriteTransaction((database) => { maintenance?.assertOwnedInTransaction(database.db); ensureAgentDatabaseLeaseSchema(database.db); const db = getNodeSqliteKysely(database.db); executeSqliteQuerySync(database.db, db.deleteFrom("agent_database_leases").where("lease_id", "in", staleLeaseIds)); }, options); const staleLeaseIdSet = new Set(staleLeaseIds); for (const row of rows) { if (staleLeaseIdSet.has(row.lease_id)) continue; const deletionFence = agentId ? prepareAgentDeletionPathFence({ agentId: row.agent_id, path: row.path, fenceAgentId: agentId }, options) : void 0; let leaseStillExists = false; runOpenClawStateWriteTransaction((database) => { maintenance?.assertOwnedInTransaction(database.db); ensureAgentDatabaseLeaseSchema(database.db); const db = getNodeSqliteKysely(database.db); leaseStillExists = executeSqliteQueryTakeFirstSync(database.db, db.selectFrom("agent_database_leases").select("lease_id").where("lease_id", "=", row.lease_id)) !== void 0; if (leaseStillExists && row.agent_id !== agentId && deletionFence) assertAgentDeletionPathFence(database, deletionFence); }, options); if (leaseStillExists && (!agentId || row.agent_id === agentId)) { const remediation = agentId ? "." : "; stop that process and rerun openclaw doctor --fix."; throw new OpenClawAgentDatabaseLeaseActiveError(`Agent ${row.agent_id} database is still open in another process${remediation}`); } } } //#endregion export { createAgentDeletionDatabaseCleanup as C, isIncognitoOpenClawAgentSqlitePath as D, releaseAgentDeletionDatabaseCleanup as E, resolveIncognitoOpenClawAgentSqlitePath as O, assertAgentDeletionDatabaseCleanupAccess as S, registerAgentDeletionDatabaseCleanup as T, readAgentDeletionJournal as _, assertNoOpenClawAgentDatabaseLeases as a, updateAgentDeletionJournalDatabasePaths as b, releaseOpenClawAgentDatabaseLease as c, assertAgentDeletionPathFence as d, beginAgentDeletionJournal as f, prepareAgentDeletionPathFence as g, completeAgentDeletionJournalInDatabase as h, assertAgentDatabaseMaintenanceAuthorityIfPresent as i, resolveOpenClawAgentSqlitePath as k, renewAgentDatabaseMaintenanceAuthorityIfPresent as l, completeAgentDeletionJournal as m, OpenClawAgentDatabaseLeaseActiveError as n, assertOpenClawAgentDatabaseLease as o, claimCompletedAgentDeletionJournal as p, assertAgentDatabaseMaintenanceAuthority as r, claimOpenClawAgentDatabaseLease as s, AGENT_DATABASE_MAINTENANCE_LEASE as t, runWithAgentDatabaseMaintenanceAuthority as u, removeAgentDeletionJournal as v, getAgentDeletionDatabaseCleanup as w, assertAgentDeletionCleanupAliases as x, updateAgentDeletionJournalCleanupPaths as y };