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