70 lines
2.0 KiB
TypeScript
70 lines
2.0 KiB
TypeScript
import {MemoryCache} from './memory-cache.ts';
|
|
import {extractMetadata, Memory, MemoryNode} from './memory.ts';
|
|
|
|
export function buildMemoryGraph(memories: Memory[] | MemoryCache): MemoryNode[] {
|
|
const mems = memories instanceof MemoryCache ? memories.memories : memories;
|
|
const nameSet = new Set(mems.map(m => m.name));
|
|
const ghosts = new Set<string>();
|
|
|
|
const nodes: MemoryNode[] = mems.map(m => {
|
|
const {links, backlinks} = extractMetadata(m.content);
|
|
return {
|
|
name: m.name,
|
|
missing: false,
|
|
links,
|
|
backlinks,
|
|
};
|
|
});
|
|
|
|
for (const node of nodes) {
|
|
for (const link of node.links) {
|
|
if (!nameSet.has(link)) ghosts.add(link);
|
|
}
|
|
}
|
|
|
|
return [
|
|
...nodes,
|
|
...[...ghosts].map(name => ({
|
|
name,
|
|
missing: true,
|
|
links: [],
|
|
backlinks: nodes
|
|
.filter(n => n.links.includes(name))
|
|
.map(n => n.name),
|
|
}))
|
|
];
|
|
}
|
|
|
|
export function renderMemoryGraph(nodes) {
|
|
if (!nodes.length) return 'No memories yet.';
|
|
|
|
const groups = new Map();
|
|
for (const node of nodes) {
|
|
const [prefix, ...rest] = node.name.split('/');
|
|
const group = rest.length ? prefix : 'Root';
|
|
const label = rest.length ? rest.join('/') : node.name;
|
|
if (!groups.has(group)) groups.set(group, []);
|
|
groups.get(group).push({...node, label});
|
|
}
|
|
|
|
const ghostCount = nodes.filter(n => n.missing).length;
|
|
const lines = [`Memory Graph (${nodes.length} nodes, ${ghostCount} ghost${ghostCount === 1 ? '' : 's'})`, ''];
|
|
|
|
for (const group of [...groups.keys()].sort()) {
|
|
const items = groups.get(group).sort((a, b) => a.label.localeCompare(b.label));
|
|
lines.push(`${group}/`);
|
|
items.forEach((n, i) => {
|
|
const last = i === items.length - 1;
|
|
const branch = last ? '└─' : '├─';
|
|
const pad = last ? ' ' : '│ ';
|
|
const tag = n.missing ? ' (ghost)' : '';
|
|
lines.push(` ${branch} ${n.label}${tag}`);
|
|
if (n.links.length) lines.push(` ${pad} → ${n.links.join(', ')}`);
|
|
if (n.backlinks.length) lines.push(` ${pad} ← ${n.backlinks.join(', ')}`);
|
|
});
|
|
lines.push('');
|
|
}
|
|
|
|
return lines.join('\n').trimEnd();
|
|
}
|