UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

166 lines (165 loc) • 8.6 kB
import { r as isPathInside } from "./path-guards-CH7noY0Z.mjs"; import { h as withSqliteReadOnlyWorkerScope, u as runSqliteReadOnlyOperation } from "./sqlite-readonly-worker-RO6waSGe.mjs"; import { a as resolveSqliteDatabaseFilePaths } from "./sqlite-files-D1rDNZzV.mjs"; import { n as normalizeAgentId } from "./agent-id-D1-Q6vR4.mjs"; import "./session-key-DY3MOX4N.mjs"; import { i as listAgentIds } from "./agent-roster-DH6r_8f4.mjs"; import { A as registerResolvedAgentDir, M as unregisterResolvedAgentDir, O as isPathOwnedByAnotherRegisteredAgent, a as resolveAgentDir, j as resolveRegisteredAgentIdForDir, k as normalizeAgentDirRegistryPath } from "./agent-scope-config-BEk6-ThS.mjs"; import { c as resolveIncognitoOpenClawAgentSqlitePath, l as resolveOpenClawAgentSqlitePath } from "./openclaw-agent-db.paths-BbmZlEP5.mjs"; import { n as assertNoAgentDatabaseLeasesAsync } from "./agent-deletion-journal-DkfGlzu8.mjs"; import { t as executeExistingOpenClawStateRead } from "./openclaw-state-db-readonly-ywwvuxdQ.mjs"; import { n as captureOpenClawStateReadWorkerContext } from "./openclaw-state-worker-context-BvvgY6-t.mjs"; import { l as prepareOpenClawAgentDatabaseRegistrySnapshotRead, o as invalidateRegisteredAgentDatabasesMemo } from "./openclaw-agent-db-registry-listing-DIA5wIwi.mjs"; import "./openclaw-agent-db-DWI9Bgur.mjs"; import { a as closeOpenClawAgentDatabaseByPathAsync } from "./openclaw-agent-db-lifecycle-C9dal1XJ.mjs"; import "./agent-scope-bJOokm5r.mjs"; import { r as closeAuthProfileReadPool } from "./sqlite-read-pool-5mytRHYl.mjs"; import { t as findOverlappingWorkspaceAgentIds } from "./agent-delete-safety-DLY4aeLQ.mjs"; import { n as assertAgentSessionStoreDeletionBlocker } from "./agent-delete-session-store-safety-ji1TpSo4.mjs"; import { n as prepareAgentSessionStoreDeletionSafety, t as assertAgentSessionStoreDeletionTargetsCurrent } from "./agent-delete-session-store-safety.targets-BDM1rHre.mjs"; import path from "node:path"; //#region src/agents/agent-delete-databases.ts async function retireAgentDeleteRuntime(cfg, deletion, agentDirs) { const agentId = deletion.entry.agentId; const { retirePreparedModelRuntimeAgent } = await import("./prepared-model-runtime-s1zOG1oY.mjs"); await deletion.assertCurrentAsync(); await retirePreparedModelRuntimeAgent({ agentId, agentDirs }); const { closeActiveMemorySearchManagerCore } = await import("./memory-runtime-Pd7EDJtH.mjs"); await deletion.assertCurrentAsync(); await closeActiveMemorySearchManagerCore({ cfg, agentId }); await deletion.assertCurrentAsync(); } async function finishAgentDeleteDatabases(params) { const { deletion, agentDir, deleteFiles, complete } = params; await deletion.assertCurrentAsync(); if (!complete) return; const agentId = deletion.entry.agentId; unregisterResolvedAgentDir({ agentId, agentDir }); await deletion.finish({ unregisterDatabases: deleteFiles }); } /** Destructive planning includes every registered owner, regardless of runtime schema readiness. */ async function readAgentDeleteDatabaseRegistry(options = {}) { invalidateRegisteredAgentDatabasesMemo(options); const read = await prepareOpenClawAgentDatabaseRegistrySnapshotRead({ ...options, includeIncompatibleSchemaVersions: true }).read(); read.assertCurrent(); if (read.result.status !== "available") throw new Error("OpenClaw agent database registry is unavailable during deletion."); return read.result.entries; } function prepareJournaledAgentDirOwnership(cfg, agentId, agentDir) { for (const configuredAgentId of listAgentIds(cfg)) resolveAgentDir(cfg, configuredAgentId); if (resolveRegisteredAgentIdForDir(agentDir) !== void 0) return; registerResolvedAgentDir({ agentId, agentDir }); } /** Check before journaling: retaining the file alone would still fence its shared owner. */ async function assertAgentSessionStoreDeletionSafe(cfg, agentId, options = {}) { if (!cfg.session?.store?.trim()) return; const input = prepareAgentSessionStoreDeletionSafety(cfg, agentId, options.env ?? process.env); const context = captureOpenClawStateReadWorkerContext({ path: options.database?.path ?? options.path, env: input.env }); const reply = await executeExistingOpenClawStateRead({ path: context.admission.databasePath, env: context.environment }, { type: "agentDeletion.sessionStoreBlocker", input: { ...input, databasePath: context.admission.databasePath, env: context.environment } }, { context, current: true }); context.admission.assertCurrent(); assertAgentSessionStoreDeletionTargetsCurrent(input.targets); if (reply && (!reply.ok || reply.type !== "agentDeletion.sessionStoreBlocker")) throw new Error("Unexpected agent session-store deletion safety result"); let blocker = reply?.blocker; if (!reply) { const anchor = input.targets.candidates.find(({ identity }) => identity.key.startsWith("file:")); if (anchor) { const result = await withSqliteReadOnlyWorkerScope(() => runSqliteReadOnlyOperation(anchor.identity.canonicalPath, { type: "agentRetirement.sessionStoreBlocker", input }, { source: "canonical", expectedIdentity: anchor.identity.key, env: input.env })); context.admission.assertCurrent(); assertAgentSessionStoreDeletionTargetsCurrent(input.targets); blocker = result.blocker; } } assertAgentSessionStoreDeletionBlocker(input.agentId, blocker); } function resolveSurvivingDatabaseFilePaths(registeredDatabases, agentId, env) { return [...new Set(registeredDatabases.filter((entry) => normalizeAgentId(entry.agentId) !== agentId).flatMap((entry) => resolveSqliteDatabaseFilePaths(entry.path)).map((pathname) => normalizeAgentDirRegistryPath(pathname, env)))]; } function isPathOwnedBySurvivingAgent(cfg, agentId, pathname, survivingDatabaseFilePaths = [], env) { const canonicalPath = normalizeAgentDirRegistryPath(pathname, env); return isPathOwnedByAnotherRegisteredAgent({ agentId, pathname, env }) || findOverlappingWorkspaceAgentIds(cfg, agentId, pathname, env).length > 0 || survivingDatabaseFilePaths.some((databasePath) => databasePath === canonicalPath || isPathInside(databasePath, canonicalPath) || isPathInside(canonicalPath, databasePath)); } async function prepareAgentDeleteDatabases(cfg, agentId, agentDir, options = {}, deletion) { const registeredDatabases = await readAgentDeleteDatabaseRegistry(options); const survivingDatabaseFilePaths = resolveSurvivingDatabaseFilePaths(registeredDatabases, agentId, options.env); const registeredDatabasePaths = /* @__PURE__ */ new Set([resolveOpenClawAgentSqlitePath({ agentId, env: options.env, path: path.join(agentDir, "openclaw-agent.sqlite") }), ...registeredDatabases.filter((entry) => normalizeAgentId(entry.agentId) === agentId).map((entry) => entry.path)]); for (const databasePath of registeredDatabasePaths) { if (deletion) await deletion.assertCurrentAsync(); await closeOpenClawAgentDatabaseByPathAsync(databasePath, agentId); } if (deletion) await deletion.assertCurrentAsync(); await closeOpenClawAgentDatabaseByPathAsync(resolveIncognitoOpenClawAgentSqlitePath({ agentId, env: options.env }), agentId); const databasePaths = [...registeredDatabasePaths].filter((pathname) => resolveSqliteDatabaseFilePaths(pathname).every((filePath) => !isPathOwnedBySurvivingAgent(cfg, agentId, filePath, survivingDatabaseFilePaths, options.env))); if (deletion) await deletion.assertCurrentAsync(); for (const databasePath of databasePaths) closeAuthProfileReadPool({ kind: "database", databasePath }); if (deletion) await deletion.runWithWorker((scope, guard) => scope.execute({ type: "agentDeletion.assertNoDatabaseLeases", input: { guard } })); else await assertNoAgentDatabaseLeasesAsync(agentId, options); const fileGroups = databasePaths.map(resolveSqliteDatabaseFilePaths); const relocatedFileGroups = fileGroups.filter((fileGroup) => { const relative = path.relative(agentDir, fileGroup[0] ?? agentDir); return relative.startsWith("..") || path.isAbsolute(relative); }); return { agentDirs: [agentDir, ...Array.from(registeredDatabasePaths, (databasePath) => path.dirname(databasePath))], registrationPaths: [...registeredDatabasePaths], readerPaths: databasePaths, fileGroups, relocatedFileGroups }; } //#endregion export { prepareJournaledAgentDirOwnership as a, retireAgentDeleteRuntime as c, prepareAgentDeleteDatabases as i, finishAgentDeleteDatabases as n, readAgentDeleteDatabaseRegistry as o, isPathOwnedBySurvivingAgent as r, resolveSurvivingDatabaseFilePaths as s, assertAgentSessionStoreDeletionSafe as t };