@claude-flow/cli 3.27.0 → 3.27.2
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-version +1 -1
- package/.claude/helpers/helpers.manifest.json +4 -4
- package/.claude/helpers/hook-handler.cjs +37 -17
- package/.claude/helpers/statusline.cjs +44 -2
- package/catalog-manifest.json +2 -2
- package/dist/src/init/statusline-generator.js +44 -2
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
3.
|
|
1
|
+
3.23.0
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest": {
|
|
3
|
-
"version": "3.27.
|
|
3
|
+
"version": "3.27.2",
|
|
4
4
|
"files": {
|
|
5
5
|
"auto-memory-hook.mjs": "68be7e9a9eba7bf9c4e8a230db7bf61a243b965639f8504842799d6c6ca28762",
|
|
6
|
-
"hook-handler.cjs": "
|
|
6
|
+
"hook-handler.cjs": "2e4927ff158c0079a67a6f0ef0b99ac748d600d33798b0a5fbd5a6a82225ec03",
|
|
7
7
|
"intelligence.cjs": "bd1f8e4b034944aee1df0391dc47ac2e8cc4b3aa542c65407a59d49620bbf76b",
|
|
8
|
-
"statusline.cjs": "
|
|
8
|
+
"statusline.cjs": "f553f12a34e7df405a64501cdedb684374ef92670279380bc95f625fc68b2d1b"
|
|
9
9
|
}
|
|
10
10
|
},
|
|
11
|
-
"signature": "
|
|
11
|
+
"signature": "40Y8+mFRgH7LZZ5TeeDM6aIUcAKrNaN82nyJJzFyepx/HM1chZeK2yEUIbtPhyE0PdyoO4W1OuR3mlxLHgBjCA==",
|
|
12
12
|
"algorithm": "ed25519"
|
|
13
13
|
}
|
|
@@ -23,6 +23,18 @@ const helpersDir = __dirname;
|
|
|
23
23
|
// statusline-generator.ts's resolveCliBin() candidate list. Used only to
|
|
24
24
|
// spawn the detached funnel-refresh helper below; failures are silent (no
|
|
25
25
|
// candidate found just means the refresh never fires this session).
|
|
26
|
+
//
|
|
27
|
+
// Verifies dist/src/index.js exists alongside bin/cli.js, not just the bin
|
|
28
|
+
// itself — Claude Code's own plugin marketplace mechanism installs by
|
|
29
|
+
// `git clone`/`git pull` with no build step, so `~/.claude/plugins/
|
|
30
|
+
// marketplaces/ruflo` is a SOURCE-ONLY checkout by construction: bin/cli.js
|
|
31
|
+
// is present on disk but importing dist/src/index.js throws
|
|
32
|
+
// ERR_MODULE_NOT_FOUND on every real command (confirmed live — only
|
|
33
|
+
// `--version` happens to survive it, since it reads package.json directly).
|
|
34
|
+
// Without this check, resolveCliBinForHook() picked that doomed candidate
|
|
35
|
+
// first every time and spawnDetachedFunnelRefresh() below had no fallback,
|
|
36
|
+
// so the promo/disclosure row could never populate for any marketplace
|
|
37
|
+
// install, on any OS.
|
|
26
38
|
function resolveCliBinForHook() {
|
|
27
39
|
try {
|
|
28
40
|
const home = os.homedir();
|
|
@@ -38,7 +50,11 @@ function resolveCliBinForHook() {
|
|
|
38
50
|
path.join(helpersDir, '..', '..', 'bin', 'cli.js'),
|
|
39
51
|
];
|
|
40
52
|
for (const p of candidates) {
|
|
41
|
-
|
|
53
|
+
try {
|
|
54
|
+
if (fs.existsSync(p) && fs.existsSync(path.join(path.dirname(p), '..', 'dist', 'src', 'index.js'))) {
|
|
55
|
+
return p;
|
|
56
|
+
}
|
|
57
|
+
} catch (e) { /* try next candidate */ }
|
|
42
58
|
}
|
|
43
59
|
} catch (e) { /* ignore */ }
|
|
44
60
|
return null;
|
|
@@ -54,12 +70,22 @@ function resolveCliBinForHook() {
|
|
|
54
70
|
// session-restore's own process has already exited, so it actually gets a
|
|
55
71
|
// chance to write the cache. Never awaited here — must not add to
|
|
56
72
|
// SessionStart's own timeout budget.
|
|
57
|
-
|
|
73
|
+
//
|
|
74
|
+
// No usable local candidate (resolveCliBinForHook() returned null) falls
|
|
75
|
+
// back to npx: this call is detached/unref'd, so a slower npx cold-start
|
|
76
|
+
// costs nothing perceptible — unlike the statusline's own synchronous
|
|
77
|
+
// render path, where local-first exists purely for per-render latency.
|
|
78
|
+
// `--prefer-offline` avoids a registry round trip for the tarball when
|
|
79
|
+
// already cached while still resolving the current `@latest` version.
|
|
80
|
+
function spawnDetachedHookRefresh(subcommand) {
|
|
58
81
|
try {
|
|
59
|
-
const cliBin = resolveCliBinForHook();
|
|
60
|
-
if (!cliBin) return;
|
|
61
82
|
const { spawn } = require('child_process');
|
|
62
|
-
const
|
|
83
|
+
const cliBin = resolveCliBinForHook();
|
|
84
|
+
const cmd = process.platform === 'win32' ? 'npx.cmd' : 'npx';
|
|
85
|
+
const spawnArgs = cliBin
|
|
86
|
+
? [process.execPath, [cliBin, 'hooks', subcommand, '--quiet']]
|
|
87
|
+
: [cmd, ['--prefer-offline', '@claude-flow/cli', 'hooks', subcommand, '--quiet']];
|
|
88
|
+
const child = spawn(spawnArgs[0], spawnArgs[1], {
|
|
63
89
|
detached: true,
|
|
64
90
|
stdio: 'ignore',
|
|
65
91
|
env: process.env,
|
|
@@ -68,24 +94,18 @@ function spawnDetachedFunnelRefresh() {
|
|
|
68
94
|
} catch (e) { /* best-effort only */ }
|
|
69
95
|
}
|
|
70
96
|
|
|
71
|
-
|
|
97
|
+
function spawnDetachedFunnelRefresh() {
|
|
98
|
+
spawnDetachedHookRefresh('refresh-funnel');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Same fallback-aware pattern as spawnDetachedFunnelRefresh() above, for
|
|
72
102
|
// ADR-316's co-pilot advisor tip. Safe to call on EVERY session-restore:
|
|
73
103
|
// refresh-advisor's own action checks consent + a 24h TTL BEFORE spending
|
|
74
104
|
// anything, so an unconsented or already-fresh install is a fast no-op file
|
|
75
105
|
// read, never a network call. Never awaited here — must not add to
|
|
76
106
|
// SessionStart's own timeout budget.
|
|
77
107
|
function spawnDetachedAdvisorRefresh() {
|
|
78
|
-
|
|
79
|
-
const cliBin = resolveCliBinForHook();
|
|
80
|
-
if (!cliBin) return;
|
|
81
|
-
const { spawn } = require('child_process');
|
|
82
|
-
const child = spawn(process.execPath, [cliBin, 'hooks', 'refresh-advisor', '--quiet'], {
|
|
83
|
-
detached: true,
|
|
84
|
-
stdio: 'ignore',
|
|
85
|
-
env: process.env,
|
|
86
|
-
});
|
|
87
|
-
child.unref();
|
|
88
|
-
} catch (e) { /* best-effort only */ }
|
|
108
|
+
spawnDetachedHookRefresh('refresh-advisor');
|
|
89
109
|
}
|
|
90
110
|
|
|
91
111
|
// Safe require with stdout suppression - the helper modules have CLI
|
|
@@ -116,7 +116,20 @@ function resolveCliBinCandidates() {
|
|
|
116
116
|
}
|
|
117
117
|
} catch { /* ignore */ }
|
|
118
118
|
} catch { /* ignore */ }
|
|
119
|
-
return candidates.filter((p) => {
|
|
119
|
+
return candidates.filter((p) => {
|
|
120
|
+
try {
|
|
121
|
+
if (!fs.existsSync(p)) return false;
|
|
122
|
+
// A candidate's bin/cli.js can exist on disk while its compiled
|
|
123
|
+
// dist/ never got built (Claude Code's own plugin marketplace just
|
|
124
|
+
// git-clones the repo — no install/build step — so every marketplace
|
|
125
|
+
// install is a source-only checkout by construction). Importing
|
|
126
|
+
// dist/src/index.js from bin/cli.js then throws MODULE_NOT_FOUND on
|
|
127
|
+
// every real command; only --version happens to survive it. Check
|
|
128
|
+
// for the compiled entrypoint too so a doomed candidate is skipped
|
|
129
|
+
// up front instead of wasting a spawn-and-fail on every render.
|
|
130
|
+
return fs.existsSync(path.join(path.dirname(p), '..', 'dist', 'src', 'index.js'));
|
|
131
|
+
} catch { return false; }
|
|
132
|
+
});
|
|
120
133
|
}
|
|
121
134
|
|
|
122
135
|
// Return { fresh, promoFresh, data }. 'fresh' is true only if within the TTL
|
|
@@ -585,6 +598,22 @@ function getCostFromStdin() {
|
|
|
585
598
|
}
|
|
586
599
|
|
|
587
600
|
// Read package version from the first package.json we find.
|
|
601
|
+
// Compares dotted-numeric version strings (e.g. "3.27.1" vs "3.27.10").
|
|
602
|
+
// Returns >0 if a>b, <0 if a<b, 0 if equal-as-far-as-parseable. Deliberately
|
|
603
|
+
// simple (no prerelease/build-metadata handling) — this only orders local
|
|
604
|
+
// package.json versions against each other, never anything untrusted from
|
|
605
|
+
// a payload, so a full semver implementation would be dead weight here.
|
|
606
|
+
function compareVersions(a, b) {
|
|
607
|
+
const pa = String(a).split('.').map((n) => parseInt(n, 10));
|
|
608
|
+
const pb = String(b).split('.').map((n) => parseInt(n, 10));
|
|
609
|
+
for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
|
|
610
|
+
const na = Number.isFinite(pa[i]) ? pa[i] : 0;
|
|
611
|
+
const nb = Number.isFinite(pb[i]) ? pb[i] : 0;
|
|
612
|
+
if (na !== nb) return na - nb;
|
|
613
|
+
}
|
|
614
|
+
return 0;
|
|
615
|
+
}
|
|
616
|
+
|
|
588
617
|
function getPkgVersion() {
|
|
589
618
|
let ver = '3.6';
|
|
590
619
|
try {
|
|
@@ -616,11 +645,24 @@ function getPkgVersion() {
|
|
|
616
645
|
);
|
|
617
646
|
}
|
|
618
647
|
} catch { /* ignore */ }
|
|
648
|
+
// Pick the HIGHEST version among every candidate that exists, not the
|
|
649
|
+
// first one found. The marketplace plugin path is probed first (list
|
|
650
|
+
// order above), but Claude Code's own plugin marketplace mechanism
|
|
651
|
+
// syncs on its own git-pull cadence, independent of npm publishes — a
|
|
652
|
+
// freshly-published npm version can sit alongside a stale marketplace
|
|
653
|
+
// checkout for a while (observed live: marketplace one release behind
|
|
654
|
+
// right after a publish). Taking the first EXISTING candidate meant the
|
|
655
|
+
// header could show a stale version even when a newer install (e.g.
|
|
656
|
+
// node_modules/@claude-flow/cli from a plain npm install) was sitting right there.
|
|
657
|
+
let found = false;
|
|
619
658
|
for (const p of pkgPaths) {
|
|
620
659
|
if (!fs.existsSync(p)) continue;
|
|
621
660
|
try {
|
|
622
661
|
const pkg = JSON.parse(fs.readFileSync(p, 'utf-8'));
|
|
623
|
-
if (pkg && typeof pkg.version === 'string' && pkg.version.length > 0) {
|
|
662
|
+
if (pkg && typeof pkg.version === 'string' && pkg.version.length > 0) {
|
|
663
|
+
if (!found || compareVersions(pkg.version, ver) > 0) ver = pkg.version;
|
|
664
|
+
found = true;
|
|
665
|
+
}
|
|
624
666
|
} catch { /* ignore */ }
|
|
625
667
|
}
|
|
626
668
|
} catch { /* ignore */ }
|
package/catalog-manifest.json
CHANGED
|
@@ -139,7 +139,20 @@ function resolveCliBinCandidates() {
|
|
|
139
139
|
}
|
|
140
140
|
} catch { /* ignore */ }
|
|
141
141
|
} catch { /* ignore */ }
|
|
142
|
-
return candidates.filter((p) => {
|
|
142
|
+
return candidates.filter((p) => {
|
|
143
|
+
try {
|
|
144
|
+
if (!fs.existsSync(p)) return false;
|
|
145
|
+
// A candidate's bin/cli.js can exist on disk while its compiled
|
|
146
|
+
// dist/ never got built (Claude Code's own plugin marketplace just
|
|
147
|
+
// git-clones the repo — no install/build step — so every marketplace
|
|
148
|
+
// install is a source-only checkout by construction). Importing
|
|
149
|
+
// dist/src/index.js from bin/cli.js then throws MODULE_NOT_FOUND on
|
|
150
|
+
// every real command; only --version happens to survive it. Check
|
|
151
|
+
// for the compiled entrypoint too so a doomed candidate is skipped
|
|
152
|
+
// up front instead of wasting a spawn-and-fail on every render.
|
|
153
|
+
return fs.existsSync(path.join(path.dirname(p), '..', 'dist', 'src', 'index.js'));
|
|
154
|
+
} catch { return false; }
|
|
155
|
+
});
|
|
143
156
|
}
|
|
144
157
|
|
|
145
158
|
// Return { fresh, promoFresh, data }. 'fresh' is true only if within the TTL
|
|
@@ -608,6 +621,22 @@ function getCostFromStdin() {
|
|
|
608
621
|
}
|
|
609
622
|
|
|
610
623
|
// Read package version from the first package.json we find.
|
|
624
|
+
// Compares dotted-numeric version strings (e.g. "3.27.1" vs "3.27.10").
|
|
625
|
+
// Returns >0 if a>b, <0 if a<b, 0 if equal-as-far-as-parseable. Deliberately
|
|
626
|
+
// simple (no prerelease/build-metadata handling) — this only orders local
|
|
627
|
+
// package.json versions against each other, never anything untrusted from
|
|
628
|
+
// a payload, so a full semver implementation would be dead weight here.
|
|
629
|
+
function compareVersions(a, b) {
|
|
630
|
+
const pa = String(a).split('.').map((n) => parseInt(n, 10));
|
|
631
|
+
const pb = String(b).split('.').map((n) => parseInt(n, 10));
|
|
632
|
+
for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
|
|
633
|
+
const na = Number.isFinite(pa[i]) ? pa[i] : 0;
|
|
634
|
+
const nb = Number.isFinite(pb[i]) ? pb[i] : 0;
|
|
635
|
+
if (na !== nb) return na - nb;
|
|
636
|
+
}
|
|
637
|
+
return 0;
|
|
638
|
+
}
|
|
639
|
+
|
|
611
640
|
function getPkgVersion() {
|
|
612
641
|
let ver = '3.6';
|
|
613
642
|
try {
|
|
@@ -639,11 +668,24 @@ function getPkgVersion() {
|
|
|
639
668
|
);
|
|
640
669
|
}
|
|
641
670
|
} catch { /* ignore */ }
|
|
671
|
+
// Pick the HIGHEST version among every candidate that exists, not the
|
|
672
|
+
// first one found. The marketplace plugin path is probed first (list
|
|
673
|
+
// order above), but Claude Code's own plugin marketplace mechanism
|
|
674
|
+
// syncs on its own git-pull cadence, independent of npm publishes — a
|
|
675
|
+
// freshly-published npm version can sit alongside a stale marketplace
|
|
676
|
+
// checkout for a while (observed live: marketplace one release behind
|
|
677
|
+
// right after a publish). Taking the first EXISTING candidate meant the
|
|
678
|
+
// header could show a stale version even when a newer install (e.g.
|
|
679
|
+
// node_modules/@claude-flow/cli from a plain npm install) was sitting right there.
|
|
680
|
+
let found = false;
|
|
642
681
|
for (const p of pkgPaths) {
|
|
643
682
|
if (!fs.existsSync(p)) continue;
|
|
644
683
|
try {
|
|
645
684
|
const pkg = JSON.parse(fs.readFileSync(p, 'utf-8'));
|
|
646
|
-
if (pkg && typeof pkg.version === 'string' && pkg.version.length > 0) {
|
|
685
|
+
if (pkg && typeof pkg.version === 'string' && pkg.version.length > 0) {
|
|
686
|
+
if (!found || compareVersions(pkg.version, ver) > 0) ver = pkg.version;
|
|
687
|
+
found = true;
|
|
688
|
+
}
|
|
647
689
|
} catch { /* ignore */ }
|
|
648
690
|
}
|
|
649
691
|
} catch { /* ignore */ }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claude-flow/cli",
|
|
3
|
-
"version": "3.27.
|
|
3
|
+
"version": "3.27.2",
|
|
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",
|