claude-flow 3.5.79 → 3.5.80
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/package.json +1 -1
- package/v3/@claude-flow/cli/dist/src/commands/index.d.ts +7 -0
- package/v3/@claude-flow/cli/dist/src/commands/index.js +9 -0
- package/v3/@claude-flow/cli/dist/src/commands/init.js +3 -7
- package/v3/@claude-flow/cli/dist/src/index.js +8 -2
- package/v3/@claude-flow/cli/dist/src/init/executor.js +0 -10
- package/v3/@claude-flow/cli/dist/src/mcp-tools/types.d.ts +3 -20
- package/v3/@claude-flow/cli/dist/src/mcp-tools/types.js +4 -65
- package/v3/@claude-flow/cli/dist/src/mcp-tools/validate-input.js +10 -3
- package/v3/@claude-flow/cli/dist/src/parser.d.ts +9 -0
- package/v3/@claude-flow/cli/dist/src/parser.js +41 -7
- package/v3/@claude-flow/cli/package.json +3 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-flow",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.80",
|
|
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",
|
|
@@ -83,6 +83,13 @@ export declare function getCommandAsync(name: string): Promise<Command | undefin
|
|
|
83
83
|
* Check if command exists (sync check for core commands)
|
|
84
84
|
*/
|
|
85
85
|
export declare function hasCommand(name: string): boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Get the names of all lazy-loadable commands (the commandLoaders keys).
|
|
88
|
+
* Used by the CLI constructor to register these names with the parser so
|
|
89
|
+
* the two-pass argument walker can recognize them as commands before their
|
|
90
|
+
* modules have been imported. Fix for #1596.
|
|
91
|
+
*/
|
|
92
|
+
export declare function getLazyCommandNames(): string[];
|
|
86
93
|
/**
|
|
87
94
|
* Get all command names (including aliases and lazy-loadable)
|
|
88
95
|
*/
|
|
@@ -280,6 +280,15 @@ export async function getCommandAsync(name) {
|
|
|
280
280
|
export function hasCommand(name) {
|
|
281
281
|
return loadedCommands.has(name) || commandRegistry.has(name) || name in commandLoaders;
|
|
282
282
|
}
|
|
283
|
+
/**
|
|
284
|
+
* Get the names of all lazy-loadable commands (the commandLoaders keys).
|
|
285
|
+
* Used by the CLI constructor to register these names with the parser so
|
|
286
|
+
* the two-pass argument walker can recognize them as commands before their
|
|
287
|
+
* modules have been imported. Fix for #1596.
|
|
288
|
+
*/
|
|
289
|
+
export function getLazyCommandNames() {
|
|
290
|
+
return Object.keys(commandLoaders);
|
|
291
|
+
}
|
|
283
292
|
/**
|
|
284
293
|
* Get all command names (including aliases and lazy-loadable)
|
|
285
294
|
*/
|
|
@@ -231,12 +231,8 @@ const initAction = async (ctx) => {
|
|
|
231
231
|
}
|
|
232
232
|
output.printBox(summary.join('\n'), 'Summary');
|
|
233
233
|
output.writeln();
|
|
234
|
-
// Show what was created
|
|
235
|
-
if (
|
|
236
|
-
output.printBox('Skipped (--skip-claude): no files written under .claude/ or ~/.claude/', 'Claude Code Integration');
|
|
237
|
-
output.writeln();
|
|
238
|
-
}
|
|
239
|
-
else if (options.components.claudeMd || options.components.settings || options.components.skills || options.components.commands || options.components.agents) {
|
|
234
|
+
// Show what was created
|
|
235
|
+
if (options.components.claudeMd || options.components.settings || options.components.skills || options.components.commands || options.components.agents) {
|
|
240
236
|
output.printBox([
|
|
241
237
|
options.components.claudeMd ? `CLAUDE.md: Swarm guidance & configuration` : '',
|
|
242
238
|
options.components.settings ? `Settings: .claude/settings.json` : '',
|
|
@@ -913,7 +909,7 @@ export const initCommand = {
|
|
|
913
909
|
},
|
|
914
910
|
{
|
|
915
911
|
name: 'skip-claude',
|
|
916
|
-
description: 'Skip
|
|
912
|
+
description: 'Skip .claude/ directory creation (runtime only)',
|
|
917
913
|
type: 'boolean',
|
|
918
914
|
default: false,
|
|
919
915
|
},
|
|
@@ -9,7 +9,7 @@ import { fileURLToPath } from 'url';
|
|
|
9
9
|
import { dirname, join } from 'path';
|
|
10
10
|
import { commandParser } from './parser.js';
|
|
11
11
|
import { output } from './output.js';
|
|
12
|
-
import { commands, getCommandsByCategory, getCommand, getCommandAsync, getCommandNames, hasCommand } from './commands/index.js';
|
|
12
|
+
import { commands, getCommandsByCategory, getCommand, getCommandAsync, getCommandNames, getLazyCommandNames, hasCommand } from './commands/index.js';
|
|
13
13
|
import { suggestCommand } from './suggest.js';
|
|
14
14
|
import { runStartupUpdateCheck } from './update/index.js';
|
|
15
15
|
// Read version from package.json at runtime
|
|
@@ -44,10 +44,16 @@ export class CLI {
|
|
|
44
44
|
this.parser = commandParser;
|
|
45
45
|
this.output = output;
|
|
46
46
|
this.interactive = options.interactive ?? process.stdin.isTTY ?? false;
|
|
47
|
-
// Register all commands
|
|
47
|
+
// Register all core (synchronously loaded) commands with full definitions
|
|
48
48
|
for (const cmd of commands) {
|
|
49
49
|
this.parser.registerCommand(cmd);
|
|
50
50
|
}
|
|
51
|
+
// Register lazy command names so the parser can recognize them during
|
|
52
|
+
// argument resolution without importing their modules. Fix for #1596:
|
|
53
|
+
// prevents `daemon start` from being mis-routed to the `start` command.
|
|
54
|
+
for (const name of getLazyCommandNames()) {
|
|
55
|
+
this.parser.registerLazyCommandName(name);
|
|
56
|
+
}
|
|
51
57
|
}
|
|
52
58
|
/**
|
|
53
59
|
* Run the CLI with given arguments
|
|
@@ -1663,11 +1663,6 @@ async function writeClaudeMd(targetDir, options, result) {
|
|
|
1663
1663
|
result.created.files.push('CLAUDE.md');
|
|
1664
1664
|
}
|
|
1665
1665
|
// Also write/append global ~/.claude/CLAUDE.md so ruflo tools are used automatically (#1497)
|
|
1666
|
-
// Guarded to never overwrite user content and to respect opt-out env var (#1597).
|
|
1667
|
-
// Opt out entirely with CLAUDE_FLOW_SKIP_GLOBAL_CLAUDE_MD=1.
|
|
1668
|
-
if (process.env.CLAUDE_FLOW_SKIP_GLOBAL_CLAUDE_MD === '1') {
|
|
1669
|
-
return;
|
|
1670
|
-
}
|
|
1671
1666
|
const homeDir = process.env.HOME || process.env.USERPROFILE || '';
|
|
1672
1667
|
if (homeDir) {
|
|
1673
1668
|
const globalClaudeDir = path.join(homeDir, '.claude');
|
|
@@ -1687,13 +1682,8 @@ async function writeClaudeMd(targetDir, options, result) {
|
|
|
1687
1682
|
if (fs.existsSync(globalClaudeMd)) {
|
|
1688
1683
|
const existing = fs.readFileSync(globalClaudeMd, 'utf-8');
|
|
1689
1684
|
if (!existing.includes('Ruflo Integration')) {
|
|
1690
|
-
// Always back up existing user content before any modification (#1597).
|
|
1691
|
-
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
1692
|
-
const backupPath = `${globalClaudeMd}.backup-${timestamp}`;
|
|
1693
|
-
fs.copyFileSync(globalClaudeMd, backupPath);
|
|
1694
1685
|
fs.appendFileSync(globalClaudeMd, rufloBlock);
|
|
1695
1686
|
result.created.files.push('~/.claude/CLAUDE.md (appended ruflo block)');
|
|
1696
|
-
result.created.files.push(`~/.claude/CLAUDE.md.backup-${timestamp} (backup of pre-existing content)`);
|
|
1697
1687
|
}
|
|
1698
1688
|
}
|
|
1699
1689
|
else {
|
|
@@ -18,28 +18,11 @@ export interface MCPToolResult {
|
|
|
18
18
|
isError?: boolean;
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
|
-
* Returns the effective project working directory
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* 1. CLAUDE_FLOW_PROJECT_DIR — explicit ruflo project override
|
|
25
|
-
* 2. CLAUDE_FLOW_CWD — legacy ruflo override set by install script
|
|
26
|
-
* 3. CLAUDE_PROJECT_DIR — Claude Code's native project dir env var
|
|
27
|
-
* 4. INIT_CWD — npm's original invocation dir
|
|
28
|
-
* 5. process.cwd() — if it is not a system directory
|
|
29
|
-
* 6. os.homedir() — safe fallback
|
|
30
|
-
*
|
|
31
|
-
* System directories (e.g. C:\Windows\System32 on Windows, where MCP servers
|
|
32
|
-
* spawned by AI agents commonly inherit cwd) are rejected at every step.
|
|
33
|
-
*
|
|
34
|
-
* Only use this for storage path resolution. When the actual runtime working
|
|
35
|
-
* directory matters (e.g. child process cwd, user-facing status), call
|
|
36
|
-
* process.cwd() directly.
|
|
21
|
+
* Returns the effective project working directory.
|
|
22
|
+
* Prefers CLAUDE_FLOW_CWD (set by the install script for global/MCP installs
|
|
23
|
+
* where process.cwd() may resolve to '/') over the real process.cwd().
|
|
37
24
|
*/
|
|
38
25
|
export declare function getProjectCwd(): string;
|
|
39
|
-
/**
|
|
40
|
-
* Reset cached value. Intended for tests only.
|
|
41
|
-
*/
|
|
42
|
-
export declare function __resetProjectCwdCache(): void;
|
|
43
26
|
export interface MCPTool {
|
|
44
27
|
name: string;
|
|
45
28
|
description: string;
|
|
@@ -3,73 +3,12 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Local type definitions to avoid external imports outside package boundary.
|
|
5
5
|
*/
|
|
6
|
-
import { homedir } from 'node:os';
|
|
7
|
-
// System directories that must not be used for project storage (#1577).
|
|
8
|
-
// On Windows, MCP servers spawned by AI agents often inherit System32 as cwd
|
|
9
|
-
// — writing there fails with EPERM.
|
|
10
|
-
const SYSTEM_DIR_PREFIXES = [
|
|
11
|
-
'c:\\windows',
|
|
12
|
-
'c:/windows',
|
|
13
|
-
'/windows/system32',
|
|
14
|
-
];
|
|
15
|
-
function isSystemDir(dir) {
|
|
16
|
-
if (!dir)
|
|
17
|
-
return true;
|
|
18
|
-
const lower = dir.toLowerCase().replace(/\\/g, '/');
|
|
19
|
-
return SYSTEM_DIR_PREFIXES.some((p) => lower.startsWith(p.replace(/\\/g, '/')));
|
|
20
|
-
}
|
|
21
|
-
let _cachedProjectCwd;
|
|
22
6
|
/**
|
|
23
|
-
* Returns the effective project working directory
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* 1. CLAUDE_FLOW_PROJECT_DIR — explicit ruflo project override
|
|
27
|
-
* 2. CLAUDE_FLOW_CWD — legacy ruflo override set by install script
|
|
28
|
-
* 3. CLAUDE_PROJECT_DIR — Claude Code's native project dir env var
|
|
29
|
-
* 4. INIT_CWD — npm's original invocation dir
|
|
30
|
-
* 5. process.cwd() — if it is not a system directory
|
|
31
|
-
* 6. os.homedir() — safe fallback
|
|
32
|
-
*
|
|
33
|
-
* System directories (e.g. C:\Windows\System32 on Windows, where MCP servers
|
|
34
|
-
* spawned by AI agents commonly inherit cwd) are rejected at every step.
|
|
35
|
-
*
|
|
36
|
-
* Only use this for storage path resolution. When the actual runtime working
|
|
37
|
-
* directory matters (e.g. child process cwd, user-facing status), call
|
|
38
|
-
* process.cwd() directly.
|
|
7
|
+
* Returns the effective project working directory.
|
|
8
|
+
* Prefers CLAUDE_FLOW_CWD (set by the install script for global/MCP installs
|
|
9
|
+
* where process.cwd() may resolve to '/') over the real process.cwd().
|
|
39
10
|
*/
|
|
40
11
|
export function getProjectCwd() {
|
|
41
|
-
|
|
42
|
-
return _cachedProjectCwd;
|
|
43
|
-
const envKeys = [
|
|
44
|
-
'CLAUDE_FLOW_PROJECT_DIR',
|
|
45
|
-
'CLAUDE_FLOW_CWD',
|
|
46
|
-
'CLAUDE_PROJECT_DIR',
|
|
47
|
-
'INIT_CWD',
|
|
48
|
-
];
|
|
49
|
-
for (const key of envKeys) {
|
|
50
|
-
const val = process.env[key];
|
|
51
|
-
if (val && !isSystemDir(val)) {
|
|
52
|
-
_cachedProjectCwd = val;
|
|
53
|
-
return _cachedProjectCwd;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
try {
|
|
57
|
-
const cwd = process.cwd();
|
|
58
|
-
if (!isSystemDir(cwd)) {
|
|
59
|
-
_cachedProjectCwd = cwd;
|
|
60
|
-
return _cachedProjectCwd;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
catch {
|
|
64
|
-
// process.cwd() can throw ENOENT if the cwd was deleted — fall through.
|
|
65
|
-
}
|
|
66
|
-
_cachedProjectCwd = homedir();
|
|
67
|
-
return _cachedProjectCwd;
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Reset cached value. Intended for tests only.
|
|
71
|
-
*/
|
|
72
|
-
export function __resetProjectCwdCache() {
|
|
73
|
-
_cachedProjectCwd = undefined;
|
|
12
|
+
return process.env.CLAUDE_FLOW_CWD || process.cwd();
|
|
74
13
|
}
|
|
75
14
|
//# sourceMappingURL=types.js.map
|
|
@@ -113,18 +113,25 @@ export async function validateAgentSpawn(input) {
|
|
|
113
113
|
if (!r.valid)
|
|
114
114
|
errors.push(r.error);
|
|
115
115
|
}
|
|
116
|
-
// Try enhanced Zod validation if available
|
|
116
|
+
// Try enhanced Zod validation if available.
|
|
117
|
+
// Fix for #1567: @claude-flow/security's SpawnAgentSchema expects `type` and
|
|
118
|
+
// `id` (not `agentType`/`name`), so the previous call always failed with
|
|
119
|
+
// "type: Required". Also swallow `invalid_enum_value` errors because the
|
|
120
|
+
// schema enumerates only 15 built-in agent types — we support custom types
|
|
121
|
+
// (the inline validator already checked the identifier is safe).
|
|
117
122
|
const sec = await getSecurityModule();
|
|
118
123
|
if (sec?.SpawnAgentSchema) {
|
|
119
124
|
try {
|
|
120
125
|
sec.SpawnAgentSchema.parse({
|
|
121
|
-
|
|
122
|
-
|
|
126
|
+
type: input.agentType,
|
|
127
|
+
id: input.agentId,
|
|
123
128
|
});
|
|
124
129
|
}
|
|
125
130
|
catch (zodErr) {
|
|
126
131
|
if (zodErr.issues) {
|
|
127
132
|
for (const issue of zodErr.issues) {
|
|
133
|
+
if (issue.code === 'invalid_enum_value')
|
|
134
|
+
continue;
|
|
128
135
|
errors.push(`${issue.path.join('.')}: ${issue.message}`);
|
|
129
136
|
}
|
|
130
137
|
}
|
|
@@ -21,10 +21,19 @@ export interface ParserOptions {
|
|
|
21
21
|
export declare class CommandParser {
|
|
22
22
|
private options;
|
|
23
23
|
private commands;
|
|
24
|
+
private lazyCommandNames;
|
|
24
25
|
private globalOptions;
|
|
25
26
|
constructor(options?: ParserOptions);
|
|
26
27
|
private initializeGlobalOptions;
|
|
27
28
|
registerCommand(command: Command): void;
|
|
29
|
+
/**
|
|
30
|
+
* Register a lazy-loaded command's name so Pass 1/Pass 2 can recognize it as
|
|
31
|
+
* a command position even though its full definition hasn't been loaded yet.
|
|
32
|
+
* Fix for #1596: without this, lazy commands like `daemon start` were
|
|
33
|
+
* mis-routed because Pass 1 walked past `daemon` and greedy-matched `start`.
|
|
34
|
+
*/
|
|
35
|
+
registerLazyCommandName(name: string): void;
|
|
36
|
+
private isKnownCommandName;
|
|
28
37
|
getCommand(name: string): Command | undefined;
|
|
29
38
|
getAllCommands(): Command[];
|
|
30
39
|
parse(args: string[]): ParseResult;
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
export class CommandParser {
|
|
6
6
|
options;
|
|
7
7
|
commands = new Map();
|
|
8
|
+
lazyCommandNames = new Set();
|
|
8
9
|
globalOptions = [];
|
|
9
10
|
constructor(options = {}) {
|
|
10
11
|
this.options = {
|
|
@@ -83,6 +84,18 @@ export class CommandParser {
|
|
|
83
84
|
}
|
|
84
85
|
}
|
|
85
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Register a lazy-loaded command's name so Pass 1/Pass 2 can recognize it as
|
|
89
|
+
* a command position even though its full definition hasn't been loaded yet.
|
|
90
|
+
* Fix for #1596: without this, lazy commands like `daemon start` were
|
|
91
|
+
* mis-routed because Pass 1 walked past `daemon` and greedy-matched `start`.
|
|
92
|
+
*/
|
|
93
|
+
registerLazyCommandName(name) {
|
|
94
|
+
this.lazyCommandNames.add(name);
|
|
95
|
+
}
|
|
96
|
+
isKnownCommandName(name) {
|
|
97
|
+
return this.commands.has(name) || this.lazyCommandNames.has(name);
|
|
98
|
+
}
|
|
86
99
|
getCommand(name) {
|
|
87
100
|
return this.commands.get(name);
|
|
88
101
|
}
|
|
@@ -103,16 +116,33 @@ export class CommandParser {
|
|
|
103
116
|
positional: [],
|
|
104
117
|
raw: [...args]
|
|
105
118
|
};
|
|
106
|
-
// Pass 1: Identify command and subcommand (skip flags)
|
|
119
|
+
// Pass 1: Identify command and subcommand (skip flags).
|
|
120
|
+
// Fix for #1596: the first non-flag positional is ALWAYS the command slot.
|
|
121
|
+
// If it's a known command (sync or lazy) we resolve it; otherwise we stop
|
|
122
|
+
// searching — we MUST NOT walk past it and greedy-match a later arg as the
|
|
123
|
+
// command, because that's what caused `daemon start` to resolve as `start`
|
|
124
|
+
// with `daemon` left as a positional.
|
|
107
125
|
let resolvedCmd;
|
|
108
126
|
let resolvedSub;
|
|
127
|
+
let sawFirstPositional = false;
|
|
109
128
|
for (const arg of args) {
|
|
110
129
|
if (arg.startsWith('-'))
|
|
111
130
|
continue;
|
|
112
|
-
if (!
|
|
113
|
-
|
|
131
|
+
if (!sawFirstPositional) {
|
|
132
|
+
sawFirstPositional = true;
|
|
133
|
+
if (this.commands.has(arg)) {
|
|
134
|
+
resolvedCmd = this.commands.get(arg);
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
// Lazy command: we know its name but not its subcommands. Stop the
|
|
138
|
+
// walk here — we'll rely on Pass 2 to push it onto commandPath.
|
|
139
|
+
if (this.lazyCommandNames.has(arg)) {
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
// Unknown first positional — not a command. Stop walking.
|
|
143
|
+
break;
|
|
114
144
|
}
|
|
115
|
-
|
|
145
|
+
if (resolvedCmd && !resolvedSub && resolvedCmd.subcommands) {
|
|
116
146
|
resolvedSub = resolvedCmd.subcommands.find(sc => sc.name === arg || sc.aliases?.includes(arg));
|
|
117
147
|
}
|
|
118
148
|
}
|
|
@@ -138,11 +168,15 @@ export class CommandParser {
|
|
|
138
168
|
i = parseResult.nextIndex;
|
|
139
169
|
continue;
|
|
140
170
|
}
|
|
141
|
-
// Handle positional arguments
|
|
142
|
-
|
|
171
|
+
// Handle positional arguments.
|
|
172
|
+
// Fix for #1596: treat lazy command names as commands here too so that
|
|
173
|
+
// downstream dispatch sees `commandPath = ['daemon', 'start']` instead of
|
|
174
|
+
// `commandPath = ['start'], positional = ['daemon']`.
|
|
175
|
+
if (result.command.length === 0 && this.isKnownCommandName(arg)) {
|
|
143
176
|
// This is a command
|
|
144
177
|
result.command.push(arg);
|
|
145
|
-
// Check for subcommand (level 1)
|
|
178
|
+
// Check for subcommand (level 1) — only possible for sync commands
|
|
179
|
+
// whose subcommand definitions are already loaded.
|
|
146
180
|
const cmd = this.commands.get(arg);
|
|
147
181
|
if (cmd?.subcommands && i + 1 < args.length) {
|
|
148
182
|
const nextArg = args[i + 1];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claude-flow/cli",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.80",
|
|
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",
|
|
@@ -115,7 +115,8 @@
|
|
|
115
115
|
"@ruvector/rvagent-wasm": "^0.1.0",
|
|
116
116
|
"@ruvector/diskann": "^0.1.0",
|
|
117
117
|
"@ruvector/sona": "^0.1.5",
|
|
118
|
-
"agentdb": "^3.0.0-alpha.11"
|
|
118
|
+
"agentdb": "^3.0.0-alpha.11",
|
|
119
|
+
"agentic-flow": "^3.0.0-alpha.1"
|
|
119
120
|
},
|
|
120
121
|
"publishConfig": {
|
|
121
122
|
"access": "public",
|