UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

591 lines (590 loc) • 29.2 kB
import { a as resolveGlobalSingleton } from "./global-singleton-0m-JziJW.mjs"; import { c as isRecord } from "./record-coerce-TIsquoVR.mjs"; import { i as getSqliteRuntimeCapabilities, r as ensureSqliteLibrarySelected } from "./bun-sqlite-library-CBSPJxTD.mjs"; import { r as flatMapRetainedOperation, t as createRetainedOperation } from "./retained-operation-CODoIe4t.mjs"; import { a as createSqliteLifecycleAggregateError, s as throwSqliteLifecycleErrors } from "./sqlite-lifecycle-errors-DuOygjcn.mjs"; import { t as captureRuntimeWorkerSource } from "./runtime-worker-generation-DCJaEqeS.mjs"; import { n as resolveRuntimeProcessEntrypointUrl } from "./runtime-process-url-D3H3_asn.mjs"; import { n as hydrateOpenClawStateWorkerError, r as retainOpenClawStateWorkerErrorPayload } from "./openclaw-state-worker-error-Cmtk9G4_.mjs"; import { t as captureRetainedNativeWorkerSource } from "./worker-native-lifecycle-VAONWs_C.mjs"; import { i as DEFAULT_WORKER_PENDING_BYTES, r as WorkerTaskError } from "./src-WCJCjrey.mjs"; import { n as createOwnedWorkerTaskPool } from "./worker-task-pool-iI3pfrsK.mjs"; import { _ as registerOpenClawStateDatabaseAsyncResource, v as registerOpenClawStateDatabaseLifecycleListener } from "./openclaw-state-db-cache-BKCnj4of.mjs"; import { t as SQLITE_IDLE_HANDLE_TTL_MS } from "./sqlite-handle-lifecycle-dWd9h3ii.mjs"; import { AsyncLocalStorage } from "node:async_hooks"; //#region src/channels/message/ingress-queue-read-contract.ts function isChannelIngressReadCommand(value) { if (!isRecord(value)) return false; if (value.type === "channelIngress.failedHealth") return value.input === void 0; if (value.type === "channelIngress.accounts") return isRecord(value.input) && typeof value.input.channelId === "string"; return value.type === "channelIngress.pressureHealth" && isRecord(value.input) && typeof value.input.now === "number"; } //#endregion //#region src/gateway/worker-environments/placement-workspace-journal.types.ts function isJournalOwner(value) { return isRecord(value) && typeof value.sessionId === "string" && typeof value.environmentId === "string" && typeof value.ownerEpoch === "number" && typeof value.placementGeneration === "number"; } function isWorkspaceJournalReadCommand(value) { return isRecord(value) && (value.type === "placementJournals.owners" || (value.type === "placementJournals.placement" || value.type === "placementJournals.load") && isJournalOwner(value.owner) && (value.allowFailedOwner === void 0 || typeof value.allowFailedOwner === "boolean")); } function isWorkspaceJournalReceipt(value) { return isRecord(value) && (value.type === "placementJournals.begin" || value.type === "placementJournals.abort" || value.type === "placementJournals.prune") && Array.isArray(value.owners) && value.owners.every(isJournalOwner) && Array.isArray(value.changes) && value.changes.every((change) => isRecord(change) && (change.all === true && change.scope === "worker-placements" || typeof change.agentId === "string" && typeof change.sessionKey === "string")); } //#endregion //#region src/state/openclaw-state-read-request.ts function captureCommand(command) { if (command.type === "secrets.metadata" || command.type === "secrets.execEnvironment" || command.type === "secrets.value" || command.type === "sessionState.versions" || command.type === "sessionState.ambientTargets" || command.type === "sessionState.events" || command.type === "operatorApprovals.history" || command.type === "diagnostic.latest" || command.type === "operatorApprovals.listCronGrants" || command.type === "acpSessions.metadata" || command.type === "githubPublication.knownPullRequestUrls" || command.type === "githubRepository.knownPullRequestUrls" || command.type === "workers.placementProjection") return structuredClone(command); if (isWorkspaceJournalReadCommand(command)) return command.type === "placementJournals.owners" ? { ...command } : { ...command, owner: { ...command.owner } }; if (command.type === "workerPlacements.changeSnapshot" && command.profileIds) return { ...command, profileIds: [...command.profileIds] }; if (command.type === "cron.scratch") return { ...command, selector: { ...command.selector } }; if (command.type === "userProfiles.avatar.read") return { ...command, expected: { ...command.expected } }; if (command.type === "channelIngress.failedHealth") return { type: command.type }; if (command.type === "channelIngress.pressureHealth") return { type: command.type, input: { now: command.input.now } }; if (command.type === "channelIngress.accounts") return { type: command.type, input: { channelId: command.input.channelId } }; if (command.type === "cron.jobNames") return { ...command, jobIds: [...command.jobIds] }; if (command.type === "cron.quarantine") return { type: command.type, storeKey: command.storeKey }; if (command.type === "githubPublication.sharedObservation") return { type: command.type, input: { ...command.input, session: { ...command.input.session }, selector: { ...command.input.selector }, entry: { ...command.input.entry, ...command.input.entry.worktree ? { worktree: { ...command.input.entry.worktree } } : {} } } }; if (command.type === "sessionRepositoryWorkspaces.find") return { type: command.type, owners: command.owners.map(({ agentId, sessionKey }) => ({ agentId, sessionKey })) }; if (command.type === "userProfiles.channelIdentity.resolve") return { type: command.type, identity: structuredClone(command.identity) }; if (command.type === "userProfiles.githubAttribution.resolve" || command.type === "userPreferences.values") return { ...command, profileIds: [...command.profileIds] }; if (command.type === "subagents.runs") return { ...command, scope: command.scope.kind === "descendants" ? { kind: "descendants", sessionKeys: [...command.scope.sessionKeys], liveTopology: command.scope.liveTopology.map((link) => ({ ...link })) } : command.scope.kind === "ids" ? { kind: "ids", runIds: [...command.scope.runIds] } : { ...command.scope } }; if (command.type === "mcpOAuth.statuses") return { type: command.type, input: [...command.input] }; if (command.type === "sessionGroups.members") return { ...command, cfg: structuredClone(command.cfg) }; if (command.type === "conversationBindings.inspect") { const { channel, accountId, conversationId, parentConversationId } = command.conversation; return { type: command.type, conversation: { channel, accountId, conversationId, ...parentConversationId !== void 0 ? { parentConversationId } : {} } }; } if (command.type === "cron.currentReceipt") { const { receiptId, storeKey, jobId, agentId, ownerPid, ownerStartTime } = command.handle; return { type: command.type, handle: { receiptId, storeKey, jobId, agentId, ownerPid, ownerStartTime }, includeJob: command.includeJob, includeAvailability: command.includeAvailability }; } if (command.type === "cron.observeRunRecovery") return { type: command.type, storeKey: command.storeKey, proposals: command.proposals.map(({ jobId, queuedAtMs, runningAtMs }) => ({ jobId, ...queuedAtMs === void 0 ? {} : { queuedAtMs }, ...runningAtMs === void 0 ? {} : { runningAtMs } })) }; if (command.type === "devicePairing.bootstrapContext") return { ...command, input: { ...command.input } }; if (command.type === "pluginBlob.lookup") { const { pluginId, namespace, key } = command.input; return { type: command.type, input: { pluginId, namespace, key } }; } if (command.type === "pluginBlob.entries") { const { pluginId, namespace } = command.input; return { type: command.type, input: { pluginId, namespace } }; } if (command.type === "updateRuns.list") return { ...command, input: { ...command.input } }; if (command.type === "updateRuns.reconciliationCandidates") return { ...command, input: { ...command.input, ...command.input.runIds ? { runIds: [...command.input.runIds] } : {} } }; if (command.type === "skills.library.descriptions" || command.type === "skills.library.manifests") return { type: command.type, input: command.input.map(({ skillId, revision }) => ({ skillId, revision })) }; if (command.type === "audit.run.inspect") { const input = command.input; const common = { now: input.now, decisionCursor: input.decisionCursor, decisionLimit: input.decisionLimit }; return { type: command.type, input: "executionId" in input ? { ...common, executionId: input.executionId } : { ...common, runId: input.runId, executionOffset: input.executionOffset, executionLimit: input.executionLimit } }; } if (command.type === "workerEnvironments.pruneCandidates") return { type: command.type, input: { ...command.input, cursor: command.input.cursor ? { ...command.input.cursor } : void 0 } }; if (command.type === "workerEnvironments.snapshot") return { type: command.type, ...command.ids ? { ids: [...command.ids] } : {} }; return { ...command }; } function stringBytes(values) { return values.reduce((bytes, value) => bytes + Buffer.byteLength(value ?? "", "utf8"), 0); } function commandBytes(command) { if (command.type === "secrets.execEnvironment" || command.type === "secrets.value" || command.type === "sessionState.versions" || command.type === "sessionState.ambientTargets" || command.type === "sessionState.events" || command.type === "workers.placementProjection" || command.type === "workers.placementPendingResults" || isWorkspaceJournalReadCommand(command)) return Buffer.byteLength(JSON.stringify(command), "utf8"); let bytes = Buffer.byteLength(command.type, "utf8"); if (command.type === "generatedHtmlProvenance.read") return bytes + Buffer.byteLength(command.input, "utf8"); if (command.type === "diagnostic.latest") return bytes + Buffer.byteLength(command.input.scope, "utf8") + 16; if (command.type === "cron.activeReceiptOwners") return bytes + Buffer.byteLength(command.agentId, "utf8"); if (command.type === "claws.packageOwnership") return bytes + Buffer.byteLength(command.agentId ?? "", "utf8"); if (command.type === "workerPlacements.changeSnapshot") return bytes + stringBytes(command.profileIds ?? []); if (command.type === "tui.lastSession.read") return bytes + Buffer.byteLength(command.stateKey, "utf8"); if (isChannelIngressReadCommand(command)) return bytes + Buffer.byteLength(JSON.stringify(command.input ?? null), "utf8"); if (command.type === "acpSessions.metadata") return command.entries.reduce((total, input) => total + stringBytes([ ...input.keys, input.legacyKey, input.entry?.lifecycleRevision, input.entry?.sessionId ]) + (input.entry?.sessionStartedAt === void 0 ? 0 : 8), bytes); if (command.type === "capture.readOnlyEvents") return bytes + Buffer.byteLength(command.sessionId, "utf8") + 8; if (command.type === "capture.readOnlyBlob") return bytes + Buffer.byteLength(command.blobId, "utf8"); if (command.type === "cron.jobNames") return bytes + stringBytes([command.storePath, ...command.jobIds]); if (command.type === "cron.quarantine") return bytes + Buffer.byteLength(command.storeKey, "utf8"); if (command.type === "githubPublication.sharedObservation") return bytes + Buffer.byteLength(JSON.stringify(command.input), "utf8"); if (command.type === "sessionRepositoryWorkspaces.find") return command.owners.reduce((total, owner) => total + stringBytes([owner.agentId, owner.sessionKey]), bytes); if (command.type === "agentDatabaseDeletion.snapshot") return bytes + Buffer.byteLength(command.purpose, "utf8"); if (command.type === "agentDeletionJournal.status" || command.type === "agentDeletionJournal.authority") return bytes + Buffer.byteLength(command.agentId, "utf8"); if (command.type === "subagents.runs") return bytes + (command.scope.kind === "descendants" ? stringBytes(command.scope.sessionKeys) + command.scope.liveTopology.reduce((total, link) => total + stringBytes([link.childSessionKey, link.requesterSessionKey]), 0) : command.scope.kind === "session" ? Buffer.byteLength(command.scope.sessionKey, "utf8") : command.scope.kind === "ids" ? stringBytes(command.scope.runIds) : 0); if (command.type === "mcpOAuth.statuses") return bytes + stringBytes(command.input); if (command.type === "mcpOAuth.readOnly" || command.type === "mcpOAuth.keys" || command.type === "mcpOAuth.pending" || command.type === "mcpOAuth.countPrincipals") return bytes + Buffer.byteLength(command.input, "utf8"); if (command.type === "sessionGroups.members") return bytes + Buffer.byteLength(JSON.stringify(command.cfg), "utf8"); if (command.type === "conversationBindings.inspect") return bytes + stringBytes(Object.values(command.conversation)); if (command.type === "cron.currentReceipt") return bytes + Buffer.byteLength(JSON.stringify(command.handle), "utf8") + 2; if (command.type === "cron.observeRunRecovery") return command.proposals.reduce((total, proposal) => total + Buffer.byteLength(proposal.jobId, "utf8") + (proposal.queuedAtMs === void 0 ? 0 : 8) + (proposal.runningAtMs === void 0 ? 0 : 8), bytes + Buffer.byteLength(command.storeKey, "utf8")); if (command.type === "cron.scratch") return bytes + Buffer.byteLength(command.storeKey, "utf8") + Buffer.byteLength(command.selector.kind, "utf8") + (command.selector.kind === "job" ? 8 : 0) + Buffer.byteLength(command.selector.kind === "job" ? command.selector.jobId : command.selector.agentId, "utf8"); if (command.type === "devicePairing.bootstrapContext") return bytes + Buffer.byteLength(command.input.token) + Buffer.byteLength(command.input.deviceId) + Buffer.byteLength(command.input.publicKey) + 8; if (command.type === "devicePairing.lookup") return bytes + Buffer.byteLength(command.deviceId); if (command.type === "devicePairing.pending") return bytes + Buffer.byteLength(command.requestId) + 8; if (command.type === "devicePairing.list") return bytes + 8 + Buffer.byteLength(command.publishedRevision ?? ""); if (command.type === "operatorApprovals.history") return bytes + Buffer.byteLength(command.input.cursor ?? "", "utf8") + Buffer.byteLength(command.input.kind ?? "", "utf8") + 16; if (command.type === "operatorApprovals.listCronGrants") return bytes + 8; if (command.type === "deliveryQueue.outbound") return bytes + Buffer.byteLength(command.id ?? "", "utf8"); if (command.type === "githubPublication.request" || command.type === "githubRepository.request" || command.type === "githubPublication.lifecycle") return bytes + Buffer.byteLength(command.requestId, "utf8") + 8; if (command.type === "githubPublication.knownPullRequestUrls" || command.type === "githubRepository.knownPullRequestUrls") return Object.values(command.input).reduce((total, value) => total + (typeof value === "string" ? Buffer.byteLength(value, "utf8") : 8), bytes); if (command.type === "pluginBlob.lookup" || command.type === "pluginBlob.entries") return bytes + Buffer.byteLength(command.input.pluginId, "utf8") + Buffer.byteLength(command.input.namespace, "utf8") + (command.type === "pluginBlob.lookup" ? Buffer.byteLength(command.input.key, "utf8") : 0); if (command.type === "subagents.forChildSession") return bytes + Buffer.byteLength(command.childSessionKey, "utf8"); if (command.type === "sandboxRegistry.get") return bytes + Buffer.byteLength(command.containerName, "utf8"); if (command.type === "sandboxRegistry.runtimeIds") return bytes + Buffer.byteLength(command.backendId, "utf8") + Buffer.byteLength(command.scopeKey, "utf8"); if (command.type === "updateRuns.get" || command.type === "updateRuns.reconciliationCandidate") return bytes + Buffer.byteLength(command.runId, "utf8"); if (command.type === "updateRuns.reconciliationCandidates") return bytes + stringBytes(command.input.runIds ?? []) + 3 + (command.input.repairHistorySinceMs === void 0 ? 0 : 8); if (command.type === "updateRuns.list") return bytes + Buffer.byteLength(command.input.reason ?? "", "utf8") + Buffer.byteLength(command.input.includeRunId ?? "", "utf8") + (command.input.limit === void 0 ? 0 : 8) + (command.input.active === void 0 ? 0 : 1); if (command.type === "skills.library.descriptions" || command.type === "skills.library.manifests") return command.input.reduce((total, pin) => total + stringBytes([pin.skillId, pin.revision]), bytes); if (command.type === "fleet.get") return bytes + Buffer.byteLength(command.tenantId, "utf8"); if (command.type === "onboardingRecommendations.read") return bytes + Buffer.byteLength(command.configKey, "utf8"); if (command.type === "userModelAccounts.links" || command.type === "userProfiles.reconcile" || command.type === "userProfiles.avatar.inspect" || command.type === "userProfiles.channelIdentity.list" || command.type === "userProfiles.authority.resolve") return bytes + Buffer.byteLength(command.profileId, "utf8"); if (command.type === "userProfiles.avatar.read") return bytes + Buffer.byteLength(command.profileId, "utf8") + stringBytes(Object.values(command.expected)); if (command.type === "userProfiles.githubIdentity.cached") return bytes + Buffer.byteLength(command.email, "utf8") + 8; if (command.type === "userProfiles.githubAttribution.resolve" || command.type === "userPreferences.values") return bytes + stringBytes(command.profileIds) + (command.type === "userPreferences.values" ? Buffer.byteLength(command.key) : 0); if (command.type === "userProfiles.channelIdentity.resolve") return bytes + Buffer.byteLength(JSON.stringify(command.identity), "utf8"); if (command.type === "userProfiles.email.resolve") return bytes + Buffer.byteLength(command.email, "utf8"); if (command.type === "workspace.snapshot") return bytes + Buffer.byteLength(command.workspaceDir, "utf8"); if (command.type === "audit.run.inspect") { const input = command.input; bytes += Buffer.byteLength(input.decisionCursor ?? "", "utf8") + 8; if (input.decisionLimit !== void 0) bytes += 8; if ("executionId" in input) return bytes + Buffer.byteLength(input.executionId, "utf8"); return bytes + Buffer.byteLength(input.runId, "utf8") + (input.executionOffset === void 0 ? 0 : 8) + (input.executionLimit === void 0 ? 0 : 8); } if (command.type === "workerEnvironments.pruneCandidates") return bytes + 8 + (command.input.limit === void 0 ? 0 : 8) + (command.input.cursor ? 8 + Buffer.byteLength(command.input.cursor.environmentId, "utf8") : 0); if (command.type === "workerEnvironments.snapshot") return bytes + stringBytes(command.ids ?? []); return bytes; } function requestBytes(request) { return commandBytes(request.command) + stringBytes([ ...Object.entries(request.context.environment).flatMap(([key, value]) => [key, value]), request.context.existingSchemaPath, request.databasePath, request.location, request.expectedIdentity, request.snapshotRoot ]); } //#endregion //#region src/state/openclaw-state-read-worker.ts function closeReadResources(pool, key) { if (!pool) return; return getSqliteRuntimeCapabilities().explicitSqliteCloseReleasesNativeResources ? pool.closeResources(key) : pool.rotate(); } async function closeReadPool(state) { if (state.closing) return await state.closing; const pool = state.pool; if (!pool) return; const closing = Promise.resolve().then(() => closeReadResources(pool)).then(() => pool.close()).then(() => { state.pool = void 0; }); state.closing = closing; try { await closing; } finally { state.closing = void 0; } } function readRuntimes() { return resolveGlobalSingleton(Symbol.for("openclaw.stateReadWorkers"), () => { const sources = /* @__PURE__ */ new Map(); registerOpenClawStateDatabaseAsyncResource({ phase: "after-resources", async close(identity) { const results = await Promise.allSettled([...sources.values()].map(async (state) => { if (identity) await closeReadResources(state.pool, identity.key); else await closeReadPool(state); })); throwSqliteLifecycleErrors(results.flatMap((result) => result.status === "rejected" ? [result.reason] : []), "Shared-state reader source cleanup failed"); } }); registerOpenClawStateDatabaseLifecycleListener((event) => { if (event.kind !== "opened" && event.identity) for (const state of sources.values()) closeReadResources(state.pool, event.identity.key)?.catch((error) => { process.emitWarning(`Shared-state reader invalidation failed: ${String(error)}`); }); }); return sources; }); } /** Retire cached workers only after every independently admitted reader has joined. */ async function retireIdleOpenClawStateReadWorkers(nativeSource) { const state = readRuntimes().get(nativeSource); if (!state) return true; if (state.operations.size > 0) return false; await closeReadPool(state); return true; } function readPool(state, admitted) { if (state.sealed && !admitted || state.closing) throw new WorkerTaskError("Shared-state readers are closing", "unavailable"); if (!state.pool) { ensureSqliteLibrarySelected(); state.pool = createOwnedWorkerTaskPool({ workerUrl: state.workerUrl, workerOptions: { resourceLimits: { maxOldGenerationSizeMb: 512 } }, maxWorkers: 2, idleTimeoutMs: SQLITE_IDLE_HANDLE_TTL_MS, maxPendingTasks: 128, maxPendingBytes: DEFAULT_WORKER_PENDING_BYTES }, { retainedTransport: true, nativeSource: state.nativeSource }); } return state.pool; } /** Capture the execution source before snapshot preparation yields. */ function captureOpenClawStateReadSource() { const captured = captureRuntimeWorkerSource(resolveRuntimeProcessEntrypointUrl("stateRead")); const nativeSource = captureRetainedNativeWorkerSource({ runtimeGeneration: captured.runtimeGeneration }); const sources = readRuntimes(); let runtime = sources.get(nativeSource); if (!runtime) { const created = { nativeSource, workerUrl: captured.moduleUrl, operations: /* @__PURE__ */ new Set(), servicing: false, sealed: false }; nativeSource.retain(created, () => { created.sealed = true; if (!created.stopping) created.stopping = Promise.resolve().then(async () => { const results = await Promise.allSettled([...created.operations].map((operation) => Promise.resolve().then(() => operation.close()))); throwSqliteLifecycleErrors(results.flatMap((result) => result.status === "rejected" ? [result.reason] : []), "Shared-state reader source cleanup failed"); await closeReadPool(created); sources.delete(nativeSource); }).finally(() => { created.stopping = void 0; }); return created.stopping; }); sources.set(nativeSource, created); runtime = created; } const state = runtime; const admitted = /* @__PURE__ */ new Set(); return { createTransport: (command) => createReadTransport(command, state, () => admitted.size > 0), own(service, close) { if (state.sealed || state.closing) throw new WorkerTaskError("Shared-state readers are closing", "unavailable"); const inContext = AsyncLocalStorage.snapshot(); const operation = { service: () => inContext(service), close: () => inContext(close) }; state.operations.add(operation); admitted.add(operation); return () => { state.operations.delete(operation); admitted.delete(operation); }; }, service() { if (state.servicing) return; state.servicing = true; const errors = []; try { const operations = Array.from(state.operations); for (const operation of operations) if (state.operations.has(operation)) try { operation.service(); } catch (error) { errors.push(error); } } finally { state.servicing = false; } throwSqliteLifecycleErrors(errors, "Shared-state reader source cleanup failed"); } }; } function decodeTaskReply(reply) { if (reply.ok) return { value: reply }; const error = new Error(reply.message); retainOpenClawStateWorkerErrorPayload(error, reply.error); return { error: hydrateOpenClawStateWorkerError(error, { includeOrdinary: true }), sourceAdmitted: reply.sourceAdmitted === true }; } function createReadTransport(command, state, ownsAdmission) { const capturedCommand = captureCommand(command); const tasks = /* @__PURE__ */ new Map(); let closed = false; let closing; const startCloseTask = (task) => { const inContext = AsyncLocalStorage.snapshot(); const cleanup = tasks.get(task); let release; const completion = createRetainedOperation(() => inContext(service)); const fail = (error) => completion.reject(cleanup?.error ? createSqliteLifecycleAggregateError([cleanup.error, error], "Shared-state reader cleanup and worker retirement failed", cleanup.error) : error); function service() { if (completion.operation.read().status !== "pending") return; try { release.service(); const outcome = release.read(); if (outcome.status === "pending") return; if (outcome.status === "rejected") throw outcome.error; tasks.delete(task); completion.resolve(void 0); } catch (error) { fail(error); } } try { release = task.release(cleanup?.retire ? { retire: true } : void 0); release.result.then(() => completion.operation.service(), () => completion.operation.service()); completion.operation.service(); } catch (error) { fail(error); } return completion.operation; }; const startRun = (context, location, checkFreshAdmission, readCommand, authority, expectedIdentity, snapshotRoot) => { const inContext = AsyncLocalStorage.snapshot(); let task; const cleanup = { retire: true }; const completion = createRetainedOperation(() => inContext(service)); function service() { if (!task || completion.operation.read().status !== "pending") return; let outcome; try { task.service(); const read = task.read(); if (read.status === "pending") return; if (read.status === "rejected") throw read.error; const reply = read.value; if (reply.nativeCleanupFailure) { const error = /* @__PURE__ */ new Error("Shared-state reader native cleanup was not confirmed"); retainOpenClawStateWorkerErrorPayload(error, reply.nativeCleanupFailure.error); cleanup.error = hydrateOpenClawStateWorkerError(error, { includeOrdinary: true }); } outcome = decodeTaskReply(reply); } catch (error) { outcome = { error }; } cleanup.retire = "error" in outcome || cleanup.error !== void 0; completion.resolve(outcome); } try { if (closed) throw new WorkerTaskError("Shared-state read transport is closed", "unavailable"); const request = { context: { environment: { ...context.environment }, existingSchemaPath: context.existingSchemaPath }, databasePath: context.admission.databasePath, location, checkFreshAdmission, expectedIdentity, snapshotRoot, command: { ...readCommand } }; task = readPool(state, ownsAdmission()).startTask(() => { authority.assertCurrent(); return request; }, { signal: authority.signal, inputBytes: requestBytes(request) }); tasks.set(task, cleanup); task.result.then(() => completion.operation.service(), () => completion.operation.service()); completion.operation.service(); } catch (error) { completion.reject(error); } return { task, operation: completion.operation }; }; const startValidateFresh = (context, authority) => { const run = startRun(context, context.admission.databasePath, true, { type: "admit" }, authority); return flatMapRetainedOperation(run.operation, (read) => { if ("error" in read) throw read.error; authority.assertCurrent(); if (!run.task) throw new Error("Shared-state admission completed without its retained task"); return startCloseTask(run.task); }); }; const startRead = (source, authority) => startRun(source.context, source.location, source.checkFreshAdmission, capturedCommand, authority, source.expectedIdentity, source.snapshotRoot).operation; const startClose = () => { closed = true; if (closing) return closing; const releases = [...tasks.keys()].map(startCloseTask); const inContext = AsyncLocalStorage.snapshot(); const completion = createRetainedOperation(() => inContext(service)); closing = completion.operation; function service() { if (completion.operation.read().status !== "pending") return; const errors = []; let pending = false; for (const release of releases) { release.service(); const outcome = release.read(); pending ||= outcome.status === "pending"; if (outcome.status === "rejected") errors.push(outcome.error); } if (pending) return; closing = void 0; try { throwSqliteLifecycleErrors(errors, "Shared-state reader task cleanup failed"); completion.resolve(void 0); } catch (error) { completion.reject(error); } } for (const release of releases) release.result.then(() => completion.operation.service(), () => completion.operation.service()); completion.operation.service(); return completion.operation; }; return { startValidateFresh, startRead, startClose }; } //#endregion export { retireIdleOpenClawStateReadWorkers as n, isWorkspaceJournalReceipt as r, captureOpenClawStateReadSource as t };