openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
147 lines (146 loc) • 6.05 kB
JavaScript
import { i as asOptionalObjectRecord } from "./record-coerce-TIsquoVR.mjs";
import { a as getNodeSqliteKysely, i as executeSqliteQueryTakeFirstSync, r as executeSqliteQuerySync } from "./kysely-sync-K7ftY-g4.mjs";
import { t as clearNodeSqliteKyselyCacheForDatabase } from "./kysely-sync-cache-state-eUau8Jaa.mjs";
import { t as openNodeSqliteDatabase } from "./node-sqlite-XIcwmOrl.mjs";
import { i as tableExists } from "./openclaw-state-db-schema-helpers-BlZefrPy.mjs";
import { a as runSqliteImmediateTransactionSync } from "./sqlite-transaction-DsZ3X6nD.mjs";
import { i as ensureOpenClawAgentProgressCardSchemaInTransaction } from "./openclaw-agent-progress-card-schema-CFYelX0N.mjs";
import fs from "node:fs";
//#region src/session-cards/progress-card-store.ts
function withProgressCardDatabase(input, readOnly, operation) {
if (typeof input !== "string") return operation(input, "openclaw-agent.sqlite");
const db = openNodeSqliteDatabase(input, { readOnly });
try {
if (!readOnly) db.exec("PRAGMA foreign_keys = ON;");
return operation(db, input);
} finally {
clearNodeSqliteKyselyCacheForDatabase(db);
db.close();
}
}
function selectProgressCard(db, sessionKey) {
const kysely = getNodeSqliteKysely(db);
return executeSqliteQueryTakeFirstSync(db, kysely.selectFrom("session_progress_cards").select([
"session_key",
"markdown",
"steps_json",
"revision",
"created_at",
"updated_at"
]).where("session_key", "=", sessionKey).limit(1)) ?? null;
}
function selectProgressCardMetadata(db, sessionKey) {
const kysely = getNodeSqliteKysely(db);
return executeSqliteQueryTakeFirstSync(db, kysely.selectFrom("session_progress_cards").select([
"session_key",
"revision",
"created_at",
"updated_at"
]).where("session_key", "=", sessionKey).limit(1)) ?? null;
}
function rowToProgressCard(row) {
const steps = row.steps_json ? readStoredSteps(row.steps_json) : void 0;
if (!row.markdown && !steps?.length) return null;
return {
sessionKey: row.session_key,
revision: row.revision,
updatedAt: row.updated_at,
...row.markdown ? { markdown: row.markdown } : {},
...steps && steps.length > 0 ? { steps } : {}
};
}
function readStoredSteps(value) {
const parsed = JSON.parse(value);
if (!Array.isArray(parsed)) throw new Error("stored progress-card steps are not an array");
return parsed.map((entry, index) => {
const record = asOptionalObjectRecord(entry);
if (!record) throw new Error(`stored progress-card step ${index} is invalid`);
const { step, status } = record;
if (typeof step !== "string" || status !== "pending" && status !== "in_progress" && status !== "completed") throw new Error(`stored progress-card step ${index} is invalid`);
return {
step,
status
};
});
}
function readSessionProgressCard(dbPathOrDb, sessionKey) {
if (typeof dbPathOrDb === "string" && !fs.existsSync(dbPathOrDb)) return null;
return withProgressCardDatabase(dbPathOrDb, true, (db) => {
if (!tableExists(db, "session_progress_cards")) return null;
const row = selectProgressCard(db, sessionKey);
return row ? rowToProgressCard(row) : null;
});
}
/** Retain revision tombstones, but keep never-used lazy storage dormant during reset. */
function clearSessionProgressCardForReset(db, sessionKey) {
if (!tableExists(db, "session_progress_cards") || !selectProgressCardMetadata(db, sessionKey)) return false;
writeSessionProgressCard(db, sessionKey, {});
return true;
}
function writeSessionProgressCard(dbPathOrDb, sessionKey, input) {
return writePreparedSessionProgressCard(dbPathOrDb, sessionKey, prepareSessionProgressCardWrite(input));
}
function prepareSessionProgressCardWrite(input) {
const markdown = input.markdown?.trim() ? input.markdown : void 0;
const steps = input.steps && input.steps.length > 0 ? input.steps : void 0;
return {
markdown,
steps,
stepsJson: steps ? JSON.stringify(steps) : null,
expectedRevision: input.expectedRevision
};
}
function writePreparedSessionProgressCard(dbPathOrDb, sessionKey, input) {
return withProgressCardDatabase(dbPathOrDb, false, (db, label) => {
const write = () => {
ensureOpenClawAgentProgressCardSchemaInTransaction(db);
const kysely = getNodeSqliteKysely(db);
const { markdown, steps, stepsJson } = input;
if (!markdown && !steps) {
let previous;
if (input.expectedRevision !== void 0) {
const currentRow = selectProgressCard(db, sessionKey);
const current = currentRow ? rowToProgressCard(currentRow) : null;
if (!currentRow || currentRow.revision !== input.expectedRevision || !current) return { card: current };
previous = currentRow;
} else previous = selectProgressCardMetadata(db, sessionKey);
if (previous) executeSqliteQuerySync(db, kysely.updateTable("session_progress_cards").set({
markdown: null,
steps_json: null,
revision: previous.revision + 1,
updated_at: Date.now()
}).where("session_key", "=", sessionKey));
return { cleared: true };
}
const previous = selectProgressCardMetadata(db, sessionKey);
const now = Date.now();
const revision = (previous?.revision ?? 0) + 1;
executeSqliteQuerySync(db, kysely.insertInto("session_progress_cards").values({
session_key: sessionKey,
markdown: markdown ?? null,
steps_json: stepsJson,
revision,
created_at: previous?.created_at ?? now,
updated_at: now
}).onConflict((conflict) => conflict.column("session_key").doUpdateSet({
markdown: markdown ?? null,
steps_json: stepsJson,
revision,
updated_at: now
})));
return { card: {
sessionKey,
revision,
updatedAt: now,
...markdown ? { markdown } : {},
...steps ? { steps } : {}
} };
};
return db.isTransaction ? write() : runSqliteImmediateTransactionSync(db, write, {
databaseLabel: label,
operationLabel: "progress-card.write"
});
});
}
//#endregion
export { writeSessionProgressCard as a, writePreparedSessionProgressCard as i, prepareSessionProgressCardWrite as n, readSessionProgressCard as r, clearSessionProgressCardForReset as t };