openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
186 lines (185 loc) • 8.3 kB
JavaScript
import { i as getNodeSqliteKysely, n as executeSqliteQuerySync, r as executeSqliteQueryTakeFirstSync } from "./kysely-sync-BMSZn9yz.mjs";
import { i as requestSqliteWorkerOperationAdmission, r as deferSqliteWorkerCommitReceipt } from "./sqlite-worker-operation-admission-DqFz0WIG.mjs";
import { l as runOpenClawStateWriteTransaction } from "./openclaw-state-db-VZFEEleX.mjs";
//#region src/gateway/managed-image-record-store.kernel.ts
const MANAGED_IMAGE_RECORD_COLUMNS = [
"attachment_id",
"session_key",
"agent_id",
"message_id",
"created_at",
"updated_at",
"retention_class",
"alt",
"original_media_root",
"original_media_id",
"original_media_subdir",
"original_content_type",
"original_width",
"original_height",
"original_size_bytes",
"original_filename",
"cleanup_pending"
];
function managedImageRecordToRow(record) {
return {
attachment_id: record.attachmentId,
session_key: record.sessionKey,
agent_id: record.agentId ?? null,
message_id: record.messageId,
created_at: record.createdAt,
updated_at: record.updatedAt ?? null,
retention_class: record.retentionClass ?? null,
alt: record.alt,
original_media_root: record.original.mediaRoot,
original_media_id: record.original.mediaId,
original_media_subdir: record.original.mediaSubdir,
original_content_type: record.original.contentType,
original_width: record.original.width,
original_height: record.original.height,
original_size_bytes: record.original.sizeBytes,
original_filename: record.original.filename,
record_json: JSON.stringify(record)
};
}
function managedImageRecordFromRow(row) {
return {
attachmentId: row.attachment_id,
sessionKey: row.session_key,
...row.agent_id ? { agentId: row.agent_id } : {},
messageId: row.message_id,
createdAt: row.created_at,
...row.updated_at ? { updatedAt: row.updated_at } : {},
...row.retention_class === "history" || row.retention_class === "transient" ? { retentionClass: row.retention_class } : {},
alt: row.alt,
original: {
mediaRoot: row.original_media_root,
mediaId: row.original_media_id,
mediaSubdir: row.original_media_subdir,
contentType: row.original_content_type,
width: row.original_width,
height: row.original_height,
sizeBytes: row.original_size_bytes,
filename: row.original_filename
}
};
}
function managedImageRecordsEqual(left, right) {
return JSON.stringify(left) === JSON.stringify(right);
}
function readManagedImageRecordInDatabase(db, attachmentId) {
const row = executeSqliteQueryTakeFirstSync(db, getNodeSqliteKysely(db).selectFrom("managed_outgoing_image_records").select(MANAGED_IMAGE_RECORD_COLUMNS).where("attachment_id", "=", attachmentId).where("cleanup_pending", "=", 0));
return row ? managedImageRecordFromRow(row) : null;
}
function listManagedImageRecordEntriesInDatabase(db, sessionKey) {
let query = getNodeSqliteKysely(db).selectFrom("managed_outgoing_image_records").select(MANAGED_IMAGE_RECORD_COLUMNS);
if (sessionKey) query = query.where("session_key", "=", sessionKey);
return executeSqliteQuerySync(db, query.orderBy("created_at", "desc").orderBy("attachment_id", "asc")).rows.map((row) => ({
record: managedImageRecordFromRow(row),
cleanupPending: row.cleanup_pending === 1
}));
}
function listManagedImageOriginalMediaIdsInDatabase(db) {
return executeSqliteQuerySync(db, getNodeSqliteKysely(db).selectFrom("managed_outgoing_image_records").select([
"original_media_id",
"original_width",
"original_height",
"original_size_bytes",
"cleanup_pending"
]).orderBy("created_at", "desc").orderBy("attachment_id", "asc")).rows.map((row) => row.original_media_id);
}
function insertManagedImageRecordInDatabase(db, record) {
executeSqliteQuerySync(db, getNodeSqliteKysely(db).insertInto("managed_outgoing_image_records").values(managedImageRecordToRow(record)));
return true;
}
/** Promote a transient record atomically so concurrent message commits cannot lose state. */
function attachManagedImageRecordInDatabase(db, params) {
const stateDb = getNodeSqliteKysely(db);
const row = executeSqliteQueryTakeFirstSync(db, stateDb.selectFrom("managed_outgoing_image_records").select(MANAGED_IMAGE_RECORD_COLUMNS).where("attachment_id", "=", params.attachmentId).where("session_key", "=", params.sessionKey));
if (!row) return false;
if (row.cleanup_pending === 1) return false;
const current = managedImageRecordFromRow(row);
if (current.messageId === params.messageId && current.retentionClass === "history") return true;
const nextRow = managedImageRecordToRow({
...current,
messageId: params.messageId,
retentionClass: "history",
updatedAt: params.updatedAt
});
executeSqliteQuerySync(db, stateDb.updateTable("managed_outgoing_image_records").set({
message_id: nextRow.message_id,
retention_class: nextRow.retention_class,
updated_at: nextRow.updated_at,
record_json: nextRow.record_json
}).where("attachment_id", "=", params.attachmentId));
return true;
}
/** Claim only the exact row cleanup planned against; concurrent updates win. */
function claimManagedImageRecordCleanupInDatabase(db, planned) {
const stateDb = getNodeSqliteKysely(db);
const row = executeSqliteQueryTakeFirstSync(db, stateDb.selectFrom("managed_outgoing_image_records").select(MANAGED_IMAGE_RECORD_COLUMNS).where("attachment_id", "=", planned.attachmentId));
if (!row || row.cleanup_pending === 1 || !managedImageRecordsEqual(managedImageRecordFromRow(row), planned)) return false;
executeSqliteQuerySync(db, stateDb.updateTable("managed_outgoing_image_records").set({ cleanup_pending: 1 }).where("attachment_id", "=", planned.attachmentId));
return true;
}
/** Delete a durably claimed row only after its attachment file is gone. */
function deleteClaimedManagedImageRecordInDatabase(db, planned) {
const stateDb = getNodeSqliteKysely(db);
const row = executeSqliteQueryTakeFirstSync(db, stateDb.selectFrom("managed_outgoing_image_records").select(MANAGED_IMAGE_RECORD_COLUMNS).where("attachment_id", "=", planned.attachmentId));
if (!row || row.cleanup_pending !== 1 || !managedImageRecordsEqual(managedImageRecordFromRow(row), planned)) return false;
executeSqliteQuerySync(db, stateDb.deleteFrom("managed_outgoing_image_records").where("attachment_id", "=", planned.attachmentId));
return true;
}
function executeManagedImageRecordMutation(command, database) {
return runOpenClawStateWriteTransaction(({ db }) => {
requestSqliteWorkerOperationAdmission({
stage: "transaction",
facts: void 0
});
let result;
switch (command.type) {
case "managedImages.insert":
result = insertManagedImageRecordInDatabase(db, command.input);
break;
case "managedImages.attach":
result = attachManagedImageRecordInDatabase(db, command.input);
break;
case "managedImages.claimCleanup":
result = claimManagedImageRecordCleanupInDatabase(db, command.input);
break;
case "managedImages.deleteClaimed": result = deleteClaimedManagedImageRecordInDatabase(db, command.input);
}
const receipt = {
type: command.type,
result
};
requestSqliteWorkerOperationAdmission({
stage: "commit",
facts: receipt
});
deferSqliteWorkerCommitReceipt(db, receipt);
return result;
}, { database }, { operationLabel: command.type });
}
function isManagedImageRecordCommand(command) {
switch (command.type) {
case "managedImages.insert":
case "managedImages.attach":
case "managedImages.claimCleanup":
case "managedImages.deleteClaimed":
case "managedImages.read":
case "managedImages.entries":
case "managedImages.originalMediaIds": return true;
default: return false;
}
}
function executeManagedImageRecordCommand(command, database) {
switch (command.type) {
case "managedImages.read": return readManagedImageRecordInDatabase(database.db, command.input.attachmentId);
case "managedImages.entries": return listManagedImageRecordEntriesInDatabase(database.db, command.input.sessionKey);
case "managedImages.originalMediaIds": return listManagedImageOriginalMediaIdsInDatabase(database.db);
default: return executeManagedImageRecordMutation(command, database);
}
}
//#endregion
export { managedImageRecordsEqual as a, managedImageRecordToRow as i, isManagedImageRecordCommand as n, managedImageRecordFromRow as r, executeManagedImageRecordCommand as t };