claude-flow 3.7.0-alpha.27 → 3.7.0-alpha.29
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/hook-handler.cjs +4 -1
- package/.claude/helpers/statusline.cjs +15 -4
- package/package.json +2 -2
- package/v3/@claude-flow/cli/dist/src/commands/doctor.js +17 -6
- package/v3/@claude-flow/cli/dist/src/init/helpers-generator.js +6 -2
- package/v3/@claude-flow/cli/dist/src/init/settings-generator.js +33 -12
- package/v3/@claude-flow/cli/dist/src/init/statusline-generator.js +25 -14
- package/v3/@claude-flow/cli/dist/src/memory/memory-bridge.js +29 -5
- package/v3/@claude-flow/cli/dist/src/memory/memory-initializer.js +6 -3
- package/v3/@claude-flow/cli/package.json +1 -1
|
@@ -100,7 +100,10 @@ async function main() {
|
|
|
100
100
|
var toolInput = hookInput.toolInput || hookInput.tool_input || {};
|
|
101
101
|
var toolName = hookInput.toolName || hookInput.tool_name || '';
|
|
102
102
|
|
|
103
|
-
|
|
103
|
+
// `toolInput` is an object (e.g. {command:"ls"}) — falling back to it
|
|
104
|
+
// directly bound `prompt` to the object and tripped `.toLowerCase()` /
|
|
105
|
+
// `.substring()` on every Bash hook (#1944). Use the `.command` field.
|
|
106
|
+
var prompt = hookInput.prompt || hookInput.command || toolInput.command
|
|
104
107
|
|| process.env.PROMPT || process.env.TOOL_INPUT_command || '';
|
|
105
108
|
|
|
106
109
|
const handlers = {
|
|
@@ -26,18 +26,29 @@ const CONFIG = {
|
|
|
26
26
|
|
|
27
27
|
const CWD = process.cwd();
|
|
28
28
|
|
|
29
|
-
// Read package version once at startup
|
|
29
|
+
// Read package version once at startup. Probe the plugin's own install
|
|
30
|
+
// location first — `~/.claude/plugins/marketplaces/ruflo/package.json` — so
|
|
31
|
+
// users who installed via `/plugin install ruflo@ruflo` see the real version,
|
|
32
|
+
// not the hardcoded fallback (#1951).
|
|
30
33
|
let pkgVersion = '3.5';
|
|
31
34
|
try {
|
|
35
|
+
const os = require('os');
|
|
36
|
+
const home = os.homedir();
|
|
32
37
|
const pkgPaths = [
|
|
38
|
+
path.join(home, '.claude', 'plugins', 'marketplaces', 'ruflo', 'package.json'),
|
|
33
39
|
path.join(CWD, 'node_modules', '@claude-flow', 'cli', 'package.json'),
|
|
40
|
+
path.join(CWD, 'node_modules', 'ruflo', 'package.json'),
|
|
34
41
|
path.join(CWD, 'v3', '@claude-flow', 'cli', 'package.json'),
|
|
35
42
|
];
|
|
36
43
|
for (const p of pkgPaths) {
|
|
37
|
-
if (fs.existsSync(p))
|
|
44
|
+
if (!fs.existsSync(p)) continue;
|
|
45
|
+
try {
|
|
38
46
|
const pkg = JSON.parse(fs.readFileSync(p, 'utf-8'));
|
|
39
|
-
if (pkg.version
|
|
40
|
-
|
|
47
|
+
if (pkg && typeof pkg.version === 'string' && pkg.version.length > 0) {
|
|
48
|
+
pkgVersion = pkg.version;
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
} catch { /* malformed package.json — try next */ }
|
|
41
52
|
}
|
|
42
53
|
} catch { /* use default */ }
|
|
43
54
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-flow",
|
|
3
|
-
"version": "3.7.0-alpha.
|
|
3
|
+
"version": "3.7.0-alpha.29",
|
|
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",
|
|
@@ -152,4 +152,4 @@
|
|
|
152
152
|
"access": "public",
|
|
153
153
|
"tag": "latest"
|
|
154
154
|
}
|
|
155
|
-
}
|
|
155
|
+
}
|
|
@@ -139,12 +139,23 @@ async function checkDaemonStatus() {
|
|
|
139
139
|
}
|
|
140
140
|
// Check memory database
|
|
141
141
|
async function checkMemoryDatabase() {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
142
|
+
// Authoritative path comes from `getMemoryRoot()` (honors
|
|
143
|
+
// `CLAUDE_FLOW_MEMORY_PATH`, claude-flow.config.json's `memory.persistPath`,
|
|
144
|
+
// then defaults to `.swarm/`). #1946: the previous hard-coded list missed
|
|
145
|
+
// `data/memory/memory.db` (a common config) and ignored the env var
|
|
146
|
+
// entirely, so doctor reported "Not initialized" on perfectly-init'd DBs.
|
|
147
|
+
// Try the configured path first, then fall back to the historic candidates.
|
|
148
|
+
const candidates = [];
|
|
149
|
+
try {
|
|
150
|
+
const { getMemoryRoot } = await import('../memory/memory-initializer.js');
|
|
151
|
+
candidates.push(join(getMemoryRoot(), 'memory.db'));
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
/* memory-initializer not available — fall through to legacy candidates */
|
|
155
|
+
}
|
|
156
|
+
candidates.push('.swarm/memory.db', '.claude-flow/memory.db', 'data/memory/memory.db', // matches `CLAUDE_FLOW_MEMORY_PATH=data/memory`
|
|
157
|
+
'data/memory.db');
|
|
158
|
+
for (const dbPath of candidates) {
|
|
148
159
|
if (existsSync(dbPath)) {
|
|
149
160
|
try {
|
|
150
161
|
const stats = statSync(dbPath);
|
|
@@ -424,8 +424,12 @@ export function generateHookHandler() {
|
|
|
424
424
|
' if (stdinData.trim()) {',
|
|
425
425
|
' try { hookInput = JSON.parse(stdinData); } catch (e) { /* ignore */ }',
|
|
426
426
|
' }',
|
|
427
|
-
' // Prefer stdin fields, then env, then argv',
|
|
428
|
-
|
|
427
|
+
' // Prefer stdin fields, then env, then argv. `hookInput.toolInput` is an',
|
|
428
|
+
' // object (e.g. {command:"ls"}); falling back to it directly bound prompt',
|
|
429
|
+
' // to the object and tripped .toLowerCase() / .substring() on every Bash',
|
|
430
|
+
' // hook (#1944). Pull `.command` off whichever stdin shape Claude Code sent.',
|
|
431
|
+
' var toolInputObj = hookInput.toolInput || hookInput.tool_input || {};',
|
|
432
|
+
" var prompt = hookInput.prompt || hookInput.command || toolInputObj.command || process.env.PROMPT || process.env.TOOL_INPUT_command || args.join(' ') || '';",
|
|
429
433
|
'',
|
|
430
434
|
'const handlers = {',
|
|
431
435
|
" 'route': () => {",
|
|
@@ -154,21 +154,35 @@ export function generateSettings(options) {
|
|
|
154
154
|
*/
|
|
155
155
|
const IS_WINDOWS = process.platform === 'win32';
|
|
156
156
|
/**
|
|
157
|
-
* Build a hook command
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
157
|
+
* Build a hook command that resolves to the right helpers dir on every
|
|
158
|
+
* install layout. `ruflo init` can land helpers either project-locally
|
|
159
|
+
* (`<project>/.claude/helpers/…`, when run from a project root) or globally
|
|
160
|
+
* (`$HOME/.claude/helpers/…`, when settings.json gets merged into the
|
|
161
|
+
* user-level Claude Code config). The earlier `${CLAUDE_PROJECT_DIR:-.}`
|
|
162
|
+
* form assumed project-local — so any global-install user hit
|
|
163
|
+
* `MODULE_NOT_FOUND` on every Bash/Edit/Session hook (#1943).
|
|
164
|
+
*
|
|
165
|
+
* The fix is a tiny POSIX `sh` probe: try `$CLAUDE_PROJECT_DIR/.claude/...`
|
|
166
|
+
* first, fall back to `$HOME/.claude/...` if it's missing. Both modes work,
|
|
167
|
+
* the global install never crashes, and project-local overrides still take
|
|
168
|
+
* precedence when present. On Windows, the same probe via `cmd /c` (the %~%
|
|
169
|
+
* fallback uses `IF EXIST`).
|
|
162
170
|
*/
|
|
163
171
|
function hookCmd(script, subcommand) {
|
|
164
172
|
if (IS_WINDOWS) {
|
|
165
|
-
|
|
173
|
+
// cmd.exe equivalent of the sh probe below. `IF EXIST` checks the
|
|
174
|
+
// project-local path; falls back to %USERPROFILE% if missing.
|
|
175
|
+
return `cmd /c "IF EXIST \"%CLAUDE_PROJECT_DIR%\\${script.replace(/\//g, '\\')}\" (node \"%CLAUDE_PROJECT_DIR%\\${script.replace(/\//g, '\\')}\" ${subcommand}) ELSE (node \"%USERPROFILE%\\${script.replace(/\//g, '\\')}\" ${subcommand})"`;
|
|
166
176
|
}
|
|
167
|
-
//
|
|
168
|
-
//
|
|
177
|
+
// POSIX sh: prefer project-local helpers, fall back to $HOME/.claude/.
|
|
178
|
+
// The fallback handles `ruflo init`'s global-install path where helpers
|
|
179
|
+
// live at `$HOME/.claude/helpers/` but Claude Code still sets
|
|
180
|
+
// `CLAUDE_PROJECT_DIR` to the *project* root (which has no helpers).
|
|
169
181
|
// eslint-disable-next-line no-template-curly-in-string
|
|
170
|
-
const
|
|
171
|
-
|
|
182
|
+
const projVar = '${CLAUDE_PROJECT_DIR:-.}';
|
|
183
|
+
// eslint-disable-next-line no-template-curly-in-string
|
|
184
|
+
const homeVar = '${HOME}';
|
|
185
|
+
return `sh -c 'D="${projVar}"; [ -f "$D/${script}" ] || D="${homeVar}"; exec node "$D/${script}" ${subcommand}'`;
|
|
172
186
|
}
|
|
173
187
|
/** Shorthand for CJS hook-handler commands */
|
|
174
188
|
function hookHandlerCmd(subcommand) {
|
|
@@ -188,11 +202,18 @@ function generateStatusLineConfig(_options) {
|
|
|
188
202
|
// The script runs after each assistant message (debounced 300ms).
|
|
189
203
|
// NOTE: statusline must NOT use `cmd /c` — Claude Code manages its stdin
|
|
190
204
|
// directly for statusline commands, and `cmd /c` blocks stdin forwarding.
|
|
205
|
+
//
|
|
206
|
+
// Same project-local / $HOME fallback as `hookCmd()` (see #1943): the
|
|
207
|
+
// earlier `${CLAUDE_PROJECT_DIR:-.}` form broke statusline for any
|
|
208
|
+
// global-install user. Probe project-local first, fall back to $HOME.
|
|
209
|
+
const script = '.claude/helpers/statusline.cjs';
|
|
210
|
+
// eslint-disable-next-line no-template-curly-in-string
|
|
211
|
+
const projVar = '${CLAUDE_PROJECT_DIR:-.}';
|
|
191
212
|
// eslint-disable-next-line no-template-curly-in-string
|
|
192
|
-
const
|
|
213
|
+
const homeVar = '${HOME}';
|
|
193
214
|
return {
|
|
194
215
|
type: 'command',
|
|
195
|
-
command: `sh -c 'exec node "${
|
|
216
|
+
command: `sh -c 'D="${projVar}"; [ -f "$D/${script}" ] || D="${homeVar}"; exec node "$D/${script}"'`,
|
|
196
217
|
};
|
|
197
218
|
}
|
|
198
219
|
/**
|
|
@@ -637,23 +637,34 @@ function generateStatusline() {
|
|
|
637
637
|
const integration = getIntegrationStatus();
|
|
638
638
|
const lines = [];
|
|
639
639
|
|
|
640
|
-
// Header
|
|
641
|
-
//
|
|
640
|
+
// Header — read version from the FIRST package.json we find, preferring
|
|
641
|
+
// the plugin install at ~/.claude/plugins/marketplaces/ruflo/package.json.
|
|
642
|
+
// The previous list only checked project-local node_modules, so plugin
|
|
643
|
+
// users saw the hard-coded fallback (V3.5) even on newer alphas (#1951).
|
|
642
644
|
let pkgVersion = '3.6';
|
|
643
645
|
try {
|
|
644
|
-
const
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
646
|
+
const home = require('os').homedir();
|
|
647
|
+
const pkgPaths = [
|
|
648
|
+
// 1. The plugin's own root (installed via /plugin install).
|
|
649
|
+
path.join(home, '.claude', 'plugins', 'marketplaces', 'ruflo', 'package.json'),
|
|
650
|
+
// 2. Project-local @claude-flow/cli — npm-style install.
|
|
651
|
+
path.join(CWD, 'node_modules', '@claude-flow', 'cli', 'package.json'),
|
|
652
|
+
// 3. Project-local ruflo umbrella.
|
|
653
|
+
path.join(CWD, 'node_modules', 'ruflo', 'package.json'),
|
|
654
|
+
// 4. Source-checkout location (when developing in this repo).
|
|
655
|
+
path.join(CWD, 'v3', '@claude-flow', 'cli', 'package.json'),
|
|
656
|
+
];
|
|
657
|
+
for (const p of pkgPaths) {
|
|
658
|
+
if (!fs.existsSync(p)) continue;
|
|
659
|
+
try {
|
|
660
|
+
const pkg = JSON.parse(fs.readFileSync(p, 'utf-8'));
|
|
661
|
+
if (pkg && typeof pkg.version === 'string' && pkg.version.length > 0) {
|
|
662
|
+
pkgVersion = pkg.version;
|
|
663
|
+
break;
|
|
664
|
+
}
|
|
665
|
+
} catch { /* malformed package.json — try next */ }
|
|
655
666
|
}
|
|
656
|
-
} catch { /*
|
|
667
|
+
} catch { /* fall through to the hardcoded default */ }
|
|
657
668
|
let header = c.bold + c.brightPurple + '\\u258A RuFlo V' + pkgVersion + ' ' + c.reset;
|
|
658
669
|
header += (swarm.coordinationActive ? c.brightCyan : c.dim) + '\\u25CF ' + c.brightCyan + git.name + c.reset;
|
|
659
670
|
if (git.gitBranch) {
|
|
@@ -18,26 +18,50 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import * as path from 'path';
|
|
20
20
|
import * as crypto from 'crypto';
|
|
21
|
+
import { createRequire } from 'node:module';
|
|
21
22
|
// ===== Lazy singleton =====
|
|
22
23
|
let registryPromise = null;
|
|
23
24
|
let registryInstance = null;
|
|
24
25
|
let bridgeAvailable = null;
|
|
25
26
|
/**
|
|
26
27
|
* Resolve database path with path traversal protection.
|
|
27
|
-
* Only allows paths within or below the project's
|
|
28
|
+
* Only allows paths within or below the project's working directory,
|
|
28
29
|
* or the special ':memory:' path.
|
|
30
|
+
*
|
|
31
|
+
* #1945: the previous hard-coded `<cwd>/.swarm/memory.db` default ignored
|
|
32
|
+
* `CLAUDE_FLOW_MEMORY_PATH` / `claude-flow.config.json#memory.persistPath`
|
|
33
|
+
* — so users with non-default memory paths had `memory init` write to e.g.
|
|
34
|
+
* `data/memory/memory.db` while `bridgeStoreEntry()` wrote to
|
|
35
|
+
* `.swarm/memory.db`. CLI store reported success against the wrong file and
|
|
36
|
+
* a fresh process reading the configured path saw nothing.
|
|
37
|
+
*
|
|
38
|
+
* Use `getMemoryRoot()` (from memory-initializer) so the bridge and the
|
|
39
|
+
* initializer agree on the same file. Imported via require() to avoid a
|
|
40
|
+
* circular ESM dep between memory-initializer.ts and memory-bridge.ts.
|
|
29
41
|
*/
|
|
30
42
|
function getDbPath(customPath) {
|
|
31
|
-
|
|
43
|
+
let defaultDir = path.resolve(process.cwd(), '.swarm');
|
|
44
|
+
try {
|
|
45
|
+
// `getMemoryRoot()` honors $CLAUDE_FLOW_MEMORY_PATH, then the
|
|
46
|
+
// claude-flow.config.json `memory.persistPath`, then defaults to `.swarm`.
|
|
47
|
+
const cjsRequire = createRequire(import.meta.url);
|
|
48
|
+
const mod = cjsRequire('./memory-initializer.js');
|
|
49
|
+
if (typeof mod.getMemoryRoot === 'function') {
|
|
50
|
+
defaultDir = mod.getMemoryRoot();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
/* memory-initializer not resolvable in this build — keep `.swarm/` default */
|
|
55
|
+
}
|
|
32
56
|
if (!customPath)
|
|
33
|
-
return path.join(
|
|
57
|
+
return path.join(defaultDir, 'memory.db');
|
|
34
58
|
if (customPath === ':memory:')
|
|
35
59
|
return ':memory:';
|
|
36
60
|
const resolved = path.resolve(customPath);
|
|
37
|
-
// Ensure the path doesn't escape the working directory
|
|
61
|
+
// Ensure the path doesn't escape the working directory.
|
|
38
62
|
const cwd = process.cwd();
|
|
39
63
|
if (!resolved.startsWith(cwd)) {
|
|
40
|
-
return path.join(
|
|
64
|
+
return path.join(defaultDir, 'memory.db'); // fallback to safe default
|
|
41
65
|
}
|
|
42
66
|
return resolved;
|
|
43
67
|
}
|
|
@@ -866,10 +866,13 @@ INSERT OR REPLACE INTO metadata (key, value) VALUES
|
|
|
866
866
|
('temporal_decay', 'enabled'),
|
|
867
867
|
('hnsw_indexing', 'enabled');
|
|
868
868
|
|
|
869
|
-
-- Create default vector index configuration
|
|
869
|
+
-- Create default vector index configuration. Dimension matches the default
|
|
870
|
+
-- ONNX embedding model (Xenova/all-MiniLM-L6-v2, 384-dim); HNSW rejects
|
|
871
|
+
-- inserts whose dim does not match this row, so a 768 here breaks every
|
|
872
|
+
-- memory_store --vector and memory_search on a fresh install (#1947).
|
|
870
873
|
INSERT OR IGNORE INTO vector_indexes (id, name, dimensions) VALUES
|
|
871
|
-
('default', 'default',
|
|
872
|
-
('patterns', 'patterns',
|
|
874
|
+
('default', 'default', 384),
|
|
875
|
+
('patterns', 'patterns', 384);
|
|
873
876
|
`;
|
|
874
877
|
}
|
|
875
878
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claude-flow/cli",
|
|
3
|
-
"version": "3.7.0-alpha.
|
|
3
|
+
"version": "3.7.0-alpha.29",
|
|
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",
|