claude-flow 3.5.71 → 3.5.73
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/package.json +1 -1
- package/v3/@claude-flow/cli/dist/src/commands/plugins.js +6 -0
- package/v3/@claude-flow/cli/dist/src/commands/security.js +350 -34
- package/v3/@claude-flow/cli/dist/src/commands/swarm.js +100 -15
- package/v3/@claude-flow/cli/dist/src/init/claudemd-generator.js +15 -17
- package/v3/@claude-flow/cli/dist/src/mcp-tools/hooks-tools.js +58 -13
- package/v3/@claude-flow/cli/dist/src/mcp-tools/neural-tools.js +49 -2
- package/v3/@claude-flow/cli/dist/src/mcp-tools/performance-tools.js +7 -5
- package/v3/@claude-flow/cli/dist/src/mcp-tools/system-tools.js +53 -18
- package/v3/@claude-flow/cli/dist/src/memory/sona-optimizer.d.ts +21 -3
- package/v3/@claude-flow/cli/dist/src/memory/sona-optimizer.js +74 -7
- package/v3/@claude-flow/cli/dist/src/ruvector/vector-db.d.ts +4 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/vector-db.js +22 -1
- package/v3/@claude-flow/cli/package.json +1 -1
|
@@ -52,9 +52,8 @@ function concurrencyRules() {
|
|
|
52
52
|
return `## Concurrency: 1 MESSAGE = ALL RELATED OPERATIONS
|
|
53
53
|
|
|
54
54
|
- All operations MUST be concurrent/parallel in a single message
|
|
55
|
-
- Use Claude Code's
|
|
56
|
-
- ALWAYS
|
|
57
|
-
- ALWAYS spawn ALL agents in ONE message with full instructions via Task tool
|
|
55
|
+
- Use Claude Code's Agent tool for spawning agents, not just MCP
|
|
56
|
+
- ALWAYS spawn ALL agents in ONE message with full instructions via Agent tool
|
|
58
57
|
- ALWAYS batch ALL file reads/writes/edits in ONE message
|
|
59
58
|
- ALWAYS batch ALL Bash commands in ONE message`;
|
|
60
59
|
}
|
|
@@ -62,9 +61,9 @@ function swarmOrchestration() {
|
|
|
62
61
|
return `## Swarm Orchestration
|
|
63
62
|
|
|
64
63
|
- MUST initialize the swarm using CLI tools when starting complex tasks
|
|
65
|
-
- MUST spawn concurrent agents using Claude Code's
|
|
66
|
-
- Never use CLI tools alone for execution —
|
|
67
|
-
- MUST call CLI tools AND
|
|
64
|
+
- MUST spawn concurrent agents using Claude Code's Agent tool
|
|
65
|
+
- Never use CLI tools alone for execution — Agent tool agents do the actual work
|
|
66
|
+
- MUST call CLI tools AND Agent tool in ONE message for complex work
|
|
68
67
|
|
|
69
68
|
### 3-Tier Model Routing (ADR-026)
|
|
70
69
|
|
|
@@ -74,8 +73,7 @@ function swarmOrchestration() {
|
|
|
74
73
|
| **2** | Haiku | ~500ms | $0.0002 | Simple tasks, low complexity (<30%) |
|
|
75
74
|
| **3** | Sonnet/Opus | 2-5s | $0.003-0.015 | Complex reasoning, architecture, security (>30%) |
|
|
76
75
|
|
|
77
|
-
-
|
|
78
|
-
- Use Edit tool directly when \`[AGENT_BOOSTER_AVAILABLE]\``;
|
|
76
|
+
- For Tier 1 simple transforms, use Edit tool directly — no LLM agent needed`;
|
|
79
77
|
}
|
|
80
78
|
function antiDriftConfig() {
|
|
81
79
|
return `## Swarm Configuration & Anti-Drift
|
|
@@ -103,11 +101,11 @@ When the user requests a complex task, spawn agents in background and WAIT:
|
|
|
103
101
|
Bash("npx @claude-flow/cli@latest swarm init --topology hierarchical --max-agents 8 --strategy specialized")
|
|
104
102
|
|
|
105
103
|
// STEP 2: Spawn ALL agents IN BACKGROUND in a SINGLE message
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
104
|
+
Agent("Research requirements", "Analyze codebase patterns and store findings in memory", {subagent_type: "researcher", run_in_background: true})
|
|
105
|
+
Agent("Design architecture", "Design architecture based on research", {subagent_type: "system-architect", run_in_background: true})
|
|
106
|
+
Agent("Implement solution", "Implement the solution following the design", {subagent_type: "coder", run_in_background: true})
|
|
107
|
+
Agent("Write tests", "Write comprehensive tests for the implementation", {subagent_type: "tester", run_in_background: true})
|
|
108
|
+
Agent("Review code quality", "Review code quality, security, and best practices", {subagent_type: "reviewer", run_in_background: true})
|
|
111
109
|
\`\`\`
|
|
112
110
|
|
|
113
111
|
### Agent Routing
|
|
@@ -128,10 +126,10 @@ Task({prompt: "Review code quality...", subagent_type: "reviewer", run_in_backgr
|
|
|
128
126
|
function executionRules() {
|
|
129
127
|
return `## Swarm Execution Rules
|
|
130
128
|
|
|
131
|
-
- ALWAYS use \`run_in_background: true\` for all
|
|
132
|
-
- ALWAYS put ALL
|
|
129
|
+
- ALWAYS use \`run_in_background: true\` for all Agent tool calls
|
|
130
|
+
- ALWAYS put ALL Agent calls in ONE message for parallel execution
|
|
133
131
|
- After spawning, STOP — do NOT add more tool calls or check status
|
|
134
|
-
- Never poll
|
|
132
|
+
- Never poll agent status repeatedly — trust agents to return
|
|
135
133
|
- When agent results arrive, review ALL results before proceeding`;
|
|
136
134
|
}
|
|
137
135
|
function cliCommandsTable() {
|
|
@@ -407,7 +405,7 @@ npx @claude-flow/cli@latest doctor --fix
|
|
|
407
405
|
|
|
408
406
|
## Claude Code vs MCP Tools
|
|
409
407
|
|
|
410
|
-
- **Claude Code
|
|
408
|
+
- **Claude Code Agent tool** handles execution: agents, file ops, code generation, git
|
|
411
409
|
- **MCP tools** (via ToolSearch) handle coordination: swarm, memory, hooks, routing, hive-mind
|
|
412
410
|
- **CLI commands** (via Bash) are the same tools with terminal output
|
|
413
411
|
- Use \`ToolSearch("keyword")\` to discover available MCP tools
|
|
@@ -291,6 +291,7 @@ async function getSemanticRouter() {
|
|
|
291
291
|
}
|
|
292
292
|
nativeVectorDb = db;
|
|
293
293
|
routerBackend = 'native';
|
|
294
|
+
console.log('[hooks] Semantic router initialized: native VectorDb (HNSW, 16k+ routes/s)');
|
|
294
295
|
return { router: null, backend: routerBackend, native: nativeVectorDb };
|
|
295
296
|
}
|
|
296
297
|
}
|
|
@@ -312,10 +313,12 @@ async function getSemanticRouter() {
|
|
|
312
313
|
});
|
|
313
314
|
}
|
|
314
315
|
routerBackend = 'pure-js';
|
|
316
|
+
console.log('[hooks] Semantic router initialized: pure JS (cosine, 47k routes/s)');
|
|
315
317
|
}
|
|
316
318
|
catch {
|
|
317
319
|
semanticRouter = null;
|
|
318
320
|
routerBackend = 'none';
|
|
321
|
+
console.log('[hooks] Semantic router initialized: none (no backend available)');
|
|
319
322
|
}
|
|
320
323
|
return { router: semanticRouter, backend: routerBackend, native: nativeVectorDb };
|
|
321
324
|
}
|
|
@@ -2801,18 +2804,59 @@ export const hooksIntelligenceAttention = {
|
|
|
2801
2804
|
return { success: false, error: v.error };
|
|
2802
2805
|
}
|
|
2803
2806
|
let implementation = 'placeholder';
|
|
2807
|
+
let embeddingSource = 'none';
|
|
2804
2808
|
const results = [];
|
|
2809
|
+
// Helper: generate query embedding, preferring real ONNX embeddings over hash fallback
|
|
2810
|
+
async function getQueryEmbedding(text, dims) {
|
|
2811
|
+
// Try ONNX via @claude-flow/embeddings
|
|
2812
|
+
try {
|
|
2813
|
+
const embeddingsModule = await import('@claude-flow/embeddings').catch(() => null);
|
|
2814
|
+
if (embeddingsModule?.createEmbeddingService) {
|
|
2815
|
+
const service = embeddingsModule.createEmbeddingService({ provider: 'onnx' });
|
|
2816
|
+
const result = await service.embed(text);
|
|
2817
|
+
const arr = new Float32Array(dims);
|
|
2818
|
+
for (let i = 0; i < Math.min(dims, result.embedding.length); i++) {
|
|
2819
|
+
arr[i] = result.embedding[i];
|
|
2820
|
+
}
|
|
2821
|
+
return { embedding: arr, source: 'onnx' };
|
|
2822
|
+
}
|
|
2823
|
+
}
|
|
2824
|
+
catch {
|
|
2825
|
+
// ONNX not available, try agentic-flow
|
|
2826
|
+
}
|
|
2827
|
+
// Try agentic-flow embeddings
|
|
2828
|
+
try {
|
|
2829
|
+
const embeddingsModule = await import('@claude-flow/embeddings').catch(() => null);
|
|
2830
|
+
if (embeddingsModule?.createEmbeddingService) {
|
|
2831
|
+
const service = embeddingsModule.createEmbeddingService({ provider: 'agentic-flow' });
|
|
2832
|
+
const result = await service.embed(text);
|
|
2833
|
+
const arr = new Float32Array(dims);
|
|
2834
|
+
for (let i = 0; i < Math.min(dims, result.embedding.length); i++) {
|
|
2835
|
+
arr[i] = result.embedding[i];
|
|
2836
|
+
}
|
|
2837
|
+
return { embedding: arr, source: 'onnx' };
|
|
2838
|
+
}
|
|
2839
|
+
}
|
|
2840
|
+
catch {
|
|
2841
|
+
// agentic-flow not available
|
|
2842
|
+
}
|
|
2843
|
+
// Hash-based fallback (deterministic but not semantic)
|
|
2844
|
+
const arr = new Float32Array(dims);
|
|
2845
|
+
let seed = text.split('').reduce((acc, char, i) => acc + char.charCodeAt(0) * (i + 1), 0);
|
|
2846
|
+
for (let i = 0; i < dims; i++) {
|
|
2847
|
+
seed = (seed * 1103515245 + 12345) & 0x7fffffff;
|
|
2848
|
+
arr[i] = (seed / 0x7fffffff) * 2 - 1;
|
|
2849
|
+
}
|
|
2850
|
+
return { embedding: arr, source: 'hash-fallback' };
|
|
2851
|
+
}
|
|
2805
2852
|
if (mode === 'moe') {
|
|
2806
2853
|
// Try MoE routing
|
|
2807
2854
|
const moe = await getMoERouter();
|
|
2808
2855
|
if (moe) {
|
|
2809
2856
|
try {
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
embedding[i] = Math.sin(query.charCodeAt(i % query.length) * (i + 1) * 0.01);
|
|
2814
|
-
}
|
|
2815
|
-
const routingResult = moe.route(embedding);
|
|
2857
|
+
const embResult = await getQueryEmbedding(query, 384);
|
|
2858
|
+
embeddingSource = embResult.source;
|
|
2859
|
+
const routingResult = moe.route(embResult.embedding);
|
|
2816
2860
|
for (let i = 0; i < Math.min(topK, routingResult.experts.length); i++) {
|
|
2817
2861
|
const expert = routingResult.experts[i];
|
|
2818
2862
|
results.push({
|
|
@@ -2834,13 +2878,11 @@ export const hooksIntelligenceAttention = {
|
|
|
2834
2878
|
const flash = await getFlashAttention();
|
|
2835
2879
|
if (flash) {
|
|
2836
2880
|
try {
|
|
2837
|
-
|
|
2838
|
-
|
|
2881
|
+
const embResult = await getQueryEmbedding(query, 384);
|
|
2882
|
+
embeddingSource = embResult.source;
|
|
2883
|
+
const q = embResult.embedding;
|
|
2839
2884
|
const keys = [];
|
|
2840
2885
|
const values = [];
|
|
2841
|
-
for (let i = 0; i < 384; i++) {
|
|
2842
|
-
q[i] = Math.sin(query.charCodeAt(i % query.length) * (i + 1) * 0.01);
|
|
2843
|
-
}
|
|
2844
2886
|
// Generate some keys/values
|
|
2845
2887
|
for (let k = 0; k < topK; k++) {
|
|
2846
2888
|
const key = new Float32Array(384);
|
|
@@ -2883,10 +2925,13 @@ export const hooksIntelligenceAttention = {
|
|
|
2883
2925
|
results,
|
|
2884
2926
|
stats: {
|
|
2885
2927
|
computeTimeMs,
|
|
2886
|
-
|
|
2887
|
-
|
|
2928
|
+
implementation,
|
|
2929
|
+
_embeddingSource: embeddingSource,
|
|
2888
2930
|
_stub: implementation === 'none',
|
|
2889
2931
|
_note: implementation === 'none' ? 'No attention backend available. Install @ruvector/attention for real computation.' : undefined,
|
|
2932
|
+
...(embeddingSource === 'hash-fallback' && implementation !== 'none'
|
|
2933
|
+
? { _embeddingNote: 'Query embeddings are hash-based (not semantic). Install @claude-flow/embeddings for real ONNX embeddings.' }
|
|
2934
|
+
: {}),
|
|
2890
2935
|
},
|
|
2891
2936
|
implementation,
|
|
2892
2937
|
};
|
|
@@ -25,7 +25,7 @@ try {
|
|
|
25
25
|
realEmbeddings = { embed: (text) => rb.computeEmbedding(text) };
|
|
26
26
|
embeddingServiceName = 'agentic-flow/reasoningbank';
|
|
27
27
|
}
|
|
28
|
-
// Tier 2: @claude-flow/embeddings
|
|
28
|
+
// Tier 2: @claude-flow/embeddings with agentic-flow provider
|
|
29
29
|
if (!realEmbeddings) {
|
|
30
30
|
const embeddingsModule = await import('@claude-flow/embeddings').catch(() => null);
|
|
31
31
|
if (embeddingsModule?.createEmbeddingService) {
|
|
@@ -40,6 +40,34 @@ try {
|
|
|
40
40
|
embeddingServiceName = 'agentic-flow';
|
|
41
41
|
}
|
|
42
42
|
catch {
|
|
43
|
+
// agentic-flow provider not available, try ONNX
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// Tier 3: @claude-flow/embeddings with ONNX provider
|
|
48
|
+
if (!realEmbeddings) {
|
|
49
|
+
const embeddingsModule = await import('@claude-flow/embeddings').catch(() => null);
|
|
50
|
+
if (embeddingsModule?.createEmbeddingService) {
|
|
51
|
+
try {
|
|
52
|
+
const service = embeddingsModule.createEmbeddingService({ provider: 'onnx' });
|
|
53
|
+
realEmbeddings = {
|
|
54
|
+
embed: async (text) => {
|
|
55
|
+
const result = await service.embed(text);
|
|
56
|
+
return Array.from(result.embedding);
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
embeddingServiceName = 'onnx';
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// ONNX provider not available, fall through to mock
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Tier 4: mock fallback (last resort — embeddings are not semantic)
|
|
67
|
+
if (!realEmbeddings) {
|
|
68
|
+
const embeddingsModule = await import('@claude-flow/embeddings').catch(() => null);
|
|
69
|
+
if (embeddingsModule?.createEmbeddingService) {
|
|
70
|
+
try {
|
|
43
71
|
const service = embeddingsModule.createEmbeddingService({ provider: 'mock' });
|
|
44
72
|
realEmbeddings = {
|
|
45
73
|
embed: async (text) => {
|
|
@@ -47,7 +75,10 @@ try {
|
|
|
47
75
|
return Array.from(result.embedding);
|
|
48
76
|
},
|
|
49
77
|
};
|
|
50
|
-
embeddingServiceName = 'mock';
|
|
78
|
+
embeddingServiceName = 'mock-fallback';
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// No embedding service available at all
|
|
51
82
|
}
|
|
52
83
|
}
|
|
53
84
|
}
|
|
@@ -100,7 +131,11 @@ async function generateEmbedding(text, dims = 384) {
|
|
|
100
131
|
}
|
|
101
132
|
}
|
|
102
133
|
// Hash-based deterministic embedding (better than pure random for consistency)
|
|
134
|
+
// NOTE: No semantic meaning — only useful for consistent deduplication, not similarity search
|
|
103
135
|
if (text) {
|
|
136
|
+
if (embeddingServiceName === 'none') {
|
|
137
|
+
embeddingServiceName = 'hash-fallback';
|
|
138
|
+
}
|
|
104
139
|
const hash = text.split('').reduce((acc, char, i) => {
|
|
105
140
|
return acc + char.charCodeAt(0) * (i + 1);
|
|
106
141
|
}, 0);
|
|
@@ -207,6 +242,8 @@ export const neuralTools = [
|
|
|
207
242
|
return {
|
|
208
243
|
success: true,
|
|
209
244
|
_realEmbedding: !!realEmbeddings,
|
|
245
|
+
_embeddingSource: embeddingServiceName,
|
|
246
|
+
embeddingProvider: embeddingServiceName,
|
|
210
247
|
modelId,
|
|
211
248
|
type: modelType,
|
|
212
249
|
status: model.status,
|
|
@@ -275,6 +312,8 @@ export const neuralTools = [
|
|
|
275
312
|
return {
|
|
276
313
|
success: true,
|
|
277
314
|
_realEmbedding: !!realEmbeddings,
|
|
315
|
+
_embeddingSource: embeddingServiceName,
|
|
316
|
+
embeddingProvider: embeddingServiceName,
|
|
278
317
|
_hasStoredPatterns: storedPatterns.length > 0,
|
|
279
318
|
modelId: model?.id || 'default',
|
|
280
319
|
input: inputText,
|
|
@@ -364,6 +403,8 @@ export const neuralTools = [
|
|
|
364
403
|
return {
|
|
365
404
|
success: true,
|
|
366
405
|
_realEmbedding: !!realEmbeddings,
|
|
406
|
+
_embeddingSource: embeddingServiceName,
|
|
407
|
+
embeddingProvider: embeddingServiceName,
|
|
367
408
|
patternId,
|
|
368
409
|
name: pattern.name,
|
|
369
410
|
type: pattern.type,
|
|
@@ -386,6 +427,8 @@ export const neuralTools = [
|
|
|
386
427
|
return {
|
|
387
428
|
_realSimilarity: true,
|
|
388
429
|
_realEmbedding: !!realEmbeddings,
|
|
430
|
+
_embeddingSource: embeddingServiceName,
|
|
431
|
+
embeddingProvider: embeddingServiceName,
|
|
389
432
|
query,
|
|
390
433
|
results: results.map(r => ({
|
|
391
434
|
id: r.id,
|
|
@@ -455,6 +498,7 @@ export const neuralTools = [
|
|
|
455
498
|
saveNeuralStore(store);
|
|
456
499
|
return {
|
|
457
500
|
success: true, _real: true, method,
|
|
501
|
+
embeddingProvider: embeddingServiceName,
|
|
458
502
|
patternsCompressed: totalCompressed,
|
|
459
503
|
compressionRatio: '3.92x (Int8)',
|
|
460
504
|
beforeBytes: beforeSize,
|
|
@@ -478,6 +522,7 @@ export const neuralTools = [
|
|
|
478
522
|
saveNeuralStore(store);
|
|
479
523
|
return {
|
|
480
524
|
success: true, _real: true, method,
|
|
525
|
+
embeddingProvider: embeddingServiceName,
|
|
481
526
|
threshold,
|
|
482
527
|
patternsRemoved: toRemove.length,
|
|
483
528
|
patternsBefore: beforeCount,
|
|
@@ -511,6 +556,7 @@ export const neuralTools = [
|
|
|
511
556
|
saveNeuralStore(store);
|
|
512
557
|
return {
|
|
513
558
|
success: true, _real: true, method,
|
|
559
|
+
embeddingProvider: embeddingServiceName,
|
|
514
560
|
patternsMerged: merged.length,
|
|
515
561
|
patternsBefore: beforeCount,
|
|
516
562
|
patternsAfter: Object.keys(store.patterns).length,
|
|
@@ -670,6 +716,7 @@ export const neuralTools = [
|
|
|
670
716
|
const elapsed = Math.round(performance.now() - startTime);
|
|
671
717
|
return {
|
|
672
718
|
success: true, _real: true, target,
|
|
719
|
+
embeddingProvider: embeddingServiceName,
|
|
673
720
|
actions,
|
|
674
721
|
patternsBefore: beforeCount,
|
|
675
722
|
patternsAfter: Object.keys(store.patterns).length,
|
|
@@ -233,15 +233,15 @@ export const performanceTools = [
|
|
|
233
233
|
const suite = input.suite || 'all';
|
|
234
234
|
const iterations = input.iterations || 100;
|
|
235
235
|
const warmup = input.warmup !== false;
|
|
236
|
-
//
|
|
236
|
+
// Synthetic data benchmarks — measures actual CPU/memory throughput
|
|
237
237
|
const benchmarkFunctions = {
|
|
238
238
|
memory: () => {
|
|
239
|
-
//
|
|
239
|
+
// Synthetic data benchmark — measures actual allocation + sort throughput
|
|
240
240
|
const arr = new Array(1000).fill(0).map(() => Math.random());
|
|
241
241
|
arr.sort();
|
|
242
242
|
},
|
|
243
243
|
neural: () => {
|
|
244
|
-
//
|
|
244
|
+
// Synthetic data benchmark — measures actual matrix multiplication throughput
|
|
245
245
|
const size = 64;
|
|
246
246
|
const a = Array.from({ length: size }, () => Array.from({ length: size }, () => Math.random()));
|
|
247
247
|
const b = Array.from({ length: size }, () => Array.from({ length: size }, () => Math.random()));
|
|
@@ -255,14 +255,14 @@ export const performanceTools = [
|
|
|
255
255
|
}
|
|
256
256
|
},
|
|
257
257
|
swarm: () => {
|
|
258
|
-
//
|
|
258
|
+
// Synthetic data benchmark — measures actual object creation + manipulation throughput
|
|
259
259
|
const agents = Array.from({ length: 10 }, (_, i) => ({ id: i, status: 'active', tasks: [] }));
|
|
260
260
|
agents.forEach(a => { for (let i = 0; i < 100; i++)
|
|
261
261
|
a.tasks.push(i); });
|
|
262
262
|
agents.sort((a, b) => a.tasks.length - b.tasks.length);
|
|
263
263
|
},
|
|
264
264
|
io: () => {
|
|
265
|
-
//
|
|
265
|
+
// Synthetic data benchmark — measures actual JSON serialization throughput
|
|
266
266
|
const data = { agents: Array.from({ length: 50 }, (_, i) => ({ id: i, name: `agent-${i}` })) };
|
|
267
267
|
const json = JSON.stringify(data);
|
|
268
268
|
JSON.parse(json);
|
|
@@ -313,6 +313,7 @@ export const performanceTools = [
|
|
|
313
313
|
avgLatency: `${avgLatencyMs.toFixed(3)}ms`,
|
|
314
314
|
memoryUsage: `${Math.abs(memoryDelta)}KB`,
|
|
315
315
|
_real: true,
|
|
316
|
+
_dataSource: 'synthetic',
|
|
316
317
|
});
|
|
317
318
|
}
|
|
318
319
|
}
|
|
@@ -330,6 +331,7 @@ export const performanceTools = [
|
|
|
330
331
|
: { note: 'First benchmark run - no comparison available', totalBenchmarks: allBenchmarks.length };
|
|
331
332
|
return {
|
|
332
333
|
_real: true,
|
|
334
|
+
_note: 'Benchmarks use synthetic workloads to measure throughput. Results reflect actual CPU/memory performance.',
|
|
333
335
|
suite,
|
|
334
336
|
iterations,
|
|
335
337
|
warmup,
|
|
@@ -10,10 +10,11 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { getProjectCwd } from './types.js';
|
|
12
12
|
import { validateIdentifier } from './validate-input.js';
|
|
13
|
-
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
13
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, statfsSync } from 'node:fs';
|
|
14
14
|
import { join, dirname } from 'node:path';
|
|
15
15
|
import { fileURLToPath } from 'node:url';
|
|
16
16
|
import * as os from 'node:os';
|
|
17
|
+
import * as dns from 'node:dns';
|
|
17
18
|
// Read version dynamically from package.json
|
|
18
19
|
function getPackageVersion() {
|
|
19
20
|
try {
|
|
@@ -332,26 +333,60 @@ export const systemTools = [
|
|
|
332
333
|
message: 'Neural network health not monitored',
|
|
333
334
|
});
|
|
334
335
|
if (input.deep) {
|
|
335
|
-
// Disk check — real free space
|
|
336
|
+
// Disk check — real free space via statfsSync (Node 18.15+)
|
|
336
337
|
{
|
|
337
338
|
const t0 = performance.now();
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
339
|
+
try {
|
|
340
|
+
const stats = statfsSync(projectCwd);
|
|
341
|
+
const totalBytes = stats.blocks * stats.bsize;
|
|
342
|
+
const freeBytes = stats.bfree * stats.bsize;
|
|
343
|
+
const totalGB = Math.round((totalBytes / (1024 ** 3)) * 10) / 10;
|
|
344
|
+
const freeGB = Math.round((freeBytes / (1024 ** 3)) * 10) / 10;
|
|
345
|
+
const freePercent = Math.round((freeBytes / totalBytes) * 100);
|
|
346
|
+
const elapsed = performance.now() - t0;
|
|
347
|
+
checks.push({
|
|
348
|
+
name: 'disk',
|
|
349
|
+
status: freePercent > 10 ? 'healthy' : 'warning',
|
|
350
|
+
latency: Math.round(elapsed * 100) / 100,
|
|
351
|
+
message: `${freeGB}GB free of ${totalGB}GB (${freePercent}%)`,
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
catch {
|
|
355
|
+
const elapsed = performance.now() - t0;
|
|
356
|
+
checks.push({
|
|
357
|
+
name: 'disk',
|
|
358
|
+
status: 'unknown',
|
|
359
|
+
latency: Math.round(elapsed * 100) / 100,
|
|
360
|
+
message: 'Disk space check failed — statfsSync unavailable',
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
// Network — DNS resolution check with timeout
|
|
365
|
+
{
|
|
366
|
+
const t0 = performance.now();
|
|
367
|
+
try {
|
|
368
|
+
await Promise.race([
|
|
369
|
+
dns.promises.lookup('registry.npmjs.org'),
|
|
370
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), 3000)),
|
|
371
|
+
]);
|
|
372
|
+
const elapsed = performance.now() - t0;
|
|
373
|
+
checks.push({
|
|
374
|
+
name: 'network',
|
|
375
|
+
status: 'healthy',
|
|
376
|
+
latency: Math.round(elapsed * 100) / 100,
|
|
377
|
+
message: 'DNS resolution working',
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
catch {
|
|
381
|
+
const elapsed = performance.now() - t0;
|
|
382
|
+
checks.push({
|
|
383
|
+
name: 'network',
|
|
384
|
+
status: 'warning',
|
|
385
|
+
latency: Math.round(elapsed * 100) / 100,
|
|
386
|
+
message: 'DNS resolution failed — check network',
|
|
387
|
+
});
|
|
388
|
+
}
|
|
348
389
|
}
|
|
349
|
-
// Network — cannot verify without making a request
|
|
350
|
-
checks.push({
|
|
351
|
-
name: 'network',
|
|
352
|
-
status: 'unknown',
|
|
353
|
-
message: 'Network connectivity not monitored',
|
|
354
|
-
});
|
|
355
390
|
// Database — check if coordination store exists
|
|
356
391
|
{
|
|
357
392
|
const t0 = performance.now();
|
|
@@ -60,7 +60,7 @@ export interface RoutingSuggestion {
|
|
|
60
60
|
/** Whether Q-learning was used */
|
|
61
61
|
usedQLearning: boolean;
|
|
62
62
|
/** Source of recommendation */
|
|
63
|
-
source: 'sona-pattern' | 'q-learning' | 'keyword
|
|
63
|
+
source: 'sona-native' | 'sona-pattern' | 'q-learning' | 'sona-keyword' | 'default';
|
|
64
64
|
/** Alternative agents with scores */
|
|
65
65
|
alternatives: Array<{
|
|
66
66
|
agent: string;
|
|
@@ -103,9 +103,20 @@ export declare class SONAOptimizer {
|
|
|
103
103
|
private persistencePath;
|
|
104
104
|
private qLearningRouter;
|
|
105
105
|
private qLearningEnabled;
|
|
106
|
+
/** Real @ruvector/sona engine — null if native not available, undefined if not yet tried */
|
|
107
|
+
private sonaEngine;
|
|
106
108
|
constructor(options?: {
|
|
107
109
|
persistencePath?: string;
|
|
108
110
|
});
|
|
111
|
+
/**
|
|
112
|
+
* Attempt to load the native @ruvector/sona engine (once).
|
|
113
|
+
* Sets `sonaEngine` to the engine instance or null if unavailable.
|
|
114
|
+
*/
|
|
115
|
+
private loadSonaEngine;
|
|
116
|
+
/**
|
|
117
|
+
* Infer an agent type string from a SONA pattern result object.
|
|
118
|
+
*/
|
|
119
|
+
private inferAgentFromPattern;
|
|
109
120
|
/**
|
|
110
121
|
* Initialize the optimizer and load persisted state
|
|
111
122
|
*/
|
|
@@ -124,9 +135,16 @@ export declare class SONAOptimizer {
|
|
|
124
135
|
keywordsExtracted: string[];
|
|
125
136
|
};
|
|
126
137
|
/**
|
|
127
|
-
* Get routing suggestion based on learned patterns
|
|
138
|
+
* Get routing suggestion based on learned patterns.
|
|
139
|
+
*
|
|
140
|
+
* Priority order:
|
|
141
|
+
* 1. Real @ruvector/sona native engine (if available and has matches)
|
|
142
|
+
* 2. SONA learned pattern matching (keyword overlap + confidence)
|
|
143
|
+
* 3. Q-learning router (if enabled)
|
|
144
|
+
* 4. Keyword heuristic
|
|
145
|
+
* 5. Default fallback
|
|
128
146
|
*/
|
|
129
|
-
getRoutingSuggestion(task: string): RoutingSuggestion
|
|
147
|
+
getRoutingSuggestion(task: string): Promise<RoutingSuggestion>;
|
|
130
148
|
/**
|
|
131
149
|
* Get optimizer statistics
|
|
132
150
|
*/
|
|
@@ -104,9 +104,44 @@ export class SONAOptimizer {
|
|
|
104
104
|
persistencePath;
|
|
105
105
|
qLearningRouter = null;
|
|
106
106
|
qLearningEnabled = false;
|
|
107
|
+
/** Real @ruvector/sona engine — null if native not available, undefined if not yet tried */
|
|
108
|
+
sonaEngine = undefined;
|
|
107
109
|
constructor(options) {
|
|
108
110
|
this.persistencePath = options?.persistencePath || DEFAULT_PERSISTENCE_PATH;
|
|
109
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* Attempt to load the native @ruvector/sona engine (once).
|
|
114
|
+
* Sets `sonaEngine` to the engine instance or null if unavailable.
|
|
115
|
+
*/
|
|
116
|
+
async loadSonaEngine() {
|
|
117
|
+
if (this.sonaEngine !== undefined)
|
|
118
|
+
return; // already attempted
|
|
119
|
+
try {
|
|
120
|
+
const sona = await import('@ruvector/sona');
|
|
121
|
+
const EngineCtor = sona.SonaEngine || sona.default?.SonaEngine;
|
|
122
|
+
if (EngineCtor) {
|
|
123
|
+
this.sonaEngine = new EngineCtor({ mode: 'real-time' });
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
this.sonaEngine = null;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
this.sonaEngine = null; // native not available
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Infer an agent type string from a SONA pattern result object.
|
|
135
|
+
*/
|
|
136
|
+
inferAgentFromPattern(pattern) {
|
|
137
|
+
if (typeof pattern.agent === 'string')
|
|
138
|
+
return pattern.agent;
|
|
139
|
+
if (typeof pattern.route === 'string')
|
|
140
|
+
return pattern.route;
|
|
141
|
+
if (typeof pattern.label === 'string')
|
|
142
|
+
return pattern.label;
|
|
143
|
+
return 'coder';
|
|
144
|
+
}
|
|
110
145
|
/**
|
|
111
146
|
* Initialize the optimizer and load persisted state
|
|
112
147
|
*/
|
|
@@ -193,11 +228,43 @@ export class SONAOptimizer {
|
|
|
193
228
|
};
|
|
194
229
|
}
|
|
195
230
|
/**
|
|
196
|
-
* Get routing suggestion based on learned patterns
|
|
231
|
+
* Get routing suggestion based on learned patterns.
|
|
232
|
+
*
|
|
233
|
+
* Priority order:
|
|
234
|
+
* 1. Real @ruvector/sona native engine (if available and has matches)
|
|
235
|
+
* 2. SONA learned pattern matching (keyword overlap + confidence)
|
|
236
|
+
* 3. Q-learning router (if enabled)
|
|
237
|
+
* 4. Keyword heuristic
|
|
238
|
+
* 5. Default fallback
|
|
197
239
|
*/
|
|
198
|
-
getRoutingSuggestion(task) {
|
|
240
|
+
async getRoutingSuggestion(task) {
|
|
241
|
+
// Priority 1: Try real @ruvector/sona native engine
|
|
242
|
+
await this.loadSonaEngine();
|
|
243
|
+
if (this.sonaEngine) {
|
|
244
|
+
try {
|
|
245
|
+
const patterns = this.sonaEngine.findPatterns(task, 3);
|
|
246
|
+
if (patterns && patterns.length > 0) {
|
|
247
|
+
const best = patterns[0];
|
|
248
|
+
const agent = best.route || best.agent || this.inferAgentFromPattern(best);
|
|
249
|
+
return {
|
|
250
|
+
agent,
|
|
251
|
+
confidence: best.quality || 0.8,
|
|
252
|
+
usedQLearning: false,
|
|
253
|
+
source: 'sona-native',
|
|
254
|
+
alternatives: patterns.slice(1).map((p) => ({
|
|
255
|
+
agent: p.route || p.agent || this.inferAgentFromPattern(p),
|
|
256
|
+
score: p.quality || 0.5,
|
|
257
|
+
})),
|
|
258
|
+
matchedKeywords: best.keywords || [],
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
catch {
|
|
263
|
+
// Native SONA failed on this query — fall through to keyword matching
|
|
264
|
+
}
|
|
265
|
+
}
|
|
199
266
|
const keywords = this.extractKeywords(task);
|
|
200
|
-
// Try SONA pattern matching
|
|
267
|
+
// Priority 2: Try SONA learned pattern matching
|
|
201
268
|
const sonaResult = this.findBestPatternMatch(keywords);
|
|
202
269
|
if (sonaResult && sonaResult.confidence >= 0.6) {
|
|
203
270
|
return {
|
|
@@ -209,7 +276,7 @@ export class SONAOptimizer {
|
|
|
209
276
|
matchedKeywords: sonaResult.matchedKeywords,
|
|
210
277
|
};
|
|
211
278
|
}
|
|
212
|
-
// Try Q-learning router if available
|
|
279
|
+
// Priority 3: Try Q-learning router if available
|
|
213
280
|
if (this.qLearningRouter && this.qLearningEnabled) {
|
|
214
281
|
try {
|
|
215
282
|
const decision = this.qLearningRouter.route(task, false);
|
|
@@ -227,19 +294,19 @@ export class SONAOptimizer {
|
|
|
227
294
|
// Q-learning failed, continue to fallback
|
|
228
295
|
}
|
|
229
296
|
}
|
|
230
|
-
//
|
|
297
|
+
// Priority 4: Keyword-based heuristic
|
|
231
298
|
const keywordMatch = this.matchKeywordsToAgent(keywords);
|
|
232
299
|
if (keywordMatch) {
|
|
233
300
|
return {
|
|
234
301
|
agent: keywordMatch.agent,
|
|
235
302
|
confidence: keywordMatch.confidence,
|
|
236
303
|
usedQLearning: false,
|
|
237
|
-
source: 'keyword
|
|
304
|
+
source: 'sona-keyword',
|
|
238
305
|
alternatives: this.getAlternatives(keywords, keywordMatch.agent),
|
|
239
306
|
matchedKeywords: keywordMatch.matchedKeywords,
|
|
240
307
|
};
|
|
241
308
|
}
|
|
242
|
-
// Default fallback
|
|
309
|
+
// Priority 5: Default fallback
|
|
243
310
|
return {
|
|
244
311
|
agent: 'coder',
|
|
245
312
|
confidence: 0.3,
|
|
@@ -52,6 +52,10 @@ export declare function createVectorDB(dimensions?: number): Promise<VectorDB>;
|
|
|
52
52
|
/**
|
|
53
53
|
* Generate an embedding for text
|
|
54
54
|
* Uses ruvector if available, falls back to hash-based embedding
|
|
55
|
+
*
|
|
56
|
+
* @returns The embedding vector. When using hash fallback, the returned
|
|
57
|
+
* Float32Array will have a `_warning` property (non-enumerable)
|
|
58
|
+
* indicating it lacks semantic meaning.
|
|
55
59
|
*/
|
|
56
60
|
export declare function generateEmbedding(text: string, dimensions?: number): Float32Array;
|
|
57
61
|
/**
|