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