openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
108 lines (107 loc) • 3.48 kB
JavaScript
import { c as isRecord } from "./record-coerce-DItp3I4t.js";
import { E as tableExists } from "./openclaw-state-db-cache-C7ljO0xP.js";
//#region src/commands/doctor-session-sqlite-transcript-readers.ts
const LABEL_ROWS_SQL = "SELECT event_json, seq FROM transcript_events WHERE session_id = ? ORDER BY seq ASC";
var ReadOnlySqliteTranscriptReader = class {
constructor(database) {
this.database = database;
}
sessionIds() {
if (!tableExists(this.database, "transcript_events")) return [];
return this.database.prepare("SELECT DISTINCT session_id FROM transcript_events ORDER BY session_id ASC").all().flatMap((row) => typeof row.session_id === "string" ? [row.session_id] : []);
}
repairSnapshot(sessionId, needsRepair) {
let iterator;
try {
this.labelDetection ??= this.database.prepare(LABEL_ROWS_SQL);
iterator = this.labelDetection.iterate(sessionId);
for (const row of iterator) {
if (typeof row.event_json !== "string" || typeof row.seq !== "number") continue;
let event;
try {
event = JSON.parse(row.event_json);
} catch {
continue;
}
if (!needsRepair(event)) continue;
const rows = [];
this.labelSnapshot ??= this.database.prepare(LABEL_ROWS_SQL);
iterator = this.labelSnapshot.iterate(sessionId);
for (const candidate of iterator) if (typeof candidate.event_json === "string" && typeof candidate.seq === "number") rows.push({
eventJson: candidate.event_json,
seq: candidate.seq
});
return {
ok: true,
rows
};
}
return {
ok: true,
rows: []
};
} catch (error) {
try {
iterator?.return?.();
} catch {}
return {
ok: false,
error
};
}
}
/** Reads exact row metadata for a guarded transcript replacement without opening a writer. */
headerlessSnapshot(sessionId) {
let iterator;
try {
this.firstHeaderRow ??= this.database.prepare("SELECT event_json FROM transcript_events WHERE session_id = ? ORDER BY seq ASC LIMIT 1");
const firstRow = this.firstHeaderRow.get(sessionId);
if (typeof firstRow?.event_json === "string") {
let first;
try {
first = JSON.parse(firstRow.event_json);
} catch {
return {
ok: true,
rows: []
};
}
if (!isRecord(first) || first.type === "session") return {
ok: true,
rows: []
};
}
this.sessionKey ??= this.database.prepare("SELECT session_key FROM session_windows WHERE session_id = ? LIMIT 1");
const sessionKeyRow = this.sessionKey.get(sessionId);
const storageRows = [];
this.headerSnapshot ??= this.database.prepare("SELECT created_at, event_json, seq FROM transcript_events WHERE session_id = ? ORDER BY seq ASC");
iterator = this.headerSnapshot.iterate(sessionId);
for (const row of iterator) {
if (typeof row.created_at !== "number" || typeof row.event_json !== "string" || typeof row.seq !== "number") return {
ok: false,
error: /* @__PURE__ */ new Error(`Invalid transcript row metadata for session ${sessionId}`)
};
storageRows.push({
createdAt: row.created_at,
eventJson: row.event_json,
seq: row.seq
});
}
return {
ok: true,
rows: storageRows,
...typeof sessionKeyRow?.session_key === "string" ? { sessionKey: sessionKeyRow.session_key } : {}
};
} catch (error) {
try {
iterator?.return?.();
} catch {}
return {
ok: false,
error
};
}
}
};
//#endregion
export { ReadOnlySqliteTranscriptReader as t };