claude-flow 3.6.14 → 3.6.16
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/.claude/scheduled_tasks.lock +1 -0
- package/package.json +13 -2
- package/v3/@claude-flow/cli/bin/cli.js +20 -4
- package/v3/@claude-flow/cli/bin/mcp-server.js +13 -2
- package/v3/@claude-flow/cli/dist/src/mcp-tools/coordination-tools.js +27 -2
- package/v3/@claude-flow/cli/dist/src/mcp-tools/hooks-tools.js +65 -15
- package/v3/@claude-flow/cli/dist/src/mcp-tools/neural-tools.js +71 -12
- package/v3/@claude-flow/cli/dist/src/mcp-tools/performance-tools.js +30 -7
- package/v3/@claude-flow/cli/dist/src/memory/memory-bridge.js +115 -37
- package/v3/@claude-flow/cli/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"sessionId":"36428a63-dfb2-42a4-a159-cf8be916193e","pid":86429,"procStart":"Sun May 3 19:17:47 2026","acquiredAt":1777840775529}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-flow",
|
|
3
|
-
"version": "3.6.
|
|
3
|
+
"version": "3.6.16",
|
|
4
4
|
"description": "Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -70,7 +70,18 @@
|
|
|
70
70
|
},
|
|
71
71
|
"overrides": {
|
|
72
72
|
"hono": ">=4.11.4",
|
|
73
|
-
"@ruvector/rvf-wasm": "0.1.5"
|
|
73
|
+
"@ruvector/rvf-wasm": "0.1.5",
|
|
74
|
+
"@hono/node-server": ">=1.19.10",
|
|
75
|
+
"flatted": ">=3.4.0",
|
|
76
|
+
"tar": ">=7.5.0",
|
|
77
|
+
"picomatch": ">=4.0.3",
|
|
78
|
+
"path-to-regexp": ">=8.2.1",
|
|
79
|
+
"undici": ">=7.18.0",
|
|
80
|
+
"minimatch": ">=10.0.0",
|
|
81
|
+
"@isaacs/brace-expansion": ">=5.0.1",
|
|
82
|
+
"cacache": ">=20.0.0",
|
|
83
|
+
"make-fetch-happen": ">=15.0.0",
|
|
84
|
+
"express-rate-limit": ">=8.4.1"
|
|
74
85
|
},
|
|
75
86
|
"devDependencies": {
|
|
76
87
|
"@openai/codex": "^0.98.0",
|
|
@@ -10,14 +10,30 @@
|
|
|
10
10
|
|
|
11
11
|
import { randomUUID } from 'crypto';
|
|
12
12
|
|
|
13
|
-
// Suppress
|
|
14
|
-
//
|
|
13
|
+
// Suppress the SPECIFIC cosmetic "[AgentDB Patch] Controller index not found"
|
|
14
|
+
// warning from agentic-flow's runtime patch — these are emitted because the
|
|
15
|
+
// patch was written for agentdb v1.x and we use v3, where the controllers
|
|
16
|
+
// dist directory is laid out differently. The warning surfaces on every
|
|
17
|
+
// command and the audit (audit_1776483149979) flagged a too-broad suppression
|
|
18
|
+
// as a security risk because it could hide legitimate [AgentDB Patch] warnings.
|
|
19
|
+
//
|
|
20
|
+
// Tight match: must include both the prefix AND the specific "Controller
|
|
21
|
+
// index not found" text. Anything else (including future [AgentDB Patch]
|
|
22
|
+
// warnings about real issues) flows through unchanged. Also patch
|
|
23
|
+
// console.log because the underlying code uses it (the previous filter
|
|
24
|
+
// only caught console.warn and was therefore a no-op).
|
|
15
25
|
const _origWarn = console.warn;
|
|
26
|
+
const _origLog = console.log;
|
|
27
|
+
const _isCosmeticAgentdbPatchNoise = (msg) =>
|
|
28
|
+
msg.includes('[AgentDB Patch]') && msg.includes('Controller index not found');
|
|
16
29
|
console.warn = (...args) => {
|
|
17
|
-
|
|
18
|
-
if (msg.includes('[AgentDB Patch]')) return;
|
|
30
|
+
if (_isCosmeticAgentdbPatchNoise(String(args[0] ?? ''))) return;
|
|
19
31
|
_origWarn.apply(console, args);
|
|
20
32
|
};
|
|
33
|
+
console.log = (...args) => {
|
|
34
|
+
if (_isCosmeticAgentdbPatchNoise(String(args[0] ?? ''))) return;
|
|
35
|
+
_origLog.apply(console, args);
|
|
36
|
+
};
|
|
21
37
|
|
|
22
38
|
// Check if we should run in MCP server mode
|
|
23
39
|
// Conditions:
|
|
@@ -9,12 +9,23 @@
|
|
|
9
9
|
|
|
10
10
|
import { randomUUID } from 'crypto';
|
|
11
11
|
|
|
12
|
-
// Suppress [AgentDB Patch]
|
|
12
|
+
// Suppress the SPECIFIC cosmetic "[AgentDB Patch] Controller index not found"
|
|
13
|
+
// noise. Tight match (both prefix AND "Controller index not found") so other
|
|
14
|
+
// [AgentDB Patch] warnings about real issues still flow through. Also patch
|
|
15
|
+
// console.log because the underlying call site uses it. See bin/cli.js for
|
|
16
|
+
// the same rationale.
|
|
13
17
|
const _origWarn = console.warn;
|
|
18
|
+
const _origLog = console.log;
|
|
19
|
+
const _isCosmeticAgentdbPatchNoise = (msg) =>
|
|
20
|
+
msg.includes('[AgentDB Patch]') && msg.includes('Controller index not found');
|
|
14
21
|
console.warn = (...args) => {
|
|
15
|
-
if (String(args[0] ?? '')
|
|
22
|
+
if (_isCosmeticAgentdbPatchNoise(String(args[0] ?? ''))) return;
|
|
16
23
|
_origWarn.apply(console, args);
|
|
17
24
|
};
|
|
25
|
+
console.log = (...args) => {
|
|
26
|
+
if (_isCosmeticAgentdbPatchNoise(String(args[0] ?? ''))) return;
|
|
27
|
+
_origLog.apply(console, args);
|
|
28
|
+
};
|
|
18
29
|
|
|
19
30
|
import { listMCPTools, callMCPTool, hasTool } from '../dist/src/mcp-client.js';
|
|
20
31
|
|
|
@@ -634,15 +634,40 @@ export const coordinationTools = [
|
|
|
634
634
|
const agents = input.agents || Object.keys(store.nodes);
|
|
635
635
|
const strategy = input.strategy || 'parallel';
|
|
636
636
|
const orchestrationId = `orch-${Date.now()}`;
|
|
637
|
+
// ADR-093 F7: this tool only schedules an orchestration record — it
|
|
638
|
+
// does not actually execute. Previously it returned a hardcoded
|
|
639
|
+
// `estimatedCompletion: "50ms"` which was misleading. Now we return
|
|
640
|
+
// an honest stub-status with a note pointing callers at agent_spawn
|
|
641
|
+
// / Task tool / hive-mind tools for real orchestration. Persist the
|
|
642
|
+
// record so callers can list/inspect what was scheduled.
|
|
643
|
+
const orchestration = {
|
|
644
|
+
id: orchestrationId,
|
|
645
|
+
task,
|
|
646
|
+
strategy,
|
|
647
|
+
agents,
|
|
648
|
+
status: 'scheduled',
|
|
649
|
+
scheduledAt: new Date().toISOString(),
|
|
650
|
+
topology: store.topology.type,
|
|
651
|
+
};
|
|
652
|
+
const orchStore = store;
|
|
653
|
+
if (!Array.isArray(orchStore.orchestrations))
|
|
654
|
+
orchStore.orchestrations = [];
|
|
655
|
+
orchStore.orchestrations.push(orchestration);
|
|
656
|
+
if (orchStore.orchestrations.length > 100) {
|
|
657
|
+
orchStore.orchestrations = orchStore.orchestrations.slice(-100);
|
|
658
|
+
}
|
|
659
|
+
saveCoordStore(orchStore);
|
|
637
660
|
return {
|
|
638
661
|
success: true,
|
|
639
662
|
orchestrationId,
|
|
640
663
|
task,
|
|
641
664
|
strategy,
|
|
642
665
|
agents,
|
|
643
|
-
status: '
|
|
666
|
+
status: 'scheduled',
|
|
644
667
|
topology: store.topology.type,
|
|
645
|
-
|
|
668
|
+
// Honest stub: no executor wired up yet. Don't lie about completion time.
|
|
669
|
+
executor: 'none',
|
|
670
|
+
_note: 'coordination_orchestrate currently records the orchestration request but does not execute it. For real multi-agent execution use agent_spawn + the Task tool, or hive-mind_spawn for queen-led coordination.',
|
|
646
671
|
};
|
|
647
672
|
},
|
|
648
673
|
},
|
|
@@ -2988,40 +2988,90 @@ export const hooksIntelligenceAttention = {
|
|
|
2988
2988
|
}
|
|
2989
2989
|
}
|
|
2990
2990
|
else if (mode === 'flash') {
|
|
2991
|
-
// Try Flash Attention
|
|
2991
|
+
// Try Flash Attention. ADR-093 F10: previously this attended over
|
|
2992
|
+
// synthetic cosine-derived keys/values with constant-vector values,
|
|
2993
|
+
// which produced uniform 0.333 weights and labels like "Flash
|
|
2994
|
+
// attention target #1/2/3". Now we attend over actual stored
|
|
2995
|
+
// patterns when available — real semantic content yields non-uniform
|
|
2996
|
+
// weights and human-readable labels.
|
|
2992
2997
|
const flash = await getFlashAttention();
|
|
2993
2998
|
if (flash) {
|
|
2994
2999
|
try {
|
|
2995
3000
|
const embResult = await getQueryEmbedding(query, 384);
|
|
2996
3001
|
embeddingSource = embResult.source;
|
|
2997
3002
|
const q = embResult.embedding;
|
|
3003
|
+
// Pull real stored patterns to attend over. If none exist yet,
|
|
3004
|
+
// fall back to the synthetic harness but mark it honestly.
|
|
3005
|
+
const realPatterns = [];
|
|
3006
|
+
try {
|
|
3007
|
+
const { searchEntries: searchFn } = await import('../memory/memory-initializer.js');
|
|
3008
|
+
const hits = await searchFn({ query, limit: topK });
|
|
3009
|
+
if (Array.isArray(hits)) {
|
|
3010
|
+
for (const h of hits.slice(0, topK)) {
|
|
3011
|
+
const content = h.content ?? h.value ?? '';
|
|
3012
|
+
const id = String(h.id ?? h.key ?? `pattern-${realPatterns.length}`);
|
|
3013
|
+
realPatterns.push({ id, content: String(content) });
|
|
3014
|
+
}
|
|
3015
|
+
}
|
|
3016
|
+
}
|
|
3017
|
+
catch { /* memory not initialized — fall through to synthetic */ }
|
|
3018
|
+
const useReal = realPatterns.length > 0;
|
|
2998
3019
|
const keys = [];
|
|
2999
3020
|
const values = [];
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3021
|
+
const labels = [];
|
|
3022
|
+
if (useReal) {
|
|
3023
|
+
// Build keys from real pattern embeddings (re-embed if no vector cached)
|
|
3024
|
+
for (let k = 0; k < realPatterns.length; k++) {
|
|
3025
|
+
const p = realPatterns[k];
|
|
3026
|
+
let keyEmbedding;
|
|
3027
|
+
if (p.embedding && p.embedding.length === 384) {
|
|
3028
|
+
keyEmbedding = new Float32Array(p.embedding);
|
|
3029
|
+
}
|
|
3030
|
+
else {
|
|
3031
|
+
const enc = await getQueryEmbedding(p.content.slice(0, 1024), 384);
|
|
3032
|
+
keyEmbedding = enc.embedding;
|
|
3033
|
+
}
|
|
3034
|
+
const value = new Float32Array(384);
|
|
3035
|
+
// Value carries pattern identity strength — magnitude = recency proxy (k position)
|
|
3036
|
+
const strength = 1 / (k + 1);
|
|
3037
|
+
for (let i = 0; i < 384; i++)
|
|
3038
|
+
value[i] = keyEmbedding[i] * strength;
|
|
3039
|
+
keys.push(keyEmbedding);
|
|
3040
|
+
values.push(value);
|
|
3041
|
+
const label = p.content.length > 0
|
|
3042
|
+
? `${p.id}: ${p.content.slice(0, 60)}${p.content.length > 60 ? '…' : ''}`
|
|
3043
|
+
: p.id;
|
|
3044
|
+
labels.push(label);
|
|
3045
|
+
}
|
|
3046
|
+
}
|
|
3047
|
+
else {
|
|
3048
|
+
// No real patterns — surface a synthetic harness honestly.
|
|
3049
|
+
for (let k = 0; k < topK; k++) {
|
|
3050
|
+
const key = new Float32Array(384);
|
|
3051
|
+
const value = new Float32Array(384);
|
|
3052
|
+
for (let i = 0; i < 384; i++) {
|
|
3053
|
+
key[i] = Math.cos((k + 1) * (i + 1) * 0.01);
|
|
3054
|
+
value[i] = k + 1;
|
|
3055
|
+
}
|
|
3056
|
+
keys.push(key);
|
|
3057
|
+
values.push(value);
|
|
3058
|
+
labels.push(`(synthetic harness) pattern #${k + 1}`);
|
|
3007
3059
|
}
|
|
3008
|
-
keys.push(key);
|
|
3009
|
-
values.push(value);
|
|
3010
3060
|
}
|
|
3011
3061
|
const attentionResult = flash.attention([q], keys, values);
|
|
3012
3062
|
// Compute softmax weights from output magnitudes
|
|
3013
3063
|
const outputMags = attentionResult.output[0]
|
|
3014
|
-
? Array.from(attentionResult.output[0]).slice(0,
|
|
3015
|
-
: new Array(
|
|
3064
|
+
? Array.from(attentionResult.output[0]).slice(0, keys.length).map(v => Math.abs(v))
|
|
3065
|
+
: new Array(keys.length).fill(1);
|
|
3016
3066
|
const sumMags = outputMags.reduce((a, b) => a + b, 0) || 1;
|
|
3017
|
-
for (let i = 0; i <
|
|
3067
|
+
for (let i = 0; i < keys.length; i++) {
|
|
3018
3068
|
results.push({
|
|
3019
3069
|
index: i,
|
|
3020
3070
|
weight: outputMags[i] / sumMags,
|
|
3021
|
-
pattern:
|
|
3071
|
+
pattern: labels[i],
|
|
3022
3072
|
});
|
|
3023
3073
|
}
|
|
3024
|
-
implementation = 'real-flash-attention';
|
|
3074
|
+
implementation = useReal ? 'real-flash-attention+memory' : 'real-flash-attention+synthetic-harness';
|
|
3025
3075
|
}
|
|
3026
3076
|
catch {
|
|
3027
3077
|
// Fall back to placeholder
|
|
@@ -222,10 +222,38 @@ export const neuralTools = [
|
|
|
222
222
|
continue;
|
|
223
223
|
const embedding = await generateEmbedding(text, 384);
|
|
224
224
|
const patternId = `${modelId}-train-${i}`;
|
|
225
|
+
// ADR-093 F11: extract a meaningful label instead of dumping raw
|
|
226
|
+
// training JSON as the pattern name. Audit reported neural_predict
|
|
227
|
+
// returned `label: <raw training data JSON>` because the previous
|
|
228
|
+
// fallback was `text.slice(0, 100)` where text was `JSON.stringify(entry)`.
|
|
229
|
+
let label;
|
|
230
|
+
if (typeof entry === 'string') {
|
|
231
|
+
label = entry.slice(0, 80);
|
|
232
|
+
}
|
|
233
|
+
else if (entry && typeof entry === 'object') {
|
|
234
|
+
const e = entry;
|
|
235
|
+
// Prefer common semantic fields over a JSON dump
|
|
236
|
+
const labelField = e.label ?? e.category ?? e.class ?? e.tag ?? e.intent ?? e.name ?? e.title;
|
|
237
|
+
if (typeof labelField === 'string' && labelField.length > 0) {
|
|
238
|
+
label = labelField.slice(0, 80);
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
const summaryField = e.text ?? e.input ?? e.task ?? e.description ?? e.content;
|
|
242
|
+
if (typeof summaryField === 'string' && summaryField.length > 0) {
|
|
243
|
+
label = `${summaryField.slice(0, 60)}${summaryField.length > 60 ? '…' : ''}`;
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
// Last resort: reduce to a stable short hash-like id
|
|
247
|
+
label = `${modelType}:entry-${i}`;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
label = `${modelType}:entry-${i}`;
|
|
253
|
+
}
|
|
225
254
|
store.patterns[patternId] = {
|
|
226
255
|
id: patternId,
|
|
227
|
-
name:
|
|
228
|
-
? String(entry.label) : text.slice(0, 100),
|
|
256
|
+
name: label,
|
|
229
257
|
type: modelType,
|
|
230
258
|
embedding,
|
|
231
259
|
metadata: { modelId, epoch: epochs, index: i, raw: entry },
|
|
@@ -294,36 +322,67 @@ export const neuralTools = [
|
|
|
294
322
|
const startTime = performance.now();
|
|
295
323
|
const embedding = await generateEmbedding(inputText, 384);
|
|
296
324
|
const latency = Math.round(performance.now() - startTime);
|
|
297
|
-
//
|
|
325
|
+
// ADR-093 F11: real classifier head over stored patterns. Previously
|
|
326
|
+
// confidence was the raw cosine similarity (often clamped to 0 when
|
|
327
|
+
// stored embeddings were stale or zero-vectored). Now we run k-NN
|
|
328
|
+
// with cosine distance and apply a temperature-controlled softmax
|
|
329
|
+
// over the top-K so confidence is a proper distribution that sums
|
|
330
|
+
// to 1, and we surface enough metadata to trust the result.
|
|
298
331
|
const storedPatterns = Object.values(store.patterns);
|
|
299
332
|
let predictions;
|
|
300
333
|
if (storedPatterns.length > 0) {
|
|
301
|
-
//
|
|
302
|
-
|
|
303
|
-
.map(p =>
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
334
|
+
// Step 1: k-NN with cosine
|
|
335
|
+
const scored = storedPatterns
|
|
336
|
+
.map(p => {
|
|
337
|
+
const sim = cosineSimilarity(embedding, p.embedding);
|
|
338
|
+
return {
|
|
339
|
+
patternId: p.id,
|
|
340
|
+
label: p.name || p.type || p.id,
|
|
341
|
+
cosineSimilarity: sim,
|
|
342
|
+
};
|
|
343
|
+
})
|
|
344
|
+
.sort((a, b) => b.cosineSimilarity - a.cosineSimilarity)
|
|
309
345
|
.slice(0, topK);
|
|
346
|
+
// Step 2: temperature-softmax over the top-K so confidence sums to 1.
|
|
347
|
+
// Temperature 0.1 sharpens differences between similar candidates.
|
|
348
|
+
const tau = 0.1;
|
|
349
|
+
const exps = scored.map(s => Math.exp(s.cosineSimilarity / tau));
|
|
350
|
+
const z = exps.reduce((a, b) => a + b, 0) || 1;
|
|
351
|
+
predictions = scored.map((s, i) => ({
|
|
352
|
+
label: s.label,
|
|
353
|
+
patternId: s.patternId,
|
|
354
|
+
cosineSimilarity: Number(s.cosineSimilarity.toFixed(4)),
|
|
355
|
+
confidence: Number((exps[i] / z).toFixed(4)),
|
|
356
|
+
}));
|
|
310
357
|
}
|
|
311
358
|
else {
|
|
312
|
-
// No patterns stored — no predictions possible
|
|
359
|
+
// No patterns stored — no predictions possible. Be honest about it
|
|
360
|
+
// instead of returning empty silently.
|
|
313
361
|
predictions = [];
|
|
314
362
|
}
|
|
363
|
+
const topConfidence = predictions[0]?.confidence ?? 0;
|
|
364
|
+
const topSimilarity = predictions[0]?.cosineSimilarity ?? 0;
|
|
315
365
|
return {
|
|
316
366
|
success: true,
|
|
317
367
|
_realEmbedding: !!realEmbeddings,
|
|
318
368
|
_embeddingSource: embeddingServiceName,
|
|
319
369
|
embeddingProvider: embeddingServiceName,
|
|
320
370
|
_hasStoredPatterns: storedPatterns.length > 0,
|
|
371
|
+
_classifierHead: storedPatterns.length > 0 ? 'knn-cosine+softmax(tau=0.1)' : 'none',
|
|
321
372
|
modelId: model?.id || 'default',
|
|
322
373
|
input: inputText,
|
|
323
374
|
predictions,
|
|
375
|
+
// Surface cosineSimilarity separately so callers know whether the
|
|
376
|
+
// softmax confidence reflects true match strength.
|
|
377
|
+
topPrediction: predictions[0]?.label ?? null,
|
|
378
|
+
topConfidence,
|
|
379
|
+
topSimilarity,
|
|
324
380
|
embedding: embedding.slice(0, 8), // Preview of embedding
|
|
325
381
|
embeddingDims: embedding.length,
|
|
326
382
|
latency,
|
|
383
|
+
...(storedPatterns.length === 0 ? {
|
|
384
|
+
_note: 'No patterns stored. Train with neural_train(modelType, trainingData) before predicting.',
|
|
385
|
+
} : {}),
|
|
327
386
|
};
|
|
328
387
|
},
|
|
329
388
|
},
|
|
@@ -74,7 +74,27 @@ export const performanceTools = [
|
|
|
74
74
|
const freeMem = os.freemem();
|
|
75
75
|
// Calculate real CPU usage percentage from load average
|
|
76
76
|
const cpuPercent = (loadAvg[0] / cpus.length) * 100;
|
|
77
|
-
//
|
|
77
|
+
// ADR-093 F8: replace hardcoded latency fixtures (50/40/100/200) with
|
|
78
|
+
// an actual self-measured latency probe. Throughput now reflects real
|
|
79
|
+
// metric collection cadence (calls/min over the stored history) rather
|
|
80
|
+
// than an arbitrary +1/+10 increment per call.
|
|
81
|
+
const probeStart = process.hrtime.bigint();
|
|
82
|
+
// Tiny CPU+memory work that mirrors a typical MCP tool call
|
|
83
|
+
let probeAcc = 0;
|
|
84
|
+
for (let i = 0; i < 1000; i++)
|
|
85
|
+
probeAcc += Math.sqrt(i);
|
|
86
|
+
const probeNs = Number(process.hrtime.bigint() - probeStart);
|
|
87
|
+
const selfLatencyMs = probeNs / 1e6;
|
|
88
|
+
const recent = store.metrics.slice(-10);
|
|
89
|
+
const recentLatencies = recent.map(m => m.latency.avg).filter(n => Number.isFinite(n));
|
|
90
|
+
recentLatencies.push(selfLatencyMs);
|
|
91
|
+
const sorted = [...recentLatencies].sort((a, b) => a - b);
|
|
92
|
+
const pct = (p) => sorted.length === 0 ? selfLatencyMs : sorted[Math.min(sorted.length - 1, Math.floor((p / 100) * sorted.length))];
|
|
93
|
+
const avg = recentLatencies.reduce((s, n) => s + n, 0) / Math.max(1, recentLatencies.length);
|
|
94
|
+
// Throughput from real cadence: count metric samples in the last 60s.
|
|
95
|
+
const cutoff = Date.now() - 60_000;
|
|
96
|
+
const samplesInLastMinute = store.metrics.filter(m => new Date(m.timestamp).getTime() >= cutoff).length + 1;
|
|
97
|
+
const opsPerSecond = samplesInLastMinute / 60;
|
|
78
98
|
const currentMetrics = {
|
|
79
99
|
timestamp: new Date().toISOString(),
|
|
80
100
|
cpu: { usage: Math.min(cpuPercent, 100), cores: cpus.length },
|
|
@@ -84,17 +104,20 @@ export const performanceTools = [
|
|
|
84
104
|
heap: Math.round(memUsage.heapUsed / 1024 / 1024),
|
|
85
105
|
},
|
|
86
106
|
latency: {
|
|
87
|
-
avg:
|
|
88
|
-
p50:
|
|
89
|
-
p95:
|
|
90
|
-
p99:
|
|
107
|
+
avg: Number(avg.toFixed(3)),
|
|
108
|
+
p50: Number(pct(50).toFixed(3)),
|
|
109
|
+
p95: Number(pct(95).toFixed(3)),
|
|
110
|
+
p99: Number(pct(99).toFixed(3)),
|
|
91
111
|
},
|
|
92
112
|
throughput: {
|
|
93
|
-
requests: store.metrics.length
|
|
94
|
-
operations:
|
|
113
|
+
requests: store.metrics.length + 1,
|
|
114
|
+
operations: Number(opsPerSecond.toFixed(2)),
|
|
95
115
|
},
|
|
96
116
|
errors: { count: 0, rate: 0 },
|
|
97
117
|
};
|
|
118
|
+
// probeAcc kept reachable to prevent V8 dead-code elimination of the loop
|
|
119
|
+
if (probeAcc < 0)
|
|
120
|
+
currentMetrics.errors.count = -1;
|
|
98
121
|
store.metrics.push(currentMetrics);
|
|
99
122
|
// Keep last 100 metrics
|
|
100
123
|
if (store.metrics.length > 100) {
|
|
@@ -93,47 +93,116 @@ async function getRegistry(dbPath) {
|
|
|
93
93
|
finally {
|
|
94
94
|
console.log = origLog;
|
|
95
95
|
}
|
|
96
|
-
// Wire intelligence module as the learning backend
|
|
97
|
-
// AgentDB's ReasoningBank/LearningSystem need a better-sqlite3 db
|
|
98
|
-
// which ControllerRegistry doesn't expose. Instead, use the
|
|
99
|
-
// module (SONA + LocalReasoningBank + file
|
|
96
|
+
// Wire intelligence module as the learning backend.
|
|
97
|
+
// AgentDB's ReasoningBank/LearningSystem need a better-sqlite3 db
|
|
98
|
+
// handle which ControllerRegistry doesn't expose. Instead, use the
|
|
99
|
+
// local intelligence module (SONA + LocalReasoningBank + file
|
|
100
|
+
// persistence) for learning.
|
|
101
|
+
//
|
|
102
|
+
// PERF: parallelize the two independent post-init paths
|
|
103
|
+
// (intelligence module load + agentdb import). Previously these
|
|
104
|
+
// ran serially, adding ~50-150ms to cold start. Both can resolve
|
|
105
|
+
// concurrently because they touch disjoint controller slots.
|
|
100
106
|
try {
|
|
101
|
-
const intelligence = await import('./intelligence.js');
|
|
102
|
-
const initResult = await intelligence.initializeIntelligence();
|
|
103
107
|
const reg = registry;
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
108
|
+
const intelligencePromise = (async () => {
|
|
109
|
+
try {
|
|
110
|
+
const intelligence = await import('./intelligence.js');
|
|
111
|
+
const initResult = await intelligence.initializeIntelligence();
|
|
112
|
+
if (initResult.reasoningBankEnabled) {
|
|
113
|
+
const rb = intelligence.getReasoningBank();
|
|
114
|
+
if (rb && !reg.get('reasoningBank')) {
|
|
115
|
+
if (typeof reg.set === 'function')
|
|
116
|
+
reg.set('reasoningBank', rb);
|
|
117
|
+
else
|
|
118
|
+
reg._controllers = { ...(reg._controllers || {}), reasoningBank: rb };
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (initResult.sonaEnabled) {
|
|
122
|
+
const sona = intelligence.getSonaCoordinator();
|
|
123
|
+
if (sona && !reg.get('learningSystem')) {
|
|
124
|
+
if (typeof reg.set === 'function')
|
|
125
|
+
reg.set('learningSystem', sona);
|
|
126
|
+
else
|
|
127
|
+
reg._controllers = { ...(reg._controllers || {}), learningSystem: sona };
|
|
128
|
+
}
|
|
129
|
+
}
|
|
111
130
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
reg._controllers = { ...(reg._controllers || {}), learningSystem: sona };
|
|
131
|
+
catch { /* intelligence module not available — learning stays unwired */ }
|
|
132
|
+
})();
|
|
133
|
+
const agentdbPromise = (async () => {
|
|
134
|
+
// Single import shared across SkillLibrary + SemanticRouter probe.
|
|
135
|
+
let agentdb = null;
|
|
136
|
+
try {
|
|
137
|
+
agentdb = (await import('agentdb'));
|
|
120
138
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
try {
|
|
124
|
-
const agentdb = await import('agentdb');
|
|
125
|
-
if (agentdb.SkillLibrary && !reg.get('skills')) {
|
|
126
|
-
const sk = new agentdb.SkillLibrary();
|
|
127
|
-
if (typeof reg.set === 'function')
|
|
128
|
-
reg.set('skills', sk);
|
|
129
|
-
else
|
|
130
|
-
reg._controllers = { ...(reg._controllers || {}), skills: sk };
|
|
139
|
+
catch {
|
|
140
|
+
return; /* AgentDB not available */
|
|
131
141
|
}
|
|
132
|
-
|
|
133
|
-
|
|
142
|
+
// SkillLibrary (no db required)
|
|
143
|
+
try {
|
|
144
|
+
const SkillCtor = agentdb.SkillLibrary;
|
|
145
|
+
if (SkillCtor && !reg.get('skills')) {
|
|
146
|
+
const sk = new SkillCtor();
|
|
147
|
+
if (typeof reg.set === 'function')
|
|
148
|
+
reg.set('skills', sk);
|
|
149
|
+
else
|
|
150
|
+
reg._controllers = { ...(reg._controllers || {}), skills: sk };
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
catch { /* SkillLibrary optional */ }
|
|
154
|
+
// ADR-093 F9: probe multiple router class names across agentdb
|
|
155
|
+
// alpha versions (alpha.10 had SemanticRouter; alpha.11+ removed
|
|
156
|
+
// it in favor of @ruvector/router; future versions may
|
|
157
|
+
// reintroduce). Wire only if .route() is callable.
|
|
158
|
+
try {
|
|
159
|
+
const candidates = ['SemanticRouter', 'IntentRouter', 'TaskRouter'];
|
|
160
|
+
let routerInstance = null;
|
|
161
|
+
for (const name of candidates) {
|
|
162
|
+
const Ctor = agentdb[name];
|
|
163
|
+
if (typeof Ctor === 'function') {
|
|
164
|
+
try {
|
|
165
|
+
const inst = (() => {
|
|
166
|
+
try {
|
|
167
|
+
return new Ctor({ dimension: 384 });
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
return new Ctor();
|
|
171
|
+
}
|
|
172
|
+
})();
|
|
173
|
+
if (inst && typeof inst.route === 'function') {
|
|
174
|
+
routerInstance = inst;
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
catch { /* try next candidate */ }
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
if (routerInstance && !reg.get('semanticRouter')) {
|
|
182
|
+
if (typeof reg.set === 'function')
|
|
183
|
+
reg.set('semanticRouter', routerInstance);
|
|
184
|
+
else
|
|
185
|
+
reg._controllers = { ...(reg._controllers || {}), semanticRouter: routerInstance };
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
catch { /* router optional */ }
|
|
189
|
+
})();
|
|
190
|
+
// Run both in parallel; settle either way so a single failing
|
|
191
|
+
// path doesn't tear down the rest of the post-init wiring.
|
|
192
|
+
await Promise.allSettled([intelligencePromise, agentdbPromise]);
|
|
193
|
+
// Other disabled controllers remain disabled and tracked in
|
|
194
|
+
// ADR-093 F9 for future enablement:
|
|
195
|
+
// - mutationGuard (write protection — needs config)
|
|
196
|
+
// - attestationLog (needs sqlite db handle the registry does
|
|
197
|
+
// not currently expose)
|
|
198
|
+
// - gnnService (graph neural net — heavy deps, needs WASM/CUDA)
|
|
199
|
+
// - guardedVectorBackend (secured vector backend variant —
|
|
200
|
+
// needs key material)
|
|
201
|
+
// - rvfOptimizer (RVF format optimizer — needs RVF storage)
|
|
202
|
+
// - graphAdapter (graph DB adapter — needs graph DB)
|
|
134
203
|
}
|
|
135
204
|
catch {
|
|
136
|
-
//
|
|
205
|
+
// Top-level catch — registry stays usable even if post-init wiring fails wholesale.
|
|
137
206
|
}
|
|
138
207
|
registryInstance = registry;
|
|
139
208
|
bridgeAvailable = true;
|
|
@@ -1545,13 +1614,22 @@ export async function bridgeSemanticRoute(params) {
|
|
|
1545
1614
|
return null;
|
|
1546
1615
|
try {
|
|
1547
1616
|
const router = registry.get('semanticRouter');
|
|
1548
|
-
if (!router)
|
|
1549
|
-
|
|
1617
|
+
if (!router) {
|
|
1618
|
+
// ADR-093 F9: surface an actionable error pointing callers at the
|
|
1619
|
+
// alternative routing surfaces that DO work, instead of just
|
|
1620
|
+
// saying "not available".
|
|
1621
|
+
return {
|
|
1622
|
+
route: null,
|
|
1623
|
+
error: 'SemanticRouter not available in current agentdb build',
|
|
1624
|
+
recommendation: 'Use bridgeRouteTask (registers as `agentdb_route` MCP tool) for keyword+pattern routing, or hooks_model-route for ADR-026 model selection.',
|
|
1625
|
+
controller: 'none',
|
|
1626
|
+
};
|
|
1627
|
+
}
|
|
1550
1628
|
const result = await router.route(params.input);
|
|
1551
1629
|
return { route: result, controller: 'semanticRouter' };
|
|
1552
1630
|
}
|
|
1553
1631
|
catch (e) {
|
|
1554
|
-
return { route: null, error: e.message };
|
|
1632
|
+
return { route: null, error: e.message, controller: 'error' };
|
|
1555
1633
|
}
|
|
1556
1634
|
}
|
|
1557
1635
|
// ===== RaBitQ data export =====
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claude-flow/cli",
|
|
3
|
-
"version": "3.6.
|
|
3
|
+
"version": "3.6.16",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Ruflo CLI - Enterprise AI agent orchestration with 60+ specialized agents, swarm coordination, MCP server, self-learning hooks, and vector memory for Claude Code",
|
|
6
6
|
"main": "dist/src/index.js",
|