@iworkforces/tracelattice 2.3.0 → 2.3.5
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/README.md +14 -1
- package/dist/cli.js +94 -14
- package/dist/cli.js.map +1 -1
- package/dist/config/CliTransportConfig.d.ts +22 -0
- package/dist/config/CliTransportConfig.d.ts.map +1 -0
- package/dist/config/CliTransportConfig.js +52 -0
- package/dist/config/CliTransportConfig.js.map +1 -0
- package/dist/config/ConfigLoader.d.ts +0 -1
- package/dist/config/ConfigLoader.d.ts.map +1 -1
- package/dist/config/ConfigLoader.js +9 -14
- package/dist/config/ConfigLoader.js.map +1 -1
- package/dist/config/EnvironmentInteger.d.ts +2 -0
- package/dist/config/EnvironmentInteger.d.ts.map +1 -0
- package/dist/config/EnvironmentInteger.js +10 -0
- package/dist/config/EnvironmentInteger.js.map +1 -0
- package/dist/contracts/reasoning-types.d.ts +3 -3
- package/dist/contracts/reasoning-types.d.ts.map +1 -1
- package/dist/core/ThoughtEvaluator.d.ts +9 -2
- package/dist/core/ThoughtEvaluator.d.ts.map +1 -1
- package/dist/core/ThoughtEvaluator.js +9 -2
- package/dist/core/ThoughtEvaluator.js.map +1 -1
- package/dist/core/ThoughtProcessor.d.ts +1 -0
- package/dist/core/ThoughtProcessor.d.ts.map +1 -1
- package/dist/core/ThoughtProcessor.js +42 -16
- package/dist/core/ThoughtProcessor.js.map +1 -1
- package/dist/core/evaluator/GraphPatterns.d.ts +8 -0
- package/dist/core/evaluator/GraphPatterns.d.ts.map +1 -0
- package/dist/core/evaluator/GraphPatterns.js +88 -0
- package/dist/core/evaluator/GraphPatterns.js.map +1 -0
- package/dist/core/evaluator/GraphSignalComputer.d.ts +12 -0
- package/dist/core/evaluator/GraphSignalComputer.d.ts.map +1 -0
- package/dist/core/evaluator/GraphSignalComputer.js +17 -0
- package/dist/core/evaluator/GraphSignalComputer.js.map +1 -0
- package/dist/core/evaluator/PatternDetector.d.ts +4 -1
- package/dist/core/evaluator/PatternDetector.d.ts.map +1 -1
- package/dist/core/evaluator/PatternDetector.js +8 -2
- package/dist/core/evaluator/PatternDetector.js.map +1 -1
- package/dist/core/graph/EdgeEmitter.js +1 -1
- package/dist/core/graph/EdgeEmitter.js.map +1 -1
- package/dist/core/graph/GraphView.d.ts +60 -2
- package/dist/core/graph/GraphView.d.ts.map +1 -1
- package/dist/core/graph/GraphView.js +127 -11
- package/dist/core/graph/GraphView.js.map +1 -1
- package/dist/core/reasoning/GraphContext.d.ts +25 -0
- package/dist/core/reasoning/GraphContext.d.ts.map +1 -0
- package/dist/core/reasoning/GraphContext.js +32 -0
- package/dist/core/reasoning/GraphContext.js.map +1 -0
- package/dist/core/reasoning.d.ts +10 -0
- package/dist/core/reasoning.d.ts.map +1 -1
- package/dist/lib.d.ts +12 -2
- package/dist/lib.d.ts.map +1 -1
- package/dist/lib.js +9 -4
- package/dist/lib.js.map +1 -1
- package/dist/persistence/BunSqliteDriver.d.ts +11 -0
- package/dist/persistence/BunSqliteDriver.d.ts.map +1 -0
- package/dist/persistence/BunSqliteDriver.js +36 -0
- package/dist/persistence/BunSqliteDriver.js.map +1 -0
- package/dist/persistence/SqliteDriverLoader.d.ts +11 -0
- package/dist/persistence/SqliteDriverLoader.d.ts.map +1 -0
- package/dist/persistence/SqliteDriverLoader.js +19 -0
- package/dist/persistence/SqliteDriverLoader.js.map +1 -0
- package/dist/persistence/SqlitePersistence.d.ts +2 -1
- package/dist/persistence/SqlitePersistence.d.ts.map +1 -1
- package/dist/persistence/SqlitePersistence.js +4 -9
- package/dist/persistence/SqlitePersistence.js.map +1 -1
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +4 -2
- package/dist/schema.js.map +1 -1
- package/package.json +7 -7
|
@@ -54,8 +54,9 @@ class GraphView {
|
|
|
54
54
|
const queue = [
|
|
55
55
|
rootThoughtId
|
|
56
56
|
];
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
let head = 0;
|
|
58
|
+
while(head < queue.length){
|
|
59
|
+
const current = queue[head++];
|
|
59
60
|
const out = this._store.outgoing(sessionId, current);
|
|
60
61
|
for (const edge of out)if ('branch' === edge.kind) {
|
|
61
62
|
if (!visited.has(edge.to)) {
|
|
@@ -74,8 +75,9 @@ class GraphView {
|
|
|
74
75
|
const queue = [];
|
|
75
76
|
for (const [node, deg] of inDegree)if (0 === deg) queue.push(node);
|
|
76
77
|
const order = [];
|
|
77
|
-
|
|
78
|
-
|
|
78
|
+
let head = 0;
|
|
79
|
+
while(head < queue.length){
|
|
80
|
+
const node = queue[head++];
|
|
79
81
|
order.push(node);
|
|
80
82
|
for (const edge of this._store.outgoing(sessionId, node)){
|
|
81
83
|
const next = (inDegree.get(edge.to) ?? 0) - 1;
|
|
@@ -86,11 +88,122 @@ class GraphView {
|
|
|
86
88
|
if (order.length !== inDegree.size) throw new CycleDetectedError(`Cycle detected in session '${sessionId}': topological sort incomplete (${order.length}/${inDegree.size})`);
|
|
87
89
|
return order;
|
|
88
90
|
}
|
|
89
|
-
ancestors(sessionId, thoughtId, maxDepth) {
|
|
90
|
-
return this._bfsClosure(sessionId, thoughtId, maxDepth, 'incoming');
|
|
91
|
+
ancestors(sessionId, thoughtId, maxDepth, kinds) {
|
|
92
|
+
return this._bfsClosure(sessionId, thoughtId, maxDepth, 'incoming', kinds);
|
|
91
93
|
}
|
|
92
|
-
descendants(sessionId, thoughtId, maxDepth) {
|
|
93
|
-
return this._bfsClosure(sessionId, thoughtId, maxDepth, 'outgoing');
|
|
94
|
+
descendants(sessionId, thoughtId, maxDepth, kinds) {
|
|
95
|
+
return this._bfsClosure(sessionId, thoughtId, maxDepth, 'outgoing', kinds);
|
|
96
|
+
}
|
|
97
|
+
inbound(sessionId, thoughtId) {
|
|
98
|
+
return this._store.incoming(sessionId, thoughtId).map((edge)=>({
|
|
99
|
+
id: edge.from,
|
|
100
|
+
kind: edge.kind
|
|
101
|
+
}));
|
|
102
|
+
}
|
|
103
|
+
outbound(sessionId, thoughtId) {
|
|
104
|
+
return this._store.outgoing(sessionId, thoughtId).map((edge)=>({
|
|
105
|
+
id: edge.to,
|
|
106
|
+
kind: edge.kind
|
|
107
|
+
}));
|
|
108
|
+
}
|
|
109
|
+
hasPath(sessionId, from, to, kinds) {
|
|
110
|
+
const allowed = kinds?.length ? new Set(kinds) : void 0;
|
|
111
|
+
const visited = new Set([
|
|
112
|
+
from
|
|
113
|
+
]);
|
|
114
|
+
const queue = [
|
|
115
|
+
from
|
|
116
|
+
];
|
|
117
|
+
for (const node of queue)for (const edge of this._store.outgoing(sessionId, node))if (void 0 === allowed || allowed.has(edge.kind)) {
|
|
118
|
+
if (edge.to === to) return true;
|
|
119
|
+
if (!visited.has(edge.to)) {
|
|
120
|
+
visited.add(edge.to);
|
|
121
|
+
queue.push(edge.to);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
metrics(sessionId) {
|
|
127
|
+
const edges = this._store.edgesForSession(sessionId);
|
|
128
|
+
const explicitNodes = this._store.nodesForSession?.(sessionId);
|
|
129
|
+
const { nodes, hasIncoming } = this._collectNodes(edges, explicitNodes);
|
|
130
|
+
const inDegree = this._buildInDegree(edges, explicitNodes);
|
|
131
|
+
const outDegree = new Map();
|
|
132
|
+
let maxIn = 0;
|
|
133
|
+
let maxOut = 0;
|
|
134
|
+
for (const edge of edges){
|
|
135
|
+
const degree = (outDegree.get(edge.from) ?? 0) + 1;
|
|
136
|
+
outDegree.set(edge.from, degree);
|
|
137
|
+
maxOut = Math.max(maxOut, degree);
|
|
138
|
+
}
|
|
139
|
+
for (const degree of inDegree.values())maxIn = Math.max(maxIn, degree);
|
|
140
|
+
return {
|
|
141
|
+
node_count: nodes.size,
|
|
142
|
+
edge_count: edges.length,
|
|
143
|
+
root_count: nodes.size - hasIncoming.size,
|
|
144
|
+
leaf_count: nodes.size - outDegree.size,
|
|
145
|
+
longest_path: this._longestPath(sessionId, inDegree),
|
|
146
|
+
max_out_degree: maxOut,
|
|
147
|
+
max_in_degree: maxIn,
|
|
148
|
+
edge_kind_counts: this._edgeKindCounts(edges),
|
|
149
|
+
component_count: this._componentCount(nodes, edges)
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
_edgeKindCounts(edges) {
|
|
153
|
+
const counts = {
|
|
154
|
+
sequence: 0,
|
|
155
|
+
branch: 0,
|
|
156
|
+
merge: 0,
|
|
157
|
+
verifies: 0,
|
|
158
|
+
critiques: 0,
|
|
159
|
+
derives_from: 0,
|
|
160
|
+
tool_invocation: 0,
|
|
161
|
+
revises: 0
|
|
162
|
+
};
|
|
163
|
+
for (const edge of edges)counts[edge.kind]++;
|
|
164
|
+
return counts;
|
|
165
|
+
}
|
|
166
|
+
_longestPath(sessionId, inDegree) {
|
|
167
|
+
const queue = [];
|
|
168
|
+
const distances = new Map();
|
|
169
|
+
for (const [node, degree] of inDegree)if (0 === degree) queue.push(node);
|
|
170
|
+
let longest = 0;
|
|
171
|
+
let head = 0;
|
|
172
|
+
while(head < queue.length){
|
|
173
|
+
const node = queue[head++];
|
|
174
|
+
const distance = distances.get(node) ?? 0;
|
|
175
|
+
longest = Math.max(longest, distance);
|
|
176
|
+
for (const edge of this._store.outgoing(sessionId, node)){
|
|
177
|
+
distances.set(edge.to, Math.max(distances.get(edge.to) ?? 0, distance + 1));
|
|
178
|
+
const degree = (inDegree.get(edge.to) ?? 0) - 1;
|
|
179
|
+
inDegree.set(edge.to, degree);
|
|
180
|
+
if (0 === degree) queue.push(edge.to);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return head === inDegree.size ? longest : null;
|
|
184
|
+
}
|
|
185
|
+
_componentCount(nodes, edges) {
|
|
186
|
+
const neighbours = new Map();
|
|
187
|
+
for (const node of nodes)neighbours.set(node, []);
|
|
188
|
+
for (const edge of edges){
|
|
189
|
+
neighbours.get(edge.from)?.push(edge.to);
|
|
190
|
+
neighbours.get(edge.to)?.push(edge.from);
|
|
191
|
+
}
|
|
192
|
+
const visited = new Set();
|
|
193
|
+
let count = 0;
|
|
194
|
+
for (const node of nodes){
|
|
195
|
+
if (visited.has(node)) continue;
|
|
196
|
+
count++;
|
|
197
|
+
visited.add(node);
|
|
198
|
+
const queue = [
|
|
199
|
+
node
|
|
200
|
+
];
|
|
201
|
+
for (const current of queue)for (const neighbour of neighbours.get(current) ?? [])if (!visited.has(neighbour)) {
|
|
202
|
+
visited.add(neighbour);
|
|
203
|
+
queue.push(neighbour);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return count;
|
|
94
207
|
}
|
|
95
208
|
leaves(sessionId) {
|
|
96
209
|
const edges = this._store.edgesForSession(sessionId);
|
|
@@ -130,8 +243,9 @@ class GraphView {
|
|
|
130
243
|
order.push(root);
|
|
131
244
|
queue.push(root);
|
|
132
245
|
}
|
|
133
|
-
|
|
134
|
-
|
|
246
|
+
let head = 0;
|
|
247
|
+
while(head < queue.length){
|
|
248
|
+
const node = queue[head++];
|
|
135
249
|
for (const edge of this._store.outgoing(sessionId, node))if (!visited.has(edge.to)) {
|
|
136
250
|
visited.add(edge.to);
|
|
137
251
|
order.push(edge.to);
|
|
@@ -149,7 +263,8 @@ class GraphView {
|
|
|
149
263
|
}
|
|
150
264
|
return inDegree;
|
|
151
265
|
}
|
|
152
|
-
_bfsClosure(sessionId, startId, maxDepth, direction) {
|
|
266
|
+
_bfsClosure(sessionId, startId, maxDepth, direction, kinds) {
|
|
267
|
+
const allowed = kinds?.length ? new Set(kinds) : void 0;
|
|
153
268
|
const cap = maxDepth ?? 1 / 0;
|
|
154
269
|
const visited = new Set([
|
|
155
270
|
startId
|
|
@@ -164,6 +279,7 @@ class GraphView {
|
|
|
164
279
|
for (const node of frontier){
|
|
165
280
|
const edges = 'outgoing' === direction ? this._store.outgoing(sessionId, node) : this._store.incoming(sessionId, node);
|
|
166
281
|
for (const edge of edges){
|
|
282
|
+
if (void 0 !== allowed && !allowed.has(edge.kind)) continue;
|
|
167
283
|
const neighbour = 'outgoing' === direction ? edge.to : edge.from;
|
|
168
284
|
if (!visited.has(neighbour)) {
|
|
169
285
|
visited.add(neighbour);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core/graph/GraphView.js","sources":["../../../src/core/graph/GraphView.ts"],"sourcesContent":["/**\n * GraphView — read-only graph traversal queries over an {@link IEdgeStore}.\n *\n * Provides BFS / topological / ancestor / descendant queries over the\n * thought DAG. Queries return thought ids or graph distances,\n * never `ThoughtData` objects — the view is intentionally decoupled from\n * `HistoryManager` so it can be reused by strategies that work purely in\n * terms of graph structure.\n *\n * Construction is cheap (stores a reference to the underlying store).\n * Each query reads the latest store state — no caching, no snapshots.\n *\n * @module core/graph/GraphView\n */\n\nimport type { IGraphViewStore } from '../../contracts/interfaces.js';\nimport type { SessionId, ThoughtId } from '../../contracts/ids.js';\nimport { CycleDetectedError } from '../../errors.js';\nimport type { Edge } from './Edge.js';\n\n/**\n * Read-only traversal queries over an {@link IEdgeStore}.\n *\n * @example\n * ```typescript\n * const store = new EdgeStore();\n * // ... populate store ...\n * const view = new GraphView(store);\n * const order = view.topological('s1');\n * ```\n */\nexport class GraphView {\n\tprivate readonly _store: IGraphViewStore;\n\n\t/**\n\t * Create a new GraphView backed by the given edge store.\n\t *\n\t * @param store - The edge store to query (held by reference, read-only access)\n\t *\n\t * @example\n\t * ```typescript\n\t * const view = new GraphView(edgeStore);\n\t * ```\n\t */\n\tconstructor(store: IGraphViewStore) {\n\t\tthis._store = store;\n\t}\n\n\t/**\n\t * Return all thought ids in the session, ordered by BFS from roots.\n\t *\n\t * Roots are nodes with no incoming edges. Within a layer, neighbours\n\t * are visited in `outgoing` order (which the underlying store keeps\n\t * sorted by `createdAt` ascending).\n\t *\n\t * @param sessionId - Session to query\n\t * @returns Thought ids in chronological BFS order\n\t *\n\t * @example\n\t * ```typescript\n\t * const ids = view.chronological('s1');\n\t * ```\n\t */\n\tchronological(sessionId: SessionId): readonly ThoughtId[] {\n\t\tconst edges = this._store.edgesForSession(sessionId);\n\t\tconst { nodes, hasIncoming } = this._collectNodes(\n\t\t\tedges,\n\t\t\tthis._store.nodesForSession?.(sessionId)\n\t\t);\n\t\tif (nodes.size === 0) return [];\n\t\tconst roots = this._findRoots(nodes, hasIncoming, edges);\n\t\treturn this._bfsFromRoots(sessionId, roots) as readonly ThoughtId[];\n\t}\n\n\t/**\n\t * Return the shortest directed distance from any retained root to a thought.\n\t *\n\t * Nodes are derived from edges unless an immutable snapshot supplies original\n\t * endpoint nodes. Thoughts never referenced by an audit edge remain invisible.\n\t * Every edge kind participates in the traversal.\n\t *\n\t * @param sessionId - Session to query\n\t * @param thoughtId - Thought whose root distance to resolve\n\t * @returns Zero for a root, or `undefined` when no root can reach the thought\n\t */\n\tdepthFromRoots(sessionId: SessionId, thoughtId: ThoughtId): number | undefined {\n\t\tconst edges = this._store.edgesForSession(sessionId);\n\t\tconst nodes = new Set<ThoughtId>(this._store.nodesForSession?.(sessionId) ?? []);\n\t\tconst hasIncoming = new Set<ThoughtId>();\n\t\tconst outgoing = new Map<ThoughtId, ThoughtId[]>();\n\t\tfor (const edge of edges) {\n\t\t\tnodes.add(edge.from);\n\t\t\tnodes.add(edge.to);\n\t\t\thasIncoming.add(edge.to);\n\t\t\tconst children = outgoing.get(edge.from);\n\t\t\tif (children === undefined) outgoing.set(edge.from, [edge.to]);\n\t\t\telse children.push(edge.to);\n\t\t}\n\t\tif (!nodes.has(thoughtId)) return undefined;\n\n\t\tlet frontier: ThoughtId[] = [];\n\t\tfor (const node of nodes) {\n\t\t\tif (!hasIncoming.has(node)) frontier.push(node);\n\t\t}\n\t\tconst visited = new Set<ThoughtId>(frontier);\n\t\tlet depth = 0;\n\t\twhile (frontier.length > 0) {\n\t\t\tconst next: ThoughtId[] = [];\n\t\t\tfor (const node of frontier) {\n\t\t\t\tif (node === thoughtId) return depth;\n\t\t\t\tfor (const child of outgoing.get(node) ?? []) {\n\t\t\t\t\tif (visited.has(child)) continue;\n\t\t\t\t\tvisited.add(child);\n\t\t\t\t\tnext.push(child);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfrontier = next;\n\t\t\tdepth++;\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Return all thought ids reachable from `rootThoughtId` via `'branch'`\n\t * edges, including the root itself.\n\t *\n\t * Non-branch edges are ignored. Cycles (if any) do not cause infinite\n\t * loops because each node is visited at most once.\n\t *\n\t * @param sessionId - Session to query\n\t * @param rootThoughtId - The starting thought id (typically the branch root)\n\t * @returns Thought ids forming the branch (includes root)\n\t *\n\t * @example\n\t * ```typescript\n\t * const branchIds = view.branchThoughts('s1', 'thought-root');\n\t * ```\n\t */\n\tbranchThoughts(sessionId: SessionId, rootThoughtId: ThoughtId): readonly ThoughtId[] {\n\t\tconst visited = new Set<string>([rootThoughtId]);\n\t\tconst order: string[] = [rootThoughtId];\n\t\tconst queue: string[] = [rootThoughtId];\n\t\twhile (queue.length > 0) {\n\t\t\tconst current = queue.shift()!;\n\t\t\tconst out = this._store.outgoing(sessionId, current as ThoughtId);\n\t\t\tfor (const edge of out) {\n\t\t\t\tif (edge.kind !== 'branch') continue;\n\t\t\t\tif (visited.has(edge.to)) continue;\n\t\t\t\tvisited.add(edge.to);\n\t\t\t\torder.push(edge.to);\n\t\t\t\tqueue.push(edge.to);\n\t\t\t}\n\t\t}\n\t\treturn order as ThoughtId[];\n\t}\n\n\t/**\n\t * Return a topological ordering of all thought ids in the session\n\t * using Kahn's algorithm.\n\t *\n\t * @param sessionId - Session to query\n\t * @returns Thought ids in topological order\n\t * @throws {CycleDetectedError} If the graph contains a cycle\n\t *\n\t * @example\n\t * ```typescript\n\t * const order = view.topological('s1');\n\t * ```\n\t */\n\ttopological(sessionId: SessionId): readonly ThoughtId[] {\n\t\tconst edges = this._store.edgesForSession(sessionId);\n\t\tconst inDegree = this._buildInDegree(edges, this._store.nodesForSession?.(sessionId));\n\t\tif (inDegree.size === 0) return [];\n\t\tconst queue: string[] = [];\n\t\tfor (const [node, deg] of inDegree) {\n\t\t\tif (deg === 0) queue.push(node);\n\t\t}\n\t\tconst order: string[] = [];\n\t\twhile (queue.length > 0) {\n\t\t\tconst node = queue.shift()!;\n\t\t\torder.push(node);\n\t\t\tfor (const edge of this._store.outgoing(sessionId, node as ThoughtId)) {\n\t\t\t\tconst next = (inDegree.get(edge.to) ?? 0) - 1;\n\t\t\t\tinDegree.set(edge.to, next);\n\t\t\t\tif (next === 0) queue.push(edge.to);\n\t\t\t}\n\t\t}\n\t\tif (order.length !== inDegree.size) {\n\t\t\tthrow new CycleDetectedError(\n\t\t\t\t`Cycle detected in session '${sessionId}': topological sort incomplete (${order.length}/${inDegree.size})`\n\t\t\t);\n\t\t}\n\t\treturn order as ThoughtId[];\n\t}\n\n\t/**\n\t * Return all ancestors of `thoughtId` via incoming-edge BFS.\n\t *\n\t * The starting node is NOT included. Cycles do not cause infinite loops.\n\t *\n\t * @param sessionId - Session to query\n\t * @param thoughtId - The thought to traverse from\n\t * @param maxDepth - Optional maximum traversal depth (1 = direct parents only)\n\t * @returns Ancestor thought ids in BFS order\n\t *\n\t * @example\n\t * ```typescript\n\t * const parents = view.ancestors('s1', 'thought-id', 1);\n\t * ```\n\t */\n\tancestors(sessionId: SessionId, thoughtId: ThoughtId, maxDepth?: number): readonly ThoughtId[] {\n\t\treturn this._bfsClosure(sessionId, thoughtId, maxDepth, 'incoming') as readonly ThoughtId[];\n\t}\n\n\t/**\n\t * Return all descendants of `thoughtId` via outgoing-edge BFS.\n\t *\n\t * The starting node is NOT included. Cycles do not cause infinite loops.\n\t *\n\t * @param sessionId - Session to query\n\t * @param thoughtId - The thought to traverse from\n\t * @param maxDepth - Optional maximum traversal depth (1 = direct children only)\n\t * @returns Descendant thought ids in BFS order\n\t *\n\t * @example\n\t * ```typescript\n\t * const children = view.descendants('s1', 'thought-id');\n\t * ```\n\t */\n\tdescendants(sessionId: SessionId, thoughtId: ThoughtId, maxDepth?: number): readonly ThoughtId[] {\n\t\treturn this._bfsClosure(sessionId, thoughtId, maxDepth, 'outgoing') as readonly ThoughtId[];\n\t}\n\n\t/**\n\t * Return all thought ids in the session that have no outgoing edges.\n\t *\n\t * @param sessionId - Session to query\n\t * @returns Thought ids that are graph leaves\n\t *\n\t * @example\n\t * ```typescript\n\t * const tips = view.leaves('s1');\n\t * ```\n\t */\n\tleaves(sessionId: SessionId): readonly ThoughtId[] {\n\t\tconst edges = this._store.edgesForSession(sessionId);\n\t\tconst { nodes } = this._collectNodes(edges, this._store.nodesForSession?.(sessionId));\n\t\tif (nodes.size === 0) return [];\n\t\tconst result: string[] = [];\n\t\tfor (const node of nodes) {\n\t\t\tif (this._store.outgoing(sessionId, node as ThoughtId).length === 0) {\n\t\t\t\tresult.push(node);\n\t\t\t}\n\t\t}\n\t\treturn result as ThoughtId[];\n\t}\n\n\t/**\n\t * Collect every node id referenced by the edges and a set of nodes\n\t * that have at least one incoming edge.\n\t */\n\tprivate _collectNodes(\n\t\tedges: readonly Edge[],\n\t\texplicitNodes: readonly ThoughtId[] = []\n\t): {\n\t\tnodes: Set<string>;\n\t\thasIncoming: Set<string>;\n\t} {\n\t\tconst nodes = new Set<string>(explicitNodes);\n\t\tconst hasIncoming = new Set<string>();\n\t\tfor (const edge of edges) {\n\t\t\tnodes.add(edge.from);\n\t\t\tnodes.add(edge.to);\n\t\t\thasIncoming.add(edge.to);\n\t\t}\n\t\treturn { nodes, hasIncoming };\n\t}\n\n\t/**\n\t * Find roots (no incoming) ordered by the earliest outgoing edge\n\t * `createdAt`. Nodes with no outgoing edges fall back to the order\n\t * they appear among edges (already sorted by `createdAt`).\n\t */\n\tprivate _findRoots(\n\t\tnodes: Set<string>,\n\t\thasIncoming: Set<string>,\n\t\tedges: readonly Edge[]\n\t): string[] {\n\t\tconst earliest = new Map<string, number>();\n\t\tfor (const edge of edges) {\n\t\t\tif (!earliest.has(edge.from)) {\n\t\t\t\tearliest.set(edge.from, edge.createdAt);\n\t\t\t}\n\t\t}\n\t\tconst roots: string[] = [];\n\t\tfor (const node of nodes) {\n\t\t\tif (!hasIncoming.has(node)) roots.push(node);\n\t\t}\n\t\troots.sort((a, b) => (earliest.get(a) ?? Infinity) - (earliest.get(b) ?? Infinity));\n\t\treturn roots;\n\t}\n\n\t/**\n\t * BFS from a list of root ids, visiting each node at most once.\n\t */\n\tprivate _bfsFromRoots(sessionId: SessionId, roots: readonly string[]): readonly string[] {\n\t\tconst visited = new Set<string>();\n\t\tconst order: string[] = [];\n\t\tconst queue: string[] = [];\n\t\tfor (const root of roots) {\n\t\t\tif (visited.has(root)) continue;\n\t\t\tvisited.add(root);\n\t\t\torder.push(root);\n\t\t\tqueue.push(root);\n\t\t}\n\t\twhile (queue.length > 0) {\n\t\t\tconst node = queue.shift()!;\n\t\t\tfor (const edge of this._store.outgoing(sessionId, node as ThoughtId)) {\n\t\t\t\tif (visited.has(edge.to)) continue;\n\t\t\t\tvisited.add(edge.to);\n\t\t\t\torder.push(edge.to);\n\t\t\t\tqueue.push(edge.to);\n\t\t\t}\n\t\t}\n\t\treturn order;\n\t}\n\n\t/**\n\t * Build an in-degree map covering every node referenced by the edges.\n\t */\n\tprivate _buildInDegree(\n\t\tedges: readonly Edge[],\n\t\texplicitNodes: readonly ThoughtId[] = []\n\t): Map<string, number> {\n\t\tconst inDegree = new Map<string, number>();\n\t\tfor (const node of explicitNodes) inDegree.set(node, 0);\n\t\tfor (const edge of edges) {\n\t\t\tif (!inDegree.has(edge.from)) inDegree.set(edge.from, 0);\n\t\t\tinDegree.set(edge.to, (inDegree.get(edge.to) ?? 0) + 1);\n\t\t}\n\t\treturn inDegree;\n\t}\n\n\t/**\n\t * Generic BFS closure in either direction. Excludes the start node\n\t * from the result and respects an optional depth cap.\n\t */\n\tprivate _bfsClosure(\n\t\tsessionId: SessionId,\n\t\tstartId: string,\n\t\tmaxDepth: number | undefined,\n\t\tdirection: 'incoming' | 'outgoing'\n\t): readonly string[] {\n\t\tconst cap = maxDepth ?? Number.POSITIVE_INFINITY;\n\t\tconst visited = new Set<string>([startId]);\n\t\tconst order: string[] = [];\n\t\tlet frontier: string[] = [startId];\n\t\tlet depth = 0;\n\t\twhile (frontier.length > 0 && depth < cap) {\n\t\t\tconst next: string[] = [];\n\t\t\tfor (const node of frontier) {\n\t\t\t\tconst edges =\n\t\t\t\t\tdirection === 'outgoing'\n\t\t\t\t\t\t? this._store.outgoing(sessionId, node as ThoughtId)\n\t\t\t\t\t\t: this._store.incoming(sessionId, node as ThoughtId);\n\t\t\t\tfor (const edge of edges) {\n\t\t\t\t\tconst neighbour = direction === 'outgoing' ? edge.to : edge.from;\n\t\t\t\t\tif (visited.has(neighbour)) continue;\n\t\t\t\t\tvisited.add(neighbour);\n\t\t\t\t\torder.push(neighbour);\n\t\t\t\t\tnext.push(neighbour);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfrontier = next;\n\t\t\tdepth++;\n\t\t}\n\t\treturn order;\n\t}\n}\n"],"names":["GraphView","store","sessionId","edges","nodes","hasIncoming","roots","thoughtId","Set","outgoing","Map","edge","children","undefined","frontier","node","visited","depth","next","child","rootThoughtId","order","queue","current","out","inDegree","deg","CycleDetectedError","maxDepth","result","explicitNodes","earliest","a","b","Infinity","root","startId","direction","cap","Number","neighbour"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"core/graph/GraphView.js","sources":["../../../src/core/graph/GraphView.ts"],"sourcesContent":["/**\n * GraphView — read-only graph traversal queries over an {@link IEdgeStore}.\n *\n * Provides BFS / topological / ancestor / descendant queries over the\n * thought DAG. Queries return thought ids or graph distances,\n * never `ThoughtData` objects — the view is intentionally decoupled from\n * `HistoryManager` so it can be reused by strategies that work purely in\n * terms of graph structure.\n *\n * Construction is cheap (stores a reference to the underlying store).\n * Each query reads the latest store state — no caching, no snapshots.\n *\n * @module core/graph/GraphView\n */\n\nimport type { IGraphViewStore } from '../../contracts/interfaces.js';\nimport type { SessionId, ThoughtId } from '../../contracts/ids.js';\nimport { CycleDetectedError } from '../../errors.js';\nimport type { Edge, EdgeKind } from './Edge.js';\n\nexport interface GraphMetrics {\n\t/** Distinct visible edge endpoints and explicit nodes. */\n\treadonly node_count: number;\n\treadonly edge_count: number;\n\t/** Nodes with no incoming edge. */\n\treadonly root_count: number;\n\t/** Nodes with no outgoing edge. */\n\treadonly leaf_count: number;\n\t/** Longest path in edges; zero without edges, null when any cycle exists. */\n\treadonly longest_path: number | null;\n\t/** Maximum outgoing edge count; zero without edges. */\n\treadonly max_out_degree: number;\n\t/** Maximum incoming edge count; zero without edges. */\n\treadonly max_in_degree: number;\n\t/** Counts for all eight kinds, including absent kinds. */\n\treadonly edge_kind_counts: Readonly<Record<EdgeKind, number>>;\n\t/** Weakly connected components; zero for an empty graph. */\n\treadonly component_count: number;\n}\n\nexport interface GraphRelation {\n\treadonly id: ThoughtId;\n\treadonly kind: EdgeKind;\n}\n\n/**\n * Read-only traversal queries over an {@link IEdgeStore}.\n *\n * @example\n * ```typescript\n * const store = new EdgeStore();\n * // ... populate store ...\n * const view = new GraphView(store);\n * const order = view.topological('s1');\n * ```\n */\nexport class GraphView {\n\tprivate readonly _store: IGraphViewStore;\n\n\t/**\n\t * Create a new GraphView backed by the given edge store.\n\t *\n\t * @param store - The edge store to query (held by reference, read-only access)\n\t *\n\t * @example\n\t * ```typescript\n\t * const view = new GraphView(edgeStore);\n\t * ```\n\t */\n\tconstructor(store: IGraphViewStore) {\n\t\tthis._store = store;\n\t}\n\n\t/**\n\t * Return all thought ids in the session, ordered by BFS from roots.\n\t *\n\t * Roots are nodes with no incoming edges. Within a layer, neighbours\n\t * are visited in `outgoing` order (which the underlying store keeps\n\t * sorted by `createdAt` ascending).\n\t *\n\t * @param sessionId - Session to query\n\t * @returns Thought ids in chronological BFS order\n\t *\n\t * @example\n\t * ```typescript\n\t * const ids = view.chronological('s1');\n\t * ```\n\t */\n\tchronological(sessionId: SessionId): readonly ThoughtId[] {\n\t\tconst edges = this._store.edgesForSession(sessionId);\n\t\tconst { nodes, hasIncoming } = this._collectNodes(\n\t\t\tedges,\n\t\t\tthis._store.nodesForSession?.(sessionId)\n\t\t);\n\t\tif (nodes.size === 0) return [];\n\t\tconst roots = this._findRoots(nodes, hasIncoming, edges);\n\t\treturn this._bfsFromRoots(sessionId, roots) as readonly ThoughtId[];\n\t}\n\n\t/**\n\t * Return the shortest directed distance from any retained root to a thought.\n\t *\n\t * Nodes are derived from edges unless an immutable snapshot supplies original\n\t * endpoint nodes. Thoughts never referenced by an audit edge remain invisible.\n\t * Every edge kind participates in the traversal.\n\t *\n\t * @param sessionId - Session to query\n\t * @param thoughtId - Thought whose root distance to resolve\n\t * @returns Zero for a root, or `undefined` when no root can reach the thought\n\t */\n\tdepthFromRoots(sessionId: SessionId, thoughtId: ThoughtId): number | undefined {\n\t\tconst edges = this._store.edgesForSession(sessionId);\n\t\tconst nodes = new Set<ThoughtId>(this._store.nodesForSession?.(sessionId) ?? []);\n\t\tconst hasIncoming = new Set<ThoughtId>();\n\t\tconst outgoing = new Map<ThoughtId, ThoughtId[]>();\n\t\tfor (const edge of edges) {\n\t\t\tnodes.add(edge.from);\n\t\t\tnodes.add(edge.to);\n\t\t\thasIncoming.add(edge.to);\n\t\t\tconst children = outgoing.get(edge.from);\n\t\t\tif (children === undefined) outgoing.set(edge.from, [edge.to]);\n\t\t\telse children.push(edge.to);\n\t\t}\n\t\tif (!nodes.has(thoughtId)) return undefined;\n\n\t\tlet frontier: ThoughtId[] = [];\n\t\tfor (const node of nodes) {\n\t\t\tif (!hasIncoming.has(node)) frontier.push(node);\n\t\t}\n\t\tconst visited = new Set<ThoughtId>(frontier);\n\t\tlet depth = 0;\n\t\twhile (frontier.length > 0) {\n\t\t\tconst next: ThoughtId[] = [];\n\t\t\tfor (const node of frontier) {\n\t\t\t\tif (node === thoughtId) return depth;\n\t\t\t\tfor (const child of outgoing.get(node) ?? []) {\n\t\t\t\t\tif (visited.has(child)) continue;\n\t\t\t\t\tvisited.add(child);\n\t\t\t\t\tnext.push(child);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfrontier = next;\n\t\t\tdepth++;\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Return all thought ids reachable from `rootThoughtId` via `'branch'`\n\t * edges, including the root itself.\n\t *\n\t * Non-branch edges are ignored. Cycles (if any) do not cause infinite\n\t * loops because each node is visited at most once.\n\t *\n\t * @param sessionId - Session to query\n\t * @param rootThoughtId - The starting thought id (typically the branch root)\n\t * @returns Thought ids forming the branch (includes root)\n\t *\n\t * @example\n\t * ```typescript\n\t * const branchIds = view.branchThoughts('s1', 'thought-root');\n\t * ```\n\t */\n\tbranchThoughts(sessionId: SessionId, rootThoughtId: ThoughtId): readonly ThoughtId[] {\n\t\tconst visited = new Set<string>([rootThoughtId]);\n\t\tconst order: string[] = [rootThoughtId];\n\t\tconst queue: string[] = [rootThoughtId];\n\t\tlet head = 0;\n\t\twhile (head < queue.length) {\n\t\t\tconst current = queue[head++]!;\n\t\t\tconst out = this._store.outgoing(sessionId, current as ThoughtId);\n\t\t\tfor (const edge of out) {\n\t\t\t\tif (edge.kind !== 'branch') continue;\n\t\t\t\tif (visited.has(edge.to)) continue;\n\t\t\t\tvisited.add(edge.to);\n\t\t\t\torder.push(edge.to);\n\t\t\t\tqueue.push(edge.to);\n\t\t\t}\n\t\t}\n\t\treturn order as ThoughtId[];\n\t}\n\n\t/**\n\t * Return a topological ordering of all thought ids in the session\n\t * using Kahn's algorithm.\n\t *\n\t * @param sessionId - Session to query\n\t * @returns Thought ids in topological order\n\t * @throws {CycleDetectedError} If the graph contains a cycle\n\t *\n\t * @example\n\t * ```typescript\n\t * const order = view.topological('s1');\n\t * ```\n\t */\n\ttopological(sessionId: SessionId): readonly ThoughtId[] {\n\t\tconst edges = this._store.edgesForSession(sessionId);\n\t\tconst inDegree = this._buildInDegree(edges, this._store.nodesForSession?.(sessionId));\n\t\tif (inDegree.size === 0) return [];\n\t\tconst queue: string[] = [];\n\t\tfor (const [node, deg] of inDegree) {\n\t\t\tif (deg === 0) queue.push(node);\n\t\t}\n\t\tconst order: string[] = [];\n\t\tlet head = 0;\n\t\twhile (head < queue.length) {\n\t\t\tconst node = queue[head++]!;\n\t\t\torder.push(node);\n\t\t\tfor (const edge of this._store.outgoing(sessionId, node as ThoughtId)) {\n\t\t\t\tconst next = (inDegree.get(edge.to) ?? 0) - 1;\n\t\t\t\tinDegree.set(edge.to, next);\n\t\t\t\tif (next === 0) queue.push(edge.to);\n\t\t\t}\n\t\t}\n\t\tif (order.length !== inDegree.size) {\n\t\t\tthrow new CycleDetectedError(\n\t\t\t\t`Cycle detected in session '${sessionId}': topological sort incomplete (${order.length}/${inDegree.size})`\n\t\t\t);\n\t\t}\n\t\treturn order as ThoughtId[];\n\t}\n\n\t/**\n\t * Return all ancestors of `thoughtId` via incoming-edge BFS.\n\t *\n\t * The starting node is NOT included. Cycles do not cause infinite loops.\n\t *\n\t * @param sessionId - Session to query\n\t * @param thoughtId - The thought to traverse from\n\t * @param maxDepth - Optional maximum traversal depth (1 = direct parents only)\n\t * @param kinds - Optional edge kinds to follow; empty follows all kinds\n\t * @returns Ancestor thought ids in BFS order\n\t *\n\t * @example\n\t * ```typescript\n\t * const parents = view.ancestors('s1', 'thought-id', 1);\n\t * ```\n\t */\n\tancestors(\n\t\tsessionId: SessionId,\n\t\tthoughtId: ThoughtId,\n\t\tmaxDepth?: number,\n\t\tkinds?: readonly EdgeKind[]\n\t): readonly ThoughtId[] {\n\t\treturn this._bfsClosure(\n\t\t\tsessionId,\n\t\t\tthoughtId,\n\t\t\tmaxDepth,\n\t\t\t'incoming',\n\t\t\tkinds\n\t\t) as readonly ThoughtId[];\n\t}\n\n\t/**\n\t * Return all descendants of `thoughtId` via outgoing-edge BFS.\n\t *\n\t * The starting node is NOT included. Cycles do not cause infinite loops.\n\t *\n\t * @param sessionId - Session to query\n\t * @param thoughtId - The thought to traverse from\n\t * @param maxDepth - Optional maximum traversal depth (1 = direct children only)\n\t * @param kinds - Optional edge kinds to follow; empty follows all kinds\n\t * @returns Descendant thought ids in BFS order\n\t *\n\t * @example\n\t * ```typescript\n\t * const children = view.descendants('s1', 'thought-id');\n\t * ```\n\t */\n\tdescendants(\n\t\tsessionId: SessionId,\n\t\tthoughtId: ThoughtId,\n\t\tmaxDepth?: number,\n\t\tkinds?: readonly EdgeKind[]\n\t): readonly ThoughtId[] {\n\t\treturn this._bfsClosure(\n\t\t\tsessionId,\n\t\t\tthoughtId,\n\t\t\tmaxDepth,\n\t\t\t'outgoing',\n\t\t\tkinds\n\t\t) as readonly ThoughtId[];\n\t}\n\n\t/**\n\t * Return incoming relations in store order.\n\t * @param sessionId - Session to query\n\t * @param thoughtId - Thought whose incoming edges to list\n\t * @returns Source ids and edge kinds, or an empty array for an unknown node\n\t */\n\tinbound(sessionId: SessionId, thoughtId: ThoughtId): readonly GraphRelation[] {\n\t\treturn this._store.incoming(sessionId, thoughtId).map((edge) => ({\n\t\t\tid: edge.from,\n\t\t\tkind: edge.kind,\n\t\t}));\n\t}\n\n\t/**\n\t * Return outgoing relations in store order.\n\t * @param sessionId - Session to query\n\t * @param thoughtId - Thought whose outgoing edges to list\n\t * @returns Target ids and edge kinds, or an empty array for an unknown node\n\t */\n\toutbound(sessionId: SessionId, thoughtId: ThoughtId): readonly GraphRelation[] {\n\t\treturn this._store.outgoing(sessionId, thoughtId).map((edge) => ({\n\t\t\tid: edge.to,\n\t\t\tkind: edge.kind,\n\t\t}));\n\t}\n\n\t/**\n\t * Test reachability by one or more directed edges, including cycles.\n\t * @param sessionId - Session to query\n\t * @param from - Starting thought id\n\t * @param to - Target thought id\n\t * @param kinds - Optional edge kinds to follow; empty follows all kinds\n\t * @returns Whether a nonempty directed path reaches the target\n\t */\n\thasPath(\n\t\tsessionId: SessionId,\n\t\tfrom: ThoughtId,\n\t\tto: ThoughtId,\n\t\tkinds?: readonly EdgeKind[]\n\t): boolean {\n\t\tconst allowed = kinds?.length ? new Set(kinds) : undefined;\n\t\tconst visited = new Set<ThoughtId>([from]);\n\t\tconst queue: ThoughtId[] = [from];\n\t\tfor (const node of queue) {\n\t\t\tfor (const edge of this._store.outgoing(sessionId, node)) {\n\t\t\t\tif (allowed !== undefined && !allowed.has(edge.kind)) continue;\n\t\t\t\tif (edge.to === to) return true;\n\t\t\t\tif (visited.has(edge.to)) continue;\n\t\t\t\tvisited.add(edge.to);\n\t\t\t\tqueue.push(edge.to);\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Compute structural metrics over every visible node and edge kind.\n\t * @param sessionId - Session to query\n\t * @returns Counts and longest path length, with null longest_path on cycles\n\t */\n\tmetrics(sessionId: SessionId): GraphMetrics {\n\t\tconst edges = this._store.edgesForSession(sessionId);\n\t\tconst explicitNodes = this._store.nodesForSession?.(sessionId);\n\t\tconst { nodes, hasIncoming } = this._collectNodes(edges, explicitNodes);\n\t\tconst inDegree = this._buildInDegree(edges, explicitNodes);\n\t\tconst outDegree = new Map<string, number>();\n\t\tlet maxIn = 0;\n\t\tlet maxOut = 0;\n\t\tfor (const edge of edges) {\n\t\t\tconst degree = (outDegree.get(edge.from) ?? 0) + 1;\n\t\t\toutDegree.set(edge.from, degree);\n\t\t\tmaxOut = Math.max(maxOut, degree);\n\t\t}\n\t\tfor (const degree of inDegree.values()) maxIn = Math.max(maxIn, degree);\n\t\treturn {\n\t\t\tnode_count: nodes.size,\n\t\t\tedge_count: edges.length,\n\t\t\troot_count: nodes.size - hasIncoming.size,\n\t\t\tleaf_count: nodes.size - outDegree.size,\n\t\t\tlongest_path: this._longestPath(sessionId, inDegree),\n\t\t\tmax_out_degree: maxOut,\n\t\t\tmax_in_degree: maxIn,\n\t\t\tedge_kind_counts: this._edgeKindCounts(edges),\n\t\t\tcomponent_count: this._componentCount(nodes, edges),\n\t\t};\n\t}\n\n\tprivate _edgeKindCounts(edges: readonly Edge[]): Record<EdgeKind, number> {\n\t\tconst counts: Record<EdgeKind, number> = {\n\t\t\tsequence: 0,\n\t\t\tbranch: 0,\n\t\t\tmerge: 0,\n\t\t\tverifies: 0,\n\t\t\tcritiques: 0,\n\t\t\tderives_from: 0,\n\t\t\ttool_invocation: 0,\n\t\t\trevises: 0,\n\t\t};\n\t\tfor (const edge of edges) counts[edge.kind]++;\n\t\treturn counts;\n\t}\n\n\tprivate _longestPath(sessionId: SessionId, inDegree: Map<string, number>): number | null {\n\t\tconst queue: string[] = [];\n\t\tconst distances = new Map<string, number>();\n\t\tfor (const [node, degree] of inDegree) {\n\t\t\tif (degree === 0) queue.push(node);\n\t\t}\n\t\tlet longest = 0;\n\t\tlet head = 0;\n\t\twhile (head < queue.length) {\n\t\t\tconst node = queue[head++]!;\n\t\t\tconst distance = distances.get(node) ?? 0;\n\t\t\tlongest = Math.max(longest, distance);\n\t\t\tfor (const edge of this._store.outgoing(sessionId, node as ThoughtId)) {\n\t\t\t\tdistances.set(edge.to, Math.max(distances.get(edge.to) ?? 0, distance + 1));\n\t\t\t\tconst degree = (inDegree.get(edge.to) ?? 0) - 1;\n\t\t\t\tinDegree.set(edge.to, degree);\n\t\t\t\tif (degree === 0) queue.push(edge.to);\n\t\t\t}\n\t\t}\n\t\treturn head === inDegree.size ? longest : null;\n\t}\n\n\tprivate _componentCount(nodes: ReadonlySet<string>, edges: readonly Edge[]): number {\n\t\tconst neighbours = new Map<string, string[]>();\n\t\tfor (const node of nodes) neighbours.set(node, []);\n\t\tfor (const edge of edges) {\n\t\t\tneighbours.get(edge.from)?.push(edge.to);\n\t\t\tneighbours.get(edge.to)?.push(edge.from);\n\t\t}\n\t\tconst visited = new Set<string>();\n\t\tlet count = 0;\n\t\tfor (const node of nodes) {\n\t\t\tif (visited.has(node)) continue;\n\t\t\tcount++;\n\t\t\tvisited.add(node);\n\t\t\tconst queue = [node];\n\t\t\tfor (const current of queue) {\n\t\t\t\tfor (const neighbour of neighbours.get(current) ?? []) {\n\t\t\t\t\tif (visited.has(neighbour)) continue;\n\t\t\t\t\tvisited.add(neighbour);\n\t\t\t\t\tqueue.push(neighbour);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn count;\n\t}\n\n\t/**\n\t * Return all thought ids in the session that have no outgoing edges.\n\t *\n\t * @param sessionId - Session to query\n\t * @returns Thought ids that are graph leaves\n\t *\n\t * @example\n\t * ```typescript\n\t * const tips = view.leaves('s1');\n\t * ```\n\t */\n\tleaves(sessionId: SessionId): readonly ThoughtId[] {\n\t\tconst edges = this._store.edgesForSession(sessionId);\n\t\tconst { nodes } = this._collectNodes(edges, this._store.nodesForSession?.(sessionId));\n\t\tif (nodes.size === 0) return [];\n\t\tconst result: string[] = [];\n\t\tfor (const node of nodes) {\n\t\t\tif (this._store.outgoing(sessionId, node as ThoughtId).length === 0) {\n\t\t\t\tresult.push(node);\n\t\t\t}\n\t\t}\n\t\treturn result as ThoughtId[];\n\t}\n\n\t/**\n\t * Collect every node id referenced by the edges and a set of nodes\n\t * that have at least one incoming edge.\n\t */\n\tprivate _collectNodes(\n\t\tedges: readonly Edge[],\n\t\texplicitNodes: readonly ThoughtId[] = []\n\t): {\n\t\tnodes: Set<string>;\n\t\thasIncoming: Set<string>;\n\t} {\n\t\tconst nodes = new Set<string>(explicitNodes);\n\t\tconst hasIncoming = new Set<string>();\n\t\tfor (const edge of edges) {\n\t\t\tnodes.add(edge.from);\n\t\t\tnodes.add(edge.to);\n\t\t\thasIncoming.add(edge.to);\n\t\t}\n\t\treturn { nodes, hasIncoming };\n\t}\n\n\t/**\n\t * Find roots (no incoming) ordered by the earliest outgoing edge\n\t * `createdAt`. Nodes with no outgoing edges fall back to the order\n\t * they appear among edges (already sorted by `createdAt`).\n\t */\n\tprivate _findRoots(\n\t\tnodes: Set<string>,\n\t\thasIncoming: Set<string>,\n\t\tedges: readonly Edge[]\n\t): string[] {\n\t\tconst earliest = new Map<string, number>();\n\t\tfor (const edge of edges) {\n\t\t\tif (!earliest.has(edge.from)) {\n\t\t\t\tearliest.set(edge.from, edge.createdAt);\n\t\t\t}\n\t\t}\n\t\tconst roots: string[] = [];\n\t\tfor (const node of nodes) {\n\t\t\tif (!hasIncoming.has(node)) roots.push(node);\n\t\t}\n\t\troots.sort((a, b) => (earliest.get(a) ?? Infinity) - (earliest.get(b) ?? Infinity));\n\t\treturn roots;\n\t}\n\n\t/**\n\t * BFS from a list of root ids, visiting each node at most once.\n\t */\n\tprivate _bfsFromRoots(sessionId: SessionId, roots: readonly string[]): readonly string[] {\n\t\tconst visited = new Set<string>();\n\t\tconst order: string[] = [];\n\t\tconst queue: string[] = [];\n\t\tfor (const root of roots) {\n\t\t\tif (visited.has(root)) continue;\n\t\t\tvisited.add(root);\n\t\t\torder.push(root);\n\t\t\tqueue.push(root);\n\t\t}\n\t\tlet head = 0;\n\t\twhile (head < queue.length) {\n\t\t\tconst node = queue[head++]!;\n\t\t\tfor (const edge of this._store.outgoing(sessionId, node as ThoughtId)) {\n\t\t\t\tif (visited.has(edge.to)) continue;\n\t\t\t\tvisited.add(edge.to);\n\t\t\t\torder.push(edge.to);\n\t\t\t\tqueue.push(edge.to);\n\t\t\t}\n\t\t}\n\t\treturn order;\n\t}\n\n\t/**\n\t * Build an in-degree map covering every node referenced by the edges.\n\t */\n\tprivate _buildInDegree(\n\t\tedges: readonly Edge[],\n\t\texplicitNodes: readonly ThoughtId[] = []\n\t): Map<string, number> {\n\t\tconst inDegree = new Map<string, number>();\n\t\tfor (const node of explicitNodes) inDegree.set(node, 0);\n\t\tfor (const edge of edges) {\n\t\t\tif (!inDegree.has(edge.from)) inDegree.set(edge.from, 0);\n\t\t\tinDegree.set(edge.to, (inDegree.get(edge.to) ?? 0) + 1);\n\t\t}\n\t\treturn inDegree;\n\t}\n\n\t/**\n\t * Generic BFS closure in either direction. Excludes the start node\n\t * from the result and respects an optional depth cap.\n\t */\n\tprivate _bfsClosure(\n\t\tsessionId: SessionId,\n\t\tstartId: string,\n\t\tmaxDepth: number | undefined,\n\t\tdirection: 'incoming' | 'outgoing',\n\t\tkinds?: readonly EdgeKind[]\n\t): readonly string[] {\n\t\tconst allowed = kinds?.length ? new Set(kinds) : undefined;\n\t\tconst cap = maxDepth ?? Number.POSITIVE_INFINITY;\n\t\tconst visited = new Set<string>([startId]);\n\t\tconst order: string[] = [];\n\t\tlet frontier: string[] = [startId];\n\t\tlet depth = 0;\n\t\twhile (frontier.length > 0 && depth < cap) {\n\t\t\tconst next: string[] = [];\n\t\t\tfor (const node of frontier) {\n\t\t\t\tconst edges =\n\t\t\t\t\tdirection === 'outgoing'\n\t\t\t\t\t\t? this._store.outgoing(sessionId, node as ThoughtId)\n\t\t\t\t\t\t: this._store.incoming(sessionId, node as ThoughtId);\n\t\t\t\tfor (const edge of edges) {\n\t\t\t\t\tif (allowed !== undefined && !allowed.has(edge.kind)) continue;\n\t\t\t\t\tconst neighbour = direction === 'outgoing' ? edge.to : edge.from;\n\t\t\t\t\tif (visited.has(neighbour)) continue;\n\t\t\t\t\tvisited.add(neighbour);\n\t\t\t\t\torder.push(neighbour);\n\t\t\t\t\tnext.push(neighbour);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfrontier = next;\n\t\t\tdepth++;\n\t\t}\n\t\treturn order;\n\t}\n}\n"],"names":["GraphView","store","sessionId","edges","nodes","hasIncoming","roots","thoughtId","Set","outgoing","Map","edge","children","undefined","frontier","node","visited","depth","next","child","rootThoughtId","order","queue","head","current","out","inDegree","deg","CycleDetectedError","maxDepth","kinds","from","to","allowed","explicitNodes","outDegree","maxIn","maxOut","degree","Math","counts","distances","longest","distance","neighbours","count","neighbour","result","earliest","a","b","Infinity","root","startId","direction","cap","Number"],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GraphContext — describe a thought's position in the active-evidence graph.
|
|
3
|
+
* @module core/reasoning/GraphContext
|
|
4
|
+
*/
|
|
5
|
+
import type { SessionId } from '../../contracts/ids.js';
|
|
6
|
+
import type { ActiveEvidenceProjection } from '../../contracts/strategy.js';
|
|
7
|
+
import type { EdgeKind } from '../graph/Edge.js';
|
|
8
|
+
import type { ThoughtData } from '../thought.js';
|
|
9
|
+
export interface GraphNeighbour {
|
|
10
|
+
readonly thought_number: number;
|
|
11
|
+
readonly kind: EdgeKind;
|
|
12
|
+
readonly branch_id?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface GraphContext {
|
|
15
|
+
/** Shortest directed distance from a root; null when no root reaches the thought. */
|
|
16
|
+
readonly root_distance: number | null;
|
|
17
|
+
/** Distinct thoughts this thought transitively rests on (all edge kinds, incoming BFS). */
|
|
18
|
+
readonly ancestor_count: number;
|
|
19
|
+
/** Incoming edges (neighbour -> this thought), store order. */
|
|
20
|
+
readonly inbound: readonly GraphNeighbour[];
|
|
21
|
+
/** Outgoing edges (this thought -> neighbour), store order. */
|
|
22
|
+
readonly outbound: readonly GraphNeighbour[];
|
|
23
|
+
}
|
|
24
|
+
export declare function buildGraphContext(sessionId: SessionId, thought: ThoughtData, evidence: ActiveEvidenceProjection): GraphContext | undefined;
|
|
25
|
+
//# sourceMappingURL=GraphContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GraphContext.d.ts","sourceRoot":"","sources":["../../../src/core/reasoning/GraphContext.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAa,MAAM,wBAAwB,CAAC;AACnE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,YAAY;IAC5B,qFAAqF;IACrF,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,2FAA2F;IAC3F,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,CAAC;IAC5C,+DAA+D;IAC/D,QAAQ,CAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,CAAC;CAC7C;AAED,wBAAgB,iBAAiB,CAChC,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,wBAAwB,GAChC,YAAY,GAAG,SAAS,CAiB1B"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
function buildGraphContext(sessionId, thought, evidence) {
|
|
2
|
+
const graph = evidence.graph;
|
|
3
|
+
if (void 0 === graph || void 0 === thought.id) return;
|
|
4
|
+
const inbound = graph.inbound(sessionId, thought.id);
|
|
5
|
+
const outbound = graph.outbound(sessionId, thought.id);
|
|
6
|
+
if (0 === inbound.length && 0 === outbound.length) return;
|
|
7
|
+
const thoughts = new Map();
|
|
8
|
+
for (const activeThought of evidence.activeThoughts)if (void 0 !== activeThought.id) thoughts.set(activeThought.id, activeThought);
|
|
9
|
+
return {
|
|
10
|
+
root_distance: graph.depthFromRoots(sessionId, thought.id) ?? null,
|
|
11
|
+
ancestor_count: graph.ancestors(sessionId, thought.id).length,
|
|
12
|
+
inbound: mapNeighbours(inbound, thoughts),
|
|
13
|
+
outbound: mapNeighbours(outbound, thoughts)
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function mapNeighbours(relations, thoughts) {
|
|
17
|
+
return relations.flatMap(({ id, kind })=>{
|
|
18
|
+
const neighbour = thoughts.get(id);
|
|
19
|
+
return void 0 === neighbour ? [] : [
|
|
20
|
+
{
|
|
21
|
+
thought_number: neighbour.thought_number,
|
|
22
|
+
kind,
|
|
23
|
+
...void 0 === neighbour.branch_id ? {} : {
|
|
24
|
+
branch_id: neighbour.branch_id
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
];
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
export { buildGraphContext };
|
|
31
|
+
|
|
32
|
+
//# sourceMappingURL=GraphContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core/reasoning/GraphContext.js","sources":["../../../src/core/reasoning/GraphContext.ts"],"sourcesContent":["/**\n * GraphContext — describe a thought's position in the active-evidence graph.\n * @module core/reasoning/GraphContext\n */\n\nimport type { SessionId, ThoughtId } from '../../contracts/ids.js';\nimport type { ActiveEvidenceProjection } from '../../contracts/strategy.js';\nimport type { EdgeKind } from '../graph/Edge.js';\nimport type { GraphRelation } from '../graph/GraphView.js';\nimport type { ThoughtData } from '../thought.js';\n\nexport interface GraphNeighbour {\n\treadonly thought_number: number;\n\treadonly kind: EdgeKind;\n\treadonly branch_id?: string;\n}\n\nexport interface GraphContext {\n\t/** Shortest directed distance from a root; null when no root reaches the thought. */\n\treadonly root_distance: number | null;\n\t/** Distinct thoughts this thought transitively rests on (all edge kinds, incoming BFS). */\n\treadonly ancestor_count: number;\n\t/** Incoming edges (neighbour -> this thought), store order. */\n\treadonly inbound: readonly GraphNeighbour[];\n\t/** Outgoing edges (this thought -> neighbour), store order. */\n\treadonly outbound: readonly GraphNeighbour[];\n}\n\nexport function buildGraphContext(\n\tsessionId: SessionId,\n\tthought: ThoughtData,\n\tevidence: ActiveEvidenceProjection\n): GraphContext | undefined {\n\tconst graph = evidence.graph;\n\tif (graph === undefined || thought.id === undefined) return undefined;\n\tconst inbound = graph.inbound(sessionId, thought.id);\n\tconst outbound = graph.outbound(sessionId, thought.id);\n\tif (inbound.length === 0 && outbound.length === 0) return undefined;\n\n\tconst thoughts = new Map<ThoughtId, ThoughtData>();\n\tfor (const activeThought of evidence.activeThoughts) {\n\t\tif (activeThought.id !== undefined) thoughts.set(activeThought.id, activeThought);\n\t}\n\treturn {\n\t\troot_distance: graph.depthFromRoots(sessionId, thought.id) ?? null,\n\t\tancestor_count: graph.ancestors(sessionId, thought.id).length,\n\t\tinbound: mapNeighbours(inbound, thoughts),\n\t\toutbound: mapNeighbours(outbound, thoughts),\n\t};\n}\n\nfunction mapNeighbours(\n\trelations: readonly GraphRelation[],\n\tthoughts: ReadonlyMap<ThoughtId, ThoughtData>\n): readonly GraphNeighbour[] {\n\treturn relations.flatMap(({ id, kind }) => {\n\t\tconst neighbour = thoughts.get(id);\n\t\treturn neighbour === undefined\n\t\t\t? []\n\t\t\t: [\n\t\t\t\t\t{\n\t\t\t\t\t\tthought_number: neighbour.thought_number,\n\t\t\t\t\t\tkind,\n\t\t\t\t\t\t...(neighbour.branch_id === undefined ? {} : { branch_id: neighbour.branch_id }),\n\t\t\t\t\t},\n\t\t\t\t];\n\t});\n}\n"],"names":["buildGraphContext","sessionId","thought","evidence","graph","undefined","inbound","outbound","thoughts","Map","activeThought","mapNeighbours","relations","id","kind","neighbour"],"mappings":"AA4BO,SAASA,kBACfC,SAAoB,EACpBC,OAAoB,EACpBC,QAAkC;IAElC,MAAMC,QAAQD,SAAS,KAAK;IAC5B,IAAIC,AAAUC,WAAVD,SAAuBF,AAAeG,WAAfH,QAAQ,EAAE,EAAgB;IACrD,MAAMI,UAAUF,MAAM,OAAO,CAACH,WAAWC,QAAQ,EAAE;IACnD,MAAMK,WAAWH,MAAM,QAAQ,CAACH,WAAWC,QAAQ,EAAE;IACrD,IAAII,AAAmB,MAAnBA,QAAQ,MAAM,IAAUC,AAAoB,MAApBA,SAAS,MAAM,EAAQ;IAEnD,MAAMC,WAAW,IAAIC;IACrB,KAAK,MAAMC,iBAAiBP,SAAS,cAAc,CAClD,IAAIO,AAAqBL,WAArBK,cAAc,EAAE,EAAgBF,SAAS,GAAG,CAACE,cAAc,EAAE,EAAEA;IAEpE,OAAO;QACN,eAAeN,MAAM,cAAc,CAACH,WAAWC,QAAQ,EAAE,KAAK;QAC9D,gBAAgBE,MAAM,SAAS,CAACH,WAAWC,QAAQ,EAAE,EAAE,MAAM;QAC7D,SAASS,cAAcL,SAASE;QAChC,UAAUG,cAAcJ,UAAUC;IACnC;AACD;AAEA,SAASG,cACRC,SAAmC,EACnCJ,QAA6C;IAE7C,OAAOI,UAAU,OAAO,CAAC,CAAC,EAAEC,EAAE,EAAEC,IAAI,EAAE;QACrC,MAAMC,YAAYP,SAAS,GAAG,CAACK;QAC/B,OAAOE,AAAcV,WAAdU,YACJ,EAAE,GACF;YACA;gBACC,gBAAgBA,UAAU,cAAc;gBACxCD;gBACA,GAAIC,AAAwBV,WAAxBU,UAAU,SAAS,GAAiB,CAAC,IAAI;oBAAE,WAAWA,UAAU,SAAS;gBAAC,CAAC;YAChF;SACA;IACJ;AACD"}
|
package/dist/core/reasoning.d.ts
CHANGED
|
@@ -8,6 +8,14 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import type { CalibrationMetrics } from '../contracts/calibrator.js';
|
|
10
10
|
import type { PatternName, ThoughtType } from '../contracts/reasoning-types.js';
|
|
11
|
+
import type { GraphMetrics } from './graph/GraphView.js';
|
|
12
|
+
/** DAG topology plus derived measures of branching and explicit relations. */
|
|
13
|
+
export interface GraphSignals extends GraphMetrics {
|
|
14
|
+
/** Mean out-degree over nodes with at least one outgoing edge. */
|
|
15
|
+
readonly branching_factor: number;
|
|
16
|
+
/** Share of edges with a kind other than sequence, in [0, 1]. */
|
|
17
|
+
readonly relational_density: number;
|
|
18
|
+
}
|
|
11
19
|
/**
|
|
12
20
|
* A detected reasoning pattern — surfaced as metadata or a warning.
|
|
13
21
|
*
|
|
@@ -66,6 +74,8 @@ export interface PatternSignal {
|
|
|
66
74
|
* ```
|
|
67
75
|
*/
|
|
68
76
|
export interface ConfidenceSignals {
|
|
77
|
+
/** Present only when an active graph with at least one edge is supplied. */
|
|
78
|
+
readonly graph_signals?: GraphSignals;
|
|
69
79
|
/** Length of thought chain to this point. */
|
|
70
80
|
readonly reasoning_depth: number;
|
|
71
81
|
/** How many revisions in this chain. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reasoning.d.ts","sourceRoot":"","sources":["../../src/core/reasoning.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"reasoning.d.ts","sourceRoot":"","sources":["../../src/core/reasoning.ts"],"names":[],"mappings":"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"}
|
package/dist/lib.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { EventEmitter } from 'node:events';
|
|
2
2
|
import type * as v from 'valibot';
|
|
3
3
|
import type { ThoughtData } from './core/thought.js';
|
|
4
|
-
import {
|
|
4
|
+
import type { BranchId, SessionId, ThoughtId } from './contracts/ids.js';
|
|
5
|
+
import type { Edge } from './core/graph/Edge.js';
|
|
6
|
+
import type { Summary } from './core/compression/Summary.js';
|
|
5
7
|
import type { SequentialThinkingSchema } from './schema.js';
|
|
6
8
|
import type { IDisposable } from './types/disposable.js';
|
|
7
9
|
import type { ConfigFileOptions } from './config/ConfigLoader.js';
|
|
@@ -9,6 +11,7 @@ import { HistoryManager } from './core/HistoryManager.js';
|
|
|
9
11
|
import { type CallToolResult } from './core/ThoughtProcessor.js';
|
|
10
12
|
import { Container } from './di/Container.js';
|
|
11
13
|
import { StructuredLogger } from './logger/StructuredLogger.js';
|
|
14
|
+
import type { PersistenceBackend } from './contracts/PersistenceBackend.js';
|
|
12
15
|
import { SkillRegistry } from './registry/SkillRegistry.js';
|
|
13
16
|
import { ToolRegistry } from './registry/ToolRegistry.js';
|
|
14
17
|
import { ServerConfig } from './ServerConfig.js';
|
|
@@ -17,7 +20,7 @@ import type { HttpTransportOptions } from './transport/HttpTransport.js';
|
|
|
17
20
|
import type { TransportOptions } from './transport/BaseTransport.js';
|
|
18
21
|
import type { ITransport, TransportKind } from './contracts/transport.js';
|
|
19
22
|
export { HttpTransport, createHttpTransport };
|
|
20
|
-
export type { HttpTransportOptions, TransportOptions, ITransport, TransportKind };
|
|
23
|
+
export type { HttpTransportOptions, TransportOptions, ITransport, TransportKind, PersistenceBackend, ThoughtData, Edge, Summary, SessionId, ThoughtId, BranchId, };
|
|
21
24
|
export interface ServerOptions {
|
|
22
25
|
maxHistorySize?: number;
|
|
23
26
|
maxBranches?: number;
|
|
@@ -27,6 +30,12 @@ export interface ServerOptions {
|
|
|
27
30
|
config?: ServerConfig;
|
|
28
31
|
fileConfig?: ConfigFileOptions;
|
|
29
32
|
container?: Container;
|
|
33
|
+
/**
|
|
34
|
+
* Use this backend instead of the configured persistence factory.
|
|
35
|
+
* The caller owns and closes it; the server only drains its buffered writes.
|
|
36
|
+
* @default undefined
|
|
37
|
+
*/
|
|
38
|
+
persistenceBackend?: PersistenceBackend;
|
|
30
39
|
/**
|
|
31
40
|
* Enable automatic tool and skill discovery on server startup.
|
|
32
41
|
* @default true
|
|
@@ -139,6 +148,7 @@ export declare class ToolAwareSequentialThinkingServer extends EventEmitter impl
|
|
|
139
148
|
emit<K extends keyof ServerEvents>(event: K, payload: ServerEvents[K]): boolean;
|
|
140
149
|
on<K extends keyof ServerEvents>(event: K, listener: (payload: ServerEvents[K]) => void): this;
|
|
141
150
|
private _container;
|
|
151
|
+
private readonly _borrowedPersistence;
|
|
142
152
|
private _logger;
|
|
143
153
|
private _historyManager;
|
|
144
154
|
private _thoughtProcessor;
|
package/dist/lib.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,KAAK,CAAC,MAAM,SAAS,CAAC;AAClC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"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"}
|
package/dist/lib.js
CHANGED
|
@@ -28,6 +28,9 @@ import { ToolRegistry } from "./registry/ToolRegistry.js";
|
|
|
28
28
|
import { ServerConfig } from "./ServerConfig.js";
|
|
29
29
|
import { SkillWatcher } from "./watchers/SkillWatcher.js";
|
|
30
30
|
import { ToolWatcher } from "./watchers/ToolWatcher.js";
|
|
31
|
+
async function closeOwnedPersistence(persistence, borrowed) {
|
|
32
|
+
if (null !== persistence && persistence !== borrowed) await persistence.close();
|
|
33
|
+
}
|
|
31
34
|
function appendCleanupFailure(failures, failure) {
|
|
32
35
|
if (failure instanceof AggregateError) return void failures.push(...failure.errors);
|
|
33
36
|
failures.push(failure);
|
|
@@ -68,7 +71,7 @@ class ToolAwareSequentialThinkingServer extends EventEmitter {
|
|
|
68
71
|
()=>{
|
|
69
72
|
if (container.has('suspensionStore')) container.resolve('suspensionStore').stop();
|
|
70
73
|
},
|
|
71
|
-
()=>container.resolve('Persistence')
|
|
74
|
+
()=>closeOwnedPersistence(container.resolve('Persistence'), options.persistenceBackend ?? null),
|
|
72
75
|
()=>container.dispose()
|
|
73
76
|
]);
|
|
74
77
|
if (cleanupFailures.length > 0) throw new AggregateError([
|
|
@@ -87,6 +90,7 @@ class ToolAwareSequentialThinkingServer extends EventEmitter {
|
|
|
87
90
|
return super.on(event, listener);
|
|
88
91
|
}
|
|
89
92
|
_container;
|
|
93
|
+
_borrowedPersistence;
|
|
90
94
|
_logger;
|
|
91
95
|
_historyManager;
|
|
92
96
|
_thoughtProcessor;
|
|
@@ -106,6 +110,7 @@ class ToolAwareSequentialThinkingServer extends EventEmitter {
|
|
|
106
110
|
super();
|
|
107
111
|
if (!options.container) throw new Error('Container is required. Use createServer() or provide a container.');
|
|
108
112
|
this._container = options.container;
|
|
113
|
+
this._borrowedPersistence = options.persistenceBackend ?? null;
|
|
109
114
|
this._logger = this._container.resolve('Logger');
|
|
110
115
|
this._historyManager = this._container.resolve('HistoryManager');
|
|
111
116
|
this._historyManager.bindShutdownOwner(()=>this.stop());
|
|
@@ -270,7 +275,7 @@ class ToolAwareSequentialThinkingServer extends EventEmitter {
|
|
|
270
275
|
}
|
|
271
276
|
let persistence = null;
|
|
272
277
|
try {
|
|
273
|
-
persistence = await createPersistenceBackend(config.persistence);
|
|
278
|
+
persistence = options.persistenceBackend ?? await createPersistenceBackend(config.persistence);
|
|
274
279
|
return ToolAwareSequentialThinkingServer._createContainerCore({
|
|
275
280
|
...options,
|
|
276
281
|
config
|
|
@@ -278,7 +283,7 @@ class ToolAwareSequentialThinkingServer extends EventEmitter {
|
|
|
278
283
|
} catch (error) {
|
|
279
284
|
const acquiredPersistence = persistence;
|
|
280
285
|
const cleanupFailures = null === acquiredPersistence ? [] : await collectCleanupFailures([
|
|
281
|
-
()=>acquiredPersistence.
|
|
286
|
+
()=>closeOwnedPersistence(acquiredPersistence, options.persistenceBackend ?? null)
|
|
282
287
|
]);
|
|
283
288
|
if (cleanupFailures.length > 0) throw new AggregateError([
|
|
284
289
|
error,
|
|
@@ -392,7 +397,7 @@ class ToolAwareSequentialThinkingServer extends EventEmitter {
|
|
|
392
397
|
});
|
|
393
398
|
}
|
|
394
399
|
const persistence = this._container.resolve('Persistence');
|
|
395
|
-
if (persistence) try {
|
|
400
|
+
if (persistence && persistence !== this._borrowedPersistence) try {
|
|
396
401
|
await persistence.close();
|
|
397
402
|
this._logger.info('Persistence backend closed');
|
|
398
403
|
} catch (error) {
|