UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

377 lines (376 loc) • 16.4 kB
import { i as resolveRuntimeWorkerUrl } from "./runtime-worker-url-CFqA9Dvi.mjs"; import { d as readDatabasePathIdentitySync } from "./sqlite-worker-identity-BRNRpRyc.mjs"; import { n as runtimeProcessEntrypoints } from "./runtime-process-entrypoints-De68tE_W.mjs"; import { n as hydrateOpenClawStateWorkerError, r as retainOpenClawStateWorkerErrorPayload } from "./openclaw-state-worker-error-Bi-BnNrV.mjs"; import { g as resolveUnsuffixedSqliteTargetFromSessionStorePath } from "./paths-Bonddxfk.mjs"; import { i as isIncognitoOpenClawAgentSqlitePath } from "./openclaw-agent-db.paths-BbmZlEP5.mjs"; import { n as withOpenClawAgentDatabaseReadOnly } from "./openclaw-agent-db-readonly-DAqV3tqr.mjs"; import { r as createSqliteWorkerOperationAdmission } from "./sqlite-worker-operation-admission-C5lBzzTk.mjs"; import { c as runOpenClawAgentWriteTransaction, d as withOpenClawAgentDatabaseRuntime } from "./openclaw-agent-db-DWI9Bgur.mjs"; import { n as runOpenClawAgentWriteAdmission, t as runOpenClawAgentWorkerWrite } from "./openclaw-agent-write-admission-CXJiE5VB.mjs"; import { i as toDatabaseOptions } from "./session-accessor.sqlite-scope-helpers-CfDTAEsL.mjs"; import { t as captureSessionTranscriptStorageEnvironment } from "./transcript-target-binding-DpcuSIFy.mjs"; import { i as prepareSqliteTargetFromSessionStorePath } from "./session-sqlite-target-Dd3VSz82.mjs"; import { Sr as validateProgressCardRefreshParams, br as validateProgressCardGetParams, xr as validateProgressCardPutParams } from "./src-D6kL8tMP.mjs"; import { n as captureOpenClawAgentDatabaseExecution } from "./openclaw-agent-execution-C2B2fucX.mjs"; import { n as openOpenClawAgentSqliteWorkerStore } from "./openclaw-agent-worker-store-BE9hhRoh.mjs"; import { t as ErrorCodes } from "./gateway-error-details-gTekQWj2.mjs"; import { d as errorShape } from "./error-codes-D0WRV4Bq.mjs"; import { s as resolveSqliteScope } from "./session-accessor.sqlite-scope-BkgwxatT.mjs"; import { r as captureIncognitoSessionOperation } from "./session-incognito-binding-Dp6RTei2.mjs"; import { _ as withSessionHistoryWorkerReadCandidates } from "./session-transcript-worker-resources-cnBmyJ1M.mjs"; import { c as withSessionHistoryWorkerDatabase } from "./session-transcript-worker-runtime-BdmdicNg.mjs"; import { a as writeSessionProgressCard, r as readSessionProgressCard } from "./progress-card-store-Ntv0Giw7.mjs"; import { t as captureSessionStoreReadCandidates } from "./session-store-target-inventory-C9ERDnSH.mjs"; import { n as withSessionStoreTarget } from "./session-store-target-runtime-BCIudNUA.mjs"; import { n as resolveRequestedSessionStoreTarget } from "./session-store-key-Dvf3CKvN.mjs"; import { r as normalizeProgressCardInput, t as ProgressCardInputError } from "./progress-card-input-DpZWr3eq.mjs"; import { t as SessionMutationAuthorizationChangedError } from "./session-mutation-authorization-error-Cdqn6r49.mjs"; import { t as assertValidParams } from "./validation-UW_NLjlV.mjs"; import { n as captureGatewaySessionStoreScope } from "./board-store-3Y8VDNrq.mjs"; import { g as sessionObserverScopeKey } from "./session-observer-model-C1xAPnwC.mjs"; import { t as retainSessionScopedRead } from "./session-scoped-read-Di7DSq1n.mjs"; //#region src/gateway/progress-card-store.ts /** * The activation owner captures routing and supplies live, SQL-free authority. * @internal Knip production exception; atomic activation installs this store. */ function createIncognitoProgressCardStore(resolveSession) { const capture = (sessionKey, agentId, assertCurrent) => { const scope = resolveSession(sessionKey, agentId); const target = resolveSqliteScope(scope); const { actor, authority } = scope.incognito; if (actor.agentId !== target.agentId || actor.path !== toDatabaseOptions(target).path) throw new Error("Progress-card target differs from its captured incognito actor"); const claim = actor.sessions.captureCurrent(target.sessionKey); const expected = actor.sessions.readSharing(target.sessionKey)?.entry; const current = { assertCurrent() { assertCurrent?.(); authority.assertCurrent(); actor.assertCurrent(); }, authorize(stage, facts) { if (facts.sharing?.entry?.sessionId !== expected?.sessionId || facts.sharing?.entry?.lifecycleRevision !== expected?.lifecycleRevision) throw new Error("progress-card session changed; retry"); return authority.authorize?.(stage, facts); } }; current.assertCurrent(); return { actor, current, claim, sessionKey: target.sessionKey }; }; return { async get(sessionKey, agentId) { const target = capture(sessionKey, agentId); const card = await target.actor.sessions.withSharedState(() => target.actor.sessions.sideData(target.current, { type: "session.progressCard.get", input: { sessionKey: target.sessionKey } })); target.current.assertCurrent(); target.claim.assertCurrent(); target.actor.assertReadable(); return card; }, async put(sessionKey, input, agentId) { const target = capture(sessionKey, agentId, input.assertCurrent); const captured = structuredClone({ markdown: input.markdown, steps: input.steps, expectedRevision: input.expectedRevision }); const result = await target.actor.sessions.withSharedState(() => target.actor.sessions.sideData(target.current, { type: "session.progressCard.put", input: { ...captured, sessionKey: target.sessionKey } })); target.current.assertCurrent(); target.claim.assertCurrent(); target.actor.assertReadable(); return "card" in result ? result : { card: null }; } }; } const progressCardStore = { async get(sessionKey, agentId) { const incognito = captureIncognitoSessionOperation({ sessionKey, agentId }); if (incognito) return createIncognitoProgressCardStore(() => ({ sessionKey, agentId: incognito.actor.agentId, storePath: incognito.actor.path, incognito })).get(sessionKey, agentId); const env = captureSessionTranscriptStorageEnvironment(process.env); const scope = captureGatewaySessionStoreScope(sessionKey, agentId); const unsuffixed = resolveUnsuffixedSqliteTargetFromSessionStorePath(scope.storePath); if (isIncognitoOpenClawAgentSqlitePath(unsuffixed.path, { agentId: scope.agentId, env })) { const result = withOpenClawAgentDatabaseReadOnly((database) => readSessionProgressCard(database.db, scope.sessionKey), { agentId: scope.agentId, path: unsuffixed.path, env }); return result.found ? result.value : null; } const target = await prepareSqliteTargetFromSessionStorePath(scope.storePath, { agentId: scope.agentId, env }); return await withSessionHistoryWorkerDatabase({ agentId: target.agentId ?? scope.agentId, path: target.path, env }, (owner) => owner.readProgressCard({ sessionKey: scope.sessionKey, env })); }, async put(sessionKey, input, agentId) { const incognito = captureIncognitoSessionOperation({ sessionKey, agentId }); if (incognito) return createIncognitoProgressCardStore(() => ({ sessionKey, agentId: incognito.actor.agentId, storePath: incognito.actor.path, incognito })).put(sessionKey, input, agentId); const resolved = captureGatewaySessionStoreScope(sessionKey, agentId); const env = captureSessionTranscriptStorageEnvironment(process.env); const capturedInput = structuredClone({ markdown: input.markdown, steps: input.steps, expectedRevision: input.expectedRevision }); const assertCurrent = () => { input.assertCurrent?.(); const current = captureGatewaySessionStoreScope(sessionKey, agentId); if (current.agentId !== resolved.agentId || current.storePath !== resolved.storePath || current.sessionKey !== resolved.sessionKey) throw new Error("progress-card session changed; retry"); }; assertCurrent(); const unsuffixed = resolveUnsuffixedSqliteTargetFromSessionStorePath(resolved.storePath); if (isIncognitoOpenClawAgentSqlitePath(unsuffixed.path, { agentId: resolved.agentId, env })) { const databaseOptions = { agentId: resolved.agentId, path: unsuffixed.path, env }; const result = await runOpenClawAgentWriteAdmission(databaseOptions, () => withOpenClawAgentDatabaseRuntime(databaseOptions, () => runOpenClawAgentWriteTransaction((database) => { assertCurrent(); return writeSessionProgressCard(database.db, resolved.sessionKey, capturedInput); }, databaseOptions, { operationLabel: "progress-card.put" }), assertCurrent), true); return "card" in result ? result : { card: null }; } const candidates = captureSessionStoreReadCandidates(resolved.storePath); const identities = new Map(candidates.filter((candidate) => !candidate.scope).map((candidate) => { const identity = readDatabasePathIdentitySync(candidate.path); return [identity.canonicalPath, identity]; })); const prepare = () => withSessionStoreTarget({ ...resolved, env, candidates }, async (target, owner) => { const options = { ...target.database, env }; const identity = identities.get(options.path) ?? readDatabasePathIdentitySync(options.path); if (!identities.has(options.path) && identity.key.startsWith("file:")) throw new Error("Progress-card target appeared after source capture"); const execution = captureOpenClawAgentDatabaseExecution(options, identity.key.startsWith("file:") ? { expectedIdentity: { kind: "file", physicalIdentity: identity.key.slice(5), nativeLocation: identity.canonicalPath, birthtime: identity.birthtime } } : { expectedCreationIdentity: identity }); const assertOwnerCurrent = () => { assertCurrent(); owner.assertCurrent(); execution.assertCurrent(); }; try { return await runOpenClawAgentWriteAdmission(options, async () => { await owner.refreshBeforeDispatch(() => execution.assertCurrent()); await runOpenClawAgentWorkerWrite(options, () => execution.prepare({ assertCurrent: assertOwnerCurrent, onRegistryChange: owner.onRegistryChange, createAdmission(binding) { return () => ({ nativeLocations: binding.nativeLocations, admission: createSqliteWorkerOperationAdmission((request, grant) => { binding.authorize(request); assertOwnerCurrent(); if (!grant()) throw new Error("Progress-card preparation authority expired"); }, binding.attachment) }); } })); await owner.revalidateTarget(); const worker = await openOpenClawAgentSqliteWorkerStore(options, { execution }, { moduleUrl: resolveRuntimeWorkerUrl(runtimeProcessEntrypoints.progressCardStore), input: void 0 }); try { const receipt = await worker.execute({ type: "put", input: { sessionKey: resolved.sessionKey, ...capturedInput } }, assertOwnerCurrent); if (!receipt.ok) { const error = /* @__PURE__ */ new Error("Progress-card transaction failed"); retainOpenClawStateWorkerErrorPayload(error, receipt.error); throw hydrateOpenClawStateWorkerError(error, { includeOrdinary: true }); } return receipt.value; } finally { await worker.close(); } }, true); } finally { await execution.release(); } }, assertCurrent); const result = await withSessionHistoryWorkerReadCandidates(candidates, async (custody) => { const persist = () => { custody.assertCurrent(); return prepare(); }; return unsuffixed.agentId || unsuffixed.shared ? runOpenClawAgentWriteAdmission({ agentId: resolved.agentId, path: unsuffixed.path, env }, persist, true) : persist(); }); return "card" in result ? result : { card: null }; } }; //#endregion //#region src/gateway/server-methods/progress-card.ts function resolveProgressCardSession(params, context, respond) { const cfg = context.getRuntimeConfig(); const requested = resolveRequestedSessionStoreTarget(cfg, params.sessionKey, params.agentId); if (!requested.ok) { respond(false, void 0, requested.error); return; } const { sessionKey, agentId } = requested.value; return { sessionKey, agentId, scopeKey: sessionObserverScopeKey(sessionKey, agentId) }; } function projectProgressCard(card, scopeKey) { return card ? { ...card, sessionKey: scopeKey } : null; } function createProgressCardHandlers(store = progressCardStore) { return { "progressCard.refresh": async (invocation) => { const { params, respond, context, sessionMutationAuthorization } = invocation; if (!assertValidParams(params, validateProgressCardRefreshParams, "progressCard.refresh", respond)) return; const session = resolveProgressCardSession(params, context, respond); if (!session) return; const readCard = async () => { sessionMutationAuthorization?.assertCurrent(); const card = await store.get(session.sessionKey, session.agentId); sessionMutationAuthorization?.assertCurrent(); return card; }; const card = await readCard(); if (!card) { respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, "There is no progress card to refresh.")); return; } const { requestProgressCardRefresh } = await import("./progress-card-refresh-DHZlxzyv.mjs"); invocation.sessionMutationCommitGuard?.(); sessionMutationAuthorization?.assertCurrent(); await requestProgressCardRefresh(invocation, session, card, params.idempotencyKey, readCard); }, "progressCard.get": async (options) => { const { params, respond, context, sessionMutationAuthorization } = options; if (!assertValidParams(params, validateProgressCardGetParams, "progressCard.get", respond)) return; const session = resolveProgressCardSession(params, context, respond); if (!session) return; sessionMutationAuthorization?.assertCurrent(); const read = retainSessionScopedRead(options, session.sessionKey, session.agentId); try { const card = await store.get(session.sessionKey, session.agentId); sessionMutationAuthorization?.assertCurrent(); read?.assertCurrent(); respond(true, { card: projectProgressCard(card, session.scopeKey) }, void 0); } catch (error) { if (error instanceof SessionMutationAuthorizationChangedError) throw error; respond(false, void 0, errorShape(ErrorCodes.UNAVAILABLE, String(error))); } finally { read?.release(); } }, "progressCard.put": async (invocation) => { const { params, respond, context, sessionMutationAuthorization } = invocation; if (!assertValidParams(params, validateProgressCardPutParams, "progressCard.put", respond)) return; let input; try { input = normalizeProgressCardInput({ markdown: params.markdown, plan: params.plan }); } catch (error) { if (!(error instanceof ProgressCardInputError)) throw error; respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, error.message)); return; } if (params.expectedRevision !== void 0 && (input.markdown || input.steps?.length)) { respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, "expectedRevision is only valid when clearing a card")); return; } const session = resolveProgressCardSession(params, context, respond); if (!session) return; sessionMutationAuthorization?.assertCurrent(); const assertCurrent = () => { invocation.signal?.throwIfAborted(); invocation.sessionMutationCommitGuard?.(); sessionMutationAuthorization?.assertCurrent(); }; try { const result = await store.put(session.sessionKey, { ...input, expectedRevision: params.expectedRevision, assertCurrent }, session.agentId); assertCurrent(); if (params.expectedRevision === void 0 || result.card === null) context.broadcast("progressCard.changed", { sessionKey: session.scopeKey, revision: result.card?.revision ?? null }, { sessionKeys: [session.sessionKey], agentId: session.agentId }); respond(true, { card: projectProgressCard(result.card, session.scopeKey) }, void 0); } catch (error) { if (error instanceof SessionMutationAuthorizationChangedError) throw error; respond(false, void 0, errorShape(ErrorCodes.UNAVAILABLE, String(error))); } } }; } const progressCardHandlers = createProgressCardHandlers(); //#endregion export { progressCardHandlers };