rax-flow-core 0.1.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/cache/semantic-cache.d.ts +10 -0
- package/dist/cache/semantic-cache.d.ts.map +1 -0
- package/dist/cache/semantic-cache.js +50 -0
- package/dist/cache/semantic-cache.js.map +1 -0
- package/dist/governance/policies/pii-policy.d.ts +37 -0
- package/dist/governance/policies/pii-policy.d.ts.map +1 -0
- package/dist/governance/policies/pii-policy.js +177 -0
- package/dist/governance/policies/pii-policy.js.map +1 -0
- package/dist/graph/workflow-graph.d.ts +5 -0
- package/dist/graph/workflow-graph.d.ts.map +1 -0
- package/dist/graph/workflow-graph.js +38 -0
- package/dist/graph/workflow-graph.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/memory/graph-memory.d.ts +46 -0
- package/dist/memory/graph-memory.d.ts.map +1 -0
- package/dist/memory/graph-memory.js +122 -0
- package/dist/memory/graph-memory.js.map +1 -0
- package/dist/memory/local-vector-store.d.ts +36 -0
- package/dist/memory/local-vector-store.d.ts.map +1 -0
- package/dist/memory/local-vector-store.js +125 -0
- package/dist/memory/local-vector-store.js.map +1 -0
- package/dist/memory/memory-manager.d.ts +42 -0
- package/dist/memory/memory-manager.d.ts.map +1 -0
- package/dist/memory/memory-manager.js +98 -0
- package/dist/memory/memory-manager.js.map +1 -0
- package/dist/metrics/metrics-engine.d.ts +13 -0
- package/dist/metrics/metrics-engine.d.ts.map +1 -0
- package/dist/metrics/metrics-engine.js +27 -0
- package/dist/metrics/metrics-engine.js.map +1 -0
- package/dist/orchestrator/blueprint-committer.d.ts +69 -0
- package/dist/orchestrator/blueprint-committer.d.ts.map +1 -0
- package/dist/orchestrator/blueprint-committer.js +305 -0
- package/dist/orchestrator/blueprint-committer.js.map +1 -0
- package/dist/orchestrator/core-orchestrator.d.ts +168 -0
- package/dist/orchestrator/core-orchestrator.d.ts.map +1 -0
- package/dist/orchestrator/core-orchestrator.js +451 -0
- package/dist/orchestrator/core-orchestrator.js.map +1 -0
- package/dist/orchestrator/decomposition-engine.d.ts +41 -0
- package/dist/orchestrator/decomposition-engine.d.ts.map +1 -0
- package/dist/orchestrator/decomposition-engine.js +133 -0
- package/dist/orchestrator/decomposition-engine.js.map +1 -0
- package/dist/orchestrator/decomposition.d.ts +10 -0
- package/dist/orchestrator/decomposition.d.ts.map +1 -0
- package/dist/orchestrator/decomposition.js +15 -0
- package/dist/orchestrator/decomposition.js.map +1 -0
- package/dist/orchestrator/default-workflow.d.ts +59 -0
- package/dist/orchestrator/default-workflow.d.ts.map +1 -0
- package/dist/orchestrator/default-workflow.js +221 -0
- package/dist/orchestrator/default-workflow.js.map +1 -0
- package/dist/orchestrator/dynamic-planner.d.ts +46 -0
- package/dist/orchestrator/dynamic-planner.d.ts.map +1 -0
- package/dist/orchestrator/dynamic-planner.js +232 -0
- package/dist/orchestrator/dynamic-planner.js.map +1 -0
- package/dist/orchestrator/kernel-bridge.d.ts +57 -0
- package/dist/orchestrator/kernel-bridge.d.ts.map +1 -0
- package/dist/orchestrator/kernel-bridge.js +211 -0
- package/dist/orchestrator/kernel-bridge.js.map +1 -0
- package/dist/orchestrator/mutation-applier.d.ts +47 -0
- package/dist/orchestrator/mutation-applier.d.ts.map +1 -0
- package/dist/orchestrator/mutation-applier.js +253 -0
- package/dist/orchestrator/mutation-applier.js.map +1 -0
- package/dist/orchestrator/routing.d.ts +4 -0
- package/dist/orchestrator/routing.d.ts.map +1 -0
- package/dist/orchestrator/routing.js +41 -0
- package/dist/orchestrator/routing.js.map +1 -0
- package/dist/orchestrator/verify-fix.d.ts +79 -0
- package/dist/orchestrator/verify-fix.d.ts.map +1 -0
- package/dist/orchestrator/verify-fix.js +153 -0
- package/dist/orchestrator/verify-fix.js.map +1 -0
- package/dist/plugins/governance-plugin.d.ts +43 -0
- package/dist/plugins/governance-plugin.d.ts.map +1 -0
- package/dist/plugins/governance-plugin.js +88 -0
- package/dist/plugins/governance-plugin.js.map +1 -0
- package/dist/plugins/long-term-memory-plugin.d.ts +31 -0
- package/dist/plugins/long-term-memory-plugin.d.ts.map +1 -0
- package/dist/plugins/long-term-memory-plugin.js +67 -0
- package/dist/plugins/long-term-memory-plugin.js.map +1 -0
- package/dist/plugins/plugin-system.d.ts +29 -0
- package/dist/plugins/plugin-system.d.ts.map +1 -0
- package/dist/plugins/plugin-system.js +22 -0
- package/dist/plugins/plugin-system.js.map +1 -0
- package/dist/recovery/error-recovery.d.ts +15 -0
- package/dist/recovery/error-recovery.d.ts.map +1 -0
- package/dist/recovery/error-recovery.js +12 -0
- package/dist/recovery/error-recovery.js.map +1 -0
- package/dist/runtime/concurrency-scheduler.d.ts +2 -0
- package/dist/runtime/concurrency-scheduler.d.ts.map +1 -0
- package/dist/runtime/concurrency-scheduler.js +18 -0
- package/dist/runtime/concurrency-scheduler.js.map +1 -0
- package/dist/runtime/runtime-events.d.ts +59 -0
- package/dist/runtime/runtime-events.d.ts.map +1 -0
- package/dist/runtime/runtime-events.js +12 -0
- package/dist/runtime/runtime-events.js.map +1 -0
- package/dist/types/contracts.d.ts +127 -0
- package/dist/types/contracts.d.ts.map +1 -0
- package/dist/types/contracts.js +2 -0
- package/dist/types/contracts.js.map +1 -0
- package/dist/validator/structured-output-validator.d.ts +10 -0
- package/dist/validator/structured-output-validator.d.ts.map +1 -0
- package/dist/validator/structured-output-validator.js +19 -0
- package/dist/validator/structured-output-validator.js.map +1 -0
- package/package.json +18 -0
- package/src/cache/semantic-cache.ts +64 -0
- package/src/governance/policies/pii-policy.ts +213 -0
- package/src/graph/workflow-graph.ts +41 -0
- package/src/index.ts +25 -0
- package/src/memory/graph-memory.ts +150 -0
- package/src/memory/local-vector-store.ts +129 -0
- package/src/memory/memory-manager.ts +126 -0
- package/src/metrics/metrics-engine.ts +39 -0
- package/src/orchestrator/blueprint-committer.ts +351 -0
- package/src/orchestrator/core-orchestrator.ts +582 -0
- package/src/orchestrator/decomposition-engine.ts +165 -0
- package/src/orchestrator/decomposition.ts +25 -0
- package/src/orchestrator/default-workflow.ts +269 -0
- package/src/orchestrator/dynamic-planner.ts +277 -0
- package/src/orchestrator/kernel-bridge.ts +251 -0
- package/src/orchestrator/mutation-applier.ts +279 -0
- package/src/orchestrator/routing.ts +44 -0
- package/src/orchestrator/verify-fix.ts +218 -0
- package/src/plugins/governance-plugin.ts +106 -0
- package/src/plugins/long-term-memory-plugin.ts +72 -0
- package/src/plugins/plugin-system.ts +34 -0
- package/src/recovery/error-recovery.ts +23 -0
- package/src/runtime/concurrency-scheduler.ts +18 -0
- package/src/runtime/runtime-events.ts +27 -0
- package/src/types/contracts.ts +159 -0
- package/src/validator/structured-output-validator.ts +20 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
|
|
4
|
+
export interface GraphNode {
|
|
5
|
+
id: string;
|
|
6
|
+
type: "action" | "artifact" | "concept" | "agent";
|
|
7
|
+
content: string;
|
|
8
|
+
metadata: Record<string, any>;
|
|
9
|
+
timestamp: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface GraphEdge {
|
|
13
|
+
from: string;
|
|
14
|
+
to: string;
|
|
15
|
+
type: "produced" | "triggered_by" | "depends_on" | "relates_to";
|
|
16
|
+
metadata?: Record<string, any>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Quantum Semantic Graph Memory (QSGM) Core.
|
|
21
|
+
* Manages relationships between actions, artifacts, and concepts.
|
|
22
|
+
*/
|
|
23
|
+
export class GraphMemory {
|
|
24
|
+
private nodes: Map<string, GraphNode> = new Map();
|
|
25
|
+
private edges: GraphEdge[] = [];
|
|
26
|
+
|
|
27
|
+
constructor(private persistPath?: string) { }
|
|
28
|
+
|
|
29
|
+
public addNode(node: GraphNode): void {
|
|
30
|
+
this.nodes.set(node.id, node);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public removeNode(nodeId: string): boolean {
|
|
34
|
+
if (!this.nodes.has(nodeId)) return false;
|
|
35
|
+
this.nodes.delete(nodeId);
|
|
36
|
+
this.edges = this.edges.filter(e => e.from !== nodeId && e.to !== nodeId);
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public addEdge(edge: GraphEdge): void {
|
|
41
|
+
this.edges.push(edge);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Traverses the graph to find nodes related to a starting point.
|
|
46
|
+
* Useful for finding "ripple effects" or deep context.
|
|
47
|
+
*/
|
|
48
|
+
public traverse(startNodeId: string, maxDepth: number = 2): GraphNode[] {
|
|
49
|
+
const visited = new Set<string>();
|
|
50
|
+
const results: GraphNode[] = [];
|
|
51
|
+
const queue: { id: string; depth: number }[] = [{ id: startNodeId, depth: 0 }];
|
|
52
|
+
|
|
53
|
+
while (queue.length > 0) {
|
|
54
|
+
const { id, depth } = queue.shift()!;
|
|
55
|
+
if (visited.has(id) || depth > maxDepth) continue;
|
|
56
|
+
|
|
57
|
+
visited.add(id);
|
|
58
|
+
const node = this.nodes.get(id);
|
|
59
|
+
if (node) {
|
|
60
|
+
results.push(node);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Find neighbors
|
|
64
|
+
const neighbors = this.edges
|
|
65
|
+
.filter(e => e.from === id)
|
|
66
|
+
.map(e => ({ id: e.to, depth: depth + 1 }));
|
|
67
|
+
|
|
68
|
+
const reverseNeighbors = this.edges
|
|
69
|
+
.filter(e => e.to === id)
|
|
70
|
+
.map(e => ({ id: e.from, depth: depth + 1 }));
|
|
71
|
+
|
|
72
|
+
queue.push(...neighbors, ...reverseNeighbors);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return results;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
public async load(): Promise<void> {
|
|
79
|
+
if (!this.persistPath) return;
|
|
80
|
+
try {
|
|
81
|
+
const raw = await readFile(this.persistPath, "utf8");
|
|
82
|
+
const data = JSON.parse(raw);
|
|
83
|
+
this.nodes = new Map(Object.entries(data.nodes || {}));
|
|
84
|
+
this.edges = data.edges || [];
|
|
85
|
+
} catch {
|
|
86
|
+
this.nodes = new Map();
|
|
87
|
+
this.edges = [];
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
public async save(): Promise<void> {
|
|
92
|
+
if (!this.persistPath) return;
|
|
93
|
+
try {
|
|
94
|
+
await mkdir(path.dirname(this.persistPath), { recursive: true });
|
|
95
|
+
await writeFile(this.persistPath, JSON.stringify({
|
|
96
|
+
nodes: Object.fromEntries(this.nodes),
|
|
97
|
+
edges: this.edges
|
|
98
|
+
}, null, 2));
|
|
99
|
+
} catch (err) {
|
|
100
|
+
console.error("Failed to persist graph memory:", err);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
public getNodes(): GraphNode[] {
|
|
105
|
+
return Array.from(this.nodes.values());
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
public getGraphData(): { nodes: Record<string, GraphNode>; edges: GraphEdge[] } {
|
|
109
|
+
return {
|
|
110
|
+
nodes: Object.fromEntries(this.nodes),
|
|
111
|
+
edges: this.edges
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
public findByType(type: string): GraphNode[] {
|
|
116
|
+
return Array.from(this.nodes.values()).filter(n => n.type === type);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
public search(query: string, limit: number = 5): GraphNode[] {
|
|
120
|
+
return Array.from(this.nodes.values())
|
|
121
|
+
.filter(n => n.content?.includes(query) || JSON.stringify(n.metadata).includes(query))
|
|
122
|
+
.slice(0, limit);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
public getConnections(nodeId: string): { incoming: GraphNode[]; outgoing: GraphNode[] } {
|
|
126
|
+
const incoming = this.edges
|
|
127
|
+
.filter(e => e.to === nodeId)
|
|
128
|
+
.map(e => this.nodes.get(e.from)!)
|
|
129
|
+
.filter(Boolean);
|
|
130
|
+
|
|
131
|
+
const outgoing = this.edges
|
|
132
|
+
.filter(e => e.from === nodeId)
|
|
133
|
+
.map(e => this.nodes.get(e.to)!)
|
|
134
|
+
.filter(Boolean);
|
|
135
|
+
|
|
136
|
+
return { incoming, outgoing };
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
public getStats(): any {
|
|
140
|
+
return {
|
|
141
|
+
nodeCount: this.nodes.size,
|
|
142
|
+
edgeCount: this.edges.length,
|
|
143
|
+
nodesByType: Array.from(this.nodes.values()).reduce((acc: Record<string, number>, n) => {
|
|
144
|
+
acc[n.type] = (acc[n.type] || 0) + 1;
|
|
145
|
+
return acc;
|
|
146
|
+
}, {})
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { IVectorStore, MemoryDocument, SearchResult } from "../types/contracts.js";
|
|
2
|
+
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A lightweight, local vector store using Cosine Similarity.
|
|
7
|
+
* Suitable for small-to-medium datasets (thousands of records).
|
|
8
|
+
* Persists data to a simple JSON structure.
|
|
9
|
+
*/
|
|
10
|
+
export class LocalVectorStore implements IVectorStore {
|
|
11
|
+
private documents: MemoryDocument[] = [];
|
|
12
|
+
private vectors: number[][] = [];
|
|
13
|
+
private metadata: Map<string, Record<string, unknown>> = new Map();
|
|
14
|
+
|
|
15
|
+
constructor(private persistPath?: string) { }
|
|
16
|
+
|
|
17
|
+
async add(documents: MemoryDocument[], vectors: number[][]): Promise<void> {
|
|
18
|
+
if (documents.length !== vectors.length) {
|
|
19
|
+
throw new Error("Mismatched documents and vectors count.");
|
|
20
|
+
}
|
|
21
|
+
this.documents.push(...documents);
|
|
22
|
+
this.vectors.push(...vectors);
|
|
23
|
+
if (this.persistPath) await this.save();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async search(queryVector: number[], limit: number = 5): Promise<SearchResult[]> {
|
|
27
|
+
if (this.vectors.length === 0) return [];
|
|
28
|
+
|
|
29
|
+
const results: SearchResult[] = this.vectors.map((vec, i) => {
|
|
30
|
+
const score = this.cosineSimilarity(queryVector, vec);
|
|
31
|
+
return { ...this.documents[i], score };
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
return results
|
|
35
|
+
.sort((a, b) => b.score - a.score)
|
|
36
|
+
.slice(0, limit);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async clear(): Promise<void> {
|
|
40
|
+
this.documents = [];
|
|
41
|
+
this.vectors = [];
|
|
42
|
+
this.metadata.clear();
|
|
43
|
+
if (this.persistPath) await this.save();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async delete(docIds: string[]): Promise<void> {
|
|
47
|
+
for (const id of docIds) {
|
|
48
|
+
const idx = this.documents.findIndex(d => d.id === id);
|
|
49
|
+
if (idx >= 0) {
|
|
50
|
+
this.documents.splice(idx, 1);
|
|
51
|
+
this.vectors.splice(idx, 1);
|
|
52
|
+
this.metadata.delete(id);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (this.persistPath) await this.save();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async searchByMetadata(metadata: Record<string, unknown>): Promise<SearchResult[]> {
|
|
59
|
+
return this.documents.filter(doc => {
|
|
60
|
+
const docMeta = this.metadata.get(doc.id) || {};
|
|
61
|
+
return Object.entries(metadata).every(([key, value]) => docMeta[key] === value);
|
|
62
|
+
}).map(doc => ({ ...doc, score: 1.0 }));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
public count(): number {
|
|
66
|
+
return this.documents.length;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
public getMetrics() {
|
|
70
|
+
return {
|
|
71
|
+
documentCount: this.documents.length,
|
|
72
|
+
vectorDimensions: this.vectors[0]?.length || 0
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Calculates cosine similarity between two numeric vectors.
|
|
78
|
+
*/
|
|
79
|
+
private cosineSimilarity(vecA: number[], vecB: number[]): number {
|
|
80
|
+
let dotProduct = 0;
|
|
81
|
+
let normA = 0;
|
|
82
|
+
let normB = 0;
|
|
83
|
+
|
|
84
|
+
// Using common length. Error check in a production environment.
|
|
85
|
+
const len = Math.min(vecA.length, vecB.length);
|
|
86
|
+
for (let i = 0; i < len; i++) {
|
|
87
|
+
dotProduct += vecA[i] * vecB[i];
|
|
88
|
+
normA += vecA[i] * vecA[i];
|
|
89
|
+
normB += vecB[i] * vecB[i];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const denominator = Math.sqrt(normA) * Math.sqrt(normB);
|
|
93
|
+
if (denominator === 0) return 0;
|
|
94
|
+
return dotProduct / denominator;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Manually triggers a load from the persistence file.
|
|
99
|
+
*/
|
|
100
|
+
async load(): Promise<void> {
|
|
101
|
+
if (!this.persistPath) return;
|
|
102
|
+
try {
|
|
103
|
+
const raw = await readFile(this.persistPath, "utf8");
|
|
104
|
+
const data = JSON.parse(raw);
|
|
105
|
+
this.documents = data.documents || [];
|
|
106
|
+
this.vectors = data.vectors || [];
|
|
107
|
+
} catch {
|
|
108
|
+
// File might not exist yet, ignore
|
|
109
|
+
this.documents = [];
|
|
110
|
+
this.vectors = [];
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Internal save to disk.
|
|
116
|
+
*/
|
|
117
|
+
private async save(): Promise<void> {
|
|
118
|
+
if (!this.persistPath) return;
|
|
119
|
+
try {
|
|
120
|
+
await mkdir(path.dirname(this.persistPath), { recursive: true });
|
|
121
|
+
await writeFile(this.persistPath, JSON.stringify({
|
|
122
|
+
documents: this.documents,
|
|
123
|
+
vectors: this.vectors
|
|
124
|
+
}));
|
|
125
|
+
} catch (err) {
|
|
126
|
+
console.error("Failed to persist vector store:", err);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { IVectorStore, MemoryDocument, SearchResult } from "../types/contracts.js";
|
|
2
|
+
import { GraphMemory, GraphNode, GraphEdge } from "./graph-memory.js";
|
|
3
|
+
|
|
4
|
+
export interface MemoryQuery {
|
|
5
|
+
text?: string;
|
|
6
|
+
vector?: number[];
|
|
7
|
+
metadata?: Record<string, unknown>;
|
|
8
|
+
limit?: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface MemoryStatistics {
|
|
12
|
+
totalDocuments: number;
|
|
13
|
+
totalNodes: number;
|
|
14
|
+
totalEdges: number;
|
|
15
|
+
lastUpdated: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* MemoryManager coordinates Vector search and Graph traversal.
|
|
20
|
+
* This is the heart of QSGM, allowing for "logical navigation" of context.
|
|
21
|
+
*/
|
|
22
|
+
export class MemoryManager {
|
|
23
|
+
private stats: MemoryStatistics = {
|
|
24
|
+
totalDocuments: 0,
|
|
25
|
+
totalNodes: 0,
|
|
26
|
+
totalEdges: 0,
|
|
27
|
+
lastUpdated: new Date().toISOString()
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
constructor(
|
|
31
|
+
private vectorStore: IVectorStore,
|
|
32
|
+
private graphMemory: GraphMemory
|
|
33
|
+
) { }
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Retrieves context using a hybrid approach:
|
|
37
|
+
* 1. Find the most semantically relevant node via Vector Search.
|
|
38
|
+
* 2. Traverse the Graph from that node to find related concepts/actions/artifacts.
|
|
39
|
+
*/
|
|
40
|
+
public async getQuantumContext(queryVector: number[], limit: number = 3): Promise<string> {
|
|
41
|
+
const vectorResults = await this.vectorStore.search(queryVector, 1);
|
|
42
|
+
|
|
43
|
+
if (vectorResults.length === 0) return "";
|
|
44
|
+
|
|
45
|
+
const seedNodeId = vectorResults[0].id;
|
|
46
|
+
const relatedNodes = this.graphMemory.traverse(seedNodeId, 2);
|
|
47
|
+
|
|
48
|
+
return relatedNodes
|
|
49
|
+
.map(node => `[QSGM_KNOWLEDGE] (${node.type.toUpperCase()})\n${node.content}`)
|
|
50
|
+
.join("\n\n");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Records a new interaction in both stores.
|
|
55
|
+
*/
|
|
56
|
+
public async remember(doc: MemoryDocument, vector: number[], relatedToId?: string): Promise<void> {
|
|
57
|
+
// 1. Add to Vector Store for semantic search
|
|
58
|
+
await this.vectorStore.add([doc], [vector]);
|
|
59
|
+
|
|
60
|
+
// 2. Add to Graph Memory for logical navigation
|
|
61
|
+
this.graphMemory.addNode({
|
|
62
|
+
id: doc.id,
|
|
63
|
+
type: "artifact",
|
|
64
|
+
content: doc.text,
|
|
65
|
+
metadata: doc.metadata,
|
|
66
|
+
timestamp: doc.timestamp
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
if (relatedToId) {
|
|
70
|
+
this.graphMemory.addEdge({
|
|
71
|
+
from: relatedToId,
|
|
72
|
+
to: doc.id,
|
|
73
|
+
type: "produced"
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
await this.graphMemory.save();
|
|
78
|
+
this.stats.totalDocuments++;
|
|
79
|
+
this.stats.totalNodes++;
|
|
80
|
+
this.stats.lastUpdated = new Date().toISOString();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
public async search(query: MemoryQuery): Promise<SearchResult[]> {
|
|
84
|
+
if (!query.vector) return [];
|
|
85
|
+
return this.vectorStore.search(query.vector, query.limit || 5);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
public async forget(docId: string): Promise<void> {
|
|
89
|
+
if (this.vectorStore.delete) {
|
|
90
|
+
await this.vectorStore.delete([docId]);
|
|
91
|
+
}
|
|
92
|
+
this.graphMemory.removeNode(docId);
|
|
93
|
+
this.stats.totalDocuments = Math.max(0, this.stats.totalDocuments - 1);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
public async clear(): Promise<void> {
|
|
97
|
+
this.stats = {
|
|
98
|
+
totalDocuments: 0,
|
|
99
|
+
totalNodes: 0,
|
|
100
|
+
totalEdges: 0,
|
|
101
|
+
lastUpdated: new Date().toISOString()
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
public getGraphData(): any {
|
|
106
|
+
return this.graphMemory.getGraphData();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
public getStatistics(): MemoryStatistics {
|
|
110
|
+
return { ...this.stats };
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
public async batchRemember(docs: MemoryDocument[], vectors: number[][]): Promise<void> {
|
|
114
|
+
for (let i = 0; i < docs.length; i++) {
|
|
115
|
+
await this.remember(docs[i], vectors[i]);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
public async export(): Promise<any> {
|
|
120
|
+
return {
|
|
121
|
+
graphs: this.getGraphData(),
|
|
122
|
+
timestamp: new Date().toISOString(),
|
|
123
|
+
stats: this.stats
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ExecutionMetrics } from "../types/contracts.js";
|
|
2
|
+
|
|
3
|
+
export class MetricsEngine {
|
|
4
|
+
private readonly runs: ExecutionMetrics[] = [];
|
|
5
|
+
|
|
6
|
+
push(metrics: ExecutionMetrics): void {
|
|
7
|
+
this.runs.push(metrics);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
summary(): {
|
|
11
|
+
totalRuns: number;
|
|
12
|
+
avgConfidence: number;
|
|
13
|
+
avgLatencyMs: number;
|
|
14
|
+
totalCostUsd: number;
|
|
15
|
+
interventionRate: number;
|
|
16
|
+
} {
|
|
17
|
+
if (this.runs.length === 0) {
|
|
18
|
+
return { totalRuns: 0, avgConfidence: 0, avgLatencyMs: 0, totalCostUsd: 0, interventionRate: 0 };
|
|
19
|
+
}
|
|
20
|
+
const total = this.runs.length;
|
|
21
|
+
const sums = this.runs.reduce(
|
|
22
|
+
(acc, run) => {
|
|
23
|
+
acc.conf += run.confidence;
|
|
24
|
+
acc.lat += run.totalLatencyMs;
|
|
25
|
+
acc.cost += run.totalCostUsd;
|
|
26
|
+
acc.human += run.humanInterventionRequired ? 1 : 0;
|
|
27
|
+
return acc;
|
|
28
|
+
},
|
|
29
|
+
{ conf: 0, lat: 0, cost: 0, human: 0 }
|
|
30
|
+
);
|
|
31
|
+
return {
|
|
32
|
+
totalRuns: total,
|
|
33
|
+
avgConfidence: sums.conf / total,
|
|
34
|
+
avgLatencyMs: sums.lat / total,
|
|
35
|
+
totalCostUsd: Number(sums.cost.toFixed(4)),
|
|
36
|
+
interventionRate: sums.human / total
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
}
|