hippo-memory 1.19.0 → 1.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +71 -2
- package/dist/cli.js.map +1 -1
- package/dist/graph-view.d.ts +72 -0
- package/dist/graph-view.d.ts.map +1 -0
- package/dist/graph-view.js +310 -0
- package/dist/graph-view.js.map +1 -0
- package/dist/graph.d.ts +30 -4
- package/dist/graph.d.ts.map +1 -1
- package/dist/graph.js +104 -11
- package/dist/graph.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +19 -0
- package/dist/server.js.map +1 -1
- package/dist/src/cli.js +71 -2
- package/dist/src/cli.js.map +1 -1
- package/dist/src/graph-view.js +310 -0
- package/dist/src/graph-view.js.map +1 -0
- package/dist/src/graph.js +104 -11
- package/dist/src/graph.js.map +1 -1
- package/dist/src/server.js +19 -0
- package/dist/src/server.js.map +1 -1
- package/dist/src/version.js +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
- package/extensions/openclaw-plugin/package.json +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* E3 graph observability + visualization — READ-ONLY over the entity/relation
|
|
3
|
+
* graph (docs/plans/2026-06-02-graph-observability.md).
|
|
4
|
+
*
|
|
5
|
+
* This module only READS the graph (`loadEntities` / `loadRelations`) and renders
|
|
6
|
+
* view-models; it issues no INSERT/UPDATE/DELETE, so `scripts/check-graph-writes.mjs`
|
|
7
|
+
* stays green. Used by the CLI (`hippo graph show` / `hippo graph view`) and the
|
|
8
|
+
* HTTP `GET /v1/graph` route, which all build the same `GraphModel`.
|
|
9
|
+
*/
|
|
10
|
+
import { type EntityType, type RelationType } from './graph.js';
|
|
11
|
+
export interface GraphNode {
|
|
12
|
+
id: number;
|
|
13
|
+
type: EntityType;
|
|
14
|
+
name: string;
|
|
15
|
+
}
|
|
16
|
+
export interface GraphEdge {
|
|
17
|
+
from: number;
|
|
18
|
+
to: number;
|
|
19
|
+
relType: RelationType;
|
|
20
|
+
}
|
|
21
|
+
export interface GraphModel {
|
|
22
|
+
nodes: GraphNode[];
|
|
23
|
+
edges: GraphEdge[];
|
|
24
|
+
/** Conservative "maybe incomplete" flag: true when a loader returned exactly
|
|
25
|
+
* its limit (the graph MAY be truncated). Can over-report, never under-report. */
|
|
26
|
+
truncated: boolean;
|
|
27
|
+
}
|
|
28
|
+
/** Default bound for the CLI viewer / show so an unbounded set is never laid out. */
|
|
29
|
+
export declare const DEFAULT_VIEW_LIMIT = 500;
|
|
30
|
+
/**
|
|
31
|
+
* Build the view-model from the graph (reads only). With `opts.entity`, returns a
|
|
32
|
+
* focus subgraph: every entity whose name === entity, plus their 1-hop neighbours,
|
|
33
|
+
* plus the edges among that union. Dangling edges (an endpoint outside the node
|
|
34
|
+
* set) are always dropped.
|
|
35
|
+
*/
|
|
36
|
+
export declare function buildGraphModel(hippoRoot: string, tenantId: string, opts?: {
|
|
37
|
+
entity?: string;
|
|
38
|
+
limit?: number;
|
|
39
|
+
}): GraphModel;
|
|
40
|
+
/**
|
|
41
|
+
* Deterministic Fruchterman-Reingold-style force layout. Seeded circular init +
|
|
42
|
+
* fixed iterations, NO `Math.random`, so the same model always yields the same
|
|
43
|
+
* positions (testable, stable output). Non-finite coordinates from a degenerate
|
|
44
|
+
* step are clamped to the viewport centre; all positions are clamped in-bounds.
|
|
45
|
+
*/
|
|
46
|
+
export declare function layoutGraph(model: GraphModel, opts?: {
|
|
47
|
+
width?: number;
|
|
48
|
+
height?: number;
|
|
49
|
+
iterations?: number;
|
|
50
|
+
}): Map<number, {
|
|
51
|
+
x: number;
|
|
52
|
+
y: number;
|
|
53
|
+
}>;
|
|
54
|
+
/** HTML-escape for SVG text / title / markup content (XSS guard). */
|
|
55
|
+
export declare function escapeHtml(s: string): string;
|
|
56
|
+
/**
|
|
57
|
+
* Render the model as a SELF-CONTAINED, dependency-free, offline interactive HTML
|
|
58
|
+
* node-link diagram. Positions are computed server-side (deterministic). User
|
|
59
|
+
* strings are escaped per sink: SVG `<text>`/`<title>` via `escapeHtml`; the model
|
|
60
|
+
* is inlined in a `<script type="application/json">` block with `<`/`>`/`&`
|
|
61
|
+
* unicode-escaped so a `</script>` inside an entity name cannot break out (the
|
|
62
|
+
* client `JSON.parse`s it back and never `innerHTML`s a user string).
|
|
63
|
+
*/
|
|
64
|
+
export declare function renderGraphHtml(model: GraphModel): string;
|
|
65
|
+
/**
|
|
66
|
+
* Render the model as a JSON Canvas (jsoncanvas.org) document — `nodes[]` of
|
|
67
|
+
* type `text` positioned by the same deterministic layout, `edges[]` linking
|
|
68
|
+
* them by id. Opens natively in Obsidian. Pure JSON; entity names live in the
|
|
69
|
+
* `text` field (Obsidian renders/sanitizes them).
|
|
70
|
+
*/
|
|
71
|
+
export declare function renderGraphCanvas(model: GraphModel): string;
|
|
72
|
+
//# sourceMappingURL=graph-view.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-view.d.ts","sourceRoot":"","sources":["../src/graph-view.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAUL,KAAK,UAAU,EACf,KAAK,YAAY,EAClB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AACD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,YAAY,CAAC;CACvB;AACD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB;uFACmF;IACnF,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,qFAAqF;AACrF,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAEtC;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC7C,UAAU,CA8DZ;AAKD;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,UAAU,EACjB,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,GAClE,GAAG,CAAC,MAAM,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA2EvC;AAED,qEAAqE;AACrE,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAO5C;AAoDD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CA2DzD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAqB3D"}
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* E3 graph observability + visualization — READ-ONLY over the entity/relation
|
|
3
|
+
* graph (docs/plans/2026-06-02-graph-observability.md).
|
|
4
|
+
*
|
|
5
|
+
* This module only READS the graph (`loadEntities` / `loadRelations`) and renders
|
|
6
|
+
* view-models; it issues no INSERT/UPDATE/DELETE, so `scripts/check-graph-writes.mjs`
|
|
7
|
+
* stays green. Used by the CLI (`hippo graph show` / `hippo graph view`) and the
|
|
8
|
+
* HTTP `GET /v1/graph` route, which all build the same `GraphModel`.
|
|
9
|
+
*/
|
|
10
|
+
import { loadEntities, loadEntitiesByName, loadEntitiesByIds, loadRelations, loadNeighborRelations, loadRelationsAmong, withGraphReadSnapshot, } from './graph.js';
|
|
11
|
+
/** Default bound for the CLI viewer / show so an unbounded set is never laid out. */
|
|
12
|
+
export const DEFAULT_VIEW_LIMIT = 500;
|
|
13
|
+
/**
|
|
14
|
+
* Build the view-model from the graph (reads only). With `opts.entity`, returns a
|
|
15
|
+
* focus subgraph: every entity whose name === entity, plus their 1-hop neighbours,
|
|
16
|
+
* plus the edges among that union. Dangling edges (an endpoint outside the node
|
|
17
|
+
* set) are always dropped.
|
|
18
|
+
*/
|
|
19
|
+
export function buildGraphModel(hippoRoot, tenantId, opts = {}) {
|
|
20
|
+
const limit = opts.limit ?? DEFAULT_VIEW_LIMIT;
|
|
21
|
+
// All reads run inside ONE read snapshot so a concurrent `graph extract` /
|
|
22
|
+
// sleep-drain rebuild can't make the model mix old entity ids with new relation
|
|
23
|
+
// ids (codex P2). Every load* call below is passed the snapshot connection `db`.
|
|
24
|
+
return withGraphReadSnapshot(hippoRoot, (db) => {
|
|
25
|
+
let nodeEntities;
|
|
26
|
+
let relations;
|
|
27
|
+
let truncated;
|
|
28
|
+
if (opts.entity !== undefined) {
|
|
29
|
+
// Focus subgraph. (1) Query the named entity DIRECTLY (by name, not from a
|
|
30
|
+
// globally-capped list) so it is found even on a graph larger than `limit`.
|
|
31
|
+
// (2) A name can map to MANY entities (e.g. many notes for one customer), so
|
|
32
|
+
// cap the focus matches. (3) Discover 1-hop neighbours and cap the UNION to
|
|
33
|
+
// `limit` nodes. (4) Load ALL edges AMONG the union so neighbour-to-neighbour
|
|
34
|
+
// edges that don't touch the focus are included too. (codex P2s.)
|
|
35
|
+
const focus = loadEntitiesByName(hippoRoot, tenantId, opts.entity, { limit }, db);
|
|
36
|
+
if (focus.length === 0)
|
|
37
|
+
return { nodes: [], edges: [], truncated: false };
|
|
38
|
+
const focusIds = focus.map((e) => e.id);
|
|
39
|
+
const hop = loadNeighborRelations(hippoRoot, tenantId, focusIds, { limit }, db);
|
|
40
|
+
const union = new Set(focusIds);
|
|
41
|
+
let neighboursCapped = false;
|
|
42
|
+
for (const r of hop) {
|
|
43
|
+
if (union.size >= limit) {
|
|
44
|
+
neighboursCapped = true; // node cap filled before all neighbours were added
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
union.add(r.fromEntityId);
|
|
48
|
+
union.add(r.toEntityId);
|
|
49
|
+
}
|
|
50
|
+
const unionIds = [...union].slice(0, limit);
|
|
51
|
+
nodeEntities = loadEntitiesByIds(hippoRoot, tenantId, unionIds, db);
|
|
52
|
+
// Edges AMONG the union (BOTH endpoints in the set): includes
|
|
53
|
+
// neighbour-to-neighbour edges, and the LIMIT can never drop a valid in-union
|
|
54
|
+
// edge in favour of out-of-union rows (codex P2).
|
|
55
|
+
relations = loadRelationsAmong(hippoRoot, tenantId, unionIds, { limit }, db);
|
|
56
|
+
truncated =
|
|
57
|
+
focus.length >= limit ||
|
|
58
|
+
hop.length >= limit || // neighbour scan capped -> a 1-hop neighbour may be omitted (codex P2)
|
|
59
|
+
neighboursCapped || // node cap filled before all neighbours were consumed (codex P2)
|
|
60
|
+
union.size > unionIds.length ||
|
|
61
|
+
relations.length >= limit;
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
nodeEntities = loadEntities(hippoRoot, tenantId, { limit }, db);
|
|
65
|
+
relations = loadRelations(hippoRoot, tenantId, { limit }, db);
|
|
66
|
+
truncated = nodeEntities.length >= limit || relations.length >= limit;
|
|
67
|
+
}
|
|
68
|
+
const nodeIds = new Set(nodeEntities.map((e) => e.id));
|
|
69
|
+
const nodes = nodeEntities.map((e) => ({
|
|
70
|
+
id: e.id,
|
|
71
|
+
type: e.entityType,
|
|
72
|
+
name: e.name,
|
|
73
|
+
}));
|
|
74
|
+
const edges = relations
|
|
75
|
+
.filter((r) => nodeIds.has(r.fromEntityId) && nodeIds.has(r.toEntityId))
|
|
76
|
+
.map((r) => ({ from: r.fromEntityId, to: r.toEntityId, relType: r.relType }));
|
|
77
|
+
return { nodes, edges, truncated };
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
const LAYOUT_W = 1000;
|
|
81
|
+
const LAYOUT_H = 700;
|
|
82
|
+
/**
|
|
83
|
+
* Deterministic Fruchterman-Reingold-style force layout. Seeded circular init +
|
|
84
|
+
* fixed iterations, NO `Math.random`, so the same model always yields the same
|
|
85
|
+
* positions (testable, stable output). Non-finite coordinates from a degenerate
|
|
86
|
+
* step are clamped to the viewport centre; all positions are clamped in-bounds.
|
|
87
|
+
*/
|
|
88
|
+
export function layoutGraph(model, opts = {}) {
|
|
89
|
+
const width = opts.width ?? LAYOUT_W;
|
|
90
|
+
const height = opts.height ?? LAYOUT_H;
|
|
91
|
+
const iterations = opts.iterations ?? 300;
|
|
92
|
+
const cx = width / 2;
|
|
93
|
+
const cy = height / 2;
|
|
94
|
+
const nodes = model.nodes;
|
|
95
|
+
const n = nodes.length;
|
|
96
|
+
const pos = new Map();
|
|
97
|
+
if (n === 0)
|
|
98
|
+
return pos;
|
|
99
|
+
if (n === 1) {
|
|
100
|
+
pos.set(nodes[0].id, { x: cx, y: cy });
|
|
101
|
+
return pos;
|
|
102
|
+
}
|
|
103
|
+
const radius = Math.min(width, height) * 0.4;
|
|
104
|
+
nodes.forEach((node, i) => {
|
|
105
|
+
const angle = (2 * Math.PI * i) / n;
|
|
106
|
+
pos.set(node.id, { x: cx + radius * Math.cos(angle), y: cy + radius * Math.sin(angle) });
|
|
107
|
+
});
|
|
108
|
+
const idIndex = new Map(nodes.map((node, i) => [node.id, i]));
|
|
109
|
+
const k = Math.sqrt((width * height) / n); // ideal edge length
|
|
110
|
+
for (let iter = 0; iter < iterations; iter++) {
|
|
111
|
+
const disp = nodes.map(() => ({ x: 0, y: 0 }));
|
|
112
|
+
// Repulsion between all pairs.
|
|
113
|
+
for (let i = 0; i < n; i++) {
|
|
114
|
+
const pi = pos.get(nodes[i].id);
|
|
115
|
+
for (let j = i + 1; j < n; j++) {
|
|
116
|
+
const pj = pos.get(nodes[j].id);
|
|
117
|
+
const dx = pi.x - pj.x;
|
|
118
|
+
const dy = pi.y - pj.y;
|
|
119
|
+
const dist = Math.hypot(dx, dy) || 0.01;
|
|
120
|
+
const rep = (k * k) / dist;
|
|
121
|
+
const ux = dx / dist;
|
|
122
|
+
const uy = dy / dist;
|
|
123
|
+
disp[i].x += ux * rep;
|
|
124
|
+
disp[i].y += uy * rep;
|
|
125
|
+
disp[j].x -= ux * rep;
|
|
126
|
+
disp[j].y -= uy * rep;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// Attraction along edges.
|
|
130
|
+
for (const e of model.edges) {
|
|
131
|
+
const i = idIndex.get(e.from);
|
|
132
|
+
const j = idIndex.get(e.to);
|
|
133
|
+
if (i === undefined || j === undefined)
|
|
134
|
+
continue;
|
|
135
|
+
const pi = pos.get(e.from);
|
|
136
|
+
const pj = pos.get(e.to);
|
|
137
|
+
const dx = pi.x - pj.x;
|
|
138
|
+
const dy = pi.y - pj.y;
|
|
139
|
+
const dist = Math.hypot(dx, dy) || 0.01;
|
|
140
|
+
const att = (dist * dist) / k;
|
|
141
|
+
const ux = dx / dist;
|
|
142
|
+
const uy = dy / dist;
|
|
143
|
+
disp[i].x -= ux * att;
|
|
144
|
+
disp[i].y -= uy * att;
|
|
145
|
+
disp[j].x += ux * att;
|
|
146
|
+
disp[j].y += uy * att;
|
|
147
|
+
}
|
|
148
|
+
// Apply with cooling; clamp.
|
|
149
|
+
const temp = Math.max(1, (width / 10) * (1 - iter / iterations));
|
|
150
|
+
nodes.forEach((node, i) => {
|
|
151
|
+
const p = pos.get(node.id);
|
|
152
|
+
const dl = Math.hypot(disp[i].x, disp[i].y) || 0.01;
|
|
153
|
+
let nx = p.x + (disp[i].x / dl) * Math.min(dl, temp);
|
|
154
|
+
let ny = p.y + (disp[i].y / dl) * Math.min(dl, temp);
|
|
155
|
+
if (!Number.isFinite(nx))
|
|
156
|
+
nx = cx;
|
|
157
|
+
if (!Number.isFinite(ny))
|
|
158
|
+
ny = cy;
|
|
159
|
+
p.x = Math.max(20, Math.min(width - 20, nx));
|
|
160
|
+
p.y = Math.max(20, Math.min(height - 20, ny));
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
return pos;
|
|
164
|
+
}
|
|
165
|
+
/** HTML-escape for SVG text / title / markup content (XSS guard). */
|
|
166
|
+
export function escapeHtml(s) {
|
|
167
|
+
return s
|
|
168
|
+
.replace(/&/g, '&')
|
|
169
|
+
.replace(/</g, '<')
|
|
170
|
+
.replace(/>/g, '>')
|
|
171
|
+
.replace(/"/g, '"')
|
|
172
|
+
.replace(/'/g, ''');
|
|
173
|
+
}
|
|
174
|
+
const NODE_COLORS = {
|
|
175
|
+
decision: '#6366f1',
|
|
176
|
+
policy: '#10b981',
|
|
177
|
+
customer: '#f59e0b',
|
|
178
|
+
project: '#ec4899',
|
|
179
|
+
person: '#3b82f6',
|
|
180
|
+
system: '#64748b',
|
|
181
|
+
};
|
|
182
|
+
// Client script: pan (drag bg), zoom (wheel), click-to-highlight a node's edges +
|
|
183
|
+
// neighbours. Reads the inlined model via JSON.parse (never innerHTML), so user
|
|
184
|
+
// strings never reach an HTML sink here. No template literals / `${}` so it nests
|
|
185
|
+
// safely inside this module's own template strings.
|
|
186
|
+
const CLIENT_JS = [
|
|
187
|
+
"(function(){",
|
|
188
|
+
" var svg=document.getElementById('g');",
|
|
189
|
+
" var vb=svg.getAttribute('viewBox').split(' ').map(Number);",
|
|
190
|
+
" var view={x:vb[0],y:vb[1],w:vb[2],h:vb[3]};",
|
|
191
|
+
" function apply(){svg.setAttribute('viewBox',view.x+' '+view.y+' '+view.w+' '+view.h);}",
|
|
192
|
+
" var panning=false,sx=0,sy=0;",
|
|
193
|
+
" svg.addEventListener('mousedown',function(e){if(e.target.closest('.node'))return;panning=true;sx=e.clientX;sy=e.clientY;});",
|
|
194
|
+
" window.addEventListener('mouseup',function(){panning=false;});",
|
|
195
|
+
" window.addEventListener('mousemove',function(e){if(!panning)return;var r=svg.getBoundingClientRect();var k=view.w/r.width;view.x-=(e.clientX-sx)*k;view.y-=(e.clientY-sy)*k;sx=e.clientX;sy=e.clientY;apply();});",
|
|
196
|
+
" svg.addEventListener('wheel',function(e){e.preventDefault();var r=svg.getBoundingClientRect();var mx=view.x+(e.clientX-r.left)/r.width*view.w;var my=view.y+(e.clientY-r.top)/r.height*view.h;var f=e.deltaY<0?0.9:1.1;view.x=mx-(mx-view.x)*f;view.y=my-(my-view.y)*f;view.w*=f;view.h*=f;apply();},{passive:false});",
|
|
197
|
+
" var data={};try{data=JSON.parse(document.getElementById('graph-data').textContent);}catch(_){}",
|
|
198
|
+
" var adj={};(data.edges||[]).forEach(function(e){(adj[e.from]=adj[e.from]||[]).push(e.to);(adj[e.to]=adj[e.to]||[]).push(e.from);});",
|
|
199
|
+
" var active=null;",
|
|
200
|
+
" document.querySelectorAll('.node').forEach(function(g){g.addEventListener('click',function(ev){ev.stopPropagation();var id=g.getAttribute('data-id');if(active===id){clearHi();active=null;return;}active=id;highlight(id);});});",
|
|
201
|
+
" svg.addEventListener('click',function(){clearHi();active=null;});",
|
|
202
|
+
" function clearHi(){svg.classList.remove('focused');document.querySelectorAll('.hi').forEach(function(el){el.classList.remove('hi');});}",
|
|
203
|
+
" function highlight(id){clearHi();svg.classList.add('focused');var keep={};keep[id]=1;(adj[id]||[]).forEach(function(n){keep[n]=1;});document.querySelectorAll('.node').forEach(function(g){if(keep[g.getAttribute('data-id')])g.classList.add('hi');});document.querySelectorAll('.edge').forEach(function(l){if(l.getAttribute('data-from')===id||l.getAttribute('data-to')===id)l.classList.add('hi');});}",
|
|
204
|
+
"})();",
|
|
205
|
+
].join("\n");
|
|
206
|
+
const STYLE = [
|
|
207
|
+
"html,body{margin:0;height:100%;background:#0b1020;font-family:ui-sans-serif,system-ui,sans-serif}",
|
|
208
|
+
"#g{width:100vw;height:100vh;cursor:grab}",
|
|
209
|
+
"#g:active{cursor:grabbing}",
|
|
210
|
+
".edge{stroke:#475569;stroke-width:1}",
|
|
211
|
+
".node circle{stroke:#0b1020;stroke-width:1.5}",
|
|
212
|
+
".node text{fill:#e2e8f0;font-size:11px;pointer-events:none}",
|
|
213
|
+
".node{cursor:pointer}",
|
|
214
|
+
"#g.focused .node{opacity:.18}",
|
|
215
|
+
"#g.focused .edge{opacity:.07}",
|
|
216
|
+
"#g.focused .node.hi{opacity:1}",
|
|
217
|
+
"#g.focused .edge.hi{opacity:1;stroke:#e2e8f0}",
|
|
218
|
+
".legend{position:fixed;top:10px;left:12px;color:#94a3b8;font-size:12px;line-height:1.6}",
|
|
219
|
+
".legend b{color:#e2e8f0}",
|
|
220
|
+
].join("\n");
|
|
221
|
+
/**
|
|
222
|
+
* Render the model as a SELF-CONTAINED, dependency-free, offline interactive HTML
|
|
223
|
+
* node-link diagram. Positions are computed server-side (deterministic). User
|
|
224
|
+
* strings are escaped per sink: SVG `<text>`/`<title>` via `escapeHtml`; the model
|
|
225
|
+
* is inlined in a `<script type="application/json">` block with `<`/`>`/`&`
|
|
226
|
+
* unicode-escaped so a `</script>` inside an entity name cannot break out (the
|
|
227
|
+
* client `JSON.parse`s it back and never `innerHTML`s a user string).
|
|
228
|
+
*/
|
|
229
|
+
export function renderGraphHtml(model) {
|
|
230
|
+
const pos = layoutGraph(model);
|
|
231
|
+
const color = (t) => NODE_COLORS[t] ?? '#64748b';
|
|
232
|
+
const edgeSvg = model.edges
|
|
233
|
+
.map((e) => {
|
|
234
|
+
const a = pos.get(e.from);
|
|
235
|
+
const b = pos.get(e.to);
|
|
236
|
+
if (!a || !b)
|
|
237
|
+
return '';
|
|
238
|
+
return (`<line class="edge" data-from="${e.from}" data-to="${e.to}" ` +
|
|
239
|
+
`x1="${a.x.toFixed(1)}" y1="${a.y.toFixed(1)}" x2="${b.x.toFixed(1)}" y2="${b.y.toFixed(1)}"/>`);
|
|
240
|
+
})
|
|
241
|
+
.join('');
|
|
242
|
+
const nodeSvg = model.nodes
|
|
243
|
+
.map((node) => {
|
|
244
|
+
const p = pos.get(node.id);
|
|
245
|
+
if (!p)
|
|
246
|
+
return '';
|
|
247
|
+
const label = node.name.length > 22 ? node.name.slice(0, 21) + '…' : node.name;
|
|
248
|
+
return (`<g class="node" data-id="${node.id}" transform="translate(${p.x.toFixed(1)},${p.y.toFixed(1)})">` +
|
|
249
|
+
`<title>${escapeHtml(node.type + ': ' + node.name)}</title>` +
|
|
250
|
+
`<circle r="7" fill="${color(node.type)}"/>` +
|
|
251
|
+
`<text x="10" y="4">${escapeHtml(label)}</text>` +
|
|
252
|
+
`</g>`);
|
|
253
|
+
})
|
|
254
|
+
.join('');
|
|
255
|
+
// Safe inline JSON for the client: unicode-escape the HTML-significant chars so
|
|
256
|
+
// the content cannot terminate the <script> block; JSON.parse restores them.
|
|
257
|
+
const dataJson = JSON.stringify(model)
|
|
258
|
+
.replace(/</g, '\\u003c')
|
|
259
|
+
.replace(/>/g, '\\u003e')
|
|
260
|
+
.replace(/&/g, '\\u0026');
|
|
261
|
+
const types = [...new Set(model.nodes.map((nd) => nd.type))];
|
|
262
|
+
const legend = types
|
|
263
|
+
.map((t) => `<span style="color:${color(t)}">●</span> ${escapeHtml(t)}`)
|
|
264
|
+
.join(' ');
|
|
265
|
+
return [
|
|
266
|
+
'<!doctype html>',
|
|
267
|
+
'<html lang="en"><head><meta charset="utf-8">',
|
|
268
|
+
'<meta name="viewport" content="width=device-width, initial-scale=1">',
|
|
269
|
+
'<title>hippo graph</title>',
|
|
270
|
+
'<style>' + STYLE + '</style></head><body>',
|
|
271
|
+
`<div class="legend"><b>hippo graph</b> · ${model.nodes.length} entities · ${model.edges.length} relations` +
|
|
272
|
+
(model.truncated ? ' · <b style="color:#f59e0b">truncated</b>' : '') +
|
|
273
|
+
`<br>${legend}<br><span style="color:#64748b">drag to pan · scroll to zoom · click a node to focus</span></div>`,
|
|
274
|
+
`<svg id="g" viewBox="0 0 ${LAYOUT_W} ${LAYOUT_H}" preserveAspectRatio="xMidYMid meet">`,
|
|
275
|
+
`<g id="edges">${edgeSvg}</g><g id="nodes">${nodeSvg}</g>`,
|
|
276
|
+
'</svg>',
|
|
277
|
+
`<script type="application/json" id="graph-data">${dataJson}</script>`,
|
|
278
|
+
'<script>' + CLIENT_JS + '</script>',
|
|
279
|
+
'</body></html>',
|
|
280
|
+
].join('\n');
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Render the model as a JSON Canvas (jsoncanvas.org) document — `nodes[]` of
|
|
284
|
+
* type `text` positioned by the same deterministic layout, `edges[]` linking
|
|
285
|
+
* them by id. Opens natively in Obsidian. Pure JSON; entity names live in the
|
|
286
|
+
* `text` field (Obsidian renders/sanitizes them).
|
|
287
|
+
*/
|
|
288
|
+
export function renderGraphCanvas(model) {
|
|
289
|
+
const pos = layoutGraph(model, { width: 2400, height: 1600 });
|
|
290
|
+
const nodes = model.nodes.map((node) => {
|
|
291
|
+
const p = pos.get(node.id) ?? { x: 0, y: 0 };
|
|
292
|
+
return {
|
|
293
|
+
id: `n${node.id}`,
|
|
294
|
+
type: 'text',
|
|
295
|
+
x: Math.round(p.x),
|
|
296
|
+
y: Math.round(p.y),
|
|
297
|
+
width: 240,
|
|
298
|
+
height: 60,
|
|
299
|
+
text: `**${node.type}**\n${node.name}`,
|
|
300
|
+
};
|
|
301
|
+
});
|
|
302
|
+
const edges = model.edges.map((e, i) => ({
|
|
303
|
+
id: `e${i}`,
|
|
304
|
+
fromNode: `n${e.from}`,
|
|
305
|
+
toNode: `n${e.to}`,
|
|
306
|
+
label: e.relType,
|
|
307
|
+
}));
|
|
308
|
+
return JSON.stringify({ nodes, edges }, null, 2);
|
|
309
|
+
}
|
|
310
|
+
//# sourceMappingURL=graph-view.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-view.js","sourceRoot":"","sources":["../src/graph-view.ts"],"names":[],"mappings":"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"}
|
package/dist/graph.d.ts
CHANGED
|
@@ -84,14 +84,21 @@ export declare function insertEntity(hippoRoot: string, tenantId: string, opts:
|
|
|
84
84
|
*/
|
|
85
85
|
export declare function insertRelation(hippoRoot: string, tenantId: string, opts: InsertRelationOpts, txDb?: GraphTxDb): Relation;
|
|
86
86
|
export declare function loadEntityById(hippoRoot: string, tenantId: string, id: number): Entity | null;
|
|
87
|
+
/** Entities with an exact `name` (read), bounded by `limit` in SQL with a
|
|
88
|
+
* deterministic order. Lets the graph-view focus query find the `--entity NAME`
|
|
89
|
+
* entity DIRECTLY (not from a globally-capped list) WITHOUT materializing every
|
|
90
|
+
* same-name row when a name maps to many entities. */
|
|
91
|
+
export declare function loadEntitiesByName(hippoRoot: string, tenantId: string, name: string, opts?: {
|
|
92
|
+
limit?: number;
|
|
93
|
+
}, txDb?: GraphTxDb): Entity[];
|
|
87
94
|
export declare function loadEntities(hippoRoot: string, tenantId: string, opts?: {
|
|
88
95
|
entityType?: EntityType;
|
|
89
96
|
limit?: number;
|
|
90
|
-
}): Entity[];
|
|
97
|
+
}, txDb?: GraphTxDb): Entity[];
|
|
91
98
|
export declare function loadRelations(hippoRoot: string, tenantId: string, opts?: {
|
|
92
99
|
fromEntityId?: number;
|
|
93
100
|
limit?: number;
|
|
94
|
-
}): Relation[];
|
|
101
|
+
}, txDb?: GraphTxDb): Relation[];
|
|
95
102
|
/**
|
|
96
103
|
* Map consolidated source memory ids -> their graph entities. The SEED step of E3.2
|
|
97
104
|
* multi-hop recall (recall result memory ids -> entities to traverse from). Tenant-
|
|
@@ -102,7 +109,7 @@ export declare function loadEntitiesByMemoryId(hippoRoot: string, tenantId: stri
|
|
|
102
109
|
* Load entities by their primary ids. Resolves the entity rows reached during the BFS
|
|
103
110
|
* (whose `memory_id` maps back to a recall result). Tenant-scoped, read-only.
|
|
104
111
|
*/
|
|
105
|
-
export declare function loadEntitiesByIds(hippoRoot: string, tenantId: string, ids: number[]): Entity[];
|
|
112
|
+
export declare function loadEntitiesByIds(hippoRoot: string, tenantId: string, ids: number[], txDb?: GraphTxDb): Entity[];
|
|
106
113
|
/**
|
|
107
114
|
* All relations touching ANY of `entityIds` in EITHER direction (from OR to) — the
|
|
108
115
|
* per-hop neighbour query for E3.2 multi-hop traversal. ONE query for the whole frontier
|
|
@@ -112,7 +119,26 @@ export declare function loadEntitiesByIds(hippoRoot: string, tenantId: string, i
|
|
|
112
119
|
*/
|
|
113
120
|
export declare function loadNeighborRelations(hippoRoot: string, tenantId: string, entityIds: number[], opts?: {
|
|
114
121
|
limit?: number;
|
|
115
|
-
}): Relation[];
|
|
122
|
+
}, txDb?: GraphTxDb): Relation[];
|
|
123
|
+
/**
|
|
124
|
+
* Relations with BOTH endpoints in `entityIds` (edges AMONG the set, not merely
|
|
125
|
+
* touching it). Read. Used by the graph-view focus subgraph so the displayed
|
|
126
|
+
* edges are exactly the intra-union edges: the `LIMIT` only caps genuinely-many
|
|
127
|
+
* intra-union edges — no out-of-union row can evict a valid in-set edge. The
|
|
128
|
+
* caller bounds `entityIds` (<= the view limit), so a single query is safe.
|
|
129
|
+
*/
|
|
130
|
+
export declare function loadRelationsAmong(hippoRoot: string, tenantId: string, entityIds: number[], opts?: {
|
|
131
|
+
limit?: number;
|
|
132
|
+
}, txDb?: GraphTxDb): Relation[];
|
|
133
|
+
/**
|
|
134
|
+
* Run `fn` inside ONE read transaction (a single WAL snapshot) so every graph read
|
|
135
|
+
* it performs — pass the supplied `txDb` to the `load*` functions — sees a consistent
|
|
136
|
+
* view, even if a `graph extract` / sleep-drain rebuild commits concurrently between
|
|
137
|
+
* reads (the rebuild clears + reinserts entities, so separate reads could otherwise
|
|
138
|
+
* mix old entity ids with new relation ids). Reads only; the connection is opened
|
|
139
|
+
* once and closed after.
|
|
140
|
+
*/
|
|
141
|
+
export declare function withGraphReadSnapshot<T>(hippoRoot: string, fn: (txDb: GraphTxDb) => T): T;
|
|
116
142
|
/**
|
|
117
143
|
* Enqueue a consolidated memory for later graph extraction. Rejects a raw / missing /
|
|
118
144
|
* cross-tenant memory (the DB trigger is the backstop). The producer hook in
|
package/dist/graph.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../src/graph.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../src/graph.ts"],"names":[],"mappings":"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"}
|