File size: 4,406 Bytes
b682f80 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | const ROOT_JSON_KEY = '__historyRootJson';
const VERSION_META_FIELDS = ['toolCalls', 'responseEdits', 'responseSegments', 'error'];
function validateAndRepairTree(rootMessage) {
const repair = (msg) => {
if (!msg) return;
if (msg.content === undefined || msg.content === null) {
msg.content = '';
}
if (msg.versions && Array.isArray(msg.versions)) {
for (const version of msg.versions) {
if (version.content === undefined || version.content === null) {
version.content = '';
}
if (version.tail && Array.isArray(version.tail)) {
for (const tailMsg of version.tail) {
repair(tailMsg);
}
}
}
}
};
repair(rootMessage);
return rootMessage;
}
function cloneAndRepairTree(rootMessage) {
return validateAndRepairTree(JSON.parse(JSON.stringify(rootMessage)));
}
function getActiveVersion(message) {
if (!message) return null;
const versions = Array.isArray(message.versions) ? message.versions : [];
if (!versions.length) {
message.versions = [{ content: message.content ?? '', tail: [], timestamp: Date.now() }];
message.currentVersionIdx = 0;
return message.versions[0];
}
const currentVersionIdx = Number.isInteger(message.currentVersionIdx)
? Math.max(0, Math.min(message.currentVersionIdx, versions.length - 1))
: 0;
message.currentVersionIdx = currentVersionIdx;
if (!Array.isArray(message.versions[currentVersionIdx].tail)) {
message.versions[currentVersionIdx].tail = [];
}
if (message.versions[currentVersionIdx].content === undefined || message.versions[currentVersionIdx].content === null) {
message.versions[currentVersionIdx].content = message.content ?? '';
}
return message.versions[currentVersionIdx];
}
function cloneVersionMetaValue(value) {
if (value === undefined) return undefined;
return JSON.parse(JSON.stringify(value));
}
function syncMessageFromActiveVersion(message) {
if (!message) return message;
const currentVersion = getActiveVersion(message);
if (!currentVersion) return message;
message.content = currentVersion.content ?? message.content ?? '';
VERSION_META_FIELDS.forEach((key) => {
if (key in currentVersion) {
message[key] = cloneVersionMetaValue(currentVersion[key]);
} else {
delete message[key];
}
});
return message;
}
function cloneJson(value) {
return JSON.parse(JSON.stringify(value));
}
export function extractFlatHistory(rootMessage) {
if (!rootMessage) return [];
const toFlatEntry = (message) => {
const cloned = cloneJson(message);
if (cloned.content === undefined || cloned.content === null) {
cloned.content = '';
}
syncMessageFromActiveVersion(cloned);
if (Array.isArray(cloned.versions)) {
cloned.versions = cloned.versions.map((version) => ({
...version,
tail: [],
}));
}
return cloned;
};
const history = [toFlatEntry(rootMessage)];
const currentVerIdx = rootMessage.currentVersionIdx ?? 0;
if (!Array.isArray(rootMessage.versions) || currentVerIdx >= rootMessage.versions.length) {
return history;
}
const currentTail = rootMessage.versions[currentVerIdx]?.tail;
if (currentTail && Array.isArray(currentTail)) {
const walkTail = (tail) => {
for (let i = 0; i < tail.length; i++) {
const msg = tail[i];
if (msg?.content === undefined || msg?.content === null) {
msg.content = '';
}
syncMessageFromActiveVersion(msg);
history.push(toFlatEntry(msg));
const ver = msg.versions?.[msg.currentVersionIdx ?? 0];
if (ver?.tail && Array.isArray(ver.tail)) {
walkTail(ver.tail);
}
if (msg.role === 'user' && Array.isArray(msg.versions) && msg.versions.length > 1) {
break;
}
}
};
walkTail(currentTail);
}
return history;
}
export function serializeSessionForClient(session) {
const rootMessage = Array.isArray(session?.history) && session.history[0]
? cloneAndRepairTree(session.history[0])
: null;
return {
id: session?.id,
name: session?.name,
created: session?.created,
history: rootMessage ? extractFlatHistory(rootMessage) : [],
model: session?.model || null,
updatedAt: session?.updatedAt || null,
[ROOT_JSON_KEY]: rootMessage ? JSON.stringify(rootMessage) : null,
};
}
|