@memnest/ui-core 0.0.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/LICENSE +21 -0
- package/README.md +44 -0
- package/dist/chunk-JCMPD6YF.js +1076 -0
- package/dist/chunk-JCMPD6YF.js.map +1 -0
- package/dist/index.cjs +2398 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +513 -0
- package/dist/index.d.ts +513 -0
- package/dist/index.js +1277 -0
- package/dist/index.js.map +1 -0
- package/dist/layout-worker-CLScIQSu.d.cts +142 -0
- package/dist/layout-worker-CLScIQSu.d.ts +142 -0
- package/dist/layout-worker.cjs +1051 -0
- package/dist/layout-worker.cjs.map +1 -0
- package/dist/layout-worker.d.cts +1 -0
- package/dist/layout-worker.d.ts +1 -0
- package/dist/layout-worker.js +10 -0
- package/dist/layout-worker.js.map +1 -0
- package/package.json +81 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,513 @@
|
|
|
1
|
+
import { P as Point, V as Viewport, S as Size, L as LayoutRunner, B as Bounds } from './layout-worker-CLScIQSu.js';
|
|
2
|
+
export { F as ForceOptions, I as IDENTITY_VIEWPORT, a as LayeredOptions, b as LayoutEdge, c as LayoutNode, d as LayoutRequest, M as MessagePortLike, W as WORKER_LAYOUT_THRESHOLD, Z as ZOOM_LIMITS, e as boundsOf, f as clamp, g as computeLayout, h as createWorkerLayoutRunner, i as fitViewport, j as forceLayout, k as inlineLayoutRunner, l as layeredLayout, p as panBy, r as runLayoutRequest, s as seededRandom, m as serveLayoutRequests, t as toScreen, n as toWorld, z as zoomAt } from './layout-worker-CLScIQSu.js';
|
|
3
|
+
import { MemoryKind, GraphNode, GraphEdge, LineageEdge, MemnestApi, LineageGraph, Memory, DocumentRef, Chunk, SearchResponse, ExcludedReason } from '@memnest/core';
|
|
4
|
+
|
|
5
|
+
/** What every controller exposes. Framework wrappers subscribe and read; they never mutate. */
|
|
6
|
+
interface Observable<S> {
|
|
7
|
+
getState(): S;
|
|
8
|
+
/** Returns the unsubscribe function. */
|
|
9
|
+
subscribe(listener: () => void): () => void;
|
|
10
|
+
}
|
|
11
|
+
interface Store<S> extends Observable<S> {
|
|
12
|
+
/** Replaces the state with a new object, so snapshot identity changes exactly when state does. */
|
|
13
|
+
set(patch: Partial<S> | ((state: S) => Partial<S>)): void;
|
|
14
|
+
}
|
|
15
|
+
declare function createStore<S extends object>(initial: S): Store<S>;
|
|
16
|
+
/**
|
|
17
|
+
* Drops results of superseded async work: `const token = seq.next()` before awaiting,
|
|
18
|
+
* `if (!seq.isCurrent(token)) return` after.
|
|
19
|
+
*/
|
|
20
|
+
declare function createSequencer(): {
|
|
21
|
+
next: () => number;
|
|
22
|
+
isCurrent: (token: number) => boolean;
|
|
23
|
+
/** Invalidates everything in flight (dispose). */
|
|
24
|
+
cancel: () => void;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
interface Cluster {
|
|
28
|
+
/** `cluster:<key>`; the catch-all is `cluster:*`. */
|
|
29
|
+
id: string;
|
|
30
|
+
/** The shared term, or '' for the catch-all. Searching for it expands the cluster. */
|
|
31
|
+
key: string;
|
|
32
|
+
label: string;
|
|
33
|
+
count: number;
|
|
34
|
+
kinds: Record<MemoryKind, number>;
|
|
35
|
+
/** Members that are superseded or forgotten. */
|
|
36
|
+
inactive: number;
|
|
37
|
+
memberIds: string[];
|
|
38
|
+
}
|
|
39
|
+
interface ClusterEdge {
|
|
40
|
+
from: string;
|
|
41
|
+
to: string;
|
|
42
|
+
/** Memory edges between the two clusters. */
|
|
43
|
+
weight: number;
|
|
44
|
+
}
|
|
45
|
+
interface ClusterOptions {
|
|
46
|
+
/** Including the catch-all. Default 48. */
|
|
47
|
+
maxClusters?: number;
|
|
48
|
+
/** Terms never used as keys, e.g. the words of the current search. */
|
|
49
|
+
exclude?: readonly string[];
|
|
50
|
+
}
|
|
51
|
+
interface Clustering {
|
|
52
|
+
clusters: Cluster[];
|
|
53
|
+
edges: ClusterEdge[];
|
|
54
|
+
clusterOf: ReadonlyMap<string, string>;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Groups memories by topic so a large container reads as a few dozen labelled groups instead of a
|
|
58
|
+
* hairball. Each memory joins the group of its most widespread term (ignoring terms shared by more
|
|
59
|
+
* than 60% of memories, which say nothing). The largest groups are kept; the rest share a catch-all.
|
|
60
|
+
* Deterministic, and linear in the total number of terms.
|
|
61
|
+
*/
|
|
62
|
+
declare function clusterNodes(nodes: readonly GraphNode[], edges: readonly GraphEdge[], options?: ClusterOptions): Clustering;
|
|
63
|
+
|
|
64
|
+
interface HitCircle {
|
|
65
|
+
id: string;
|
|
66
|
+
x: number;
|
|
67
|
+
y: number;
|
|
68
|
+
r: number;
|
|
69
|
+
}
|
|
70
|
+
interface HitIndex {
|
|
71
|
+
/** The circle under a world point, allowing `slop` extra world units for small targets. */
|
|
72
|
+
pick(world: Point, slop?: number): HitCircle | null;
|
|
73
|
+
readonly size: number;
|
|
74
|
+
}
|
|
75
|
+
/** A quadtree over circle centres: picking stays logarithmic at 10,000 nodes. */
|
|
76
|
+
declare function createHitIndex(circles: readonly HitCircle[]): HitIndex;
|
|
77
|
+
|
|
78
|
+
/** Size by reinforcementCount: a fact stated five times is visibly bigger than one stated once. */
|
|
79
|
+
declare const nodeRadius: (node: Pick<GraphNode, "reinforcementCount">) => number;
|
|
80
|
+
declare const clusterRadius: (count: number) => number;
|
|
81
|
+
declare const documentRadius = 7;
|
|
82
|
+
/** Shortens text for labels at a word boundary. */
|
|
83
|
+
declare function shorten(text: string, max?: number): string;
|
|
84
|
+
|
|
85
|
+
declare const CLUSTER_THRESHOLD = 2000;
|
|
86
|
+
declare const GRAPH_LOAD_LIMIT = 10000;
|
|
87
|
+
interface GraphFilter {
|
|
88
|
+
/** Empty: every kind. */
|
|
89
|
+
kinds: MemoryKind[];
|
|
90
|
+
includeSuperseded: boolean;
|
|
91
|
+
includeForgotten: boolean;
|
|
92
|
+
/** Words that must all appear in the memory (case-insensitive), or an exact memory id. */
|
|
93
|
+
search: string;
|
|
94
|
+
}
|
|
95
|
+
interface GraphLineageOverlay {
|
|
96
|
+
rootId: string;
|
|
97
|
+
memoryIds: ReadonlySet<string>;
|
|
98
|
+
edges: LineageEdge[];
|
|
99
|
+
}
|
|
100
|
+
interface GraphState {
|
|
101
|
+
containerTag: string;
|
|
102
|
+
status: 'idle' | 'loading' | 'layout' | 'ready' | 'error';
|
|
103
|
+
error: string | null;
|
|
104
|
+
filter: GraphFilter;
|
|
105
|
+
/** Above the cluster threshold the graph shows topic clusters; a filter or search expands them. */
|
|
106
|
+
mode: 'nodes' | 'clusters';
|
|
107
|
+
totalMemories: number;
|
|
108
|
+
/** Nodes fetched (at most the load limit). */
|
|
109
|
+
loaded: number;
|
|
110
|
+
/** True when the container holds more memories than were fetched. */
|
|
111
|
+
truncated: boolean;
|
|
112
|
+
/** Nodes matching the filter, before clustering. */
|
|
113
|
+
matching: number;
|
|
114
|
+
nodes: GraphNode[];
|
|
115
|
+
edges: GraphEdge[];
|
|
116
|
+
clusters: Cluster[];
|
|
117
|
+
clusterEdges: ClusterEdge[];
|
|
118
|
+
positions: ReadonlyMap<string, Point>;
|
|
119
|
+
selectedId: string | null;
|
|
120
|
+
lineage: GraphLineageOverlay | null;
|
|
121
|
+
viewport: Viewport;
|
|
122
|
+
size: Size;
|
|
123
|
+
layoutMs: number | null;
|
|
124
|
+
/** What the pointer is over, and where (screen coordinates), for tooltips. */
|
|
125
|
+
hover: {
|
|
126
|
+
pick: NonNullable<GraphPick>;
|
|
127
|
+
x: number;
|
|
128
|
+
y: number;
|
|
129
|
+
} | null;
|
|
130
|
+
}
|
|
131
|
+
type GraphPick = {
|
|
132
|
+
type: 'node';
|
|
133
|
+
id: string;
|
|
134
|
+
} | {
|
|
135
|
+
type: 'cluster';
|
|
136
|
+
id: string;
|
|
137
|
+
key: string;
|
|
138
|
+
} | null;
|
|
139
|
+
interface GraphController extends Observable<GraphState> {
|
|
140
|
+
load(): Promise<void>;
|
|
141
|
+
setFilter(filter: Partial<GraphFilter>): void;
|
|
142
|
+
select(memoryId: string | null): void;
|
|
143
|
+
expandLineage(memoryId: string): Promise<void>;
|
|
144
|
+
collapseLineage(): void;
|
|
145
|
+
/** Searches for the cluster's term, which shows its members (or finer clusters). */
|
|
146
|
+
expandCluster(clusterId: string): void;
|
|
147
|
+
setSize(width: number, height: number): void;
|
|
148
|
+
panBy(dx: number, dy: number): void;
|
|
149
|
+
zoomAt(screen: Point, factor: number): void;
|
|
150
|
+
fit(): void;
|
|
151
|
+
/** What is under a screen point. */
|
|
152
|
+
pick(screen: Point): GraphPick;
|
|
153
|
+
/** Tracks the pointer for tooltips; null when it leaves. Updates state only when the target changes. */
|
|
154
|
+
hover(screen: Point | null): void;
|
|
155
|
+
dispose(): void;
|
|
156
|
+
}
|
|
157
|
+
interface GraphControllerOptions {
|
|
158
|
+
client: MemnestApi;
|
|
159
|
+
containerTag: string;
|
|
160
|
+
layout?: LayoutRunner;
|
|
161
|
+
clusterThreshold?: number;
|
|
162
|
+
limit?: number;
|
|
163
|
+
filter?: Partial<GraphFilter>;
|
|
164
|
+
/** Called when a node is picked or selected, so other views can follow. */
|
|
165
|
+
onSelect?: (memoryId: string | null) => void;
|
|
166
|
+
/** Default true. */
|
|
167
|
+
autoload?: boolean;
|
|
168
|
+
}
|
|
169
|
+
declare const DEFAULT_GRAPH_FILTER: GraphFilter;
|
|
170
|
+
declare function matchesFilter(node: GraphNode, filter: GraphFilter): boolean;
|
|
171
|
+
declare function createGraphController(options: GraphControllerOptions): GraphController;
|
|
172
|
+
|
|
173
|
+
interface CanvasGradientLike {
|
|
174
|
+
addColorStop(offset: number, color: string): void;
|
|
175
|
+
}
|
|
176
|
+
/** The subset of CanvasRenderingContext2D the renderer uses. No DOM types. */
|
|
177
|
+
interface Canvas2DLike {
|
|
178
|
+
save(): void;
|
|
179
|
+
restore(): void;
|
|
180
|
+
setTransform(a: number, b: number, c: number, d: number, e: number, f: number): void;
|
|
181
|
+
fillRect(x: number, y: number, w: number, h: number): void;
|
|
182
|
+
beginPath(): void;
|
|
183
|
+
moveTo(x: number, y: number): void;
|
|
184
|
+
lineTo(x: number, y: number): void;
|
|
185
|
+
quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void;
|
|
186
|
+
arc(x: number, y: number, r: number, start: number, end: number): void;
|
|
187
|
+
fill(): void;
|
|
188
|
+
stroke(): void;
|
|
189
|
+
fillText(text: string, x: number, y: number): void;
|
|
190
|
+
strokeText(text: string, x: number, y: number): void;
|
|
191
|
+
setLineDash(segments: number[]): void;
|
|
192
|
+
createRadialGradient(x0: number, y0: number, r0: number, x1: number, y1: number, r1: number): CanvasGradientLike;
|
|
193
|
+
fillStyle: unknown;
|
|
194
|
+
strokeStyle: unknown;
|
|
195
|
+
lineWidth: number;
|
|
196
|
+
globalAlpha: number;
|
|
197
|
+
globalCompositeOperation: string;
|
|
198
|
+
font: string;
|
|
199
|
+
textAlign: string;
|
|
200
|
+
textBaseline: string;
|
|
201
|
+
lineJoin: string;
|
|
202
|
+
lineCap: string;
|
|
203
|
+
}
|
|
204
|
+
/** Colours are hex (#rgb or #rrggbb) wherever the renderer derives glows from them. */
|
|
205
|
+
interface GraphTheme {
|
|
206
|
+
/**
|
|
207
|
+
* How light meets the ground. On a dark ground neurons and signals add light, so they glow; on a light
|
|
208
|
+
* ground adding light would wash out to white, so they lay soft colour down instead.
|
|
209
|
+
*/
|
|
210
|
+
ground: 'dark' | 'light';
|
|
211
|
+
/** A flat ground, dark or light to match `ground`. */
|
|
212
|
+
background: string;
|
|
213
|
+
/** The bright core of a signal travelling along a connection. */
|
|
214
|
+
spark: string;
|
|
215
|
+
kinds: Record<MemoryKind, string>;
|
|
216
|
+
/** Clusters are neutral: their colour would otherwise suggest a kind they do not have. */
|
|
217
|
+
cluster: string;
|
|
218
|
+
clusterStroke: string;
|
|
219
|
+
edges: {
|
|
220
|
+
updates: string;
|
|
221
|
+
extends: string;
|
|
222
|
+
aggregate: string;
|
|
223
|
+
};
|
|
224
|
+
label: string;
|
|
225
|
+
labelHalo: string;
|
|
226
|
+
selection: string;
|
|
227
|
+
lineage: string;
|
|
228
|
+
/** Opacity of superseded memories. */
|
|
229
|
+
supersededAlpha: number;
|
|
230
|
+
/** Opacity of forgotten memories (drawn hollow). */
|
|
231
|
+
forgottenAlpha: number;
|
|
232
|
+
font: string;
|
|
233
|
+
}
|
|
234
|
+
interface SceneCircle {
|
|
235
|
+
id: string;
|
|
236
|
+
x: number;
|
|
237
|
+
y: number;
|
|
238
|
+
r: number;
|
|
239
|
+
fill: string | null;
|
|
240
|
+
stroke: string | null;
|
|
241
|
+
strokeWidth: number;
|
|
242
|
+
alpha: number;
|
|
243
|
+
/** How brightly the neuron shines, 0–1. */
|
|
244
|
+
glow: number;
|
|
245
|
+
selected: boolean;
|
|
246
|
+
/** Stable per circle in [0, 1): varies each pulse so no two breathe in step. */
|
|
247
|
+
seed: number;
|
|
248
|
+
label: string | null;
|
|
249
|
+
/** Higher labels win when space is short. */
|
|
250
|
+
priority: number;
|
|
251
|
+
}
|
|
252
|
+
interface SceneLine {
|
|
253
|
+
x1: number;
|
|
254
|
+
y1: number;
|
|
255
|
+
x2: number;
|
|
256
|
+
y2: number;
|
|
257
|
+
/** The circle the line ends at, which flashes when a signal arrives. */
|
|
258
|
+
to: string | null;
|
|
259
|
+
color: string;
|
|
260
|
+
width: number;
|
|
261
|
+
alpha: number;
|
|
262
|
+
dash: number[] | null;
|
|
263
|
+
/** Draw an arrowhead at (x2, y2), outside a circle of this radius. */
|
|
264
|
+
arrow: number | null;
|
|
265
|
+
/** Stable per line in [0, 1): sets its curve and when it fires. */
|
|
266
|
+
seed: number;
|
|
267
|
+
}
|
|
268
|
+
interface Scene {
|
|
269
|
+
circles: SceneCircle[];
|
|
270
|
+
lines: SceneLine[];
|
|
271
|
+
}
|
|
272
|
+
/** Turns graph state into drawable primitives in world coordinates. Pure. */
|
|
273
|
+
declare function buildGraphScene(state: GraphState, theme: GraphTheme): Scene;
|
|
274
|
+
interface DrawOptions {
|
|
275
|
+
pixelRatio?: number;
|
|
276
|
+
/** Maximum labels per frame. Default 160. */
|
|
277
|
+
maxLabels?: number;
|
|
278
|
+
/**
|
|
279
|
+
* Milliseconds on any steady clock. When given, neurons breathe and signals travel along
|
|
280
|
+
* connections, lighting up the memory they reach. Omit for a still frame (reduced motion, snapshots).
|
|
281
|
+
*/
|
|
282
|
+
time?: number;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Draws a scene to a 2D canvas as a glowing neural network. Labels appear once a circle is large enough
|
|
286
|
+
* on screen to own one, highest priority first, capped per frame, so 2,000 nodes stay legible and fast.
|
|
287
|
+
*/
|
|
288
|
+
declare function drawScene(ctx: Canvas2DLike, scene: Scene, viewport: Viewport, size: Size, theme: GraphTheme, options?: DrawOptions): void;
|
|
289
|
+
|
|
290
|
+
interface LineageState {
|
|
291
|
+
status: 'idle' | 'loading' | 'ready' | 'not-found' | 'error';
|
|
292
|
+
error: string | null;
|
|
293
|
+
rootId: string | null;
|
|
294
|
+
graph: LineageGraph | null;
|
|
295
|
+
/** Newer memories on the left, older ones and source documents to the right. */
|
|
296
|
+
positions: ReadonlyMap<string, Point>;
|
|
297
|
+
bounds: Bounds | null;
|
|
298
|
+
}
|
|
299
|
+
interface LineageController extends Observable<LineageState> {
|
|
300
|
+
load(memoryId: string): Promise<void>;
|
|
301
|
+
reload(): Promise<void>;
|
|
302
|
+
clear(): void;
|
|
303
|
+
dispose(): void;
|
|
304
|
+
}
|
|
305
|
+
/** Lays out a lineage graph: memories and their source documents as a layered DAG. */
|
|
306
|
+
declare function layoutLineage(graph: LineageGraph): {
|
|
307
|
+
positions: Map<string, Point>;
|
|
308
|
+
bounds: Bounds | null;
|
|
309
|
+
};
|
|
310
|
+
declare function createLineageController(options: {
|
|
311
|
+
client: MemnestApi;
|
|
312
|
+
containerTag: string;
|
|
313
|
+
}): LineageController;
|
|
314
|
+
|
|
315
|
+
interface SourceDocument {
|
|
316
|
+
document: DocumentRef;
|
|
317
|
+
/** Loaded on request: the document text (redacted; empty once deleted). */
|
|
318
|
+
content: string | null;
|
|
319
|
+
/** Loaded on request: the raw chunks the memory was extracted from. Direct writes have none. */
|
|
320
|
+
chunks: Chunk[] | null;
|
|
321
|
+
loading: boolean;
|
|
322
|
+
error: string | null;
|
|
323
|
+
}
|
|
324
|
+
interface DetailState {
|
|
325
|
+
status: 'idle' | 'loading' | 'ready' | 'not-found' | 'error';
|
|
326
|
+
error: string | null;
|
|
327
|
+
memoryId: string | null;
|
|
328
|
+
memory: Memory | null;
|
|
329
|
+
/** The full version history this memory belongs to (UPDATES chain), oldest first. */
|
|
330
|
+
versions: Memory[];
|
|
331
|
+
/** Memories this one enriches, and memories that enrich it. */
|
|
332
|
+
extends: Memory[];
|
|
333
|
+
extendedBy: Memory[];
|
|
334
|
+
sources: SourceDocument[];
|
|
335
|
+
/** Forget is two steps: request, then confirm (D5). */
|
|
336
|
+
forget: 'idle' | 'confirming' | 'forgetting';
|
|
337
|
+
forgetError: string | null;
|
|
338
|
+
}
|
|
339
|
+
interface DetailController extends Observable<DetailState> {
|
|
340
|
+
load(memoryId: string): Promise<void>;
|
|
341
|
+
reload(): Promise<void>;
|
|
342
|
+
clear(): void;
|
|
343
|
+
loadSource(documentId: string): Promise<void>;
|
|
344
|
+
requestForget(): void;
|
|
345
|
+
cancelForget(): void;
|
|
346
|
+
confirmForget(): Promise<Memory | null>;
|
|
347
|
+
dispose(): void;
|
|
348
|
+
}
|
|
349
|
+
/** The UPDATES chain through `rootId`, oldest first. */
|
|
350
|
+
declare function versionChain(graph: LineageGraph, rootId: string): Memory[];
|
|
351
|
+
declare function createDetailController(options: {
|
|
352
|
+
client: MemnestApi;
|
|
353
|
+
containerTag: string;
|
|
354
|
+
/** Called after a memory is forgotten, so other views can refresh. */
|
|
355
|
+
onForgotten?: (memory: Memory) => void;
|
|
356
|
+
}): DetailController;
|
|
357
|
+
|
|
358
|
+
interface TraceRow {
|
|
359
|
+
memoryId: string;
|
|
360
|
+
/** Null when the memory could not be loaded (e.g. deleted since). */
|
|
361
|
+
content: string | null;
|
|
362
|
+
kind: MemoryKind | null;
|
|
363
|
+
lexicalRank?: number;
|
|
364
|
+
lexicalScore?: number;
|
|
365
|
+
vectorRank?: number;
|
|
366
|
+
vectorScore?: number;
|
|
367
|
+
rrfScore: number;
|
|
368
|
+
rerankScore?: number;
|
|
369
|
+
included: boolean;
|
|
370
|
+
excludedReason?: ExcludedReason;
|
|
371
|
+
tokens: number;
|
|
372
|
+
/** Tokens used by included memories up to and including this row. */
|
|
373
|
+
cumulativeTokens: number;
|
|
374
|
+
}
|
|
375
|
+
interface TraceState {
|
|
376
|
+
query: string;
|
|
377
|
+
tokenBudget: number;
|
|
378
|
+
status: 'idle' | 'loading' | 'ready' | 'error';
|
|
379
|
+
error: string | null;
|
|
380
|
+
response: SearchResponse | null;
|
|
381
|
+
/** Every candidate from either retriever, in packing order. */
|
|
382
|
+
rows: TraceRow[];
|
|
383
|
+
/** Index of the first row the budget excluded: the budget line is drawn above it. Null when nothing was cut. */
|
|
384
|
+
budgetLine: number | null;
|
|
385
|
+
/** Budget spent on chunks, which share what memories leave. */
|
|
386
|
+
chunkTokens: number;
|
|
387
|
+
}
|
|
388
|
+
interface TraceController extends Observable<TraceState> {
|
|
389
|
+
setQuery(query: string): void;
|
|
390
|
+
setTokenBudget(tokens: number): void;
|
|
391
|
+
run(): Promise<void>;
|
|
392
|
+
/** Runs the last query again, e.g. after a forget. No-op before the first run. */
|
|
393
|
+
rerun(): Promise<void>;
|
|
394
|
+
dispose(): void;
|
|
395
|
+
}
|
|
396
|
+
declare const DEFAULT_TRACE_BUDGET = 2000;
|
|
397
|
+
/** Joins the trace with memory content and computes the budget line. Pure. */
|
|
398
|
+
declare function buildTraceRows(response: SearchResponse, memories: ReadonlyMap<string, Memory>): {
|
|
399
|
+
rows: TraceRow[];
|
|
400
|
+
budgetLine: number | null;
|
|
401
|
+
};
|
|
402
|
+
declare function createTraceController(options: {
|
|
403
|
+
client: MemnestApi;
|
|
404
|
+
containerTag: string;
|
|
405
|
+
tokenBudget?: number;
|
|
406
|
+
}): TraceController;
|
|
407
|
+
|
|
408
|
+
type TimelineStatus = 'current' | 'superseded' | 'expired' | 'forgotten';
|
|
409
|
+
interface TimelineItem {
|
|
410
|
+
memory: Memory;
|
|
411
|
+
laneId: string;
|
|
412
|
+
start: string;
|
|
413
|
+
/** When the fact stopped (or will stop) being true. Null while it is true with no expiry. */
|
|
414
|
+
end: string | null;
|
|
415
|
+
status: TimelineStatus;
|
|
416
|
+
/** The memory that replaced this one, when superseded. */
|
|
417
|
+
supersededBy: string | null;
|
|
418
|
+
}
|
|
419
|
+
interface TimelineLane {
|
|
420
|
+
id: string;
|
|
421
|
+
/** The newest fact in the lane. */
|
|
422
|
+
label: string;
|
|
423
|
+
items: TimelineItem[];
|
|
424
|
+
}
|
|
425
|
+
interface TimelineTick {
|
|
426
|
+
at: string;
|
|
427
|
+
label: string;
|
|
428
|
+
}
|
|
429
|
+
interface Timeline {
|
|
430
|
+
lanes: TimelineLane[];
|
|
431
|
+
range: {
|
|
432
|
+
start: string;
|
|
433
|
+
end: string;
|
|
434
|
+
} | null;
|
|
435
|
+
ticks: TimelineTick[];
|
|
436
|
+
}
|
|
437
|
+
interface TimelineState extends Timeline {
|
|
438
|
+
topic: string;
|
|
439
|
+
status: 'idle' | 'loading' | 'ready' | 'error';
|
|
440
|
+
error: string | null;
|
|
441
|
+
}
|
|
442
|
+
interface TimelineController extends Observable<TimelineState> {
|
|
443
|
+
setTopic(topic: string): void;
|
|
444
|
+
run(): Promise<void>;
|
|
445
|
+
rerun(): Promise<void>;
|
|
446
|
+
dispose(): void;
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Facts over time. Memories linked by UPDATES share a lane; each fact runs from `validFrom` until
|
|
450
|
+
* it was superseded, expired or forgotten, whichever came first. Pure.
|
|
451
|
+
*/
|
|
452
|
+
declare function buildTimeline(memories: readonly Memory[], now: string): Timeline;
|
|
453
|
+
/** About `count` evenly spaced, human-readable ticks (UTC). */
|
|
454
|
+
declare function timeTicks(start: string, end: string, count?: number): TimelineTick[];
|
|
455
|
+
declare function createTimelineController(options: {
|
|
456
|
+
client: MemnestApi;
|
|
457
|
+
containerTag: string;
|
|
458
|
+
now?: () => string;
|
|
459
|
+
}): TimelineController;
|
|
460
|
+
|
|
461
|
+
interface FinderState {
|
|
462
|
+
query: string;
|
|
463
|
+
/** Include superseded and forgotten memories. */
|
|
464
|
+
includeHistory: boolean;
|
|
465
|
+
status: 'idle' | 'loading' | 'ready' | 'error';
|
|
466
|
+
error: string | null;
|
|
467
|
+
items: Memory[];
|
|
468
|
+
/** More pages exist (browsing without a query). */
|
|
469
|
+
hasMore: boolean;
|
|
470
|
+
}
|
|
471
|
+
interface FinderController extends Observable<FinderState> {
|
|
472
|
+
setQuery(query: string): void;
|
|
473
|
+
setIncludeHistory(include: boolean): void;
|
|
474
|
+
/** Searches when there is a query; otherwise lists the newest memories. */
|
|
475
|
+
run(): Promise<void>;
|
|
476
|
+
loadMore(): Promise<void>;
|
|
477
|
+
dispose(): void;
|
|
478
|
+
}
|
|
479
|
+
/** Finds memories to inspect: by search (with every candidate the trace names), or by browsing newest first. */
|
|
480
|
+
declare function createFinderController(options: {
|
|
481
|
+
client: MemnestApi;
|
|
482
|
+
containerTag: string;
|
|
483
|
+
}): FinderController;
|
|
484
|
+
|
|
485
|
+
interface SelectionState {
|
|
486
|
+
memoryId: string | null;
|
|
487
|
+
}
|
|
488
|
+
interface Workspace {
|
|
489
|
+
containerTag: string;
|
|
490
|
+
selection: Observable<SelectionState>;
|
|
491
|
+
/** Selecting a memory anywhere opens its detail and lineage, and highlights it in the graph. */
|
|
492
|
+
select(memoryId: string | null): void;
|
|
493
|
+
finder: FinderController;
|
|
494
|
+
detail: DetailController;
|
|
495
|
+
lineage: LineageController;
|
|
496
|
+
trace: TraceController;
|
|
497
|
+
timeline: TimelineController;
|
|
498
|
+
graph: GraphController;
|
|
499
|
+
/** Reloads every view that has data, e.g. after new memories arrive. */
|
|
500
|
+
refresh(): Promise<void>;
|
|
501
|
+
dispose(): void;
|
|
502
|
+
}
|
|
503
|
+
interface WorkspaceOptions {
|
|
504
|
+
client: MemnestApi;
|
|
505
|
+
containerTag: string;
|
|
506
|
+
layout?: LayoutRunner;
|
|
507
|
+
graph?: Pick<GraphControllerOptions, 'clusterThreshold' | 'limit' | 'filter' | 'autoload'>;
|
|
508
|
+
now?: () => string;
|
|
509
|
+
}
|
|
510
|
+
/** Every controller for one container, wired so selection and forgetting stay consistent across views. */
|
|
511
|
+
declare function createWorkspace(options: WorkspaceOptions): Workspace;
|
|
512
|
+
|
|
513
|
+
export { Bounds, CLUSTER_THRESHOLD, type Canvas2DLike, type CanvasGradientLike, type Cluster, type ClusterEdge, type ClusterOptions, type Clustering, DEFAULT_GRAPH_FILTER, DEFAULT_TRACE_BUDGET, type DetailController, type DetailState, type DrawOptions, type FinderController, type FinderState, GRAPH_LOAD_LIMIT, type GraphController, type GraphControllerOptions, type GraphFilter, type GraphLineageOverlay, type GraphPick, type GraphState, type GraphTheme, type HitCircle, type HitIndex, LayoutRunner, type LineageController, type LineageState, type Observable, Point, type Scene, type SceneCircle, type SceneLine, type SelectionState, Size, type SourceDocument, type Store, type Timeline, type TimelineController, type TimelineItem, type TimelineLane, type TimelineState, type TimelineStatus, type TimelineTick, type TraceController, type TraceRow, type TraceState, Viewport, type Workspace, type WorkspaceOptions, buildGraphScene, buildTimeline, buildTraceRows, clusterNodes, clusterRadius, createDetailController, createFinderController, createGraphController, createHitIndex, createLineageController, createSequencer, createStore, createTimelineController, createTraceController, createWorkspace, documentRadius, drawScene, layoutLineage, matchesFilter, nodeRadius, shorten, timeTicks, versionChain };
|