UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

230 lines (229 loc) 7 kB
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 };