@claude-flow/cli 3.0.0-alpha.127 → 3.0.0-alpha.129
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.
|
@@ -97,21 +97,23 @@ function getUserInfo() {
|
|
|
97
97
|
if (lastModelUsage) {
|
|
98
98
|
const modelIds = Object.keys(lastModelUsage);
|
|
99
99
|
if (modelIds.length > 0) {
|
|
100
|
-
//
|
|
101
|
-
//
|
|
100
|
+
// Find the most recently used model by checking lastUsedAt timestamps
|
|
101
|
+
// or fall back to the last key in the object (preserves insertion order in modern JS)
|
|
102
102
|
let modelId = modelIds[modelIds.length - 1];
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
103
|
+
let latestTimestamp = 0;
|
|
104
|
+
|
|
105
|
+
for (const id of modelIds) {
|
|
106
|
+
const usage = lastModelUsage[id];
|
|
107
|
+
// Check for lastUsedAt timestamp (if available)
|
|
108
|
+
if (usage.lastUsedAt) {
|
|
109
|
+
const ts = new Date(usage.lastUsedAt).getTime();
|
|
110
|
+
if (ts > latestTimestamp) {
|
|
111
|
+
latestTimestamp = ts;
|
|
111
112
|
modelId = id;
|
|
112
113
|
}
|
|
113
114
|
}
|
|
114
115
|
}
|
|
116
|
+
|
|
115
117
|
// Parse model ID to human-readable name
|
|
116
118
|
if (modelId.includes('opus')) modelName = 'Opus 4.5';
|
|
117
119
|
else if (modelId.includes('sonnet')) modelName = 'Sonnet 4';
|
|
@@ -401,6 +403,221 @@ function getSystemMetrics() {
|
|
|
401
403
|
};
|
|
402
404
|
}
|
|
403
405
|
|
|
406
|
+
// Get ADR (Architecture Decision Records) status
|
|
407
|
+
function getADRStatus() {
|
|
408
|
+
const adrPaths = [
|
|
409
|
+
path.join(process.cwd(), 'docs', 'adrs'),
|
|
410
|
+
path.join(process.cwd(), 'docs', 'adr'),
|
|
411
|
+
path.join(process.cwd(), 'adr'),
|
|
412
|
+
path.join(process.cwd(), 'ADR'),
|
|
413
|
+
path.join(process.cwd(), '.claude-flow', 'adrs'),
|
|
414
|
+
path.join(process.cwd(), 'v3', 'implementation', 'adrs'),
|
|
415
|
+
path.join(process.cwd(), 'implementation', 'adrs'),
|
|
416
|
+
];
|
|
417
|
+
|
|
418
|
+
let count = 0;
|
|
419
|
+
let implemented = 0;
|
|
420
|
+
|
|
421
|
+
for (const adrPath of adrPaths) {
|
|
422
|
+
if (fs.existsSync(adrPath)) {
|
|
423
|
+
try {
|
|
424
|
+
const files = fs.readdirSync(adrPath).filter(f =>
|
|
425
|
+
f.endsWith('.md') && (f.startsWith('ADR-') || f.startsWith('adr-') || /^\\d{4}-/.test(f))
|
|
426
|
+
);
|
|
427
|
+
count = files.length;
|
|
428
|
+
|
|
429
|
+
// Check for implemented status in ADR files
|
|
430
|
+
for (const file of files) {
|
|
431
|
+
try {
|
|
432
|
+
const content = fs.readFileSync(path.join(adrPath, file), 'utf-8');
|
|
433
|
+
if (content.includes('Status: Implemented') || content.includes('status: implemented') ||
|
|
434
|
+
content.includes('Status: Accepted') || content.includes('status: accepted')) {
|
|
435
|
+
implemented++;
|
|
436
|
+
}
|
|
437
|
+
} catch (e) {
|
|
438
|
+
// Skip unreadable files
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
break;
|
|
442
|
+
} catch (e) {
|
|
443
|
+
// Ignore
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
return { count, implemented };
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// Get hooks status (enabled/registered hooks)
|
|
452
|
+
function getHooksStatus() {
|
|
453
|
+
let enabled = 0;
|
|
454
|
+
let total = 17; // V3 has 17 hook types
|
|
455
|
+
|
|
456
|
+
// Check .claude/settings.json for hooks config
|
|
457
|
+
const settingsPaths = [
|
|
458
|
+
path.join(process.cwd(), '.claude', 'settings.json'),
|
|
459
|
+
path.join(process.cwd(), '.claude', 'settings.local.json'),
|
|
460
|
+
];
|
|
461
|
+
|
|
462
|
+
for (const settingsPath of settingsPaths) {
|
|
463
|
+
if (fs.existsSync(settingsPath)) {
|
|
464
|
+
try {
|
|
465
|
+
const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
|
|
466
|
+
if (settings.hooks) {
|
|
467
|
+
// Count enabled hooks
|
|
468
|
+
const hookTypes = Object.keys(settings.hooks);
|
|
469
|
+
enabled = hookTypes.filter(h => {
|
|
470
|
+
const hook = settings.hooks[h];
|
|
471
|
+
return hook && (hook.enabled !== false) && (hook.command || hook.script);
|
|
472
|
+
}).length;
|
|
473
|
+
}
|
|
474
|
+
break;
|
|
475
|
+
} catch (e) {
|
|
476
|
+
// Ignore parse errors
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// Also check for hook files in .claude/hooks
|
|
482
|
+
const hooksDir = path.join(process.cwd(), '.claude', 'hooks');
|
|
483
|
+
if (fs.existsSync(hooksDir)) {
|
|
484
|
+
try {
|
|
485
|
+
const hookFiles = fs.readdirSync(hooksDir).filter(f => f.endsWith('.js') || f.endsWith('.sh'));
|
|
486
|
+
enabled = Math.max(enabled, hookFiles.length);
|
|
487
|
+
} catch (e) {
|
|
488
|
+
// Ignore
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
return { enabled, total };
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// Get AgentDB memory stats
|
|
496
|
+
function getAgentDBStats() {
|
|
497
|
+
let vectorCount = 0;
|
|
498
|
+
let dbSizeKB = 0;
|
|
499
|
+
let namespaces = 0;
|
|
500
|
+
|
|
501
|
+
const dbPaths = [
|
|
502
|
+
path.join(process.cwd(), '.claude-flow', 'agentdb'),
|
|
503
|
+
path.join(process.cwd(), '.swarm', 'agentdb'),
|
|
504
|
+
path.join(process.cwd(), 'data', 'agentdb'),
|
|
505
|
+
path.join(process.cwd(), '.claude', 'memory'),
|
|
506
|
+
];
|
|
507
|
+
|
|
508
|
+
for (const dbPath of dbPaths) {
|
|
509
|
+
if (fs.existsSync(dbPath)) {
|
|
510
|
+
try {
|
|
511
|
+
const stats = fs.statSync(dbPath);
|
|
512
|
+
if (stats.isDirectory()) {
|
|
513
|
+
// Count database files and estimate vectors
|
|
514
|
+
const files = fs.readdirSync(dbPath);
|
|
515
|
+
namespaces = files.filter(f => f.endsWith('.db') || f.endsWith('.sqlite')).length;
|
|
516
|
+
|
|
517
|
+
// Calculate total size
|
|
518
|
+
for (const file of files) {
|
|
519
|
+
const filePath = path.join(dbPath, file);
|
|
520
|
+
const fileStat = fs.statSync(filePath);
|
|
521
|
+
if (fileStat.isFile()) {
|
|
522
|
+
dbSizeKB += fileStat.size / 1024;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
// Estimate vector count (~0.5KB per vector on average)
|
|
527
|
+
vectorCount = Math.floor(dbSizeKB / 0.5);
|
|
528
|
+
} else {
|
|
529
|
+
// Single file database
|
|
530
|
+
dbSizeKB = stats.size / 1024;
|
|
531
|
+
vectorCount = Math.floor(dbSizeKB / 0.5);
|
|
532
|
+
namespaces = 1;
|
|
533
|
+
}
|
|
534
|
+
break;
|
|
535
|
+
} catch (e) {
|
|
536
|
+
// Ignore
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// Also check for vectors.json (simple vector store)
|
|
542
|
+
const vectorsPath = path.join(process.cwd(), '.claude-flow', 'vectors.json');
|
|
543
|
+
if (fs.existsSync(vectorsPath) && vectorCount === 0) {
|
|
544
|
+
try {
|
|
545
|
+
const data = JSON.parse(fs.readFileSync(vectorsPath, 'utf-8'));
|
|
546
|
+
if (Array.isArray(data)) {
|
|
547
|
+
vectorCount = data.length;
|
|
548
|
+
} else if (data.vectors) {
|
|
549
|
+
vectorCount = Object.keys(data.vectors).length;
|
|
550
|
+
}
|
|
551
|
+
} catch (e) {
|
|
552
|
+
// Ignore
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
return { vectorCount, dbSizeKB: Math.floor(dbSizeKB), namespaces };
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
// Get test statistics
|
|
560
|
+
function getTestStats() {
|
|
561
|
+
let testFiles = 0;
|
|
562
|
+
let testCases = 0;
|
|
563
|
+
|
|
564
|
+
const testDirs = [
|
|
565
|
+
path.join(process.cwd(), 'tests'),
|
|
566
|
+
path.join(process.cwd(), 'test'),
|
|
567
|
+
path.join(process.cwd(), '__tests__'),
|
|
568
|
+
path.join(process.cwd(), 'src', '__tests__'),
|
|
569
|
+
path.join(process.cwd(), 'v3', '__tests__'),
|
|
570
|
+
];
|
|
571
|
+
|
|
572
|
+
// Recursively count test files
|
|
573
|
+
function countTestFiles(dir, depth = 0) {
|
|
574
|
+
if (depth > 3) return; // Limit recursion
|
|
575
|
+
if (!fs.existsSync(dir)) return;
|
|
576
|
+
|
|
577
|
+
try {
|
|
578
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
579
|
+
for (const entry of entries) {
|
|
580
|
+
if (entry.isDirectory() && !entry.name.startsWith('.') && entry.name !== 'node_modules') {
|
|
581
|
+
countTestFiles(path.join(dir, entry.name), depth + 1);
|
|
582
|
+
} else if (entry.isFile()) {
|
|
583
|
+
const name = entry.name;
|
|
584
|
+
if (name.includes('.test.') || name.includes('.spec.') ||
|
|
585
|
+
name.includes('_test.') || name.includes('_spec.') ||
|
|
586
|
+
name.startsWith('test_') || name.startsWith('spec_')) {
|
|
587
|
+
testFiles++;
|
|
588
|
+
|
|
589
|
+
// Try to estimate test cases from file
|
|
590
|
+
try {
|
|
591
|
+
const content = fs.readFileSync(path.join(dir, name), 'utf-8');
|
|
592
|
+
// Count it(), test(), describe() patterns
|
|
593
|
+
const itMatches = (content.match(/\\bit\\s*\\(/g) || []).length;
|
|
594
|
+
const testMatches = (content.match(/\\btest\\s*\\(/g) || []).length;
|
|
595
|
+
testCases += itMatches + testMatches;
|
|
596
|
+
} catch (e) {
|
|
597
|
+
// Estimate 3 tests per file if can't read
|
|
598
|
+
testCases += 3;
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
} catch (e) {
|
|
604
|
+
// Ignore
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
for (const dir of testDirs) {
|
|
609
|
+
countTestFiles(dir);
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
// Also check src directory for colocated tests
|
|
613
|
+
const srcDir = path.join(process.cwd(), 'src');
|
|
614
|
+
if (fs.existsSync(srcDir)) {
|
|
615
|
+
countTestFiles(srcDir);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
return { testFiles, testCases };
|
|
619
|
+
}
|
|
620
|
+
|
|
404
621
|
// Generate progress bar
|
|
405
622
|
function progressBar(current, total) {
|
|
406
623
|
const width = 5;
|
|
@@ -416,6 +633,10 @@ function generateStatusline() {
|
|
|
416
633
|
const security = getSecurityStatus();
|
|
417
634
|
const swarm = getSwarmStatus();
|
|
418
635
|
const system = getSystemMetrics();
|
|
636
|
+
const adrs = getADRStatus();
|
|
637
|
+
const hooks = getHooksStatus();
|
|
638
|
+
const agentdb = getAgentDBStats();
|
|
639
|
+
const tests = getTestStats();
|
|
419
640
|
const lines = [];
|
|
420
641
|
|
|
421
642
|
// Header Line
|
|
@@ -438,28 +659,41 @@ function generateStatusline() {
|
|
|
438
659
|
\`\${c.brightYellow}⚡ 1.0x\${c.reset} \${c.dim}→\${c.reset} \${c.brightYellow}2.49x-7.47x\${c.reset}\`
|
|
439
660
|
);
|
|
440
661
|
|
|
441
|
-
// Line 2: Swarm + CVE + Memory + Context + Intelligence
|
|
662
|
+
// Line 2: Swarm + Hooks + CVE + Memory + Context + Intelligence
|
|
442
663
|
const swarmIndicator = swarm.coordinationActive ? \`\${c.brightGreen}◉\${c.reset}\` : \`\${c.dim}○\${c.reset}\`;
|
|
443
664
|
const agentsColor = swarm.activeAgents > 0 ? c.brightGreen : c.red;
|
|
444
665
|
let securityIcon = security.status === 'CLEAN' ? '🟢' : security.status === 'IN_PROGRESS' ? '🟡' : '🔴';
|
|
445
666
|
let securityColor = security.status === 'CLEAN' ? c.brightGreen : security.status === 'IN_PROGRESS' ? c.brightYellow : c.brightRed;
|
|
667
|
+
const hooksColor = hooks.enabled > 0 ? c.brightGreen : c.dim;
|
|
446
668
|
|
|
447
669
|
lines.push(
|
|
448
670
|
\`\${c.brightYellow}🤖 Swarm\${c.reset} \${swarmIndicator} [\${agentsColor}\${String(swarm.activeAgents).padStart(2)}\${c.reset}/\${c.brightWhite}\${swarm.maxAgents}\${c.reset}] \` +
|
|
449
671
|
\`\${c.brightPurple}👥 \${system.subAgents}\${c.reset} \` +
|
|
672
|
+
\`\${c.brightBlue}🪝 \${hooksColor}\${hooks.enabled}\${c.reset}/\${c.brightWhite}\${hooks.total}\${c.reset} \` +
|
|
450
673
|
\`\${securityIcon} \${securityColor}CVE \${security.cvesFixed}\${c.reset}/\${c.brightWhite}\${security.totalCves}\${c.reset} \` +
|
|
451
674
|
\`\${c.brightCyan}💾 \${system.memoryMB}MB\${c.reset} \` +
|
|
452
|
-
\`\${c.brightGreen}📂 \${String(system.contextPct).padStart(3)}%\${c.reset} \` +
|
|
453
675
|
\`\${c.dim}🧠 \${String(system.intelligencePct).padStart(3)}%\${c.reset}\`
|
|
454
676
|
);
|
|
455
677
|
|
|
456
|
-
// Line 3: Architecture status
|
|
678
|
+
// Line 3: Architecture status with ADRs, AgentDB, Tests
|
|
457
679
|
const dddColor = progress.dddProgress >= 50 ? c.brightGreen : progress.dddProgress > 0 ? c.yellow : c.red;
|
|
680
|
+
const adrColor = adrs.count > 0 ? (adrs.implemented === adrs.count ? c.brightGreen : c.yellow) : c.dim;
|
|
681
|
+
const vectorColor = agentdb.vectorCount > 0 ? c.brightGreen : c.dim;
|
|
682
|
+
const testColor = tests.testFiles > 0 ? c.brightGreen : c.dim;
|
|
683
|
+
|
|
458
684
|
lines.push(
|
|
459
685
|
\`\${c.brightPurple}🔧 Architecture\${c.reset} \` +
|
|
686
|
+
\`\${c.cyan}ADRs\${c.reset} \${adrColor}●\${adrs.implemented}/\${adrs.count}\${c.reset} \${c.dim}│\${c.reset} \` +
|
|
460
687
|
\`\${c.cyan}DDD\${c.reset} \${dddColor}●\${String(progress.dddProgress).padStart(3)}%\${c.reset} \${c.dim}│\${c.reset} \` +
|
|
461
|
-
\`\${c.cyan}Security\${c.reset} \${securityColor}●\${security.status}\${c.reset}
|
|
462
|
-
|
|
688
|
+
\`\${c.cyan}Security\${c.reset} \${securityColor}●\${security.status}\${c.reset}\`
|
|
689
|
+
);
|
|
690
|
+
|
|
691
|
+
// Line 4: Memory, Vectors, Tests
|
|
692
|
+
lines.push(
|
|
693
|
+
\`\${c.brightCyan}📊 AgentDB\${c.reset} \` +
|
|
694
|
+
\`\${c.cyan}Vectors\${c.reset} \${vectorColor}●\${agentdb.vectorCount}\${c.reset} \${c.dim}│\${c.reset} \` +
|
|
695
|
+
\`\${c.cyan}Size\${c.reset} \${c.brightWhite}\${agentdb.dbSizeKB}KB\${c.reset} \${c.dim}│\${c.reset} \` +
|
|
696
|
+
\`\${c.cyan}Tests\${c.reset} \${testColor}●\${tests.testFiles}\${c.reset} \${c.dim}(\${tests.testCases} cases)\${c.reset} \${c.dim}│\${c.reset} \` +
|
|
463
697
|
\`\${c.cyan}Integration\${c.reset} \${swarm.coordinationActive ? c.brightCyan : c.dim}●\${c.reset}\`
|
|
464
698
|
);
|
|
465
699
|
|
|
@@ -474,6 +708,10 @@ function generateJSON() {
|
|
|
474
708
|
security: getSecurityStatus(),
|
|
475
709
|
swarm: getSwarmStatus(),
|
|
476
710
|
system: getSystemMetrics(),
|
|
711
|
+
adrs: getADRStatus(),
|
|
712
|
+
hooks: getHooksStatus(),
|
|
713
|
+
agentdb: getAgentDBStats(),
|
|
714
|
+
tests: getTestStats(),
|
|
477
715
|
performance: {
|
|
478
716
|
flashAttentionTarget: '2.49x-7.47x',
|
|
479
717
|
searchImprovement: '150x-12,500x',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"statusline-generator.js","sourceRoot":"","sources":["../../../src/init/statusline-generator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;;;;;;;GAQG;AACH,MAAM,UAAU,wBAAwB,CAAC,OAAoB;IAC3D,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAElC,oFAAoF;IACpF,OAAO;;;;;;;;;;;;;;;;;;aAkBI,MAAM,CAAC,OAAO;kBACT,MAAM,CAAC,YAAY;kBACnB,MAAM,CAAC,YAAY;eACtB,MAAM,CAAC,SAAS;eAChB,MAAM,CAAC,SAAS;qBACV,MAAM,CAAC,eAAe;qBACtB,MAAM,CAAC,eAAe;eAC5B,OAAO,CAAC,OAAO,CAAC,SAAS;eACzB,OAAO,CAAC,OAAO,CAAC,QAAQ
|
|
1
|
+
{"version":3,"file":"statusline-generator.js","sourceRoot":"","sources":["../../../src/init/statusline-generator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;;;;;;;GAQG;AACH,MAAM,UAAU,wBAAwB,CAAC,OAAoB;IAC3D,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAElC,oFAAoF;IACpF,OAAO;;;;;;;;;;;;;;;;;;aAkBI,MAAM,CAAC,OAAO;kBACT,MAAM,CAAC,YAAY;kBACnB,MAAM,CAAC,YAAY;eACtB,MAAM,CAAC,SAAS;eAChB,MAAM,CAAC,SAAS;qBACV,MAAM,CAAC,eAAe;qBACtB,MAAM,CAAC,eAAe;eAC5B,OAAO,CAAC,OAAO,CAAC,SAAS;eACzB,OAAO,CAAC,OAAO,CAAC,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAirBtC,CAAC;AACF,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAoB;IACzD,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;QAChC,OAAO,uBAAuB,CAAC;IACjC,CAAC;IAED,OAAO;;;;;;;;;;;;;;;;;;;;;CAqBR,CAAC;AACF,CAAC"}
|