@ai2070/l0
Version:
L0: The Missing Reliability Substrate for AI
137 lines • 4.59 kB
JavaScript
import { normalizeForModel } from "../utils/normalize";
export function formatMemory(memory, options = {}) {
if (typeof memory === "string") {
return formatMemoryString(memory, options);
}
if (!memory || memory.length === 0) {
return "";
}
const { maxEntries, includeTimestamps = false, includeMetadata = false, style = "conversational", normalize = true, } = options;
const entries = maxEntries ? memory.slice(-maxEntries) : memory;
switch (style) {
case "conversational":
return formatConversationalMemory(entries, includeTimestamps, includeMetadata, normalize);
case "structured":
return formatStructuredMemory(entries, includeTimestamps, includeMetadata, normalize);
case "compact":
return formatCompactMemory(entries, normalize);
default:
return formatConversationalMemory(entries, includeTimestamps, includeMetadata, normalize);
}
}
function formatConversationalMemory(entries, includeTimestamps, includeMetadata, normalize) {
const lines = [];
for (const entry of entries) {
const content = normalize
? normalizeForModel(entry.content)
: entry.content;
const roleLabel = getRoleLabel(entry.role);
let line = `${roleLabel}: ${content}`;
if (includeTimestamps && entry.timestamp) {
const date = new Date(entry.timestamp);
line = `[${date.toISOString()}] ${line}`;
}
if (includeMetadata && entry.metadata) {
const meta = Object.entries(entry.metadata)
.map(([k, v]) => `${k}=${v}`)
.join(", ");
if (meta) {
line += ` (${meta})`;
}
}
lines.push(line);
}
return lines.join("\n\n");
}
function formatStructuredMemory(entries, includeTimestamps, includeMetadata, normalize) {
const lines = ["<conversation_history>"];
for (const entry of entries) {
const content = normalize
? normalizeForModel(entry.content)
: entry.content;
let attrs = `role="${entry.role}"`;
if (includeTimestamps && entry.timestamp) {
attrs += ` timestamp="${entry.timestamp}"`;
}
if (includeMetadata && entry.metadata) {
const metaStr = JSON.stringify(entry.metadata);
attrs += ` metadata='${metaStr}'`;
}
lines.push(` <message ${attrs}>`);
lines.push(` ${content}`);
lines.push(` </message>`);
}
lines.push("</conversation_history>");
return lines.join("\n");
}
function formatCompactMemory(entries, normalize) {
return entries
.map((entry) => {
const content = normalize
? normalizeForModel(entry.content)
: entry.content;
const role = (entry.role[0] ?? "U").toUpperCase();
return `${role}: ${content}`;
})
.join("\n");
}
function formatMemoryString(memory, options) {
const { normalize = true } = options;
if (normalize) {
return normalizeForModel(memory);
}
return memory;
}
function getRoleLabel(role) {
switch (role) {
case "user":
return "User";
case "assistant":
return "Assistant";
case "system":
return "System";
default:
return role.charAt(0).toUpperCase() + role.slice(1);
}
}
export function createMemoryEntry(role, content, metadata) {
return {
role,
content,
timestamp: Date.now(),
metadata,
};
}
export function mergeMemory(...memories) {
return memories.flat().sort((a, b) => {
const timeA = a.timestamp || 0;
const timeB = b.timestamp || 0;
return timeA - timeB;
});
}
export function filterMemoryByRole(memory, role) {
return memory.filter((entry) => entry.role === role);
}
export function getLastNEntries(memory, n) {
return memory.slice(-n);
}
export function calculateMemorySize(memory) {
return memory.reduce((sum, entry) => sum + entry.content.length, 0);
}
export function truncateMemory(memory, maxSize) {
const result = [];
let currentSize = 0;
for (let i = memory.length - 1; i >= 0; i--) {
const entry = memory[i];
const entrySize = entry.content.length;
if (currentSize + entrySize <= maxSize) {
result.unshift(entry);
currentSize += entrySize;
}
else {
break;
}
}
return result;
}
//# sourceMappingURL=memory.js.map