@claude-flow/cli 3.71.4 → 3.72.1
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/helpers/helpers.manifest.json +4 -4
- package/.claude/helpers/hook-handler.cjs +23 -10
- package/.claude/helpers/statusline.cjs +29 -14
- package/.claude/skills/fast-code-edits/SKILL.md +45 -0
- package/.claude/skills/graph-mincut/SKILL.md +32 -0
- package/.claude/skills/injection-defense/SKILL.md +36 -0
- package/.claude/skills/lora-learning/SKILL.md +30 -0
- package/.claude/skills/sublinear-solver/SKILL.md +34 -0
- package/.claude/skills/vector-quantization/SKILL.md +36 -0
- package/README.md +18 -3
- package/bin/cli.js +13 -18
- package/bin/mcp-server.js +13 -18
- package/catalog-manifest.json +4 -4
- package/dist/src/appliance/ruvllm-bridge.d.ts +6 -2
- package/dist/src/appliance/ruvllm-bridge.js +13 -8
- package/dist/src/appliance/rvfa-distribution.js +2 -2
- package/dist/src/benchmarks/gaia-critic.d.ts +1 -7
- package/dist/src/benchmarks/gaia-critic.js +1 -7
- package/dist/src/benchmarks/gaia-decomposer.d.ts +1 -8
- package/dist/src/benchmarks/gaia-decomposer.js +1 -8
- package/dist/src/commands/agent-wasm.js +2 -2
- package/dist/src/commands/analyze.js +1 -1
- package/dist/src/commands/daemon.js +1 -1
- package/dist/src/commands/doctor.js +3 -2
- package/dist/src/commands/guidance.js +9 -9
- package/dist/src/commands/hooks.js +13 -8
- package/dist/src/commands/init.js +16 -16
- package/dist/src/commands/neural.js +87 -77
- package/dist/src/commands/route.js +1 -1
- package/dist/src/commands/ruvector/backup.js +7 -5
- package/dist/src/commands/ruvector/benchmark.js +6 -1
- package/dist/src/commands/ruvector/import.js +19 -5
- package/dist/src/commands/ruvector/init.js +1 -1
- package/dist/src/commands/start.js +1 -1
- package/dist/src/commands/status.js +1 -1
- package/dist/src/commands/task.js +18 -1
- package/dist/src/commands/update.js +1 -1
- package/dist/src/funnel/local-signals.js +7 -2
- package/dist/src/init/executor.js +13 -0
- package/dist/src/init/types.d.ts +6 -0
- package/dist/src/init/types.js +3 -0
- package/dist/src/mcp-client.js +2 -0
- package/dist/src/mcp-protocol.d.ts +90 -0
- package/dist/src/mcp-protocol.js +179 -0
- package/dist/src/mcp-server.d.ts +1 -0
- package/dist/src/mcp-server.js +20 -22
- package/dist/src/mcp-tools/agent-execute-core.js +9 -1
- package/dist/src/mcp-tools/agent-tools.d.ts +13 -0
- package/dist/src/mcp-tools/agent-tools.js +59 -8
- package/dist/src/mcp-tools/agentdb-tools.js +34 -2
- package/dist/src/mcp-tools/browser-argv.d.ts +9 -0
- package/dist/src/mcp-tools/browser-argv.js +33 -0
- package/dist/src/mcp-tools/browser-session-tools.js +4 -0
- package/dist/src/mcp-tools/browser-tools.js +12 -2
- package/dist/src/mcp-tools/coordination-tools.js +5 -4
- package/dist/src/mcp-tools/embeddings-tools.js +12 -4
- package/dist/src/mcp-tools/fast-apply-tools.d.ts +4 -0
- package/dist/src/mcp-tools/fast-apply-tools.js +85 -0
- package/dist/src/mcp-tools/glob-exclusions.d.ts +6 -0
- package/dist/src/mcp-tools/glob-exclusions.js +81 -0
- package/dist/src/mcp-tools/hive-mind-tools.js +104 -35
- package/dist/src/mcp-tools/hooks-tools.js +14 -38
- package/dist/src/mcp-tools/import-limits.d.ts +4 -0
- package/dist/src/mcp-tools/import-limits.js +28 -0
- package/dist/src/mcp-tools/memory-tools.js +21 -42
- package/dist/src/mcp-tools/metaharness-tools.js +1 -1
- package/dist/src/mcp-tools/performance-tools.js +7 -2
- package/dist/src/mcp-tools/realpath-containment.d.ts +3 -0
- package/dist/src/mcp-tools/realpath-containment.js +39 -0
- package/dist/src/mcp-tools/record-store.d.ts +8 -0
- package/dist/src/mcp-tools/record-store.js +98 -1
- package/dist/src/mcp-tools/security-tools.d.ts +9 -0
- package/dist/src/mcp-tools/security-tools.js +39 -3
- package/dist/src/mcp-tools/session-tools.js +5 -3
- package/dist/src/mcp-tools/swarm-tools.js +35 -17
- package/dist/src/mcp-tools/task-tools.js +68 -5
- package/dist/src/mcp-tools/terminal-tools.js +9 -0
- package/dist/src/mcp-tools/workflow-tools.js +13 -12
- package/dist/src/mcp-tools/x-federation-join.js +55 -14
- package/dist/src/memory/intelligence.d.ts +11 -0
- package/dist/src/memory/intelligence.js +84 -6
- package/dist/src/memory/memory-initializer.d.ts +6 -2
- package/dist/src/memory/memory-initializer.js +15 -6
- package/dist/src/mods/command-registry/schema.d.ts +12 -12
- package/dist/src/ruvector/ast-analyzer.d.ts +1 -2
- package/dist/src/ruvector/ast-analyzer.js +4 -12
- package/dist/src/ruvector/coverage-router.d.ts +1 -2
- package/dist/src/ruvector/coverage-router.js +4 -12
- package/dist/src/ruvector/diff-classifier.d.ts +1 -2
- package/dist/src/ruvector/diff-classifier.js +3 -12
- package/dist/src/ruvector/fast-apply.d.ts +46 -0
- package/dist/src/ruvector/fast-apply.js +73 -0
- package/dist/src/ruvector/graph-analyzer.d.ts +11 -1
- package/dist/src/ruvector/graph-analyzer.js +22 -36
- package/dist/src/ruvector/mincut-bridge.d.ts +70 -0
- package/dist/src/ruvector/mincut-bridge.js +172 -0
- package/dist/src/ruvector/model-router.d.ts +6 -1
- package/dist/src/ruvector/model-router.js +16 -4
- package/dist/src/services/distill-oracle.d.ts +1 -1
- package/dist/src/services/distill-oracle.js +2 -2
- package/dist/src/services/worker-daemon.js +30 -12
- package/dist/src/transfer/storage/gcs.js +3 -2
- package/node_modules/@claude-flow/codex/.agents/skills/fast-code-edits/SKILL.md +42 -0
- package/node_modules/@claude-flow/codex/.agents/skills/graph-mincut/SKILL.md +42 -0
- package/node_modules/@claude-flow/codex/.agents/skills/injection-defense/SKILL.md +45 -0
- package/node_modules/@claude-flow/codex/.agents/skills/lora-learning/SKILL.md +39 -0
- package/node_modules/@claude-flow/codex/.agents/skills/sublinear-solver/SKILL.md +38 -0
- package/node_modules/@claude-flow/codex/.agents/skills/vector-quantization/SKILL.md +49 -0
- package/node_modules/@claude-flow/codex/dist/generators/skill-md.d.ts.map +1 -1
- package/node_modules/@claude-flow/codex/dist/generators/skill-md.js +6 -0
- package/node_modules/@claude-flow/codex/dist/generators/skill-md.js.map +1 -1
- package/node_modules/@claude-flow/codex/dist/index.d.ts +3 -3
- package/node_modules/@claude-flow/codex/dist/index.js +1 -1
- package/node_modules/@claude-flow/codex/dist/templates/index.d.ts.map +1 -1
- package/node_modules/@claude-flow/codex/dist/templates/index.js +37 -0
- package/node_modules/@claude-flow/codex/dist/templates/index.js.map +1 -1
- package/node_modules/@claude-flow/codex/dist/types.d.ts +1 -1
- package/node_modules/@claude-flow/codex/dist/types.d.ts.map +1 -1
- package/node_modules/@claude-flow/codex/package.json +1 -1
- package/package.json +11 -9
- package/plugins/ruflo-metaharness/.claude-plugin/plugin.json +2 -1
- package/plugins/ruflo-metaharness/scripts/_darwin.mjs +4 -4
- package/plugins/ruflo-metaharness/scripts/_harness.mjs +1 -1
- package/plugins/ruflo-metaharness/scripts/smoke.sh +4 -4
|
@@ -35,8 +35,8 @@ const trainCommand = {
|
|
|
35
35
|
action: async (ctx) => {
|
|
36
36
|
const patternType = (ctx.flags.pattern || ctx.flags.patternType || ctx.flags['pattern-type']) || 'coordination';
|
|
37
37
|
const epochs = parseInt(ctx.flags.epochs || '50', 10);
|
|
38
|
-
const learningRate = parseFloat(ctx.flags['learning-rate'] || '0.01');
|
|
39
|
-
const batchSize = parseInt(ctx.flags['batch-size'] || '32', 10);
|
|
38
|
+
const learningRate = parseFloat((ctx.flags.learningRate ?? ctx.flags['learning-rate']) || '0.01');
|
|
39
|
+
const batchSize = parseInt((ctx.flags.batchSize ?? ctx.flags['batch-size']) || '32', 10);
|
|
40
40
|
const dim = Math.min(parseInt(ctx.flags.dim || '256', 10), 256);
|
|
41
41
|
// #2549 follow-up — backend routing: 'native' = @ruvector/ruvllm
|
|
42
42
|
// TrainingPipeline (real epochs/early-stopping/disk checkpoints),
|
|
@@ -44,7 +44,7 @@ const trainCommand = {
|
|
|
44
44
|
// 'auto' = native when the module resolves, else wasm.
|
|
45
45
|
const backendFlag = String(ctx.flags.backend || 'auto');
|
|
46
46
|
// Feature: validation split + resume (native TrainingPipeline leg).
|
|
47
|
-
const valSplitRaw = parseFloat(ctx.flags['val-split'] ?? '0.1');
|
|
47
|
+
const valSplitRaw = parseFloat((ctx.flags.valSplit ?? ctx.flags['val-split']) ?? '0.1');
|
|
48
48
|
const valSplit = Number.isFinite(valSplitRaw) ? Math.max(0, Math.min(1, valSplitRaw)) : 0.1;
|
|
49
49
|
const resumePath = ctx.flags.resume ? String(ctx.flags.resume) : undefined;
|
|
50
50
|
// --resume is a native-only capability; refuse the WASM combination up
|
|
@@ -1023,7 +1023,7 @@ const exportCommand = {
|
|
|
1023
1023
|
const outputFile = ctx.flags.output;
|
|
1024
1024
|
const pinToIpfs = ctx.flags.ipfs;
|
|
1025
1025
|
const signExport = ctx.flags.sign !== false;
|
|
1026
|
-
const stripPii = ctx.flags['strip-pii'] !== false;
|
|
1026
|
+
const stripPii = (ctx.flags.stripPii ?? ctx.flags['strip-pii']) !== false;
|
|
1027
1027
|
const customName = ctx.flags.name;
|
|
1028
1028
|
output.writeln();
|
|
1029
1029
|
output.writeln(output.bold('Secure Model Export'));
|
|
@@ -1516,81 +1516,89 @@ const benchmarkCommand = {
|
|
|
1516
1516
|
const spinner = output.createSpinner({ text: 'Running benchmarks...', spinner: 'dots' });
|
|
1517
1517
|
spinner.start();
|
|
1518
1518
|
try {
|
|
1519
|
-
|
|
1520
|
-
//
|
|
1521
|
-
//
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
const
|
|
1528
|
-
|
|
1529
|
-
const
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
const
|
|
1534
|
-
const
|
|
1535
|
-
for (let i = 0; i < dim; i++)
|
|
1536
|
-
|
|
1537
|
-
|
|
1519
|
+
const results = [];
|
|
1520
|
+
// The attention and MicroLoRA benchmarks are independent: a missing or
|
|
1521
|
+
// API-incompatible @ruvector/attention must not hide the
|
|
1522
|
+
// @ruvector/learning-wasm MicroLoRA numbers below.
|
|
1523
|
+
try {
|
|
1524
|
+
// Indirect the specifier through a string variable so tsc doesn't
|
|
1525
|
+
// statically resolve this optional dependency at build time (TS2307
|
|
1526
|
+
// when it isn't installed — install-safety / Build V3 pattern from #2586).
|
|
1527
|
+
const attentionPkg = '@ruvector/attention';
|
|
1528
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- dynamic import of optional native WASM module with no type declarations
|
|
1529
|
+
const attention = await import(attentionPkg);
|
|
1530
|
+
// Manual benchmark since benchmarkAttention has a binding bug
|
|
1531
|
+
const benchmarkMechanism = async (name, mechanism) => {
|
|
1532
|
+
const query = new Float32Array(dim);
|
|
1533
|
+
const keys = [];
|
|
1534
|
+
const values = [];
|
|
1535
|
+
for (let i = 0; i < dim; i++)
|
|
1536
|
+
query[i] = Math.random();
|
|
1537
|
+
for (let k = 0; k < numKeys; k++) {
|
|
1538
|
+
const key = new Float32Array(dim);
|
|
1539
|
+
const val = new Float32Array(dim);
|
|
1540
|
+
for (let i = 0; i < dim; i++) {
|
|
1541
|
+
key[i] = Math.random();
|
|
1542
|
+
val[i] = Math.random();
|
|
1543
|
+
}
|
|
1544
|
+
keys.push(key);
|
|
1545
|
+
values.push(val);
|
|
1538
1546
|
}
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
averageTimeMs: elapsed / iterations,
|
|
1553
|
-
opsPerSecond: Math.round((iterations / elapsed) * 1000),
|
|
1547
|
+
// Warmup
|
|
1548
|
+
for (let i = 0; i < 10; i++)
|
|
1549
|
+
mechanism.computeRaw(query, keys, values);
|
|
1550
|
+
const start = performance.now();
|
|
1551
|
+
for (let i = 0; i < iterations; i++) {
|
|
1552
|
+
mechanism.computeRaw(query, keys, values);
|
|
1553
|
+
}
|
|
1554
|
+
const elapsed = performance.now() - start;
|
|
1555
|
+
return {
|
|
1556
|
+
name,
|
|
1557
|
+
averageTimeMs: elapsed / iterations,
|
|
1558
|
+
opsPerSecond: Math.round((iterations / elapsed) * 1000),
|
|
1559
|
+
};
|
|
1554
1560
|
};
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
results.push(await benchmarkMechanism('Linear', linear));
|
|
1569
|
-
spinner.succeed('Benchmark complete');
|
|
1570
|
-
output.writeln();
|
|
1571
|
-
output.printTable({
|
|
1572
|
-
columns: [
|
|
1573
|
-
{ key: 'name', header: 'Mechanism', width: 25 },
|
|
1574
|
-
{ key: 'avgTime', header: 'Avg Time (ms)', width: 15 },
|
|
1575
|
-
{ key: 'opsPerSec', header: 'Ops/sec', width: 15 },
|
|
1576
|
-
],
|
|
1577
|
-
data: results.map(r => ({
|
|
1578
|
-
name: r.name,
|
|
1579
|
-
avgTime: r.averageTimeMs.toFixed(4),
|
|
1580
|
-
opsPerSec: r.opsPerSecond.toLocaleString(),
|
|
1581
|
-
})),
|
|
1582
|
-
});
|
|
1583
|
-
// Show speedup comparisons
|
|
1584
|
-
const dotProductResult = results.find(r => r.name.includes('DotProduct'));
|
|
1585
|
-
const flashResult = results.find(r => r.name.includes('Flash'));
|
|
1586
|
-
const hyperbolicResult = results.find(r => r.name.includes('Hyperbolic'));
|
|
1587
|
-
if (dotProductResult && flashResult) {
|
|
1588
|
-
const speedup = dotProductResult.averageTimeMs / flashResult.averageTimeMs;
|
|
1561
|
+
spinner.setText(`Benchmarking attention mechanisms (dim=${dim}, keys=${numKeys}, iter=${iterations})...`);
|
|
1562
|
+
// Benchmark each mechanism
|
|
1563
|
+
const dotProduct = new attention.DotProductAttention(dim);
|
|
1564
|
+
results.push(await benchmarkMechanism('DotProduct', dotProduct));
|
|
1565
|
+
const flash = new attention.FlashAttention(dim, 64);
|
|
1566
|
+
results.push(await benchmarkMechanism('FlashAttention', flash));
|
|
1567
|
+
const multiHead = new attention.MultiHeadAttention(dim, 4);
|
|
1568
|
+
results.push(await benchmarkMechanism('MultiHead (4 heads)', multiHead));
|
|
1569
|
+
const hyperbolic = new attention.HyperbolicAttention(dim, 1.0);
|
|
1570
|
+
results.push(await benchmarkMechanism('Hyperbolic', hyperbolic));
|
|
1571
|
+
const linear = new attention.LinearAttention(dim, dim);
|
|
1572
|
+
results.push(await benchmarkMechanism('Linear', linear));
|
|
1573
|
+
spinner.succeed('Benchmark complete');
|
|
1589
1574
|
output.writeln();
|
|
1590
|
-
output.
|
|
1575
|
+
output.printTable({
|
|
1576
|
+
columns: [
|
|
1577
|
+
{ key: 'name', header: 'Mechanism', width: 25 },
|
|
1578
|
+
{ key: 'avgTime', header: 'Avg Time (ms)', width: 15 },
|
|
1579
|
+
{ key: 'opsPerSec', header: 'Ops/sec', width: 15 },
|
|
1580
|
+
],
|
|
1581
|
+
data: results.map(r => ({
|
|
1582
|
+
name: r.name,
|
|
1583
|
+
avgTime: r.averageTimeMs.toFixed(4),
|
|
1584
|
+
opsPerSec: r.opsPerSecond.toLocaleString(),
|
|
1585
|
+
})),
|
|
1586
|
+
});
|
|
1587
|
+
// Show speedup comparisons
|
|
1588
|
+
const dotProductResult = results.find(r => r.name.includes('DotProduct'));
|
|
1589
|
+
const flashResult = results.find(r => r.name.includes('Flash'));
|
|
1590
|
+
const hyperbolicResult = results.find(r => r.name.includes('Hyperbolic'));
|
|
1591
|
+
if (dotProductResult && flashResult) {
|
|
1592
|
+
const speedup = dotProductResult.averageTimeMs / flashResult.averageTimeMs;
|
|
1593
|
+
output.writeln();
|
|
1594
|
+
output.writeln(output.highlight(`Flash Attention speedup: ${speedup.toFixed(2)}x faster than DotProduct`));
|
|
1595
|
+
}
|
|
1596
|
+
if (dotProductResult && hyperbolicResult) {
|
|
1597
|
+
output.writeln(output.dim(`Hyperbolic overhead: ${(hyperbolicResult.averageTimeMs / dotProductResult.averageTimeMs).toFixed(2)}x (expected for manifold ops)`));
|
|
1598
|
+
}
|
|
1591
1599
|
}
|
|
1592
|
-
|
|
1593
|
-
|
|
1600
|
+
catch (attentionError) {
|
|
1601
|
+
spinner.fail(`Attention benchmark skipped: ${attentionError instanceof Error ? attentionError.message : String(attentionError)}`);
|
|
1594
1602
|
}
|
|
1595
1603
|
// Also benchmark MicroLoRA
|
|
1596
1604
|
spinner.start();
|
|
@@ -1703,7 +1711,8 @@ const routerTrainCommand = {
|
|
|
1703
1711
|
action: async (ctx) => {
|
|
1704
1712
|
const corpusPath = ctx.flags.corpus;
|
|
1705
1713
|
const outPath = ctx.flags.out || './router.krr.json';
|
|
1706
|
-
const
|
|
1714
|
+
const requestedQualityBar = parseFloat(String(ctx.flags.qualityBar ?? ctx.flags['quality-bar'] ?? 0.8));
|
|
1715
|
+
const qualityBar = Number.isNaN(requestedQualityBar) ? 0.8 : requestedQualityBar;
|
|
1707
1716
|
// Indirect the optional-dep specifier through a string variable so tsc
|
|
1708
1717
|
// doesn't statically resolve `@metaharness/router` at build time (TS2307
|
|
1709
1718
|
// when it isn't installed — #2586 pattern). The dep is optional at
|
|
@@ -3464,7 +3473,8 @@ const routerBanditStateCommand = {
|
|
|
3464
3473
|
const statePath = ctx.flags.path
|
|
3465
3474
|
?? path.resolve(process.cwd(), '.swarm', 'model-router-state.json');
|
|
3466
3475
|
const fmt = ctx.flags.format || 'table';
|
|
3467
|
-
const
|
|
3476
|
+
const requestedColdThreshold = parseInt(String(ctx.flags.coldThreshold ?? ctx.flags['cold-threshold'] ?? 4), 10);
|
|
3477
|
+
const coldThreshold = Number.isNaN(requestedColdThreshold) ? 4 : requestedColdThreshold;
|
|
3468
3478
|
if (!fs.existsSync(statePath)) {
|
|
3469
3479
|
const msg = `Bandit state file not found at ${statePath}`;
|
|
3470
3480
|
if (fmt === 'json')
|
|
@@ -367,7 +367,7 @@ const feedbackCommand = {
|
|
|
367
367
|
const taskDescription = ctx.flags.task;
|
|
368
368
|
const agentId = ctx.flags.agent;
|
|
369
369
|
const reward = ctx.flags.reward;
|
|
370
|
-
const nextTask = ctx.flags
|
|
370
|
+
const nextTask = ctx.flags.nextTask;
|
|
371
371
|
if (!taskDescription || !agentId) {
|
|
372
372
|
output.printError('Task description and agent are required');
|
|
373
373
|
return { success: false, exitCode: 1 };
|
|
@@ -53,10 +53,10 @@ const backupSubcommand = {
|
|
|
53
53
|
{
|
|
54
54
|
name: 'format',
|
|
55
55
|
short: 'f',
|
|
56
|
-
description: 'Output format',
|
|
56
|
+
description: 'Output format (defaults to SQL)',
|
|
57
57
|
type: 'string',
|
|
58
|
-
default: '
|
|
59
|
-
choices: ['sql', 'json', 'csv'],
|
|
58
|
+
default: 'text',
|
|
59
|
+
choices: ['text', 'sql', 'json', 'csv'],
|
|
60
60
|
},
|
|
61
61
|
{
|
|
62
62
|
name: 'compress',
|
|
@@ -125,9 +125,11 @@ const backupSubcommand = {
|
|
|
125
125
|
const config = getConnectionConfig(ctx);
|
|
126
126
|
let outputPath = ctx.flags.output;
|
|
127
127
|
const tablesFilter = ctx.flags.tables;
|
|
128
|
-
|
|
128
|
+
// The CLI validates the shared --format flag against its global choices.
|
|
129
|
+
const requestedFormat = ctx.flags.format;
|
|
130
|
+
const format = !requestedFormat || requestedFormat === 'text' ? 'sql' : requestedFormat;
|
|
129
131
|
const compress = ctx.flags.compress;
|
|
130
|
-
const includeIndexes = ctx.flags['include-indexes'] !== false;
|
|
132
|
+
const includeIndexes = (ctx.flags.includeIndexes ?? ctx.flags['include-indexes']) !== false;
|
|
131
133
|
output.writeln();
|
|
132
134
|
output.writeln(output.bold('RuVector Backup'));
|
|
133
135
|
output.writeln(output.dim('='.repeat(60)));
|
|
@@ -158,7 +158,8 @@ export const benchmarkCommand = {
|
|
|
158
158
|
const topK = parseInt(ctx.flags.k || '10', 10);
|
|
159
159
|
const metric = ctx.flags.metric || 'cosine';
|
|
160
160
|
const indexType = ctx.flags.index || 'hnsw';
|
|
161
|
-
const
|
|
161
|
+
const batchSizeFlag = ctx.flags.batchSize ?? ctx.flags['batch-size'] ?? 1000;
|
|
162
|
+
const batchSize = typeof batchSizeFlag === 'string' ? Number(batchSizeFlag) : batchSizeFlag;
|
|
162
163
|
const cleanup = ctx.flags.cleanup !== false;
|
|
163
164
|
output.writeln();
|
|
164
165
|
output.writeln(output.bold('RuVector Performance Benchmark'));
|
|
@@ -168,6 +169,10 @@ export const benchmarkCommand = {
|
|
|
168
169
|
output.printError('Database name is required. Use --database or -d flag, or set PGDATABASE env.');
|
|
169
170
|
return { success: false, exitCode: 1 };
|
|
170
171
|
}
|
|
172
|
+
if (typeof batchSize !== 'number' || !Number.isSafeInteger(batchSize) || batchSize < 1) {
|
|
173
|
+
output.printError('--batch-size must be a positive integer');
|
|
174
|
+
return { success: false, exitCode: 1 };
|
|
175
|
+
}
|
|
171
176
|
// Show benchmark configuration
|
|
172
177
|
output.writeln(output.highlight('Benchmark Configuration:'));
|
|
173
178
|
output.printTable({
|
|
@@ -166,15 +166,21 @@ export const importCommand = {
|
|
|
166
166
|
],
|
|
167
167
|
action: async (ctx) => {
|
|
168
168
|
const inputFile = ctx.flags.input;
|
|
169
|
-
const fromMemory = ctx.flags['from-memory'];
|
|
169
|
+
const fromMemory = (ctx.flags.fromMemory ?? ctx.flags['from-memory']);
|
|
170
170
|
const outputFile = ctx.flags.output;
|
|
171
|
-
const
|
|
171
|
+
const batchSizeFlag = ctx.flags.batchSize ?? ctx.flags['batch-size'] ?? 100;
|
|
172
|
+
const batchSize = typeof batchSizeFlag === 'string' ? Number(batchSizeFlag) : batchSizeFlag;
|
|
172
173
|
const containerName = ctx.flags.container || 'ruvector-postgres';
|
|
173
174
|
const verbose = ctx.flags.verbose;
|
|
174
175
|
output.writeln();
|
|
175
176
|
output.writeln(output.bold('RuVector PostgreSQL Import'));
|
|
176
177
|
output.writeln(output.dim('='.repeat(50)));
|
|
177
178
|
output.writeln();
|
|
179
|
+
if (typeof batchSize !== 'number' || !Number.isSafeInteger(batchSize) || batchSize < 1) {
|
|
180
|
+
const message = '--batch-size must be a positive integer';
|
|
181
|
+
output.printError(message);
|
|
182
|
+
return { success: false, message };
|
|
183
|
+
}
|
|
178
184
|
// Validate input
|
|
179
185
|
if (!inputFile && !fromMemory) {
|
|
180
186
|
output.printError('Either --input <file> or --from-memory is required');
|
|
@@ -248,6 +254,7 @@ export const importCommand = {
|
|
|
248
254
|
sqlStatements.push('');
|
|
249
255
|
sqlStatements.push('BEGIN;');
|
|
250
256
|
sqlStatements.push('');
|
|
257
|
+
const inserts = [];
|
|
251
258
|
for (const entry of entries) {
|
|
252
259
|
try {
|
|
253
260
|
// Track statistics
|
|
@@ -256,9 +263,7 @@ export const importCommand = {
|
|
|
256
263
|
if (entry.embedding && entry.embedding.length > 0) {
|
|
257
264
|
stats.withEmbeddings++;
|
|
258
265
|
}
|
|
259
|
-
|
|
260
|
-
sqlStatements.push(sql);
|
|
261
|
-
sqlStatements.push('');
|
|
266
|
+
inserts.push(generateInsertSQL(entry));
|
|
262
267
|
stats.imported++;
|
|
263
268
|
if (verbose) {
|
|
264
269
|
output.writeln(output.dim(` Processed: ${entry.key} (${ns})`));
|
|
@@ -270,6 +275,15 @@ export const importCommand = {
|
|
|
270
275
|
output.printWarning(`Skipped entry "${entry.key}": ${errorMessage}`);
|
|
271
276
|
}
|
|
272
277
|
}
|
|
278
|
+
// Send each batch as one statement while keeping ordered upserts in the same transaction.
|
|
279
|
+
for (let offset = 0; offset < inserts.length; offset += batchSize) {
|
|
280
|
+
const batch = inserts.slice(offset, offset + batchSize).join('\n\n');
|
|
281
|
+
let tag = 'ruvector_batch';
|
|
282
|
+
// A value containing the delimiter must stay inside the block.
|
|
283
|
+
while (batch.includes(`$${tag}$`))
|
|
284
|
+
tag += '_';
|
|
285
|
+
sqlStatements.push(`DO $${tag}$\nBEGIN\n${batch}\nEND;\n$${tag}$;`, '');
|
|
286
|
+
}
|
|
273
287
|
sqlStatements.push('COMMIT;');
|
|
274
288
|
sqlStatements.push('');
|
|
275
289
|
sqlStatements.push(`-- Import complete: ${stats.imported} entries`);
|
|
@@ -145,7 +145,7 @@ export const initCommand = {
|
|
|
145
145
|
}
|
|
146
146
|
const force = ctx.flags.force;
|
|
147
147
|
const dimensions = parseInt(ctx.flags.dimensions || '1536', 10);
|
|
148
|
-
const indexType = ctx.flags['index-type'] || 'hnsw';
|
|
148
|
+
const indexType = (ctx.flags.indexType ?? ctx.flags['index-type']) || 'hnsw';
|
|
149
149
|
// Show configuration
|
|
150
150
|
output.writeln(output.highlight('Connection Configuration:'));
|
|
151
151
|
output.printTable({
|
|
@@ -85,7 +85,7 @@ const startAction = async (ctx) => {
|
|
|
85
85
|
const daemon = ctx.flags.daemon;
|
|
86
86
|
const port = ctx.flags.port || DEFAULT_PORT;
|
|
87
87
|
const topology = ctx.flags.topology || DEFAULT_TOPOLOGY;
|
|
88
|
-
const skipMcp = ctx.flags
|
|
88
|
+
const skipMcp = ctx.flags.skipMcp;
|
|
89
89
|
const cwd = ctx.cwd;
|
|
90
90
|
// Check initialization
|
|
91
91
|
if (!isInitialized(cwd)) {
|
|
@@ -281,7 +281,7 @@ function formatHealth(health) {
|
|
|
281
281
|
const statusAction = async (ctx) => {
|
|
282
282
|
const watch = ctx.flags.watch;
|
|
283
283
|
const interval = ctx.flags.interval || DEFAULT_WATCH_INTERVAL / 1000;
|
|
284
|
-
const healthCheck = ctx.flags
|
|
284
|
+
const healthCheck = ctx.flags.healthCheck;
|
|
285
285
|
const cwd = ctx.cwd;
|
|
286
286
|
// Check initialization
|
|
287
287
|
if (!isInitialized(cwd)) {
|
|
@@ -571,6 +571,12 @@ const assignCommand = {
|
|
|
571
571
|
taskId,
|
|
572
572
|
agentIds: selectedAgents
|
|
573
573
|
});
|
|
574
|
+
// task_assign answers a finished task or an unknown agent with
|
|
575
|
+
// success: false instead of throwing (#4725).
|
|
576
|
+
if (result.success === false) {
|
|
577
|
+
output.printError(`Failed to assign task ${taskId}: ${result.error || 'unknown error'}`);
|
|
578
|
+
return { success: false, exitCode: 1, data: result };
|
|
579
|
+
}
|
|
574
580
|
output.writeln();
|
|
575
581
|
output.printSuccess(`Task ${taskId} assigned to ${result.assignedTo.join(', ')}`);
|
|
576
582
|
return { success: true, data: result };
|
|
@@ -592,6 +598,17 @@ const assignCommand = {
|
|
|
592
598
|
agentIds: unassign ? [] : agentIds.split(',').map(id => id.trim()),
|
|
593
599
|
unassign
|
|
594
600
|
});
|
|
601
|
+
// task_assign answers a finished task or an unknown agent with
|
|
602
|
+
// success: false instead of throwing (#4725).
|
|
603
|
+
if (result.success === false) {
|
|
604
|
+
if (ctx.flags.format === 'json') {
|
|
605
|
+
output.printJson(result);
|
|
606
|
+
}
|
|
607
|
+
else {
|
|
608
|
+
output.printError(`Failed to assign task ${taskId}: ${result.error || 'unknown error'}`);
|
|
609
|
+
}
|
|
610
|
+
return { success: false, exitCode: 1, data: result };
|
|
611
|
+
}
|
|
595
612
|
output.writeln();
|
|
596
613
|
if (unassign) {
|
|
597
614
|
output.printSuccess(`Task ${taskId} unassigned`);
|
|
@@ -630,7 +647,7 @@ const retryCommand = {
|
|
|
630
647
|
],
|
|
631
648
|
action: async (ctx) => {
|
|
632
649
|
const taskId = ctx.args[0];
|
|
633
|
-
const resetState = ctx.flags['reset-state'];
|
|
650
|
+
const resetState = (ctx.flags.resetState ?? ctx.flags['reset-state']);
|
|
634
651
|
if (!taskId) {
|
|
635
652
|
output.printError('Task ID is required');
|
|
636
653
|
return { success: false, exitCode: 1 };
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import * as fs from 'fs';
|
|
11
11
|
import * as path from 'path';
|
|
12
|
-
import { execSync } from 'child_process';
|
|
12
|
+
import { execFileSync, execSync } from 'child_process';
|
|
13
13
|
export function getSecurityStatus(cwd = process.cwd()) {
|
|
14
14
|
const empty = {
|
|
15
15
|
status: 'PENDING', findings: 0, cvesFixed: 0, totalCves: 0,
|
|
@@ -67,7 +67,12 @@ export function getSwarmStatus() {
|
|
|
67
67
|
/** Count of uncommitted-changed files (git status --short line count). */
|
|
68
68
|
export function getGitUncommittedCount() {
|
|
69
69
|
try {
|
|
70
|
-
|
|
70
|
+
// #4770: no shell, so this also works on Windows.
|
|
71
|
+
const out = execFileSync('git', ['status', '--porcelain'], {
|
|
72
|
+
encoding: 'utf-8',
|
|
73
|
+
timeout: 3000,
|
|
74
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
75
|
+
});
|
|
71
76
|
const lines = out.split('\n').filter((l) => l.trim().length > 0);
|
|
72
77
|
return lines.length;
|
|
73
78
|
}
|
|
@@ -78,6 +78,17 @@ const SKILLS_MAP = {
|
|
|
78
78
|
'sparc-methodology',
|
|
79
79
|
'stream-chain',
|
|
80
80
|
],
|
|
81
|
+
// How and when to use the ecosystem packages ruflo ships or wires in:
|
|
82
|
+
// ruvector + @ruvector/mincut-wasm, @ruvector/rabitq-wasm, sublinear-time-solver,
|
|
83
|
+
// @claude-flow/aidefence, agent-booster, @ruvector/learning-wasm.
|
|
84
|
+
ecosystem: [
|
|
85
|
+
'vector-quantization',
|
|
86
|
+
'graph-mincut',
|
|
87
|
+
'sublinear-solver',
|
|
88
|
+
'injection-defense',
|
|
89
|
+
'fast-code-edits',
|
|
90
|
+
'lora-learning',
|
|
91
|
+
],
|
|
81
92
|
};
|
|
82
93
|
/**
|
|
83
94
|
* Commands to copy based on configuration
|
|
@@ -1087,6 +1098,8 @@ async function copySkills(targetDir, options, result) {
|
|
|
1087
1098
|
skillsToCopy.push(...SKILLS_MAP.dualMode);
|
|
1088
1099
|
if (skillsConfig.legacy)
|
|
1089
1100
|
skillsToCopy.push(...SKILLS_MAP.legacy);
|
|
1101
|
+
if (skillsConfig.ecosystem ?? true)
|
|
1102
|
+
skillsToCopy.push(...SKILLS_MAP.ecosystem);
|
|
1090
1103
|
}
|
|
1091
1104
|
// Find source skills directory
|
|
1092
1105
|
const sourceSkillsDir = findSourceDir('skills', options.sourceBaseDir);
|
package/dist/src/init/types.d.ts
CHANGED
|
@@ -78,6 +78,12 @@ export interface SkillsConfig {
|
|
|
78
78
|
dualMode: boolean;
|
|
79
79
|
/** Include legacy skills that document commands v3 does not ship (opt-in) */
|
|
80
80
|
legacy: boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Include ecosystem skills (vector quantization, graph min-cut, sublinear
|
|
83
|
+
* solving, injection defense, fast code edits, LoRA learning). Optional so
|
|
84
|
+
* existing SkillsConfig literals stay valid; absent means on.
|
|
85
|
+
*/
|
|
86
|
+
ecosystem?: boolean;
|
|
81
87
|
/** Include all available skills */
|
|
82
88
|
all: boolean;
|
|
83
89
|
}
|
package/dist/src/init/types.js
CHANGED
|
@@ -79,6 +79,7 @@ export const DEFAULT_INIT_OPTIONS = {
|
|
|
79
79
|
v3: false, // ADR-128: opt-in like agents.v3; use --full or `init skills --v3`
|
|
80
80
|
dualMode: false, // Optional: enable with --dual flag
|
|
81
81
|
legacy: false, // #4539: stream-chain/sparc document verbs v3 does not ship
|
|
82
|
+
ecosystem: true, // ruvector / agent-booster / aidefence usage skills
|
|
82
83
|
all: false,
|
|
83
84
|
},
|
|
84
85
|
commands: {
|
|
@@ -188,6 +189,7 @@ export const MINIMAL_INIT_OPTIONS = {
|
|
|
188
189
|
v3: false,
|
|
189
190
|
dualMode: false,
|
|
190
191
|
legacy: false,
|
|
192
|
+
ecosystem: false,
|
|
191
193
|
all: false,
|
|
192
194
|
},
|
|
193
195
|
agents: {
|
|
@@ -249,6 +251,7 @@ export const FULL_INIT_OPTIONS = {
|
|
|
249
251
|
v3: true,
|
|
250
252
|
dualMode: true, // Include in full init
|
|
251
253
|
legacy: true, // Include in full init
|
|
254
|
+
ecosystem: true,
|
|
252
255
|
all: true,
|
|
253
256
|
},
|
|
254
257
|
commands: {
|
package/dist/src/mcp-client.js
CHANGED
|
@@ -13,6 +13,7 @@ import { swarmTools } from './mcp-tools/swarm-tools.js';
|
|
|
13
13
|
import { memoryTools } from './mcp-tools/memory-tools.js';
|
|
14
14
|
import { configTools } from './mcp-tools/config-tools.js';
|
|
15
15
|
import { hooksTools } from './mcp-tools/hooks-tools.js';
|
|
16
|
+
import { fastApplyTools } from './mcp-tools/fast-apply-tools.js';
|
|
16
17
|
import { taskTools } from './mcp-tools/task-tools.js';
|
|
17
18
|
import { sessionTools } from './mcp-tools/session-tools.js';
|
|
18
19
|
import { hiveMindTools } from './mcp-tools/hive-mind-tools.js';
|
|
@@ -131,6 +132,7 @@ registerTools([
|
|
|
131
132
|
...memoryTools,
|
|
132
133
|
...configTools,
|
|
133
134
|
...hooksTools,
|
|
135
|
+
...fastApplyTools,
|
|
134
136
|
...taskTools,
|
|
135
137
|
...sessionTools,
|
|
136
138
|
...hiveMindTools,
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP protocol-version handling for the stdio servers (ADR-524).
|
|
3
|
+
*
|
|
4
|
+
* Ruflo ships three stdio entry points (`bin/cli.js` auto-detect, `bin/mcp-server.js`,
|
|
5
|
+
* and `MCPServerManager` in mcp-server.ts). All three answered `initialize` with a
|
|
6
|
+
* hardcoded `2024-11-05` and knew nothing of the 2026-07-28 revision, which drops the
|
|
7
|
+
* handshake and carries the version on every request. This module is the one place
|
|
8
|
+
* that decides which revision a message speaks, so the three handlers cannot drift.
|
|
9
|
+
*
|
|
10
|
+
* Dual-era behaviour (spec: basic/versioning):
|
|
11
|
+
* - `initialize` selects legacy semantics; the requested legacy version is echoed.
|
|
12
|
+
* - a request carrying `_meta["io.modelcontextprotocol/protocolVersion"]` is served
|
|
13
|
+
* statelessly: `resultType` and `serverInfo` on every result, cache hints on lists,
|
|
14
|
+
* `-32602` for an unknown resource, `-32022` for an unsupported version.
|
|
15
|
+
* - `server/discover` is always answered, so a dual-era client's stdio probe succeeds.
|
|
16
|
+
*/
|
|
17
|
+
export declare const MODERN_PROTOCOL_VERSIONS: readonly ["2026-07-28"];
|
|
18
|
+
export declare const LEGACY_PROTOCOL_VERSIONS: readonly ["2025-11-25", "2025-06-18", "2024-11-05"];
|
|
19
|
+
export declare const SUPPORTED_PROTOCOL_VERSIONS: readonly string[];
|
|
20
|
+
/** Offered to a legacy client whose requested version we do not know. */
|
|
21
|
+
export declare const LATEST_LEGACY_PROTOCOL_VERSION: "2025-11-25";
|
|
22
|
+
export declare const META_PROTOCOL_VERSION = "io.modelcontextprotocol/protocolVersion";
|
|
23
|
+
export declare const META_CLIENT_CAPABILITIES = "io.modelcontextprotocol/clientCapabilities";
|
|
24
|
+
export declare const META_SERVER_INFO = "io.modelcontextprotocol/serverInfo";
|
|
25
|
+
export declare const ERROR_INVALID_PARAMS = -32602;
|
|
26
|
+
export declare const ERROR_UNSUPPORTED_PROTOCOL_VERSION = -32022;
|
|
27
|
+
/** 2025-11-25 and earlier; replaced by -32602 in 2026-07-28. */
|
|
28
|
+
export declare const ERROR_LEGACY_RESOURCE_NOT_FOUND = -32002;
|
|
29
|
+
/** Tool catalogue is fixed for the life of a stdio process; five minutes is a conservative hint. */
|
|
30
|
+
export declare const TOOLS_LIST_TTL_MS = 300000;
|
|
31
|
+
export declare const DISCOVER_TTL_MS = 3600000;
|
|
32
|
+
export interface ServerIdentity {
|
|
33
|
+
name: string;
|
|
34
|
+
version: string;
|
|
35
|
+
}
|
|
36
|
+
export interface ProtocolContext {
|
|
37
|
+
/** True when the request used 2026-07-28 per-request metadata. */
|
|
38
|
+
modern: boolean;
|
|
39
|
+
/** Version the request declared, or undefined for legacy requests. */
|
|
40
|
+
version?: string;
|
|
41
|
+
/** Validated W3C traceparent, if the client propagated one. */
|
|
42
|
+
traceparent?: string;
|
|
43
|
+
tracestate?: string;
|
|
44
|
+
}
|
|
45
|
+
export interface JsonRpcMessage {
|
|
46
|
+
jsonrpc?: string;
|
|
47
|
+
id?: string | number | null;
|
|
48
|
+
method?: string;
|
|
49
|
+
params?: unknown;
|
|
50
|
+
}
|
|
51
|
+
export interface JsonRpcResponse {
|
|
52
|
+
jsonrpc: '2.0';
|
|
53
|
+
id?: string | number | null;
|
|
54
|
+
result?: Record<string, unknown>;
|
|
55
|
+
error?: {
|
|
56
|
+
code: number;
|
|
57
|
+
message: string;
|
|
58
|
+
data?: unknown;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export type Preflight = {
|
|
62
|
+
response: JsonRpcResponse;
|
|
63
|
+
context?: undefined;
|
|
64
|
+
} | {
|
|
65
|
+
response?: undefined;
|
|
66
|
+
context: ProtocolContext;
|
|
67
|
+
};
|
|
68
|
+
/** The CLI package version, read once from package.json (dist/src/ → ../../). */
|
|
69
|
+
export declare function rufloPackageVersion(): string;
|
|
70
|
+
export declare function defaultServerIdentity(): ServerIdentity;
|
|
71
|
+
/** Pick the legacy version to answer `initialize` with (spec: echo if supported, else our latest). */
|
|
72
|
+
export declare function negotiateLegacyVersion(requested: unknown): string;
|
|
73
|
+
export declare function isValidTraceparent(value: unknown): value is string;
|
|
74
|
+
/**
|
|
75
|
+
* Decide how to serve one inbound message before the handler's own switch runs.
|
|
76
|
+
* Returns a complete response for `initialize`, `server/discover` and protocol
|
|
77
|
+
* errors; otherwise returns the context the handler passes to `finalizeResponse`.
|
|
78
|
+
*/
|
|
79
|
+
export declare function protocolPreflight(message: JsonRpcMessage, capabilities: Record<string, unknown>, identity?: ServerIdentity): Preflight;
|
|
80
|
+
/** The resource-not-found code the request's revision expects. */
|
|
81
|
+
export declare function resourceNotFoundCode(context: ProtocolContext): number;
|
|
82
|
+
/** Stable, name-ordered copy so `tools/list` is byte-identical across calls (prompt-cache friendly). */
|
|
83
|
+
export declare function sortToolsDeterministically<T extends {
|
|
84
|
+
name: string;
|
|
85
|
+
}>(tools: readonly T[]): T[];
|
|
86
|
+
/** Tool-call context fields to forward, so handlers and logs can join the caller's trace. */
|
|
87
|
+
export declare function traceContextFields(context: ProtocolContext): Record<string, string>;
|
|
88
|
+
/** Add the 2026-07-28 result fields to a handler's response. Legacy responses pass through untouched. */
|
|
89
|
+
export declare function finalizeResponse(response: JsonRpcResponse | null, method: string | undefined, context: ProtocolContext, identity?: ServerIdentity): JsonRpcResponse | null;
|
|
90
|
+
//# sourceMappingURL=mcp-protocol.d.ts.map
|