monomind 2.7.4 → 2.7.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.
Files changed (45) hide show
  1. package/package.json +1 -1
  2. package/packages/@monomind/cli/bin/cli.js +17 -1
  3. package/packages/@monomind/cli/dist/src/commands/doctor-project-checks.d.ts +3 -0
  4. package/packages/@monomind/cli/dist/src/commands/doctor-project-checks.js +81 -8
  5. package/packages/@monomind/cli/dist/src/commands/doctor.js +16 -2
  6. package/packages/@monomind/cli/dist/src/commands/memory-crud.js +15 -5
  7. package/packages/@monomind/cli/dist/src/commands/security-misc.js +7 -2
  8. package/packages/@monomind/cli/dist/src/init/helpers-generator.js +5 -0
  9. package/packages/@monomind/cli/dist/src/mcp-client.js +0 -2
  10. package/packages/@monomind/cli/dist/src/mcp-tools/agent-tools.js +1 -1
  11. package/packages/@monomind/cli/dist/src/mcp-tools/embeddings-tools.d.ts +2 -0
  12. package/packages/@monomind/cli/dist/src/mcp-tools/embeddings-tools.js +11 -1
  13. package/packages/@monomind/cli/dist/src/mcp-tools/guidance-tools.js +17 -17
  14. package/packages/@monomind/cli/dist/src/mcp-tools/hive-mind-tools.d.ts +2 -0
  15. package/packages/@monomind/cli/dist/src/mcp-tools/hive-mind-tools.js +14 -2
  16. package/packages/@monomind/cli/dist/src/mcp-tools/index.d.ts +0 -1
  17. package/packages/@monomind/cli/dist/src/mcp-tools/index.js +0 -1
  18. package/packages/@monomind/cli/dist/src/mcp-tools/monograph-tools.js +1 -2
  19. package/packages/@monomind/cli/dist/src/mcp-tools/neural-tools.js +1 -1
  20. package/packages/@monomind/cli/dist/src/mcp-tools/swarm-tools.js +2 -2
  21. package/packages/@monomind/cli/dist/src/mcp-tools/transfer-tools.d.ts +2 -0
  22. package/packages/@monomind/cli/dist/src/mcp-tools/transfer-tools.js +11 -1
  23. package/packages/@monomind/cli/dist/src/ui/dashboard.html +44 -618
  24. package/packages/@monomind/cli/dist/src/ui/server.mjs +0 -275
  25. package/packages/@monomind/cli/dist/src/utils/cosine-similarity.d.ts +2 -2
  26. package/packages/@monomind/cli/dist/src/utils/cosine-similarity.js +2 -2
  27. package/packages/@monomind/cli/package.json +1 -1
  28. package/packages/@monomind/cli/dist/src/mcp-tools/coherence/causal-infer.d.ts +0 -15
  29. package/packages/@monomind/cli/dist/src/mcp-tools/coherence/causal-infer.js +0 -333
  30. package/packages/@monomind/cli/dist/src/mcp-tools/coherence/coherence-check.d.ts +0 -15
  31. package/packages/@monomind/cli/dist/src/mcp-tools/coherence/coherence-check.js +0 -188
  32. package/packages/@monomind/cli/dist/src/mcp-tools/coherence/consensus-verify.d.ts +0 -14
  33. package/packages/@monomind/cli/dist/src/mcp-tools/coherence/consensus-verify.js +0 -305
  34. package/packages/@monomind/cli/dist/src/mcp-tools/coherence/memory-gate.d.ts +0 -16
  35. package/packages/@monomind/cli/dist/src/mcp-tools/coherence/memory-gate.js +0 -279
  36. package/packages/@monomind/cli/dist/src/mcp-tools/coherence/quantum-topology.d.ts +0 -15
  37. package/packages/@monomind/cli/dist/src/mcp-tools/coherence/quantum-topology.js +0 -400
  38. package/packages/@monomind/cli/dist/src/mcp-tools/coherence/spectral-analyze.d.ts +0 -14
  39. package/packages/@monomind/cli/dist/src/mcp-tools/coherence/spectral-analyze.js +0 -312
  40. package/packages/@monomind/cli/dist/src/mcp-tools/coherence/types.d.ts +0 -430
  41. package/packages/@monomind/cli/dist/src/mcp-tools/coherence/types.js +0 -144
  42. package/packages/@monomind/cli/dist/src/mcp-tools/coherence-tools.d.ts +0 -9
  43. package/packages/@monomind/cli/dist/src/mcp-tools/coherence-tools.js +0 -25
  44. package/packages/@monomind/cli/dist/src/mcp-tools/daa-tools.d.ts +0 -13
  45. package/packages/@monomind/cli/dist/src/mcp-tools/daa-tools.js +0 -553
