openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
867 lines (866 loc) • 39.5 kB
JavaScript
import "../src-BirUqOZp.mjs";
import { t as expectDefined } from "../expect-lbe3Hgrh.mjs";
import { c as isRecord } from "../record-coerce-TIsquoVR.mjs";
import { s as sqliteReaderDatabasePathKey } from "../sqlite-reader-lifecycle-CF8Y2ajA.mjs";
import { d as readDatabasePathIdentitySync, r as assertExistingDatabaseIdentity, s as normalizeDatabasePath } from "../sqlite-worker-identity-BRNRpRyc.mjs";
import { a as createSqliteLifecycleAggregateError, s as throwSqliteLifecycleErrors } from "../sqlite-lifecycle-errors-DuOygjcn.mjs";
import { t as createSubsystemLogger } from "../subsystem-4NzR43uz.mjs";
import { t as assertTransactionUsable } from "../sqlite-transaction-DBRLvCDM.mjs";
import { h as onSqliteWalCheckpoint } from "../sqlite-wal-DfKCrDTQ.mjs";
import { a as classifySqliteFtsIntegrityFindings, c as readSqliteIntegrityFindings } from "../sqlite-integrity-D3yHPOet.mjs";
import { a as readOpenClawAgentDatabaseIdentity } from "../openclaw-agent-db-identity-BlmER9-X.mjs";
import { b as withAgentCreationClaimWitness } from "../openclaw-agent-db-resources-Cm-sH7kg.mjs";
import { c as getOpenClawAgentDatabaseValidation } from "../openclaw-agent-db-validation-cache-CHrtutWN.mjs";
import { i as isIncognitoOpenClawAgentSqlitePath } from "../openclaw-agent-db.paths-BbmZlEP5.mjs";
import { a as SQLITE_WORKER_PREPARE_ADMITTED, i as SQLITE_WORKER_OPERATION_CLEANUP, t as SQLITE_WORKER_CLOSE_RECEIPT } from "../sqlite-worker-contract-C51cJHzg.mjs";
import { d as withSqliteWorkerOperationAdmission, i as deferSqliteWorkerCommitReceipt, s as requestSqliteWorkerOperationAdmission, t as SqliteWorkerOpenRefusedError, u as takeSqliteWorkerOperationAdmissionAttachment } from "../sqlite-worker-operation-admission-C5lBzzTk.mjs";
import { b as requireOpenClawStateDatabaseIdentity, x as retainOpenClawStateDatabase } from "../openclaw-state-db-cache-CmYLFRSt.mjs";
import { T as withAgentDeletionWorkerDatabaseCleanup } from "../agent-deletion-journal-DkfGlzu8.mjs";
import { g as repairDoctorSqliteIndexCorruption, l as runOpenClawStateWriteTransaction, r as openOpenClawStateDatabase } from "../openclaw-state-db-DJZ7EKoI.mjs";
import { a as readAgentDeletionJournalStatusInDatabase } from "../agent-deletion-journal.read-BRl4UyPn.mjs";
import { c as runOpenClawAgentWriteTransaction, i as getOpenClawAgentDatabaseIfOpen, o as openOpenClawAgentDatabase } from "../openclaw-agent-db-DWI9Bgur.mjs";
import { b as mayShareAgentDatabaseFile, d as prepareOpenClawAgentDatabaseWorkerLease, f as readActiveOpenClawAgentDatabaseLeasesReadOnly } from "../openclaw-agent-db-lease-zP0JO4hP.mjs";
import { S as retainAgentDatabase, i as closeOpenClawAgentDatabaseByPath, v as recordOpenClawAgentDatabaseBackgroundVerification } from "../openclaw-agent-db-lifecycle-C9dal1XJ.mjs";
import { o as refreshOpenClawAgentDatabaseSchema, s as ensureOpenClawAgentDatabasePermissions } from "../openclaw-agent-db-schema-CppMSzFp.mjs";
import { s as verifyOpenClawStateLeaseOwnership } from "../openclaw-state-lease-storage-g4qzeMmW.mjs";
import { n as assertOpenClawStateLeaseWorkerOwnedInTransaction } from "../openclaw-state-lease-worker-Ddwq3QcA.mjs";
import { t as createWorkerOperationRegistry } from "../worker-operation-registry-DhUe8rTN.mjs";
import { n as assertAgentDeletionWorkerPredicate } from "../agent-deletion.worker-DuP8KOrz.mjs";
import { C as prepareAgentTranscript, E as requestRestrictedAgentDatabaseAdmission, S as prepareAgentNativeBindingOperation, T as createAgentDatabaseDomainOwner, _ as loadAgentTranscriptOperations, a as loadAgentEntryPatchOperations, b as loadConversationRegistryOperations, c as loadAgentMessageCutOperations, d as loadAgentProviderReviewOperations, f as loadAgentPurgeOperations, g as loadAgentTrajectoryOperations, h as loadAgentRestartRecoveryOperations, i as loadAgentCompoundOperations, l as loadAgentNativeBindingOperations, m as loadAgentReplacementOperations, n as loadAgentArchiveOperations, o as loadAgentEntryReadOperations, p as loadAgentReactionOperations, r as loadAgentArchivePruningOperations, s as loadAgentMaintenanceFinalizationOperations, t as loadAgentAcpOperations, u as loadAgentPendingInputOperations, v as loadAgentTranscriptReadOperations, x as loadUsageCacheOperations, y as loadConversationDeliveryOperations } from "../openclaw-agent-execution-operations-DpsVwNpq.mjs";
import { t as AGENT_FTS_SCHEMAS } from "../openclaw-agent-fts-schema-BY3B67St.mjs";
import { MessageChannel, MessagePort, isMainThread, receiveMessageOnPort, threadId } from "node:worker_threads";
//#region src/state/agent-deletion-cleanup.worker.ts
const log = createSubsystemLogger("state/agent-deletion");
/** Keep lease grants separate from the agent command's commit and publication grants. */
function withLeaseAdmission(guard, run) {
const { port1, port2 } = new MessageChannel();
let admission;
try {
requestSqliteWorkerOperationAdmission({
stage: "prepare",
facts: {
kind: "agent-deletion-lease",
guard,
port: port2
}
}, [port2]);
const received = receiveMessageOnPort(port1)?.message;
if (!(received instanceof MessagePort)) throw new Error("Agent deletion lost its live lease admission");
admission = received;
return run((operation) => withSqliteWorkerOperationAdmission({ port: received }, operation));
} finally {
admission?.close();
port1.close();
port2.close();
}
}
/** The executing agent worker holds agent -> shared locks through the actual agent COMMIT. */
function withAgentDeletionWorkerCleanup(guard, target, run) {
if (guard.lease.scope !== "core:agent-deletion" || guard.lease.key !== guard.predicate.agentId) throw new Error("Agent deletion requires its original target lease");
const assertSourceCurrent = () => {
requestSqliteWorkerOperationAdmission({
stage: "prepare",
facts: {
kind: "agent-deletion-current",
guard
}
});
target.assertFileCurrent();
};
const assertLease = (database) => {
verifyOpenClawStateLeaseOwnership({
...guard.lease,
leaseLabel: "agent deletion",
transaction: database.db
});
};
const assertCurrent = () => {
assertSourceCurrent();
const database = target.shared();
assertAgentDeletionWorkerPredicate(database, guard.predicate);
assertLease(database);
};
return withAgentDeletionWorkerDatabaseCleanup({
...target,
assertCurrent,
assertJournal: (statePath, entries) => {
if (statePath !== target.statePath || !entries.some((entry) => entry.agentId === guard.predicate.agentId && entry.operationId === guard.predicate.operationId && !entry.cleanupCompleted)) throw new Error(`Agent ${guard.predicate.agentId} deletion no longer owns database cleanup.`);
assertSourceCurrent();
const database = target.shared();
assertAgentDeletionWorkerPredicate(database, guard.predicate, entries.find((entry) => entry.agentId === guard.predicate.agentId) ?? null);
assertLease(database);
return guard.predicate.agentId;
},
withCommit: (commit) => {
let committed = false;
try {
withLeaseAdmission(guard, (inLeaseAdmission) => runOpenClawStateWriteTransaction((database) => {
inLeaseAdmission(() => assertOpenClawStateLeaseWorkerOwnedInTransaction(database.db, guard.lease));
assertAgentDeletionWorkerPredicate(database, guard.predicate);
inLeaseAdmission(() => assertOpenClawStateLeaseWorkerOwnedInTransaction(database.db, guard.lease, "write", "commit"));
assertSourceCurrent();
assertLease(database);
commit();
committed = true;
}, {
database: target.shared(),
path: target.statePath,
env: target.env
}, { operationLabel: "agent.deletion.agent-commit" }));
} catch (error) {
if (!committed) throw error;
try {
log.warn("Agent deletion committed, but releasing its state guard failed", {
agentId: guard.predicate.agentId,
error
});
} catch {}
}
}
}, run);
}
//#endregion
//#region src/state/openclaw-agent-execution-close.ts
/** Keep the native receipt and both cleanup modes with the same retirement owner. */
function createAgentDatabaseExecutionCloser(capture) {
let receipt;
return {
[SQLITE_WORKER_CLOSE_RECEIPT]: () => receipt,
closeAfterFailedOpen() {
const { sharedBorrow, ...state } = capture();
receipt = void 0;
receipt = closeAgentDatabaseExecution({
...state,
releaseSharedBorrow: () => sharedBorrow?.release()
});
},
async close() {
const { sharedBorrow, ...state } = capture();
receipt = void 0;
await state.database?.walMaintenance.stop();
const errors = [];
try {
receipt = closeAgentDatabaseExecution({
...state,
releaseSharedBorrow: () => {}
});
} catch (error) {
errors.push(error);
}
try {
await sharedBorrow?.releaseAsync();
} catch (error) {
errors.push(error);
}
throwSqliteLifecycleErrors(errors, "Agent database cleanup failed");
}
};
}
function closeAgentDatabaseExecution({ database, identity, releasePreparations, closeDomain, releaseBorrow, releaseSharedBorrow }) {
let checkpoint;
const errors = [];
for (const cleanup of [
...releasePreparations,
closeDomain,
() => {
if (!database) return;
const closingPath = sqliteReaderDatabasePathKey(database.path);
const stopObserving = onSqliteWalCheckpoint((observation) => {
if (observation.databasePath === closingPath) checkpoint = {
health: observation.health,
observedAtNs: observation.observedAtNs,
lastCompletedAtNs: observation.lastCompletedAtNs
};
});
try {
closeOpenClawAgentDatabaseByPath(database.path, database.agentId);
} finally {
stopObserving();
}
},
() => releaseBorrow?.(),
releaseSharedBorrow
]) try {
cleanup();
} catch (error) {
errors.push(error);
}
throwSqliteLifecycleErrors(errors, "Agent database cleanup failed");
if (identity && checkpoint) return {
identity: {
key: `file:${identity.physicalIdentity}`,
canonicalPath: identity.nativeLocation
},
incarnation: identity.incarnation,
checkpoint
};
}
//#endregion
//#region src/state/openclaw-agent-execution-incognito.worker.ts
/** The ephemeral arm retains one native owner for every admitted operation. */
function createIncognitoAgentDatabaseBackend(input, opening) {
const options = {
agentId: input.agentId,
path: input.databasePath,
env: input.environment
};
if (isMainThread || opening.databasePath !== input.databasePath || opening.target?.kind !== "ephemeral" || opening.target.handle !== input.identity.handle || opening.target.incarnation !== input.identity.incarnation || !isIncognitoOpenClawAgentSqlitePath(input.databasePath, options)) throw new Error("Incognito open differs from its worker-owned target");
try {
requestSqliteWorkerOperationAdmission({
stage: "open",
facts: input
});
} catch (error) {
throw new SqliteWorkerOpenRefusedError(error);
}
if (getOpenClawAgentDatabaseIfOpen(options)) throw new Error("Incognito actor cannot adopt another native database");
const database = openOpenClawAgentDatabase(options);
const release = retainAgentDatabase(database.db);
let closed = false;
const close = () => {
closed = true;
closeOpenClawAgentDatabaseByPath(database.path, database.agentId);
release();
};
try {
if (database.db.location()) throw new Error("Incognito actor requires memory-only SQLite storage");
requestSqliteWorkerOperationAdmission({
stage: "prepare",
facts: { identity: input.identity }
});
} catch (error) {
try {
close();
} catch (cleanupError) {
throw createSqliteLifecycleAggregateError([error, cleanupError], "Incognito open and cleanup failed", error);
}
throw error;
}
const assertCurrent = () => {
if (closed || !database.db.isOpen || getOpenClawAgentDatabaseIfOpen(options) !== database) throw new Error("Incognito actor lost its retained native database");
};
let sessions;
return {
async prepare(command) {
if (!sessions) {
const { createIncognitoSessionWorker } = await import("../session-incognito.worker-BdIPwNPH.mjs");
sessions = createIncognitoSessionWorker(database, input.identity, input.environment);
}
await sessions.prepare(command);
},
execute(command) {
assertCurrent();
requestSqliteWorkerOperationAdmission({
stage: "prepare",
facts: { identity: input.identity }
});
if (!sessions) throw new Error("Incognito session operation was not prepared");
return sessions.execute(command);
},
assertSettled() {
assertCurrent();
sessions?.assertSettled();
if (database.db.isTransaction) throw new Error("Incognito command left an unsettled native transaction");
},
close() {
sessions?.close();
close();
}
};
}
//#endregion
//#region src/state/openclaw-agent-execution-maintenance.ts
/** Metadata preparation and commit share the canonical actor's retained snapshots. */
function createAgentDatabaseMaintenanceOwner(context) {
const preparations = /* @__PURE__ */ new Map();
let maintenance;
let replacements;
const releasePreparation = (id) => {
const preparation = preparations.get(id);
if (preparation) {
preparation.prepared.release();
preparations.delete(id);
}
};
return {
operations: {
"session.maintenance.read": (plan) => {
context.assertFileIdentity();
return {
kind: "session-maintenance-read",
result: expectDefined(maintenance, "Session maintenance kernel").readSessionMaintenanceInWorker({
...plan,
databaseOptions: context.databaseOptions
}, context.readPreparedDatabase()),
workerThreadId: threadId
};
},
"session.maintenance.release": ({ id }) => releasePreparation(id),
"session.maintenance.prepare": (input) => {
const kernel = expectDefined(maintenance, "Session maintenance kernel");
context.assertFileIdentity();
if (preparations.has(input.id)) throw new Error("Session maintenance preparation is already retained");
if (preparations.size >= 2) throw new Error("Session maintenance preparation capacity is occupied");
const prepared = kernel.prepareSessionMaintenanceInWorker({
kind: "maintenance-plan",
input: input.input,
ageOwner: input.ageOwner,
ageChanges: input.ageChanges,
databaseOptions: context.databaseOptions
});
preparations.set(input.id, {
plan: input,
prepared
});
},
"session.maintenance.metadata": (input) => {
const kernel = expectDefined(maintenance, "Session maintenance kernel");
const preparePublication = expectDefined(replacements, "Session replacement kernel").prepareSessionEntryReplacementPublication;
const opened = context.openWriter();
const previous = /* @__PURE__ */ new Map();
const current = /* @__PURE__ */ new Map();
let publication;
const preparation = input.kind === "maintenance-plan" ? expectDefined(preparations.get(input.preparationId), "Session maintenance preparation") : void 0;
if (preparation && input.kind === "maintenance-plan") Object.assign(preparation.plan.input, input.protection);
const plan = input.kind === "maintenance-plan" ? {
...expectDefined(preparation, "Session maintenance preparation").plan,
kind: "maintenance-plan"
} : input;
const value = kernel.runSessionMaintenanceMetadataInTransaction({
...plan,
databaseOptions: context.databaseOptions
}, {
beforeMutation(database) {
if (database.db !== opened.db) throw new Error("Session maintenance lost its canonical database owner");
context.admit("transaction");
},
onArchived(sessionKey, before, after) {
previous.set(sessionKey, before);
current.set(sessionKey, after);
},
beforeCommit(database) {
publication = preparePublication({
pendingArchiveRecovery: false,
previous,
current,
maintenancePlans: [],
membershipInvalidatedKeys: []
}, database);
deferSqliteWorkerCommitReceipt(database.db, publication);
context.admit("commit", publication);
}
}, preparation?.prepared);
return value.kind === "maintenance-preservation-required" || value.kind === "maintenance-plan-stale" ? {
kind: "not-committed",
workerThreadId: threadId,
value
} : {
kind: "committed",
workerThreadId: threadId,
value,
publication: expectDefined(publication, "Session maintenance commit receipt")
};
}
},
prepare() {
return Promise.all([import("../session-accessor.sqlite-maintenance-transaction-wDLc5AtK.mjs"), import("../session-accessor.sqlite-replacement-state-h7Yz1bCz.mjs")]).then(([metadata, replacement]) => {
maintenance = metadata;
replacements = replacement;
});
},
cleanup(input) {
if (input.kind === "maintenance-plan") releasePreparation(input.preparationId);
},
getPreparationReleases() {
return [...preparations.keys()].map((id) => () => releasePreparation(id));
}
};
}
//#endregion
//#region src/state/openclaw-agent-execution-voice-operations.ts
async function loadAgentVoiceSessionOperations() {
const { readSessionSourceValidation } = await import("../session-source-predicate.worker-B4Tq5g8W.mjs");
const kernel = await import("../client-voice-session-write.kernel-BcBu0bNP.mjs");
const store = await import("../client-voice-session-store-Ct-PKLtv.mjs");
const entries = await import("../session-accessor.sqlite-entry-read-Cdmo5WHm.mjs");
const keys = await import("../session-accessor.sqlite-scope-helpers-HJr7Z-dj.mjs");
const canonical = await import("../session-canonical-key-GVDAgytN.mjs");
const { isIncognitoSessionKey } = await import("../incognito-session-key-B-JIffX5.mjs");
const { readSessionPendingInputAuthorityFactsInTransaction } = await import("../session-pending-input-authority.kernel-BZVfoqXF.mjs");
return {
"voice.session.read": (input, { open }) => {
const database = open();
const record = store.readVoiceSessionRecordInTransaction(database, input.voiceSessionId);
let entry;
if (record && record.effects.length > 0 && !record.digestDeliveredAt && !isIncognitoSessionKey(record.sessionKey)) {
canonical.assertCanonicalSqliteSessionKeysCurrent(database);
const key = keys.resolveSqliteSessionKey(record.sessionKey, database.agentId);
entry = entries.prepareExactSessionEntryRowReads(database, [key], "delivery", "canonical")(key)?.entry;
}
return {
record,
entry
};
},
"voice.session.mutate": (input, { writeTransaction, admit }) => writeTransaction(`voice.session.${input.kind}`, "Voice session", (database) => {
const sourceFacts = input.transactionSource ? readSessionPendingInputAuthorityFactsInTransaction(database, input.transactionSource.sessionKey, input.transactionSource.agentId) : void 0;
const sourceValidation = readSessionSourceValidation(database, input.sources);
if (sourceFacts || input.sources?.length) admit("transaction", {
kind: "voice-session-authority",
facts: sourceFacts,
sourceValidation
});
if (sourceValidation.refusedSource) throw new Error("Voice session source refusal was not rejected");
const entry = input.kind === "reserve" && input.transcriptSessionKey ? entries.readSessionEntryIdentity(database, keys.resolveSqliteSessionKey(input.transcriptSessionKey, database.agentId)) : void 0;
if (input.kind === "reserve" && input.transcriptSessionKey && !entry?.sessionId) throw new Error(`agent session not found (${input.sessionKey})`);
const result = {
record: kernel.mutateVoiceSessionInDatabase(database, input),
entry
};
deferSqliteWorkerCommitReceipt(database.db, result);
admit("commit", sourceFacts ? {
kind: "voice-session-authority",
facts: sourceFacts
} : void 0);
return result;
})
};
}
//#endregion
//#region src/state/openclaw-agent-startup-fts.ts
/** The native worker repairs only owned FTS under its existing shared write fence. */
function repairAgentDatabaseStartupFts(context) {
const { receipt, check, error } = context;
if (!(error instanceof Error) || error.name !== "SqliteIntegrityError" || error.cause || check.databaseLabel !== receipt.path || !classifySqliteFtsIntegrityFindings(check.database, readSqliteIntegrityFindings(check.database), AGENT_FTS_SCHEMAS)) return false;
return runOpenClawStateWriteTransaction((shared) => {
const admit = (phase, message) => {
context.assertCurrent();
context.assertFileIdentity();
requestSqliteWorkerOperationAdmission({
stage: "prepare",
facts: {
kind: "agent-startup-fts",
phase,
lease: receipt,
message,
agentDeletionJournalPresent: readAgentDeletionJournalStatusInDatabase(shared.db, receipt.agentId) !== "absent"
}
});
};
context.assertCurrent();
context.assertFileIdentity();
const owners = readActiveOpenClawAgentDatabaseLeasesReadOnly({
env: context.env,
path: receipt.sharedStatePath
}).filter((owner) => mayShareAgentDatabaseFile(owner.path, receipt.path));
if (owners.length !== 1 || owners[0]?.lease_id !== receipt.leaseId) throw new Error("Startup FTS repair requires an exclusive live agent database lease");
admit("begin");
admit("complete", repairDoctorSqliteIndexCorruption(check.database, check.databaseLabel, {
label: "agent " + receipt.agentId,
ftsSchemas: AGENT_FTS_SCHEMAS,
ftsOnly: true,
assertCurrent: () => admit("check"),
describeRepair: (indexes) => "Rebuilt stale SQLite FTS indexes (agent " + receipt.agentId + "): " + indexes.join(", ") + ". No table rows were removed."
}).join(" "));
return true;
}, {
env: context.env,
path: receipt.sharedStatePath
});
}
//#endregion
//#region src/state/openclaw-agent-execution.worker.ts
function createSqliteWorkerBackend(input, opening) {
if (input.kind === "ephemeral") return createIncognitoAgentDatabaseBackend(input, opening);
const backend = openAgentDatabaseBackend(input, opening);
try {
backend.execute({
type: "database.prepareWrite",
input: void 0
});
backend.assertSettled?.();
return backend;
} catch (error) {
try {
backend.closeAfterFailedOpen();
} catch (cleanupError) {
throw createSqliteLifecycleAggregateError([error, cleanupError], "Agent creation and cleanup failed", error);
}
throw error;
}
}
/** The broker supplies a private admission channel before invoking this native factory. */
const openExistingSqliteWorkerBackend = openAgentDatabaseBackend;
function openAgentDatabaseBackend(input, opening) {
if (opening.databasePath !== input.databasePath) throw new Error("Agent database open does not match its captured execution owner");
const admitOpen = () => {
try {
requestSqliteWorkerOperationAdmission({
stage: "open",
facts: input
});
} catch (error) {
throw new SqliteWorkerOpenRefusedError(error);
}
};
admitOpen();
const options = {
agentId: input.agentId,
path: input.databasePath,
env: input.environment
};
let admittedFileIdentity = input.creatingIdentity?.key ?? opening.existingIdentity ?? readDatabasePathIdentitySync(input.databasePath).key;
let admittedFileBirthtime = input.creatingIdentity?.birthtime;
const assertFileIdentity = () => {
if (input.expectedIdentity) assertExistingDatabaseIdentity(input.databasePath, `file:${input.expectedIdentity.physicalIdentity}`, input.expectedIdentity.birthtime);
const pathOnly = admittedFileIdentity.startsWith("path:");
if (pathOnly || input.creatingIdentity) {
const current = readDatabasePathIdentitySync(input.databasePath);
if (pathOnly && current.key !== admittedFileIdentity || input.creatingIdentity && current.canonicalPath !== input.creatingIdentity.canonicalPath) throw new Error("Agent database target changed before creating open");
}
if (!pathOnly) assertExistingDatabaseIdentity(input.databasePath, admittedFileIdentity, admittedFileBirthtime);
};
let database;
let shared;
let sharedBorrow;
let releaseBorrow;
let identity;
let openingFailure;
let startupJournalRequested = false;
let publicationPreparation;
const readRequestPreparation = () => {
const attachment = takeSqliteWorkerOperationAdmissionAttachment();
if (!isRecord(attachment) || attachment.kind !== "agent-execution" || typeof attachment.startupJournal !== "boolean") throw new Error("Agent execution requires its request-local preparation facts");
return {
startupJournal: attachment.startupJournal,
deletion: attachment.deletion
};
};
const openShared = () => {
if (!shared) {
shared = openOpenClawStateDatabase({
path: input.stateDatabasePath,
env: input.environment,
initializationAgentPaths: [input.databasePath]
});
sharedBorrow = retainOpenClawStateDatabase(shared);
}
return shared;
};
const withPreparation = (preparation, run) => {
startupJournalRequested = preparation.startupJournal;
try {
return preparation.deletion ? withAgentDeletionWorkerCleanup(preparation.deletion, {
agentId: input.agentId,
path: input.databasePath,
statePath: input.stateDatabasePath,
env: input.environment,
shared: openShared,
assertFileCurrent: assertFileIdentity
}, run) : run();
} finally {
startupJournalRequested = false;
}
};
const readDeletionJournal = () => readAgentDeletionJournalStatusInDatabase(expectDefined(shared, "Agent execution shared-state owner").db, input.agentId) !== "absent";
const openClaimedWriter = (refreshSchema = false) => {
let validation;
if (!database) {
admitOpen();
assertFileIdentity();
const sharedDatabase = openShared();
const lease = prepareOpenClawAgentDatabaseWorkerLease(options, sharedDatabase, input.leaseId);
const { port1, port2 } = new MessageChannel();
try {
requestSqliteWorkerOperationAdmission({
stage: "prepare",
facts: {
kind: "shared-owner",
identity: requireOpenClawStateDatabaseIdentity(sharedDatabase),
lease: lease.receipt,
validationPort: port2
}
}, [port2]);
const preparation = receiveMessageOnPort(port1)?.message;
lease.validation = preparation.validation;
lease.deferUnverifiedIntegrity = preparation.deferUnverifiedIntegrity;
lease.startupRepair = startupJournalRequested ? (check, error, assertCurrent) => repairAgentDatabaseStartupFts({
receipt: lease.receipt,
check,
error,
assertCurrent,
assertFileIdentity,
env: options.env
}) : void 0;
} catch (error) {
throw new SqliteWorkerOpenRefusedError(error);
} finally {
port1.close();
port2.close();
}
assertFileIdentity();
let registration;
let openingResult;
try {
const opened = openOpenClawAgentDatabase(options, lease, {
starting: () => requestSqliteWorkerOperationAdmission({
stage: "prepare",
facts: {
kind: "agent-registration-start",
lease: lease.receipt
}
}),
committed(receipt) {
registration = receipt;
}
});
database = opened;
releaseBorrow = retainAgentDatabase(opened.db);
openingResult = {
ok: true,
value: opened
};
} catch (error) {
openingFailure = { error };
openingResult = {
ok: false,
error
};
}
if (registration) try {
requestSqliteWorkerOperationAdmission({
stage: "prepare",
facts: {
kind: "agent-registration-committed",
registration
}
});
} catch (error) {
if (!openingResult.ok) throw createSqliteLifecycleAggregateError([openingResult.error, error], `${String(openingResult.error)}; committed registration reporting failed: ${String(error)}`, openingResult.error);
throw error;
}
if (!openingResult.ok) throw openingResult.error;
const opened = openingResult.value;
const nativeIdentity = readOpenClawAgentDatabaseIdentity(opened);
if (typeof nativeIdentity.identity !== "string") throw new Error("Disk agent execution requires its canonical file identity");
const openedFileIdentity = `file:${nativeIdentity.identity}`;
if (admittedFileIdentity.startsWith("file:") && (openedFileIdentity !== admittedFileIdentity || admittedFileBirthtime !== void 0 && nativeIdentity.birthtime !== admittedFileBirthtime)) throw new Error("Agent writer differs from its admitted physical file");
if (input.expectedIdentity && nativeIdentity.identity !== input.expectedIdentity.physicalIdentity) throw new Error("Agent writer differs from its expected physical file");
admittedFileIdentity = openedFileIdentity;
admittedFileBirthtime = nativeIdentity.birthtime;
identity = {
kind: "file",
physicalIdentity: nativeIdentity.identity,
birthtime: nativeIdentity.birthtime,
incarnation: nativeIdentity.incarnation,
nativeLocation: nativeIdentity.filename
};
validation = getOpenClawAgentDatabaseValidation(opened);
}
if (!database || !database.db.isOpen || getOpenClawAgentDatabaseIfOpen(options) !== database) throw new Error("Agent execution lost its retained native database");
if (refreshSchema) validation = refreshOpenClawAgentDatabaseSchema(database, admitOpen);
requestSqliteWorkerOperationAdmission({
stage: "prepare",
facts: {
identity,
validation,
...startupJournalRequested ? { agentDeletionJournalPresent: readDeletionJournal() } : {}
}
});
return database;
};
const openWriter = (refreshSchema = false) => input.creationClaim ? withAgentCreationClaimWitness(input.creationClaim, admitOpen, () => openClaimedWriter(refreshSchema)) : openClaimedWriter(refreshSchema);
const admit = (stage, publication, requestAdmission) => {
assertFileIdentity();
const request = {
stage,
facts: {
identity,
...startupJournalRequested ? { agentDeletionJournalPresent: readDeletionJournal() } : {},
...publication ? { publication } : {}
}
};
requestRestrictedAgentDatabaseAdmission(request, requestAdmission);
if (stage === "commit") ensureOpenClawAgentDatabasePermissions(input.databasePath, options);
};
const writeTransaction = (operationLabel, owner, write) => {
const opened = openWriter();
return runOpenClawAgentWriteTransaction((current) => {
if (current.db !== opened.db) throw new Error(`${owner} lost its canonical database owner`);
admit("transaction");
return write(current);
}, options, { operationLabel });
};
const maintenance = createAgentDatabaseMaintenanceOwner({
databaseOptions: options,
assertFileIdentity,
openWriter,
readPreparedDatabase() {
assertFileIdentity();
return expectDefined(database, "Maintenance read requires its admitted native owner");
},
admit
});
const loadMaintenanceOperations = async () => maintenance.operations;
const registry = createWorkerOperationRegistry({
"session.entry.read": loadAgentEntryReadOperations,
"voice.session.read": loadAgentVoiceSessionOperations,
"voice.session.mutate": loadAgentVoiceSessionOperations,
"session.entry.patch.prepare": loadAgentEntryPatchOperations,
"session.entry.patch.commit": loadAgentEntryPatchOperations,
"session.turn.prepare": loadAgentCompoundOperations,
"session.turn.commit": loadAgentCompoundOperations,
"session.lifecycle.reset": loadAgentCompoundOperations,
"session.lifecycle.project": loadAgentCompoundOperations,
"session.agentPurge.prepare": loadAgentPurgeOperations,
"session.agentPurge.commit": loadAgentPurgeOperations,
"session.maintenance.finalize": loadAgentMaintenanceFinalizationOperations,
"session.maintenance.size": loadAgentMaintenanceFinalizationOperations,
"session.nativeBindings.delete": loadAgentNativeBindingOperations,
"session.messageCut.commit": loadAgentMessageCutOperations,
"trajectory.events.append": loadAgentTrajectoryOperations,
"trajectory.retention.begin": loadAgentTrajectoryOperations,
"trajectory.retention.delete": loadAgentTrajectoryOperations,
"session.archives.preparePublication": loadAgentArchiveOperations,
"session.archives.recordPublication": loadAgentArchiveOperations,
"session.transcript.initialize": loadAgentTranscriptOperations,
"session.transcript.rawDelta.read": loadAgentTranscriptReadOperations,
"session.transcript.watermark.read": loadAgentTranscriptReadOperations,
"session.transcript.visibleDelta.read": loadAgentTranscriptReadOperations,
"session.transcript.memoryCapture.read": loadAgentTranscriptReadOperations,
"session.transcript.anchors.read": loadAgentTranscriptReadOperations,
"session.transcript.coldMetadata.read": loadAgentTranscriptReadOperations,
"session.entries.replace": loadAgentReplacementOperations,
"session.restart.recover": loadAgentRestartRecoveryOperations,
"session.entry.acp": loadAgentAcpOperations,
"session.providerReview.compare": loadAgentProviderReviewOperations,
"session.reaction.set": loadAgentReactionOperations,
"conversation.delivery.begin": loadConversationDeliveryOperations,
"conversation.register": loadConversationRegistryOperations,
"conversation.authority": loadConversationRegistryOperations,
"conversation.delivery.transition": loadConversationDeliveryOperations,
"session.pendingInputs.withdraw": loadAgentPendingInputOperations,
"session.pendingInputs.read": loadAgentPendingInputOperations,
"session.pendingInputs.mutate": loadAgentPendingInputOperations,
"session.pendingInputs.interruptHistory": loadAgentPendingInputOperations,
"session.archivePruning.deletePublished": loadAgentArchivePruningOperations,
"session.archivePruning.pruneRetention": loadAgentArchivePruningOperations,
"session.archivePruning.removeLegacy": loadAgentArchivePruningOperations,
"session.archivePruning.reclaimPages": loadAgentArchivePruningOperations,
"session.maintenance.prepare": loadMaintenanceOperations,
"session.maintenance.read": loadMaintenanceOperations,
"session.maintenance.metadata": loadMaintenanceOperations,
"session.maintenance.release": loadMaintenanceOperations,
"usageCache.writeRollup": loadUsageCacheOperations,
"usageCache.prune": loadUsageCacheOperations,
"usageCache.acquireLock": loadUsageCacheOperations,
"usageCache.releaseLock": loadUsageCacheOperations
});
const context = {
open: openWriter,
options,
admit,
writeTransaction,
writeSharedTransaction(source, write) {
const retained = expectDefined(shared, "Native binding shared-state owner");
const sharedIdentity = requireOpenClawStateDatabaseIdentity(retained);
if (sharedIdentity.key !== source.key || sharedIdentity.canonicalPath !== source.canonicalPath || sharedIdentity.birthtime !== source.birthtime) throw new Error("Native binding settlement changed its captured shared-state owner");
assertExistingDatabaseIdentity(source.canonicalPath, source.key, source.birthtime);
return runOpenClawStateWriteTransaction(write, {
database: retained,
path: retained.path,
env: input.environment
}, { operationLabel: "session.native-binding.settlement" });
}
};
const domain = createAgentDatabaseDomainOwner({
databasePath: input.databasePath,
assertCurrent() {
assertOpen();
const current = openWriter();
assertFileIdentity();
return current.db;
},
assertCleanupCurrent() {
if (!database || !identity || !database.db.isOpen || normalizeDatabasePath(database.db.location() ?? "") !== identity.nativeLocation || getOpenClawAgentDatabaseIfOpen(options) !== database) throw new Error("Agent cleanup lost its retained native database");
assertFileIdentity();
},
admit: (stage, requestAdmission) => admit(stage, void 0, requestAdmission)
});
let closed = false;
const assertOpen = () => {
if (closed) throw new Error("Agent database execution owner is closed");
};
const executeCommand = (command) => {
if (command.type === "database.domain.bind" || command.type === "database.domain.publish" || command.type === "database.domain.execute" || command.type === "database.domain.close") return domain.execute(command);
if (command.type === "database.prepareWrite") {
openWriter(true);
return;
}
if (command.type === "database.recordIntegrity") {
const opened = openWriter();
admit("transaction");
return recordOpenClawAgentDatabaseBackgroundVerification(opened, () => admit("commit"));
}
if (command.type === "database.walMaintenance") return openWriter().walMaintenance.maintainPeriodic?.(command.input, admit) ?? { reclaimedPages: 0 };
return registry.execute(command, context);
};
return {
...createAgentDatabaseExecutionCloser(() => {
closed = true;
return {
database,
identity,
releasePreparations: maintenance.getPreparationReleases(),
closeDomain: () => domain.close(),
releaseBorrow,
sharedBorrow
};
}),
prepare(command) {
if (command.type === "database.domain.bind" || command.type === "database.domain.publish" || command.type === "database.domain.execute" || command.type === "database.domain.close") return domain.prepare(command);
const preparing = registry.prepare(command.type);
if (command.type === "session.turn.commit" && command.input.options.voiceTranscript) return Promise.all([preparing, import("../session-turn.worker--GjV6of9.mjs").then((turn) => turn.prepareVoiceTranscriptCommit())]).then(() => {});
const nativeBindings = command.type === "session.nativeBindings.delete" ? command.input : command.type === "session.messageCut.commit" ? command.input.nativeBindings : command.type === "session.agentPurge.commit" || command.type === "session.maintenance.finalize" ? command.input.nativeBindings : void 0;
if (nativeBindings) return Promise.all([preparing, prepareAgentNativeBindingOperation(nativeBindings, input.environment)]).then(() => {});
if (command.type === "session.maintenance.prepare" || command.type === "session.maintenance.read" || command.type === "session.maintenance.metadata") return Promise.all([preparing, maintenance.prepare()]).then(() => {});
if (command.type === "session.entries.replace" && command.input.initializeTranscript) return Promise.all([preparing, prepareAgentTranscript()]).then(() => {});
return preparing;
},
[SQLITE_WORKER_PREPARE_ADMITTED](command) {
if (command.type !== "database.domain.publish") return;
publicationPreparation = readRequestPreparation();
return withPreparation(publicationPreparation, () => domain.preparePublication(command.input));
},
[SQLITE_WORKER_OPERATION_CLEANUP](command) {
if (command.type === "session.maintenance.metadata") maintenance.cleanup(command.input);
if (command.type === "database.domain.publish") try {
withPreparation(publicationPreparation ?? { startupJournal: false }, () => domain.cleanupPublication(command.input.id));
} finally {
publicationPreparation = void 0;
}
},
assertSettled() {
if (openingFailure) throw openingFailure.error;
domain.assertSettled();
if (shared) {
assertTransactionUsable(shared.db);
if (!shared.db.isOpen || shared.db.isTransaction) throw new Error("Agent database command left its shared-state participant unsettled");
}
if (database) {
assertTransactionUsable(database.db);
if (!identity || !database.db.isOpen || database.db.isTransaction) throw new Error("Agent database command left an unsettled native connection");
}
},
execute(command) {
assertOpen();
if (command.type === "database.domain.publish") {
if (publicationPreparation === void 0) throw new Error("Agent publication lost its request-local preparation facts");
return withPreparation(publicationPreparation, () => executeCommand(command));
}
return withPreparation(readRequestPreparation(), () => executeCommand(command));
}
};
}
//#endregion
export { createSqliteWorkerBackend, openExistingSqliteWorkerBackend };