claude-flow 3.38.19 → 3.38.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.
|
@@ -552,6 +552,68 @@ function getLocalSecurity(cliSecurity) {
|
|
|
552
552
|
return base;
|
|
553
553
|
}
|
|
554
554
|
|
|
555
|
+
// Cached pattern count. The store is routinely >10MB (14.5MB / 1277 patterns on
|
|
556
|
+
// the machine this was diagnosed on, costing 53ms to read+parse), and the
|
|
557
|
+
// statusline re-renders on every prompt, so the parse is keyed on the file's
|
|
558
|
+
// mtime+size and reused until the store actually changes.
|
|
559
|
+
const PATTERN_COUNT_CACHE = path.join(os.tmpdir(), 'ruflo-statusline-patterns-' + require('crypto').createHash('md5').update(CWD).digest('hex').slice(0, 8) + '.json');
|
|
560
|
+
|
|
561
|
+
function countPatternsCached(file) {
|
|
562
|
+
let stat;
|
|
563
|
+
try { stat = fs.statSync(file); } catch { return 0; }
|
|
564
|
+
const key = stat.mtimeMs + ':' + stat.size;
|
|
565
|
+
|
|
566
|
+
try {
|
|
567
|
+
const memo = JSON.parse(fs.readFileSync(PATTERN_COUNT_CACHE, 'utf-8'));
|
|
568
|
+
if (memo && memo[file] && memo[file].key === key) return memo[file].count;
|
|
569
|
+
} catch { /* no memo yet, or unreadable — fall through and recount */ }
|
|
570
|
+
|
|
571
|
+
let count = 0;
|
|
572
|
+
try {
|
|
573
|
+
const raw = JSON.parse(fs.readFileSync(file, 'utf-8'));
|
|
574
|
+
if (Array.isArray(raw)) count = raw.length;
|
|
575
|
+
else if (raw && Array.isArray(raw.patterns)) count = raw.patterns.length;
|
|
576
|
+
else if (raw && typeof raw === 'object') count = Object.keys(raw).length;
|
|
577
|
+
} catch { return 0; }
|
|
578
|
+
|
|
579
|
+
try {
|
|
580
|
+
let memo = {};
|
|
581
|
+
try { memo = JSON.parse(fs.readFileSync(PATTERN_COUNT_CACHE, 'utf-8')) || {}; } catch { /* start fresh */ }
|
|
582
|
+
memo[file] = { key, count };
|
|
583
|
+
fs.writeFileSync(PATTERN_COUNT_CACHE, JSON.stringify(memo));
|
|
584
|
+
} catch { /* cache is an optimisation, never a requirement */ }
|
|
585
|
+
|
|
586
|
+
return count;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
// `system` is nominally CLI-populated, but the pattern store is on disk, so a
|
|
590
|
+
// dead CLI must not render as "no learning". Without this, every candidate in
|
|
591
|
+
// resolveCliBinCandidates() failing (a source-only marketplace checkout, or an
|
|
592
|
+
// npx fetch that dies in a workspace root) silently degraded the brain to a
|
|
593
|
+
// hardcoded 0% while the overlaid segments beside it kept showing live data —
|
|
594
|
+
// indistinguishable from a genuine zero. Same reasoning as getLocalAgentDB(),
|
|
595
|
+
// which had to start reading locally after the statusline reported "Vectors 0"
|
|
596
|
+
// on a database holding thousands.
|
|
597
|
+
function getLocalIntelligence(current) {
|
|
598
|
+
const base = (current && typeof current === 'object') ? current : {};
|
|
599
|
+
if (typeof base.intelligencePct === 'number' && base.intelligencePct > 0) return base;
|
|
600
|
+
|
|
601
|
+
for (const file of [
|
|
602
|
+
path.join(CWD, '.claude-flow', 'neural', 'patterns.json'),
|
|
603
|
+
path.join(os.homedir(), '.claude-flow', 'neural', 'patterns.json'),
|
|
604
|
+
]) {
|
|
605
|
+
const n = countPatternsCached(file);
|
|
606
|
+
if (n > 0) {
|
|
607
|
+
base.intelligencePct = Math.min(100, Math.floor(n / 10));
|
|
608
|
+
return base;
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
// No CLI value and no local store: unknown, which is not the same as zero.
|
|
613
|
+
base.intelligencePct = null;
|
|
614
|
+
return base;
|
|
615
|
+
}
|
|
616
|
+
|
|
555
617
|
// Overlay every locally-derived block onto the CLI data (mutates in place).
|
|
556
618
|
function applyLocalOverlays(data) {
|
|
557
619
|
data.adrs = getLocalADRCount();
|
|
@@ -562,6 +624,7 @@ function applyLocalOverlays(data) {
|
|
|
562
624
|
// Security overlay: recompute freshness from disk on every render so cached
|
|
563
625
|
// CLI JSON can never freeze the pill at PENDING. See getLocalSecurity() above.
|
|
564
626
|
data.security = getLocalSecurity(data.security);
|
|
627
|
+
data.system = getLocalIntelligence(data.system);
|
|
565
628
|
return data;
|
|
566
629
|
}
|
|
567
630
|
|
|
@@ -575,7 +638,7 @@ function buildLocalFallback() {
|
|
|
575
638
|
v3Progress: { domainsCompleted: 0, totalDomains: 5, dddProgress: 0, patternsLearned: 0, sessionsCompleted: 0 },
|
|
576
639
|
security: { status: 'NONE', findings: 0, cvesFixed: 0, totalCves: 0 },
|
|
577
640
|
swarm: { activeAgents: 0, maxAgents: CONFIG.maxAgents, coordinationActive: false },
|
|
578
|
-
system: { memoryMB: memMB, contextPct: 0, intelligencePct:
|
|
641
|
+
system: { memoryMB: memMB, contextPct: 0, intelligencePct: null, subAgents: 0 },
|
|
579
642
|
lastUpdated: new Date().toISOString(),
|
|
580
643
|
});
|
|
581
644
|
}
|
|
@@ -979,7 +1042,11 @@ function generateStatusline() {
|
|
|
979
1042
|
const activeAgents = swarm.activeAgents || 0;
|
|
980
1043
|
const maxAgents = swarm.maxAgents || CONFIG.maxAgents;
|
|
981
1044
|
const coordinationActive = swarm.coordinationActive || false;
|
|
982
|
-
|
|
1045
|
+
// null/undefined means "no source answered", which must not collapse to 0 --
|
|
1046
|
+
// that is exactly the ambiguity this segment used to present.
|
|
1047
|
+
const intelligencePct = (typeof system.intelligencePct === 'number')
|
|
1048
|
+
? system.intelligencePct
|
|
1049
|
+
: null;
|
|
983
1050
|
const memoryMB = system.memoryMB || 0;
|
|
984
1051
|
const subAgents = system.subAgents || 0;
|
|
985
1052
|
const findings = Math.max(0, security.findings || 0);
|
|
@@ -1035,14 +1102,14 @@ function generateStatusline() {
|
|
|
1035
1102
|
// do next; diagnostic detail moves to `ruflo status --verbose`.
|
|
1036
1103
|
const agentsColor = activeAgents > 0 ? c.brightGreen : c.dim;
|
|
1037
1104
|
const hooksColor = hooksEnabled > 0 ? c.brightGreen : c.dim;
|
|
1038
|
-
const intellColor = intelligencePct >= 80 ? c.brightGreen : intelligencePct >= 40 ? c.brightYellow : c.dim;
|
|
1105
|
+
const intellColor = intelligencePct === null ? c.dim : intelligencePct >= 80 ? c.brightGreen : intelligencePct >= 40 ? c.brightYellow : c.dim;
|
|
1039
1106
|
const swarmInd = coordinationActive ? c.brightGreen + '◉' + c.reset + ' ' : c.dim + '○' + c.reset + ' ';
|
|
1040
1107
|
const healthAllGreen = (secStatus === 'CLEAN' || secStatus === 'NONE') && findings === 0;
|
|
1041
1108
|
const opsParts = [];
|
|
1042
1109
|
opsParts.push(c.cyan + 'Swarm ' + swarmInd + agentsColor + activeAgents + c.reset + '/' + c.brightWhite + maxAgents + c.reset);
|
|
1043
1110
|
if (subAgents > 0) opsParts.push(c.brightPurple + '👥 ' + subAgents + c.reset);
|
|
1044
1111
|
opsParts.push(c.cyan + 'Hooks ' + hooksColor + hooksEnabled + c.reset + '/' + c.brightWhite + hooksTotal + c.reset);
|
|
1045
|
-
opsParts.push(intellColor + '🧠 ' + intelligencePct + '%' + c.reset);
|
|
1112
|
+
opsParts.push(intellColor + '🧠 ' + (intelligencePct === null ? '—' : intelligencePct + '%') + c.reset);
|
|
1046
1113
|
opsParts.push(c.brightCyan + '💾 ' + memoryMB + 'MB' + c.reset);
|
|
1047
1114
|
// Health: one glyph when green, terse copy when there's something to act on.
|
|
1048
1115
|
if (healthAllGreen) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claude-flow/cli",
|
|
3
|
-
"version": "3.38.
|
|
3
|
+
"version": "3.38.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",
|