openclaw/scripts/lib/sqlite-transcript-payload.mjs
Peter Steinberger c65911334f
refactor: compact agent storage and index full-text maintenance (#153683)
* refactor: compact agent payloads and index full-text maintenance

* perf: reuse transcript metadata plans during agent migration

* fix: preserve storage upgrade fixtures and backup projections

* fix: complete compact-storage validation repairs

* fix: complete compact-storage CI contracts

* test: retain upgrade failure details and stabilize cleanup checks

* test: qualify upgrades with immutable fixture package identities

* fix: qualify storage fixtures and binary types

* docs(memory): correct storage migration schema version
2026-09-21 16:23:13 -07:00

62 lines
2.2 KiB
JavaScript

import zlib from "node:zlib";
// Release proofs decode the persisted contract independently of candidate runtime code.
const MAX_COMPRESSED_EVENT_BYTES = 4 * 1024 * 1024;
const payloadSchemas = new WeakMap();
const utf8Decoder = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true });
function hasCompressedPayloads(database) {
if (!payloadSchemas.has(database)) {
payloadSchemas.set(
database,
Boolean(
database
.prepare("SELECT 1 FROM pragma_table_info('transcript_events') WHERE name = 'event_zstd'")
.get(),
),
);
}
return payloadSchemas.get(database);
}
/** Read published legacy fixtures and current candidate databases without migrating either. */
export function sqliteTranscriptPayloadColumns(database) {
return hasCompressedPayloads(database)
? "event_json, event_zstd, event_utf8_bytes"
: "event_json";
}
/** Bound materialization before decoding any compressed event. */
export function sqliteTranscriptPayloadBytesSql(database) {
return hasCompressedPayloads(database)
? "coalesce(event_utf8_bytes, octet_length(event_json))"
: "octet_length(event_json)";
}
/** Preserve exact JSON bytes for survivor, backup, and cold-restoration comparisons. */
export function readSqliteTranscriptPayload(row) {
if (typeof row.event_json === "string" && row.event_zstd == null) {
return row.event_json;
}
const bytes = row.event_zstd;
const expectedBytes = row.event_utf8_bytes;
if (
row.event_json !== null ||
!(bytes instanceof Uint8Array) ||
bytes.byteLength === 0 ||
bytes.byteLength > MAX_COMPRESSED_EVENT_BYTES ||
!Number.isSafeInteger(expectedBytes) ||
expectedBytes < 1 ||
expectedBytes > MAX_COMPRESSED_EVENT_BYTES
) {
throw new Error("Invalid persisted transcript payload");
}
if (typeof zlib.zstdDecompressSync !== "function") {
throw new Error("Transcript verification requires a runtime with Zstd support");
}
const decoded = zlib.zstdDecompressSync(bytes, { maxOutputLength: expectedBytes });
if (decoded.byteLength !== expectedBytes) {
throw new Error("Persisted transcript payload differs from its recorded UTF-8 size");
}
return utf8Decoder.decode(decoded);
}