openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
230 lines (229 loc) • 7 kB
JavaScript
import { c as isRecord } from "./record-coerce-DItp3I4t.js";
import { At as boolean, Bt as discriminatedUnion, Et as array, Lt as custom, Rn as string, St as _null, Xn as union, Zn as unknown, dn as literal, fn as looseObject, yt as _enum } from "./schemas-zxit8y5H.js";
import { n as string$1 } from "./coerce-Drr1hytz.js";
import "./version-Bsehiavt.js";
//#region src/config/sessions/session-entry-codec.ts
const sessionEntryTypeSchema = _enum([
"message",
"thinking_level_change",
"model_change",
"compaction",
"reset",
"branch_summary",
"custom",
"custom_message",
"label",
"session_info"
]);
const readableContentSchema = union([string(), array(looseObject({ type: string() }))]);
const readableMessageSchema = discriminatedUnion("role", [
looseObject({
role: literal("user"),
content: readableContentSchema
}),
looseObject({
role: literal("assistant"),
content: readableContentSchema
}),
looseObject({
role: literal("toolResult"),
toolCallId: string(),
toolName: string(),
isError: boolean(),
content: array(unknown())
}),
looseObject({
role: literal("custom"),
customType: string(),
content: readableContentSchema
}),
looseObject({
role: literal("bashExecution"),
command: string(),
output: string()
})
]);
const indexedSessionEntryBaseShape = {
id: string().min(1),
parentId: union([string(), _null()]).optional(),
timestamp: string().optional()
};
const indexedSessionEntrySchema = discriminatedUnion("type", [
looseObject({
...indexedSessionEntryBaseShape,
type: literal("message"),
message: readableMessageSchema
}),
looseObject({
...indexedSessionEntryBaseShape,
type: literal("thinking_level_change"),
thinkingLevel: string().min(1)
}),
looseObject({
...indexedSessionEntryBaseShape,
type: literal("model_change"),
provider: string().min(1),
modelId: string().min(1)
}),
looseObject({
...indexedSessionEntryBaseShape,
type: literal("compaction"),
summary: string(),
firstKeptEntryId: string().min(1),
tokensBefore: custom((value) => typeof value === "number")
}),
looseObject({
...indexedSessionEntryBaseShape,
type: literal("reset"),
reason: string$1().pipe(_enum([
"new",
"reset",
"idle",
"daily",
"cron-stale"
])),
firstKeptEntryId: string().optional()
}),
looseObject({
...indexedSessionEntryBaseShape,
type: literal("branch_summary"),
fromId: string(),
summary: string()
}),
looseObject({
...indexedSessionEntryBaseShape,
type: literal("custom"),
customType: string().min(1)
}),
looseObject({
...indexedSessionEntryBaseShape,
type: literal("custom_message"),
customType: string().min(1),
content: readableContentSchema,
display: boolean()
}),
looseObject({
...indexedSessionEntryBaseShape,
type: literal("label"),
targetId: string().min(1),
label: string().optional()
}),
looseObject({
...indexedSessionEntryBaseShape,
type: literal("session_info"),
name: string().optional()
})
]);
const parentLinkedOpaqueEntrySchema = looseObject({
type: unknown().optional().refine((type) => type !== "session" && type !== "leaf"),
id: string().min(1),
parentId: union([string(), _null()])
});
const opaqueLeafEntrySchema = looseObject({
type: literal("leaf"),
id: string().min(1),
parentId: union([string(), _null()]),
targetId: union([string(), _null()]),
appendParentId: union([string(), _null()]).optional(),
appendMode: literal("side").optional()
});
const sessionHeaderSchema = looseObject({
type: literal("session"),
id: string()
});
function findSessionTranscriptHeader(entries) {
for (const entry of entries) if (sessionHeaderSchema.safeParse(entry).success) return entry;
}
function assertCurrentSessionTranscriptHeader(header) {
if ((header?.version ?? 1) < 3) throw new Error("Persisted legacy session transcripts require doctor/import migration before runtime use");
}
function isSessionEntryType(type) {
return sessionEntryTypeSchema.safeParse(type).success;
}
function isIndexedSessionEntry(entry) {
return indexedSessionEntrySchema.safeParse(entry).success;
}
function isReadableContent(value) {
return readableContentSchema.safeParse(value).success;
}
function isReadableMessage(value) {
return readableMessageSchema.safeParse(value).success;
}
function isReadableLegacySessionEntry(value) {
const message = isRecord(value) && value.type === "message" ? value.message : void 0;
return isRecord(value) && isSessionEntryType(value.type) && (value.type !== "message" || (isRecord(message) && message.role === "hookMessage" ? isReadableContent(message.content) : isReadableMessage(message)));
}
function normalizePersistedLegacyHookMessage(value) {
if (!isRecord(value) || value.type !== "message" || !isRecord(value.message)) return value;
const message = value.message;
if (message.role !== "custom" || message.customType !== void 0 || !isReadableContent(message.content)) return value;
return {
...value,
message: {
...message,
customType: "hook"
}
};
}
function parseParentLinkedOpaqueEntry(record) {
const parsed = parentLinkedOpaqueEntrySchema.safeParse(record);
return parsed.success ? {
id: parsed.data.id,
parentId: parsed.data.parentId
} : void 0;
}
function parseOpaqueLeafEntry(record) {
const parsed = opaqueLeafEntrySchema.safeParse(record);
if (!parsed.success) return;
const leaf = parsed.data;
return {
id: leaf.id,
parentId: leaf.parentId,
targetId: leaf.targetId,
...leaf.appendParentId !== void 0 ? { appendParentId: leaf.appendParentId } : {},
...leaf.appendMode === "side" ? { appendMode: leaf.appendMode } : {}
};
}
function classifySessionFileEntry(rawEntry, sourceVersion) {
const entry = normalizePersistedLegacyHookMessage(rawEntry);
if (sourceVersion < 3 && isReadableLegacySessionEntry(entry) || isIndexedSessionEntry(entry)) return {
entry,
recognized: true
};
return {
entry,
recognized: false
};
}
function partitionSessionFileEntries(entries) {
const fileEntries = [];
const opaqueEntries = [];
const fileEntriesByOriginalIndex = [];
const sourceVersion = findSessionTranscriptHeader(entries)?.version ?? 1;
let hasHeader = false;
for (const [originalIndex, rawEntry] of entries.entries()) {
if (!hasHeader && sessionHeaderSchema.safeParse(rawEntry).success) {
fileEntries.push(rawEntry);
fileEntriesByOriginalIndex[originalIndex] = rawEntry;
hasHeader = true;
continue;
}
const { entry, recognized } = classifySessionFileEntry(rawEntry, sourceVersion);
if (recognized) {
fileEntries.push(entry);
fileEntriesByOriginalIndex[originalIndex] = entry;
continue;
}
opaqueEntries.push({
index: fileEntries.length,
record: entry
});
}
return {
fileEntries,
opaqueEntries,
fileEntriesByOriginalIndex
};
}
//#endregion
export { parseOpaqueLeafEntry as a, isIndexedSessionEntry as i, classifySessionFileEntry as n, parseParentLinkedOpaqueEntry as o, findSessionTranscriptHeader as r, partitionSessionFileEntries as s, assertCurrentSessionTranscriptHeader as t };