UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

97 lines (96 loc) 4.76 kB
import { n as normalizeAgentId } from "./agent-id-CeT3w4ap.js"; import { c as resolveAgentConfig } from "./agent-scope-config-DcbEhP0R.js"; import "./session-key-BnWWjqNc.js"; import { s as resolveOpenClawStateSqlitePath } from "./openclaw-state-db-schema-version-c1ZL6JGz.js"; import { C as createAgentDeletionDatabaseCleanup, _ as readAgentDeletionJournal, a as assertNoOpenClawAgentDatabaseLeases, b as updateAgentDeletionJournalDatabasePaths, f as beginAgentDeletionJournal, m as completeAgentDeletionJournal, p as claimCompletedAgentDeletionJournal, v as removeAgentDeletionJournal, y as updateAgentDeletionJournalCleanupPaths } from "./openclaw-agent-db-lease-Djvd6LWN.js"; import { i as readAgentProvenance } from "./agent-provenance-Cp8HmAX0.js"; import { isDeepStrictEqual } from "node:util"; import path from "node:path"; import crypto from "node:crypto"; //#region src/agents/agent-lifecycle-registry.ts var AgentDeletionAuthorityRollbackError = class extends AggregateError {}; var AgentDeletionCommitUncertainError = class extends Error { constructor(cause) { super(cause instanceof Error ? cause.message : String(cause), { cause }); } }; /** Fence authority producers while an agent deletion is pending or committed. */ function beginAgentDeletion(entry, options = {}) { const id = normalizeAgentId(entry.agentId); const statePath = path.resolve(options.path ?? resolveOpenClawStateSqlitePath(options.env ?? process.env)); const stateOptions = { ...options, path: statePath, env: options.env && { ...options.env } }; const operationId = crypto.randomUUID(); const journal = beginAgentDeletionJournal({ ...entry, agentId: id, operationId, deleteFiles: entry.deleteFiles !== false }, stateOptions); let active = true; const assertJournal = (currentStatePath, entries) => { if (!active || path.resolve(currentStatePath) !== statePath || !entries.some((current) => current.agentId === id && current.operationId === operationId && !current.cleanupCompleted)) throw new Error(`Agent ${id} deletion no longer owns database cleanup.`); return id; }; return { entry: journal, runDatabaseCleanup: createAgentDeletionDatabaseCleanup({ statePath, assertAdmission: () => assertNoOpenClawAgentDatabaseLeases(id, stateOptions), assertJournal, assertCurrent: () => { const current = readAgentDeletionJournal(id, stateOptions); assertJournal(statePath, current ? [current] : []); } }), fenceDatabasePaths: (paths) => { if (!updateAgentDeletionJournalDatabasePaths(id, operationId, paths, stateOptions)) throw new Error(`Failed to fence database cleanup paths for agent ${id}.`); journal.databasePaths = [...new Set(paths.map((entryPath) => path.resolve(entryPath)))]; }, fenceCleanupPaths: (paths) => { if (!updateAgentDeletionJournalCleanupPaths(id, operationId, paths, stateOptions)) throw new Error(`Failed to fence cleanup paths for agent ${id}.`); journal.cleanupPaths = [...paths]; }, finish: () => { try { completeAgentDeletionJournal(id, operationId, stateOptions); } finally { active = false; } }, rollback: () => { try { removeAgentDeletionJournal(id, operationId, stateOptions); } finally { active = false; } } }; } /** Atomically claim a completed deletion tombstone for a newly created identity. */ function claimCompletedAgentDeletion(agentId, operationId, options = {}) { return claimCompletedAgentDeletionJournal(normalizeAgentId(agentId), operationId, options); } /** Return whether this process must refuse new authority for an agent id. */ function isAgentDeletionBlocked(agentId, options = {}) { return Boolean(readAgentDeletionJournal(normalizeAgentId(agentId), options)); } /** Captures the exact durable incarnation of an existing, deletion-safe agent. */ function captureAgentLifecycleBinding(config, agentId, options = {}) { const id = normalizeAgentId(agentId); if (!resolveAgentConfig(config, id) || isAgentDeletionBlocked(id, options)) return; return Object.freeze({ agentId: id, provenance: readAgentProvenance(id, options) ?? null }); } /** Revalidates an agent binding against both the roster and lifecycle owner. */ function matchesAgentLifecycleBinding(config, binding, options = {}) { const id = normalizeAgentId(binding.agentId); return id === binding.agentId && Boolean(resolveAgentConfig(config, id)) && !isAgentDeletionBlocked(id, options) && isDeepStrictEqual(readAgentProvenance(id, options) ?? null, binding.provenance); } //#endregion export { claimCompletedAgentDeletion as a, captureAgentLifecycleBinding as i, AgentDeletionCommitUncertainError as n, isAgentDeletionBlocked as o, beginAgentDeletion as r, matchesAgentLifecycleBinding as s, AgentDeletionAuthorityRollbackError as t };