@@ -1,279 +0,0 @@
1
- /**
2
- * Memory Gate Tool - pr_memory_gate
3
- *
4
- * Pre-storage coherence gate for memory entries.
5
- * Validates that new entries are coherent with existing context before storage.
6
- * Uses cosine similarity on vectors to compute coherence energy.
7
- * When no pre-computed embeddings are supplied, falls back to a deterministic
8
- * hash-based vector (structural proxy, not semantic similarity).
9
- */
10
- import { MemoryGateInputSchema, successResult, errorResult, cosineSimilarity, } from './types.js';
11
- // Default logger
12
- const defaultLogger = {
13
- debug: (msg, meta) => console.debug(`[pr_memory_gate] ${msg}`, meta),
14
- info: (msg, meta) => console.info(`[pr_memory_gate] ${msg}`, meta),
15
- warn: (msg, meta) => console.warn(`[pr_memory_gate] ${msg}`, meta),
16
- error: (msg, meta) => console.error(`[pr_memory_gate] ${msg}`, meta),
17
- };
18
- // ============================================================================
19
- // Memory Gate Functions
20
- // ============================================================================
21
- /**
22
- * Deterministic hash-based vector from value content.
23
- * This is NOT a semantic embedding -- it produces a normalized vector
24
- * derived from character codes via an LCG, so only identical (or
25
- * near-identical) strings will be "similar". It serves as a
26
- * structural-consistency proxy when no real embedding model is available.
27
- *
28
- * For real semantic similarity, use the generateEmbedding() from
29
- * neural-tools.ts which tries ONNX first and falls back to a
30
- * deterministic hash.
31
- */
32
- function hashVector(value) {
33
- const str = typeof value === 'string' ? value : JSON.stringify(value);
34
- // Seed from string content
35
- let seed = 0;
36
- for (let i = 0; i < str.length; i++) {
37
- seed = ((seed * 1103515245 + 12345) & 0x7fffffff) ^ (str.charCodeAt(i) * (i + 1));
38
- }
39
- // Generate deterministic vector via LCG
40
- const dims = 64;
41
- const vec = new Array(dims);
42
- for (let i = 0; i < dims; i++) {
43
- seed = (seed * 1103515245 + 12345) & 0x7fffffff;
44
- vec[i] = (seed / 0x7fffffff) * 2 - 1;
45
- }
46
- // Normalize
47
- let norm = 0;
48
- for (let i = 0; i < dims; i++) {
49
- norm += vec[i] * vec[i];
50
- }
51
- norm = Math.sqrt(norm);
52
- if (norm > 0) {
53
- for (let i = 0; i < dims; i++) {
54
- vec[i] /= norm;
55
- }
56
- }
57
- return vec;
58
- }
59
- /**
60
- * Compute coherence energy using Sheaf Laplacian
61
- */
62
- function computeCoherenceEnergy(newEmbedding, existingEmbeddings) {
63
- if (existingEmbeddings.length === 0)
64
- return 0;
65
- let totalDisagreement = 0;
66
- for (const existing of existingEmbeddings) {
67
- const similarity = cosineSimilarity(newEmbedding, existing);
68
- const disagreement = 1 - Math.max(0, similarity);
69
- totalDisagreement += disagreement;
70
- }
71
- return totalDisagreement / existingEmbeddings.length;
72
- }
73
- /**
74
- * Detect specific violations
75
- */
76
- function detectViolations(newEmbedding, existingEmbeddings, warnThreshold) {
77
- const violations = [];
78
- for (let i = 0; i < existingEmbeddings.length; i++) {
79
- const similarity = cosineSimilarity(newEmbedding, existingEmbeddings[i]);
80
- if (similarity < -0.3) {
81
- violations.push(`Strong contradiction with context entry ${i} (similarity: ${similarity.toFixed(3)})`);
82
- }
83
- else if (similarity < warnThreshold) {
84
- violations.push(`Weak coherence with context entry ${i} (similarity: ${similarity.toFixed(3)})`);
85
- }
86
- }
87
- return violations;
88
- }
89
- /**
90
- * Determine action based on coherence energy
91
- */
92
- function determineAction(energy, thresholds) {
93
- if (energy >= thresholds.reject) {
94
- return 'reject';
95
- }
96
- if (energy >= thresholds.warn) {
97
- return 'warn';
98
- }
99
- return 'allow';
100
- }
101
- /**
102
- * Get interpretation of memory gate result
103
- */
104
- function getInterpretation(action, energy, violations) {
105
- switch (action) {
106
- case 'allow':
107
- return 'Entry is coherent with existing context - storage allowed';
108
- case 'warn':
109
- return `Entry has minor inconsistencies (energy: ${energy.toFixed(3)}) - storage allowed with warning`;
110
- case 'reject':
111
- return `Entry contradicts existing context (energy: ${energy.toFixed(3)}) - storage blocked. ${violations.length} violation(s) detected.`;
112
- }
113
- }
114
- /**
115
- * Handler for pr_memory_gate tool
116
- */
117
- async function handler(input, context) {
118
- const logger = context?.logger ?? defaultLogger;
119
- const startTime = performance.now();
120
- try {
121
- // Validate input
122
- const validationResult = MemoryGateInputSchema.safeParse(input);
123
- if (!validationResult.success) {
124
- logger.error('Input validation failed', { error: validationResult.error.message });
125
- return errorResult(`Invalid input: ${validationResult.error.message}`);
126
- }
127
- const { key, value, existingVectors, thresholds } = validationResult.data;
128
- // Get thresholds from config or input
129
- const warnThreshold = thresholds?.warn ?? context?.config?.coherence?.warnThreshold ?? 0.3;
130
- const rejectThreshold = thresholds?.reject ?? context?.config?.coherence?.rejectThreshold ?? 0.7;
131
- logger.debug('Processing memory gate check', {
132
- key,
133
- hasExistingContext: !!existingVectors?.length,
134
- contextSize: existingVectors?.length ?? 0,
135
- warnThreshold,
136
- rejectThreshold,
137
- });
138
- // Generate hash-based vector for the new value (not a semantic embedding --
139
- // only detects near-identical content, not semantic similarity)
140
- const newEmbedding = hashVector(value);
141
- // If no existing context, always allow
142
- if (!existingVectors || existingVectors.length === 0) {
143
- const output = {
144
- allowed: true,
145
- coherenceEnergy: 0,
146
- details: {
147
- action: 'allow',
148
- violations: [],
149
- confidence: 1,
150
- interpretation: 'No existing context - entry allowed',
151
- contextSize: 0,
152
- },
153
- };
154
- const duration = performance.now() - startTime;
155
- logger.info('Memory gate check completed (no context)', {
156
- key,
157
- allowed: true,
158
- durationMs: duration.toFixed(2),
159
- });
160
- return successResult(output);
161
- }
162
- // Validate embedding dimensions match
163
- const firstDim = existingVectors[0].length;
164
- for (let i = 1; i < existingVectors.length; i++) {
165
- if (existingVectors[i].length !== firstDim) {
166
- return errorResult(`Context embedding dimension mismatch: entry ${i} has ${existingVectors[i].length} dimensions, expected ${firstDim}`);
167
- }
168
- }
169
- let coherenceEnergy;
170
- let violations;
171
- // Try to use WASM bridge if available
172
- if (context?.bridge?.initialized) {
173
- try {
174
- logger.debug('Using WASM bridge for coherence check');
175
- const allEmbeddings = [
176
- new Float32Array(newEmbedding),
177
- ...existingVectors.map(v => new Float32Array(v)),
178
- ];
179
- const result = await context.bridge.checkCoherence(allEmbeddings);
180
- coherenceEnergy = result.energy;
181
- violations = result.violations;
182
- }
183
- catch (wasmError) {
184
- logger.warn('WASM bridge failed, falling back to JS implementation', {
185
- error: wasmError instanceof Error ? wasmError.message : String(wasmError),
186
- });
187
- coherenceEnergy = computeCoherenceEnergy(newEmbedding, existingVectors);
188
- violations = detectViolations(newEmbedding, existingVectors, warnThreshold);
189
- }
190
- }
191
- else {
192
- // Pure JavaScript fallback
193
- logger.debug('Using JavaScript fallback for memory gate');
194
- coherenceEnergy = computeCoherenceEnergy(newEmbedding, existingVectors);
195
- violations = detectViolations(newEmbedding, existingVectors, warnThreshold);
196
- }
197
- const action = determineAction(coherenceEnergy, { warn: warnThreshold, reject: rejectThreshold });
198
- const allowed = action !== 'reject';
199
- const confidence = 1 - coherenceEnergy;
200
- const output = {
201
- allowed,
202
- coherenceEnergy,
203
- reason: !allowed ? `Coherence energy ${coherenceEnergy.toFixed(3)} exceeds reject threshold ${rejectThreshold}` : undefined,
204
- details: {
205
- action,
206
- violations,
207
- confidence,
208
- interpretation: getInterpretation(action, coherenceEnergy, violations),
209
- contextSize: existingVectors.length,
210
- },
211
- };
212
- const duration = performance.now() - startTime;
213
- logger.info('Memory gate check completed', {
214
- key,
215
- allowed,
216
- action,
217
- coherenceEnergy: coherenceEnergy.toFixed(4),
218
- violations: violations.length,
219
- durationMs: duration.toFixed(2),
220
- });
221
- return successResult(output);
222
- }
223
- catch (error) {
224
- const duration = performance.now() - startTime;
225
- logger.error('Memory gate check failed', {
226
- error: error instanceof Error ? error.message : String(error),
227
- durationMs: duration.toFixed(2),
228
- });
229
- return errorResult(error instanceof Error ? error : new Error(String(error)));
230
- }
231
- }
232
- /**
233
- * pr_memory_gate MCP Tool Definition
234
- */
235
- export const memoryGateTool = {
236
- name: 'pr_memory_gate',
237
- description: 'Pre-storage coherence gate for memory entries. Validates new entries against existing context vectors using cosine-similarity energy. When no pre-computed embeddings are supplied, uses a deterministic hash-based vector (structural proxy, not semantic). Blocks contradictory entries to maintain memory coherence.',
238
- category: 'memory',
239
- version: '0.1.3',
240
- tags: ['memory', 'coherence', 'gate', 'validation', 'ai-interpretability'],
241
- cacheable: false, // Context changes frequently
242
- inputSchema: {
243
- type: 'object',
244
- properties: {
245
- key: {
246
- type: 'string',
247
- description: 'Memory entry key',
248
- },
249
- value: {
250
- description: 'Value to be stored (any JSON-serializable type)',
251
- },
252
- existingVectors: {
253
- type: 'array',
254
- items: { type: 'array', items: { type: 'number' } },
255
- description: 'Existing context embeddings to check against',
256
- },
257
- thresholds: {
258
- type: 'object',
259
- properties: {
260
- warn: {
261
- type: 'number',
262
- default: 0.3,
263
- description: 'Energy threshold for warnings (0-1)',
264
- },
265
- reject: {
266
- type: 'number',
267
- default: 0.7,
268
- description: 'Energy threshold for rejection (0-1)',
269
- },
270
- },
271
- description: 'Custom coherence thresholds',
272
- },
273
- },
274
- required: ['key', 'value'],
275
- },
276
- handler,
277
- };
278
- export default memoryGateTool;
279
- //# sourceMappingURL=memory-gate.js.map
@@ -1,15 +0,0 @@
1
- /**
2
- * Computational Topology Tool - pr_quantum_topology
3
- *
4
- * Computes topological features including Betti numbers (b0, b1) and
5
- * persistence diagrams via Vietoris-Rips filtration.
6
- * Analyzes topological features of point clouds and simplicial complexes.
7
- * b2 (voids) is not computed -- requires boundary-operator linear algebra.
8
- */
9
- import type { MCPTool } from './types.js';
10
- /**
11
- * pr_quantum_topology MCP Tool Definition
12
- */
13
- export declare const quantumTopologyTool: MCPTool;
14
- export default quantumTopologyTool;
15
- //# sourceMappingURL=quantum-topology.d.ts.map
@@ -1,400 +0,0 @@
1
- /**
2
- * Computational Topology Tool - pr_quantum_topology
3
- *
4
- * Computes topological features including Betti numbers (b0, b1) and
5
- * persistence diagrams via Vietoris-Rips filtration.
6
- * Analyzes topological features of point clouds and simplicial complexes.
7
- * b2 (voids) is not computed -- requires boundary-operator linear algebra.
8
- */
9
- import { TopologyInputSchema, successResult, errorResult, } from './types.js';
10
- // Default logger
11
- const defaultLogger = {
12
- debug: (msg, meta) => console.debug(`[pr_quantum_topology] ${msg}`, meta),
13
- info: (msg, meta) => console.info(`[pr_quantum_topology] ${msg}`, meta),
14
- warn: (msg, meta) => console.warn(`[pr_quantum_topology] ${msg}`, meta),
15
- error: (msg, meta) => console.error(`[pr_quantum_topology] ${msg}`, meta),
16
- };
17
- // ============================================================================
18
- // Topology Helper Functions
19
- // ============================================================================
20
- /**
21
- * Compute Euclidean distance between two points
22
- */
23
- function euclideanDistance(a, b) {
24
- let sum = 0;
25
- for (let i = 0; i < a.length; i++) {
26
- const diff = a[i] - b[i];
27
- sum += diff * diff;
28
- }
29
- return Math.sqrt(sum);
30
- }
31
- /**
32
- * Build distance matrix from vertices
33
- */
34
- function buildDistanceMatrix(vertices) {
35
- const n = vertices.length;
36
- const matrix = [];
37
- for (let i = 0; i < n; i++) {
38
- matrix[i] = [];
39
- for (let j = 0; j < n; j++) {
40
- matrix[i][j] = euclideanDistance(vertices[i], vertices[j]);
41
- }
42
- }
43
- return matrix;
44
- }
45
- /**
46
- * Build Vietoris-Rips complex at given epsilon
47
- * Returns list of simplices (vertex index arrays)
48
- */
49
- function buildRipsComplex(distanceMatrix, epsilon, maxDimension) {
50
- const n = distanceMatrix.length;
51
- const simplices = [];
52
- // Add 0-simplices (vertices)
53
- for (let i = 0; i < n; i++) {
54
- simplices.push([i]);
55
- }
56
- if (maxDimension < 1)
57
- return simplices;
58
- // Add 1-simplices (edges)
59
- const edges = [];
60
- for (let i = 0; i < n; i++) {
61
- for (let j = i + 1; j < n; j++) {
62
- if (distanceMatrix[i][j] <= epsilon) {
63
- edges.push([i, j]);
64
- simplices.push([i, j]);
65
- }
66
- }
67
- }
68
- if (maxDimension < 2)
69
- return simplices;
70
- // Add 2-simplices (triangles)
71
- // A triangle exists if all three edges exist
72
- const edgeSet = new Set(edges.map(e => `${e[0]}-${e[1]}`));
73
- for (let i = 0; i < n; i++) {
74
- for (let j = i + 1; j < n; j++) {
75
- if (!edgeSet.has(`${i}-${j}`))
76
- continue;
77
- for (let k = j + 1; k < n; k++) {
78
- if (edgeSet.has(`${i}-${k}`) && edgeSet.has(`${j}-${k}`)) {
79
- simplices.push([i, j, k]);
80
- }
81
- }
82
- }
83
- }
84
- if (maxDimension < 3)
85
- return simplices;
86
- // Add 3-simplices (tetrahedra)
87
- // Simplified: only add if all faces exist
88
- const triangleSet = new Set(simplices
89
- .filter(s => s.length === 3)
90
- .map(t => `${t[0]}-${t[1]}-${t[2]}`));
91
- for (let i = 0; i < n; i++) {
92
- for (let j = i + 1; j < n; j++) {
93
- for (let k = j + 1; k < n; k++) {
94
- for (let l = k + 1; l < n; l++) {
95
- // Check all 4 triangular faces exist
96
- const faces = [
97
- `${i}-${j}-${k}`,
98
- `${i}-${j}-${l}`,
99
- `${i}-${k}-${l}`,
100
- `${j}-${k}-${l}`,
101
- ];
102
- if (faces.every(f => triangleSet.has(f))) {
103
- simplices.push([i, j, k, l]);
104
- }
105
- }
106
- }
107
- }
108
- }
109
- return simplices;
110
- }
111
- /**
112
- * Compute Betti numbers from simplicial complex
113
- * Uses simplified computation based on simplex counts
114
- *
115
- * Betti numbers:
116
- * - b0: Number of connected components
117
- * - b1: Number of loops/cycles
118
- * - b2: Number of voids/cavities
119
- */
120
- function computeBettiNumbers(vertices, simplices, maxDimension) {
121
- const n = vertices.length;
122
- const bettiNumbers = [];
123
- // Count simplices by dimension
124
- const simplexCounts = new Array(maxDimension + 1).fill(0);
125
- for (const simplex of simplices) {
126
- const dim = simplex.length - 1;
127
- if (dim <= maxDimension) {
128
- simplexCounts[dim]++;
129
- }
130
- }
131
- // b0: Connected components (using union-find approximation)
132
- const parent = new Array(n).fill(-1);
133
- function find(x) {
134
- if (parent[x] < 0)
135
- return x;
136
- parent[x] = find(parent[x]);
137
- return parent[x];
138
- }
139
- function union(x, y) {
140
- const px = find(x);
141
- const py = find(y);
142
- if (px !== py) {
143
- parent[px] = py;
144
- }
145
- }
146
- // Connect vertices in edges
147
- for (const simplex of simplices) {
148
- if (simplex.length === 2) {
149
- union(simplex[0], simplex[1]);
150
- }
151
- }
152
- // Count components
153
- let b0 = 0;
154
- for (let i = 0; i < n; i++) {
155
- if (parent[i] < 0)
156
- b0++;
157
- }
158
- bettiNumbers.push(b0);
159
- // b1: Approximate using Euler characteristic relationship
160
- // For connected graphs: b1 = edges - vertices + components
161
- if (maxDimension >= 1) {
162
- const edges = simplexCounts[1] || 0;
163
- const b1 = Math.max(0, edges - n + b0);
164
- bettiNumbers.push(b1);
165
- }
166
- // b2 requires computing the rank of the boundary matrices (dim-2 and dim-3),
167
- // which needs full boundary-operator linear algebra not implemented here.
168
- // We do NOT fabricate b2 -- only b0 and b1 are reported.
169
- return bettiNumbers;
170
- }
171
- /**
172
- * Compute persistence diagram using filtration
173
- * Tracks birth and death of topological features
174
- */
175
- function computePersistenceDiagram(distanceMatrix, maxDimension) {
176
- const diagram = [];
177
- // Get all unique distances (filtration values)
178
- const distances = [];
179
- const n = distanceMatrix.length;
180
- for (let i = 0; i < n; i++) {
181
- for (let j = i + 1; j < n; j++) {
182
- distances.push(distanceMatrix[i][j]);
183
- }
184
- }
185
- distances.sort((a, b) => a - b);
186
- const uniqueDistances = [...new Set(distances)];
187
- // Sample filtration values
188
- const sampleCount = Math.min(10, uniqueDistances.length);
189
- const sampleIndices = [];
190
- for (let i = 0; i < sampleCount; i++) {
191
- sampleIndices.push(Math.floor(i * uniqueDistances.length / sampleCount));
192
- }
193
- const filtrationValues = sampleIndices.map(i => uniqueDistances[i]);
194
- if (filtrationValues.length === 0)
195
- return diagram;
196
- // Track Betti numbers at each filtration value
197
- let prevBetti = [];
198
- for (let f = 0; f < filtrationValues.length; f++) {
199
- const epsilon = filtrationValues[f];
200
- const simplices = buildRipsComplex(distanceMatrix, epsilon, maxDimension);
201
- const currentBetti = computeBettiNumbers(new Array(n).fill([]).map((_, i) => [i]), simplices, maxDimension);
202
- if (f > 0) {
203
- // Detect births and deaths
204
- for (let dim = 0; dim <= maxDimension && dim < currentBetti.length; dim++) {
205
- const prevB = prevBetti[dim] || 0;
206
- const currB = currentBetti[dim] || 0;
207
- // New features born
208
- if (currB > prevB) {
209
- for (let i = 0; i < currB - prevB; i++) {
210
- diagram.push({
211
- birth: filtrationValues[f - 1],
212
- death: Infinity, // Will be updated when feature dies
213
- dimension: dim,
214
- });
215
- }
216
- }
217
- // Features died
218
- if (currB < prevB) {
219
- // Find features to kill (those born earliest)
220
- const toKill = prevB - currB;
221
- let killed = 0;
222
- for (let d = diagram.length - 1; d >= 0 && killed < toKill; d--) {
223
- if (diagram[d].dimension === dim && diagram[d].death === Infinity) {
224
- diagram[d].death = epsilon;
225
- killed++;
226
- }
227
- }
228
- }
229
- }
230
- }
231
- else {
232
- // Initial features (all vertices born at epsilon = 0)
233
- for (let dim = 0; dim <= maxDimension && dim < currentBetti.length; dim++) {
234
- for (let i = 0; i < currentBetti[dim]; i++) {
235
- diagram.push({
236
- birth: 0,
237
- death: Infinity,
238
- dimension: dim,
239
- });
240
- }
241
- }
242
- }
243
- prevBetti = currentBetti;
244
- }
245
- return diagram;
246
- }
247
- /**
248
- * Get interpretation of Betti numbers
249
- */
250
- function interpretBettiNumbers(bettiNumbers) {
251
- return {
252
- b0: `${bettiNumbers[0] || 0} connected component(s)`,
253
- b1: `${bettiNumbers[1] || 0} loop(s)/cycle(s)`,
254
- };
255
- }
256
- /**
257
- * Handler for pr_quantum_topology tool
258
- */
259
- async function handler(input, context) {
260
- const logger = context?.logger ?? defaultLogger;
261
- const startTime = performance.now();
262
- try {
263
- // Validate input
264
- const validationResult = TopologyInputSchema.safeParse(input);
265
- if (!validationResult.success) {
266
- logger.error('Input validation failed', { error: validationResult.error.message });
267
- return errorResult(`Invalid input: ${validationResult.error.message}`);
268
- }
269
- const { complex } = validationResult.data;
270
- const { vertices, maxDimension } = complex;
271
- logger.debug('Processing computational topology', {
272
- vertexCount: vertices.length,
273
- maxDimension,
274
- });
275
- if (vertices.length === 0) {
276
- return errorResult('No vertices provided');
277
- }
278
- // Validate vertex dimensions are consistent
279
- const firstDim = vertices[0].length;
280
- for (let i = 1; i < vertices.length; i++) {
281
- if (vertices[i].length !== firstDim) {
282
- return errorResult(`Vertex dimension mismatch: vertex ${i} has ${vertices[i].length} dimensions, expected ${firstDim}`);
283
- }
284
- }
285
- let bettiNumbers;
286
- let persistenceDiagram;
287
- let homologyClasses;
288
- // Try to use WASM bridge if available
289
- if (context?.bridge?.initialized) {
290
- try {
291
- logger.debug('Using WASM bridge for topology computation');
292
- const result = await context.bridge.computeTopology(complex);
293
- bettiNumbers = result.bettiNumbers;
294
- persistenceDiagram = result.persistenceDiagram.map(([birth, death], i) => ({
295
- birth,
296
- death,
297
- dimension: Math.min(i % (maxDimension + 1), maxDimension),
298
- }));
299
- homologyClasses = result.homologyClasses;
300
- }
301
- catch (wasmError) {
302
- logger.warn('WASM bridge failed, falling back to JS implementation', {
303
- error: wasmError instanceof Error ? wasmError.message : String(wasmError),
304
- });
305
- // Use JavaScript implementation
306
- const distanceMatrix = buildDistanceMatrix(vertices);
307
- const maxDistance = Math.max(...distanceMatrix.flat().filter(d => d > 0));
308
- const simplices = buildRipsComplex(distanceMatrix, maxDistance * 0.5, maxDimension);
309
- bettiNumbers = computeBettiNumbers(vertices, simplices, maxDimension);
310
- persistenceDiagram = computePersistenceDiagram(distanceMatrix, maxDimension);
311
- homologyClasses = bettiNumbers.reduce((a, b) => a + b, 0);
312
- }
313
- }
314
- else {
315
- // Pure JavaScript fallback
316
- logger.debug('Using JavaScript fallback for topology computation');
317
- const distanceMatrix = buildDistanceMatrix(vertices);
318
- const maxDistance = Math.max(...distanceMatrix.flat().filter(d => d > 0));
319
- const simplices = buildRipsComplex(distanceMatrix, maxDistance * 0.5, maxDimension);
320
- bettiNumbers = computeBettiNumbers(vertices, simplices, maxDimension);
321
- persistenceDiagram = computePersistenceDiagram(distanceMatrix, maxDimension);
322
- homologyClasses = bettiNumbers.reduce((a, b) => a + b, 0);
323
- }
324
- const output = {
325
- bettiNumbers,
326
- persistenceDiagram,
327
- details: {
328
- homologyClasses,
329
- interpretation: interpretBettiNumbers(bettiNumbers),
330
- vertexCount: vertices.length,
331
- maxDimension,
332
- },
333
- };
334
- const duration = performance.now() - startTime;
335
- logger.info('Topology computation completed', {
336
- bettiNumbers: bettiNumbers.join(', '),
337
- persistencePoints: persistenceDiagram.length,
338
- homologyClasses,
339
- durationMs: duration.toFixed(2),
340
- });
341
- return successResult(output);
342
- }
343
- catch (error) {
344
- const duration = performance.now() - startTime;
345
- logger.error('Topology computation failed', {
346
- error: error instanceof Error ? error.message : String(error),
347
- durationMs: duration.toFixed(2),
348
- });
349
- return errorResult(error instanceof Error ? error : new Error(String(error)));
350
- }
351
- }
352
- /**
353
- * pr_quantum_topology MCP Tool Definition
354
- */
355
- export const quantumTopologyTool = {
356
- name: 'pr_quantum_topology',
357
- description: 'Compute topological features via Vietoris-Rips filtration. Reports Betti numbers b0 (components) and b1 (loops) with persistence diagrams. b2 (voids) is not computed.',
358
- category: 'topology',
359
- version: '0.1.3',
360
- tags: ['topology', 'betti-numbers', 'persistence', 'homology', 'ai-interpretability'],
361
- cacheable: true,
362
- cacheTTL: 120000, // 2 minute cache (expensive computation)
363
- inputSchema: {
364
- type: 'object',
365
- properties: {
366
- complex: {
367
- type: 'object',
368
- properties: {
369
- vertices: {
370
- type: 'array',
371
- items: { type: 'array', items: { type: 'number' } },
372
- description: 'Vertex coordinates (point cloud)',
373
- },
374
- simplices: {
375
- type: 'array',
376
- items: {
377
- type: 'object',
378
- properties: {
379
- vertices: { type: 'array', items: { type: 'number' } },
380
- dimension: { type: 'number' },
381
- },
382
- },
383
- description: 'Explicit simplices (optional, computed from vertices if not provided)',
384
- },
385
- maxDimension: {
386
- type: 'number',
387
- default: 2,
388
- description: 'Maximum homology dimension to compute (0-3)',
389
- },
390
- },
391
- required: ['vertices'],
392
- description: 'Simplicial complex for topological analysis',
393
- },
394
- },
395
- required: ['complex'],
396
- },
397
- handler,
398
- };
399
- export default quantumTopologyTool;
400
- //# sourceMappingURL=quantum-topology.js.map