@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
- // Take the last model (most recently added to the object)
101
- // Or find the one with most tokens (most actively used this session)
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
- if (modelIds.length > 1) {
104
- // If multiple models, pick the one with most total tokens
105
- let maxTokens = 0;
106
- for (const id of modelIds) {
107
- const usage = lastModelUsage[id];
108
- const total = (usage.inputTokens || 0) + (usage.outputTokens || 0);
109
- if (total > maxTokens) {
110
- maxTokens = total;
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} \${c.dim}│\${c.reset} \` +
462
- \`\${c.cyan}Memory\${c.reset} \${c.brightGreen}●AgentDB\${c.reset} \${c.dim}│\${c.reset} \` +
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmctC,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"}
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"}