claude-flow 3.5.18 → 3.5.20
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/agent.js +83 -21
- package/v3/@claude-flow/cli/dist/src/commands/doctor.js +22 -5
- package/v3/@claude-flow/cli/dist/src/commands/hooks.js +45 -6
- package/v3/@claude-flow/cli/dist/src/commands/neural.js +1 -1
- package/v3/@claude-flow/cli/dist/src/commands/security.js +46 -15
- package/v3/@claude-flow/cli/dist/src/mcp-tools/agentdb-tools.js +12 -12
- package/v3/@claude-flow/cli/dist/src/memory/intelligence.js +5 -1
- package/v3/@claude-flow/cli/dist/src/parser.d.ts +10 -0
- package/v3/@claude-flow/cli/dist/src/parser.js +49 -3
- package/v3/@claude-flow/cli/package.json +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-flow",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.20",
|
|
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",
|
|
@@ -420,26 +420,86 @@ const metricsCommand = {
|
|
|
420
420
|
action: async (ctx) => {
|
|
421
421
|
const agentId = ctx.args[0];
|
|
422
422
|
const period = ctx.flags.period;
|
|
423
|
-
//
|
|
423
|
+
// Collect real metrics from .swarm/ state
|
|
424
|
+
const { existsSync, readFileSync, readdirSync, statSync } = await import('fs');
|
|
425
|
+
const { join } = await import('path');
|
|
426
|
+
let totalAgents = 0;
|
|
427
|
+
let activeAgents = 0;
|
|
428
|
+
let tasksCompleted = 0;
|
|
429
|
+
const typeCounts = {};
|
|
430
|
+
// Read swarm agent state
|
|
431
|
+
const swarmDir = join(process.cwd(), '.swarm');
|
|
432
|
+
const agentsDir = join(swarmDir, 'agents');
|
|
433
|
+
if (existsSync(agentsDir)) {
|
|
434
|
+
try {
|
|
435
|
+
const files = readdirSync(agentsDir).filter(f => f.endsWith('.json'));
|
|
436
|
+
for (const file of files) {
|
|
437
|
+
try {
|
|
438
|
+
const data = JSON.parse(readFileSync(join(agentsDir, file), 'utf-8'));
|
|
439
|
+
totalAgents++;
|
|
440
|
+
const agType = data.type || 'unknown';
|
|
441
|
+
if (!typeCounts[agType])
|
|
442
|
+
typeCounts[agType] = { count: 0, tasks: 0, success: 0 };
|
|
443
|
+
typeCounts[agType].count++;
|
|
444
|
+
if (data.status === 'active' || data.status === 'running')
|
|
445
|
+
activeAgents++;
|
|
446
|
+
if (data.tasksCompleted) {
|
|
447
|
+
typeCounts[agType].tasks += data.tasksCompleted;
|
|
448
|
+
tasksCompleted += data.tasksCompleted;
|
|
449
|
+
}
|
|
450
|
+
if (data.successCount)
|
|
451
|
+
typeCounts[agType].success += data.successCount;
|
|
452
|
+
}
|
|
453
|
+
catch { /* skip malformed */ }
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
catch { /* no agents dir */ }
|
|
457
|
+
}
|
|
458
|
+
// Read swarm activity for additional state
|
|
459
|
+
const activityFile = join(swarmDir, 'swarm-activity.json');
|
|
460
|
+
if (existsSync(activityFile)) {
|
|
461
|
+
try {
|
|
462
|
+
const activity = JSON.parse(readFileSync(activityFile, 'utf-8'));
|
|
463
|
+
if (activity.totalAgents && totalAgents === 0)
|
|
464
|
+
totalAgents = activity.totalAgents;
|
|
465
|
+
if (activity.activeAgents && activeAgents === 0)
|
|
466
|
+
activeAgents = activity.activeAgents;
|
|
467
|
+
}
|
|
468
|
+
catch { /* ignore */ }
|
|
469
|
+
}
|
|
470
|
+
// Read memory.db stats
|
|
471
|
+
let vectorCount = 0;
|
|
472
|
+
const dbPath = join(swarmDir, 'memory.db');
|
|
473
|
+
if (existsSync(dbPath)) {
|
|
474
|
+
try {
|
|
475
|
+
const dbSize = statSync(dbPath).size;
|
|
476
|
+
vectorCount = Math.floor(dbSize / 2048);
|
|
477
|
+
}
|
|
478
|
+
catch { /* ignore */ }
|
|
479
|
+
}
|
|
480
|
+
const byType = Object.entries(typeCounts).map(([type, data]) => ({
|
|
481
|
+
type,
|
|
482
|
+
count: data.count,
|
|
483
|
+
tasks: data.tasks,
|
|
484
|
+
successRate: data.tasks > 0 ? `${Math.round((data.success / data.tasks) * 100)}%` : 'N/A'
|
|
485
|
+
}));
|
|
486
|
+
const avgSuccessRate = tasksCompleted > 0
|
|
487
|
+
? `${Math.round(Object.values(typeCounts).reduce((a, d) => a + d.success, 0) / tasksCompleted * 100)}%`
|
|
488
|
+
: 'N/A';
|
|
424
489
|
const metrics = {
|
|
425
490
|
period,
|
|
426
491
|
summary: {
|
|
427
|
-
totalAgents
|
|
428
|
-
activeAgents
|
|
429
|
-
tasksCompleted
|
|
430
|
-
avgSuccessRate
|
|
431
|
-
|
|
432
|
-
|
|
492
|
+
totalAgents,
|
|
493
|
+
activeAgents,
|
|
494
|
+
tasksCompleted,
|
|
495
|
+
avgSuccessRate,
|
|
496
|
+
vectorCount,
|
|
497
|
+
note: totalAgents === 0 ? 'No agents spawned yet. Use: agent spawn -t coder' : undefined
|
|
433
498
|
},
|
|
434
|
-
byType
|
|
435
|
-
{ type: 'coder', count: 2, tasks: 45, successRate: '97%' },
|
|
436
|
-
{ type: 'researcher', count: 1, tasks: 32, successRate: '95%' },
|
|
437
|
-
{ type: 'tester', count: 1, tasks: 50, successRate: '98%' }
|
|
438
|
-
],
|
|
499
|
+
byType,
|
|
439
500
|
performance: {
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
searchImprovement: '150x faster'
|
|
501
|
+
memoryVectors: `${vectorCount} vectors`,
|
|
502
|
+
searchBackend: vectorCount > 0 ? 'HNSW-indexed' : 'none'
|
|
443
503
|
}
|
|
444
504
|
};
|
|
445
505
|
if (ctx.flags.format === 'json') {
|
|
@@ -459,8 +519,7 @@ const metricsCommand = {
|
|
|
459
519
|
{ metric: 'Active Agents', value: metrics.summary.activeAgents },
|
|
460
520
|
{ metric: 'Tasks Completed', value: metrics.summary.tasksCompleted },
|
|
461
521
|
{ metric: 'Success Rate', value: metrics.summary.avgSuccessRate },
|
|
462
|
-
{ metric: '
|
|
463
|
-
{ metric: 'Avg Response Time', value: metrics.summary.avgResponseTime }
|
|
522
|
+
{ metric: 'Memory Vectors', value: metrics.summary.vectorCount }
|
|
464
523
|
]
|
|
465
524
|
});
|
|
466
525
|
output.writeln();
|
|
@@ -474,12 +533,15 @@ const metricsCommand = {
|
|
|
474
533
|
],
|
|
475
534
|
data: metrics.byType
|
|
476
535
|
});
|
|
536
|
+
if (metrics.summary.note) {
|
|
537
|
+
output.writeln();
|
|
538
|
+
output.writeln(output.dim(metrics.summary.note));
|
|
539
|
+
}
|
|
477
540
|
output.writeln();
|
|
478
|
-
output.writeln(output.bold('
|
|
541
|
+
output.writeln(output.bold('Memory'));
|
|
479
542
|
output.printList([
|
|
480
|
-
`
|
|
481
|
-
`
|
|
482
|
-
`Search: ${output.success(metrics.performance.searchImprovement)}`
|
|
543
|
+
`Vectors: ${output.success(metrics.performance.memoryVectors)}`,
|
|
544
|
+
`Backend: ${output.success(metrics.performance.searchBackend)}`
|
|
483
545
|
]);
|
|
484
546
|
return { success: true, data: metrics };
|
|
485
547
|
}
|
|
@@ -59,12 +59,13 @@ async function checkNpmVersion() {
|
|
|
59
59
|
}
|
|
60
60
|
// Check config file
|
|
61
61
|
async function checkConfigFile() {
|
|
62
|
-
|
|
62
|
+
// JSON configs (parse-validated)
|
|
63
|
+
const jsonPaths = [
|
|
63
64
|
'.claude-flow/config.json',
|
|
64
65
|
'claude-flow.config.json',
|
|
65
66
|
'.claude-flow.json'
|
|
66
67
|
];
|
|
67
|
-
for (const configPath of
|
|
68
|
+
for (const configPath of jsonPaths) {
|
|
68
69
|
if (existsSync(configPath)) {
|
|
69
70
|
try {
|
|
70
71
|
const content = readFileSync(configPath, 'utf8');
|
|
@@ -76,6 +77,17 @@ async function checkConfigFile() {
|
|
|
76
77
|
}
|
|
77
78
|
}
|
|
78
79
|
}
|
|
80
|
+
// YAML configs (existence-checked only — no heavy yaml parser dependency)
|
|
81
|
+
const yamlPaths = [
|
|
82
|
+
'.claude-flow/config.yaml',
|
|
83
|
+
'.claude-flow/config.yml',
|
|
84
|
+
'claude-flow.config.yaml'
|
|
85
|
+
];
|
|
86
|
+
for (const configPath of yamlPaths) {
|
|
87
|
+
if (existsSync(configPath)) {
|
|
88
|
+
return { name: 'Config File', status: 'pass', message: `Found: ${configPath}` };
|
|
89
|
+
}
|
|
90
|
+
}
|
|
79
91
|
return { name: 'Config File', status: 'warn', message: 'No config file (using defaults)', fix: 'claude-flow config init' };
|
|
80
92
|
}
|
|
81
93
|
// Check daemon status
|
|
@@ -128,9 +140,14 @@ async function checkApiKeys() {
|
|
|
128
140
|
found.push(key);
|
|
129
141
|
}
|
|
130
142
|
}
|
|
143
|
+
// Detect Claude Code environment — API keys are managed internally
|
|
144
|
+
const inClaudeCode = !!(process.env.CLAUDE_CODE || process.env.CLAUDE_PROJECT_DIR || process.env.MCP_SESSION_ID);
|
|
131
145
|
if (found.includes('ANTHROPIC_API_KEY') || found.includes('CLAUDE_API_KEY')) {
|
|
132
146
|
return { name: 'API Keys', status: 'pass', message: `Found: ${found.join(', ')}` };
|
|
133
147
|
}
|
|
148
|
+
else if (inClaudeCode) {
|
|
149
|
+
return { name: 'API Keys', status: 'pass', message: 'Claude Code (managed internally)' };
|
|
150
|
+
}
|
|
134
151
|
else if (found.length > 0) {
|
|
135
152
|
return { name: 'API Keys', status: 'warn', message: `Found: ${found.join(', ')} (no Claude key)`, fix: 'export ANTHROPIC_API_KEY=your_key' };
|
|
136
153
|
}
|
|
@@ -171,12 +188,12 @@ async function checkMcpServers() {
|
|
|
171
188
|
const content = JSON.parse(readFileSync(configPath, 'utf8'));
|
|
172
189
|
const servers = content.mcpServers || content.servers || {};
|
|
173
190
|
const count = Object.keys(servers).length;
|
|
174
|
-
const hasClaudeFlow = 'claude-flow' in servers || 'claude-flow_alpha' in servers;
|
|
191
|
+
const hasClaudeFlow = 'claude-flow' in servers || 'claude-flow_alpha' in servers || 'ruflo' in servers || 'ruflo_alpha' in servers;
|
|
175
192
|
if (hasClaudeFlow) {
|
|
176
|
-
return { name: 'MCP Servers', status: 'pass', message: `${count} servers (
|
|
193
|
+
return { name: 'MCP Servers', status: 'pass', message: `${count} servers (ruflo configured)` };
|
|
177
194
|
}
|
|
178
195
|
else {
|
|
179
|
-
return { name: 'MCP Servers', status: 'warn', message: `${count} servers (
|
|
196
|
+
return { name: 'MCP Servers', status: 'warn', message: `${count} servers (ruflo not found)`, fix: 'claude mcp add ruflo -- npx -y ruflo@latest mcp start' };
|
|
180
197
|
}
|
|
181
198
|
}
|
|
182
199
|
catch {
|
|
@@ -1146,9 +1146,8 @@ const preTaskCommand = {
|
|
|
1146
1146
|
{
|
|
1147
1147
|
name: 'task-id',
|
|
1148
1148
|
short: 'i',
|
|
1149
|
-
description: 'Unique task identifier',
|
|
1150
|
-
type: 'string'
|
|
1151
|
-
required: true
|
|
1149
|
+
description: 'Unique task identifier (auto-generated if omitted)',
|
|
1150
|
+
type: 'string'
|
|
1152
1151
|
},
|
|
1153
1152
|
{
|
|
1154
1153
|
name: 'description',
|
|
@@ -1170,10 +1169,10 @@ const preTaskCommand = {
|
|
|
1170
1169
|
{ command: 'claude-flow hooks pre-task -i task-456 -d "Implement feature" --auto-spawn', description: 'With auto-spawn' }
|
|
1171
1170
|
],
|
|
1172
1171
|
action: async (ctx) => {
|
|
1173
|
-
const taskId = ctx.flags.taskId
|
|
1172
|
+
const taskId = ctx.flags.taskId || `task-${Date.now().toString(36)}`;
|
|
1174
1173
|
const description = ctx.args[0] || ctx.flags.description;
|
|
1175
|
-
if (!
|
|
1176
|
-
output.printError('
|
|
1174
|
+
if (!description) {
|
|
1175
|
+
output.printError('Description is required: --description "your task"');
|
|
1177
1176
|
return { success: false, exitCode: 1 };
|
|
1178
1177
|
}
|
|
1179
1178
|
output.printInfo(`Starting task: ${output.highlight(taskId)}`);
|
|
@@ -3649,6 +3648,45 @@ const taskCompletedCommand = {
|
|
|
3649
3648
|
}
|
|
3650
3649
|
}
|
|
3651
3650
|
};
|
|
3651
|
+
// Notify subcommand
|
|
3652
|
+
const notifyCommand = {
|
|
3653
|
+
name: 'notify',
|
|
3654
|
+
description: 'Send a notification message (logged to session)',
|
|
3655
|
+
options: [
|
|
3656
|
+
{ name: 'message', short: 'm', type: 'string', description: 'Notification message', required: true },
|
|
3657
|
+
{ name: 'level', short: 'l', type: 'string', description: 'Level: info, warn, error', default: 'info' },
|
|
3658
|
+
{ name: 'channel', short: 'c', type: 'string', description: 'Notification channel', default: 'console' },
|
|
3659
|
+
],
|
|
3660
|
+
examples: [
|
|
3661
|
+
{ command: 'claude-flow hooks notify -m "Build complete"', description: 'Send info notification' },
|
|
3662
|
+
{ command: 'claude-flow hooks notify -m "Test failed" -l error', description: 'Send error notification' },
|
|
3663
|
+
],
|
|
3664
|
+
action: async (ctx) => {
|
|
3665
|
+
const message = ctx.args[0] || ctx.flags.message;
|
|
3666
|
+
const level = ctx.flags.level || 'info';
|
|
3667
|
+
if (!message) {
|
|
3668
|
+
output.printError('Message is required: --message "your message"');
|
|
3669
|
+
return { success: false, exitCode: 1 };
|
|
3670
|
+
}
|
|
3671
|
+
const timestamp = new Date().toISOString();
|
|
3672
|
+
if (level === 'error') {
|
|
3673
|
+
output.printError(`[${timestamp}] ${message}`);
|
|
3674
|
+
}
|
|
3675
|
+
else if (level === 'warn') {
|
|
3676
|
+
output.writeln(output.warning(`[${timestamp}] ${message}`));
|
|
3677
|
+
}
|
|
3678
|
+
else {
|
|
3679
|
+
output.printInfo(`[${timestamp}] ${message}`);
|
|
3680
|
+
}
|
|
3681
|
+
// Store notification in memory if available
|
|
3682
|
+
try {
|
|
3683
|
+
const { storeEntry } = await import('../memory/memory-initializer.js');
|
|
3684
|
+
await storeEntry({ key: `notify-${Date.now()}`, value: `[${level}] ${message}`, namespace: 'notifications' });
|
|
3685
|
+
}
|
|
3686
|
+
catch { /* memory not available */ }
|
|
3687
|
+
return { success: true, data: { timestamp, level, message } };
|
|
3688
|
+
}
|
|
3689
|
+
};
|
|
3652
3690
|
// Main hooks command
|
|
3653
3691
|
export const hooksCommand = {
|
|
3654
3692
|
name: 'hooks',
|
|
@@ -3670,6 +3708,7 @@ export const hooksCommand = {
|
|
|
3670
3708
|
transferCommand,
|
|
3671
3709
|
listCommand,
|
|
3672
3710
|
intelligenceCommand,
|
|
3711
|
+
notifyCommand,
|
|
3673
3712
|
workerCommand,
|
|
3674
3713
|
progressHookCommand,
|
|
3675
3714
|
statuslineCommand,
|
|
@@ -30,7 +30,7 @@ const trainCommand = {
|
|
|
30
30
|
{ command: 'claude-flow neural train -p security --wasm --contrastive', description: 'Security patterns with contrastive learning' },
|
|
31
31
|
],
|
|
32
32
|
action: async (ctx) => {
|
|
33
|
-
const patternType = ctx.flags.pattern || 'coordination';
|
|
33
|
+
const patternType = (ctx.flags.pattern || ctx.flags.patternType || ctx.flags['pattern-type']) || 'coordination';
|
|
34
34
|
const epochs = parseInt(ctx.flags.epochs || '50', 10);
|
|
35
35
|
const learningRate = parseFloat(ctx.flags['learning-rate'] || '0.01');
|
|
36
36
|
const batchSize = parseInt(ctx.flags['batch-size'] || '32', 10);
|
|
@@ -340,21 +340,52 @@ const auditCommand = {
|
|
|
340
340
|
output.writeln();
|
|
341
341
|
output.writeln(output.bold('Security Audit Log'));
|
|
342
342
|
output.writeln(output.dim('─'.repeat(60)));
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
343
|
+
// Generate real audit entries from .swarm/ state and session history
|
|
344
|
+
const { existsSync, readFileSync, readdirSync, statSync } = await import('fs');
|
|
345
|
+
const { join } = await import('path');
|
|
346
|
+
const auditEntries = [];
|
|
347
|
+
const swarmDir = join(process.cwd(), '.swarm');
|
|
348
|
+
// Check session files for real audit events
|
|
349
|
+
if (existsSync(swarmDir)) {
|
|
350
|
+
try {
|
|
351
|
+
const files = readdirSync(swarmDir).filter(f => f.endsWith('.json'));
|
|
352
|
+
for (const file of files.slice(-10)) {
|
|
353
|
+
try {
|
|
354
|
+
const stat = statSync(join(swarmDir, file));
|
|
355
|
+
const ts = stat.mtime.toISOString().replace('T', ' ').substring(0, 19);
|
|
356
|
+
auditEntries.push({
|
|
357
|
+
timestamp: ts,
|
|
358
|
+
event: file.includes('session') ? 'SESSION_UPDATE' :
|
|
359
|
+
file.includes('swarm') ? 'SWARM_ACTIVITY' :
|
|
360
|
+
file.includes('memory') ? 'MEMORY_WRITE' : 'CONFIG_CHANGE',
|
|
361
|
+
user: 'system',
|
|
362
|
+
status: output.success('Success')
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
catch { /* skip */ }
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
catch { /* ignore */ }
|
|
369
|
+
}
|
|
370
|
+
// Add current session entry
|
|
371
|
+
const now = new Date().toISOString().replace('T', ' ').substring(0, 19);
|
|
372
|
+
auditEntries.push({ timestamp: now, event: 'AUDIT_RUN', user: 'cli', status: output.success('Success') });
|
|
373
|
+
// Sort by timestamp desc
|
|
374
|
+
auditEntries.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
|
|
375
|
+
if (auditEntries.length === 0) {
|
|
376
|
+
output.writeln(output.dim('No audit events found. Initialize a project first: claude-flow init'));
|
|
377
|
+
}
|
|
378
|
+
else {
|
|
379
|
+
output.printTable({
|
|
380
|
+
columns: [
|
|
381
|
+
{ key: 'timestamp', header: 'Timestamp', width: 22 },
|
|
382
|
+
{ key: 'event', header: 'Event', width: 20 },
|
|
383
|
+
{ key: 'user', header: 'User', width: 15 },
|
|
384
|
+
{ key: 'status', header: 'Status', width: 12 },
|
|
385
|
+
],
|
|
386
|
+
data: auditEntries.slice(0, parseInt(ctx.flags.limit || '20', 10)),
|
|
387
|
+
});
|
|
388
|
+
}
|
|
358
389
|
return { success: true };
|
|
359
390
|
},
|
|
360
391
|
};
|
|
@@ -81,7 +81,7 @@ export const agentdbControllers = {
|
|
|
81
81
|
const bridge = await getBridge();
|
|
82
82
|
const controllers = await bridge.bridgeListControllers();
|
|
83
83
|
if (!controllers)
|
|
84
|
-
return { available: false, controllers: [], error: '
|
|
84
|
+
return { available: false, controllers: [], error: 'AgentDB bridge not available — @claude-flow/memory not installed or missing controller-registry. Use memory_store/memory_search tools instead.' };
|
|
85
85
|
return {
|
|
86
86
|
available: true,
|
|
87
87
|
controllers,
|
|
@@ -118,7 +118,7 @@ export const agentdbPatternStore = {
|
|
|
118
118
|
type: validateString(params.type, 'type', 200) ?? 'general',
|
|
119
119
|
confidence: validateScore(params.confidence, 0.8),
|
|
120
120
|
});
|
|
121
|
-
return result ?? { success: false, error: '
|
|
121
|
+
return result ?? { success: false, error: 'AgentDB bridge not available. Use memory_store/memory_search instead.' };
|
|
122
122
|
}
|
|
123
123
|
catch (error) {
|
|
124
124
|
return { success: false, error: sanitizeError(error) };
|
|
@@ -182,7 +182,7 @@ export const agentdbFeedback = {
|
|
|
182
182
|
quality: validateScore(params.quality, 0.85),
|
|
183
183
|
agent: validateString(params.agent, 'agent', 200) ?? undefined,
|
|
184
184
|
});
|
|
185
|
-
return result ?? { success: false, error: '
|
|
185
|
+
return result ?? { success: false, error: 'AgentDB bridge not available. Use memory_store/memory_search instead.' };
|
|
186
186
|
}
|
|
187
187
|
catch (error) {
|
|
188
188
|
return { success: false, error: sanitizeError(error) };
|
|
@@ -221,7 +221,7 @@ export const agentdbCausalEdge = {
|
|
|
221
221
|
relation,
|
|
222
222
|
weight: typeof params.weight === 'number' ? validateScore(params.weight, 0.5) : undefined,
|
|
223
223
|
});
|
|
224
|
-
return result ?? { success: false, error: '
|
|
224
|
+
return result ?? { success: false, error: 'AgentDB bridge not available. Use memory_store/memory_search instead.' };
|
|
225
225
|
}
|
|
226
226
|
catch (error) {
|
|
227
227
|
return { success: false, error: sanitizeError(error) };
|
|
@@ -279,7 +279,7 @@ export const agentdbSessionStart = {
|
|
|
279
279
|
sessionId,
|
|
280
280
|
context: validateString(params.context, 'context', 10_000) ?? undefined,
|
|
281
281
|
});
|
|
282
|
-
return result ?? { success: false, error: '
|
|
282
|
+
return result ?? { success: false, error: 'AgentDB bridge not available. Use memory_store/memory_search instead.' };
|
|
283
283
|
}
|
|
284
284
|
catch (error) {
|
|
285
285
|
return { success: false, error: sanitizeError(error) };
|
|
@@ -310,7 +310,7 @@ export const agentdbSessionEnd = {
|
|
|
310
310
|
summary: validateString(params.summary, 'summary', 50_000) ?? undefined,
|
|
311
311
|
tasksCompleted: validatePositiveInt(params.tasksCompleted, 0, 10_000),
|
|
312
312
|
});
|
|
313
|
-
return result ?? { success: false, error: '
|
|
313
|
+
return result ?? { success: false, error: 'AgentDB bridge not available. Use memory_store/memory_search instead.' };
|
|
314
314
|
}
|
|
315
315
|
catch (error) {
|
|
316
316
|
return { success: false, error: sanitizeError(error) };
|
|
@@ -349,7 +349,7 @@ export const agentdbHierarchicalStore = {
|
|
|
349
349
|
}
|
|
350
350
|
const bridge = await getBridge();
|
|
351
351
|
const result = await bridge.bridgeHierarchicalStore({ key, value, tier });
|
|
352
|
-
return result ?? { success: false, error: '
|
|
352
|
+
return result ?? { success: false, error: 'AgentDB bridge not available. Use memory_store/memory_search instead.' };
|
|
353
353
|
}
|
|
354
354
|
catch (error) {
|
|
355
355
|
return { success: false, error: sanitizeError(error) };
|
|
@@ -384,7 +384,7 @@ export const agentdbHierarchicalRecall = {
|
|
|
384
384
|
tier: tier ?? undefined,
|
|
385
385
|
topK: validatePositiveInt(params.topK, 5, MAX_TOP_K),
|
|
386
386
|
});
|
|
387
|
-
return result ?? { results: [], error: '
|
|
387
|
+
return result ?? { results: [], error: 'AgentDB bridge not available. Use memory_search instead.' };
|
|
388
388
|
}
|
|
389
389
|
catch (error) {
|
|
390
390
|
return { results: [], error: sanitizeError(error) };
|
|
@@ -409,7 +409,7 @@ export const agentdbConsolidate = {
|
|
|
409
409
|
minAge: typeof params.minAge === 'number' ? Math.max(0, params.minAge) : undefined,
|
|
410
410
|
maxEntries: validatePositiveInt(params.maxEntries, 1000, 10_000),
|
|
411
411
|
});
|
|
412
|
-
return result ?? { success: false, error: '
|
|
412
|
+
return result ?? { success: false, error: 'AgentDB bridge not available. Use memory_store/memory_search instead.' };
|
|
413
413
|
}
|
|
414
414
|
catch (error) {
|
|
415
415
|
return { success: false, error: sanitizeError(error) };
|
|
@@ -475,7 +475,7 @@ export const agentdbBatch = {
|
|
|
475
475
|
operation,
|
|
476
476
|
entries: validatedEntries,
|
|
477
477
|
});
|
|
478
|
-
return result ?? { success: false, error: '
|
|
478
|
+
return result ?? { success: false, error: 'AgentDB bridge not available. Use memory_store/memory_search instead.' };
|
|
479
479
|
}
|
|
480
480
|
catch (error) {
|
|
481
481
|
return { success: false, error: sanitizeError(error) };
|
|
@@ -504,7 +504,7 @@ export const agentdbContextSynthesize = {
|
|
|
504
504
|
query,
|
|
505
505
|
maxEntries: validatePositiveInt(params.maxEntries, 10, MAX_TOP_K),
|
|
506
506
|
});
|
|
507
|
-
return result ?? { success: false, error: '
|
|
507
|
+
return result ?? { success: false, error: 'AgentDB bridge not available. Use memory_store/memory_search instead.' };
|
|
508
508
|
}
|
|
509
509
|
catch (error) {
|
|
510
510
|
return { success: false, error: sanitizeError(error) };
|
|
@@ -529,7 +529,7 @@ export const agentdbSemanticRoute = {
|
|
|
529
529
|
return { route: null, error: 'input is required (non-empty string, max 10KB)' };
|
|
530
530
|
const bridge = await getBridge();
|
|
531
531
|
const result = await bridge.bridgeSemanticRoute({ input });
|
|
532
|
-
return result ?? { route: null, error: '
|
|
532
|
+
return result ?? { route: null, error: 'AgentDB bridge not available. Use hooks route instead.' };
|
|
533
533
|
}
|
|
534
534
|
catch (error) {
|
|
535
535
|
return { route: null, error: sanitizeError(error) };
|
|
@@ -545,9 +545,13 @@ export async function findSimilarPatterns(query, options) {
|
|
|
545
545
|
const queryResult = await generateEmbedding(query);
|
|
546
546
|
queryEmbedding = queryResult.embedding;
|
|
547
547
|
}
|
|
548
|
+
// Hash-fallback embeddings (128-dim) produce lower cosine similarities
|
|
549
|
+
// than ONNX/transformer embeddings, so use a lower default threshold
|
|
550
|
+
const isHashFallback = queryEmbedding.length === 128;
|
|
551
|
+
const defaultThreshold = isHashFallback ? 0.1 : 0.5;
|
|
548
552
|
const results = reasoningBank.findSimilar(queryEmbedding, {
|
|
549
553
|
k: options?.k ?? 5,
|
|
550
|
-
threshold: options?.threshold ??
|
|
554
|
+
threshold: options?.threshold ?? defaultThreshold,
|
|
551
555
|
type: options?.type
|
|
552
556
|
});
|
|
553
557
|
return results.map((r) => ({
|
|
@@ -32,6 +32,16 @@ export declare class CommandParser {
|
|
|
32
32
|
private parseValue;
|
|
33
33
|
private normalizeKey;
|
|
34
34
|
private buildAliases;
|
|
35
|
+
/**
|
|
36
|
+
* Build aliases scoped to a specific command/subcommand.
|
|
37
|
+
* The resolved command's short flags take priority over global ones,
|
|
38
|
+
* fixing collisions where multiple subcommands use the same short flag (e.g. -t).
|
|
39
|
+
*/
|
|
40
|
+
private buildScopedAliases;
|
|
41
|
+
/**
|
|
42
|
+
* Get boolean flags scoped to a specific command/subcommand.
|
|
43
|
+
*/
|
|
44
|
+
private getScopedBooleanFlags;
|
|
35
45
|
private getBooleanFlags;
|
|
36
46
|
private applyDefaults;
|
|
37
47
|
validateFlags(flags: ParsedFlags, command?: Command): string[];
|
|
@@ -101,9 +101,23 @@ export class CommandParser {
|
|
|
101
101
|
positional: [],
|
|
102
102
|
raw: [...args]
|
|
103
103
|
};
|
|
104
|
-
//
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
// Pass 1: Identify command and subcommand (skip flags)
|
|
105
|
+
let resolvedCmd;
|
|
106
|
+
let resolvedSub;
|
|
107
|
+
for (const arg of args) {
|
|
108
|
+
if (arg.startsWith('-'))
|
|
109
|
+
continue;
|
|
110
|
+
if (!resolvedCmd && this.commands.has(arg)) {
|
|
111
|
+
resolvedCmd = this.commands.get(arg);
|
|
112
|
+
}
|
|
113
|
+
else if (resolvedCmd && !resolvedSub && resolvedCmd.subcommands) {
|
|
114
|
+
resolvedSub = resolvedCmd.subcommands.find(sc => sc.name === arg || sc.aliases?.includes(arg));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// Pass 2: Build aliases scoped to the resolved subcommand
|
|
118
|
+
// Subcommand-specific aliases take priority over global ones
|
|
119
|
+
const aliases = this.buildScopedAliases(resolvedSub || resolvedCmd);
|
|
120
|
+
const booleanFlags = this.getScopedBooleanFlags(resolvedSub || resolvedCmd);
|
|
107
121
|
let i = 0;
|
|
108
122
|
let parsingFlags = true;
|
|
109
123
|
while (i < args.length) {
|
|
@@ -275,6 +289,38 @@ export class CommandParser {
|
|
|
275
289
|
}
|
|
276
290
|
return { ...aliases, ...this.options.aliases };
|
|
277
291
|
}
|
|
292
|
+
/**
|
|
293
|
+
* Build aliases scoped to a specific command/subcommand.
|
|
294
|
+
* The resolved command's short flags take priority over global ones,
|
|
295
|
+
* fixing collisions where multiple subcommands use the same short flag (e.g. -t).
|
|
296
|
+
*/
|
|
297
|
+
buildScopedAliases(resolvedCmd) {
|
|
298
|
+
// Start with global aliases as base
|
|
299
|
+
const aliases = this.buildAliases();
|
|
300
|
+
// Override with the resolved command's own options (these take priority)
|
|
301
|
+
if (resolvedCmd?.options) {
|
|
302
|
+
for (const opt of resolvedCmd.options) {
|
|
303
|
+
if (opt.short) {
|
|
304
|
+
aliases[opt.short] = opt.name;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return aliases;
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Get boolean flags scoped to a specific command/subcommand.
|
|
312
|
+
*/
|
|
313
|
+
getScopedBooleanFlags(resolvedCmd) {
|
|
314
|
+
const flags = this.getBooleanFlags();
|
|
315
|
+
if (resolvedCmd?.options) {
|
|
316
|
+
for (const opt of resolvedCmd.options) {
|
|
317
|
+
if (opt.type === 'boolean') {
|
|
318
|
+
flags.add(this.normalizeKey(opt.name));
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
return flags;
|
|
323
|
+
}
|
|
278
324
|
getBooleanFlags() {
|
|
279
325
|
const flags = new Set();
|
|
280
326
|
for (const opt of this.globalOptions) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claude-flow/cli",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.20",
|
|
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",
|