claude-flow 3.5.78 → 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/index.js +8 -2
- 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 +1 -1
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
|
*/
|
|
@@ -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
|
|
@@ -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",
|