@claude-flow/cli 3.0.0-alpha.108 → 3.0.0-alpha.109
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/README.md +21 -0
- package/dist/src/commands/hooks.d.ts.map +1 -1
- package/dist/src/commands/hooks.js +243 -1
- package/dist/src/commands/hooks.js.map +1 -1
- package/dist/src/mcp-tools/agent-tools.d.ts +1 -0
- package/dist/src/mcp-tools/agent-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/agent-tools.js +127 -4
- package/dist/src/mcp-tools/agent-tools.js.map +1 -1
- package/dist/src/mcp-tools/hooks-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/hooks-tools.js +41 -1
- package/dist/src/mcp-tools/hooks-tools.js.map +1 -1
- package/dist/src/ruvector/enhanced-model-router.d.ts +146 -0
- package/dist/src/ruvector/enhanced-model-router.d.ts.map +1 -0
- package/dist/src/ruvector/enhanced-model-router.js +517 -0
- package/dist/src/ruvector/enhanced-model-router.js.map +1 -0
- package/dist/src/ruvector/flash-attention.d.ts +35 -2
- package/dist/src/ruvector/flash-attention.d.ts.map +1 -1
- package/dist/src/ruvector/flash-attention.js +226 -9
- package/dist/src/ruvector/flash-attention.js.map +1 -1
- package/dist/src/ruvector/model-router.js +1 -1
- package/dist/src/ruvector/model-router.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -82,6 +82,27 @@ Claude-Flow v3 introduces **self-learning neural capabilities** that no other ag
|
|
|
82
82
|
- **Claims System** - Human-agent work ownership with handoff protocols
|
|
83
83
|
- **Byzantine Consensus** - Fault-tolerant coordination even with malicious agents
|
|
84
84
|
|
|
85
|
+
### Intelligent 3-Tier Model Routing (ADR-026)
|
|
86
|
+
|
|
87
|
+
Automatically routes tasks to the optimal handler for **75% cost reduction** and **2.5x quota extension** for Claude Max users:
|
|
88
|
+
|
|
89
|
+
| Tier | Handler | Latency | Cost | Use Cases |
|
|
90
|
+
|------|---------|---------|------|-----------|
|
|
91
|
+
| **1** | Agent Booster (WASM) | <1ms | $0 | Simple transforms: var→const, add-types, remove-console |
|
|
92
|
+
| **2** | Haiku/Sonnet | 500ms-2s | $0.0002-$0.003 | Bug fixes, refactoring, feature implementation |
|
|
93
|
+
| **3** | Opus | 2-5s | $0.015 | Architecture, security design, distributed systems |
|
|
94
|
+
|
|
95
|
+
**Benchmark Results:** 100% accuracy, 0.57ms avg routing latency
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
# Example: Task automatically routed to appropriate tier
|
|
99
|
+
npx claude-flow@v3alpha hooks pre-task --description "Add type annotations to server.ts"
|
|
100
|
+
# → [AGENT_BOOSTER_AVAILABLE] Skip LLM - use Agent Booster for "add-types"
|
|
101
|
+
|
|
102
|
+
npx claude-flow@v3alpha hooks pre-task --description "Design OAuth2 with PKCE"
|
|
103
|
+
# → [TASK_MODEL_RECOMMENDATION] Use model="opus" for this task
|
|
104
|
+
```
|
|
105
|
+
|
|
85
106
|
---
|
|
86
107
|
|
|
87
108
|
## Quick Start
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../src/commands/hooks.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAiC,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../src/commands/hooks.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAiC,MAAM,aAAa,CAAC;AA02H1E,eAAO,MAAM,YAAY,EAAE,OAiG1B,CAAC;AAEF,eAAe,YAAY,CAAC"}
|
|
@@ -1206,6 +1206,53 @@ const preTaskCommand = {
|
|
|
1206
1206
|
output.writeln(output.bold('Recommendations'));
|
|
1207
1207
|
output.printList(result.recommendations);
|
|
1208
1208
|
}
|
|
1209
|
+
// Enhanced model routing with Agent Booster AST (ADR-026)
|
|
1210
|
+
try {
|
|
1211
|
+
const { getEnhancedModelRouter } = await import('../ruvector/enhanced-model-router.js');
|
|
1212
|
+
const router = getEnhancedModelRouter();
|
|
1213
|
+
const routeResult = await router.route(description, { filePath: ctx.flags.file });
|
|
1214
|
+
output.writeln();
|
|
1215
|
+
output.writeln(output.bold('Intelligent Model Routing'));
|
|
1216
|
+
if (routeResult.tier === 1) {
|
|
1217
|
+
// Agent Booster can handle this task - skip LLM entirely
|
|
1218
|
+
output.writeln(output.success(` Tier 1: Agent Booster (WASM)`));
|
|
1219
|
+
output.writeln(output.dim(` Intent: ${routeResult.agentBoosterIntent?.type}`));
|
|
1220
|
+
output.writeln(output.dim(` Latency: <1ms | Cost: $0`));
|
|
1221
|
+
output.writeln();
|
|
1222
|
+
output.writeln(output.dim('─'.repeat(60)));
|
|
1223
|
+
output.writeln(output.bold(output.success(`[AGENT_BOOSTER_AVAILABLE] Skip LLM - use Agent Booster for "${routeResult.agentBoosterIntent?.type}"`)));
|
|
1224
|
+
output.writeln(output.dim(`Confidence: ${(routeResult.confidence * 100).toFixed(0)}% | Intent: ${routeResult.agentBoosterIntent?.description}`));
|
|
1225
|
+
output.writeln(output.dim('─'.repeat(60)));
|
|
1226
|
+
}
|
|
1227
|
+
else {
|
|
1228
|
+
// LLM required - show tier and model recommendation
|
|
1229
|
+
output.writeln(` Tier ${routeResult.tier}: ${routeResult.handler.toUpperCase()}`);
|
|
1230
|
+
output.writeln(output.dim(` Complexity: ${((routeResult.complexity || 0) * 100).toFixed(0)}%`));
|
|
1231
|
+
output.writeln(output.dim(` Est. Latency: ${routeResult.estimatedLatencyMs}ms | Cost: $${routeResult.estimatedCost.toFixed(4)}`));
|
|
1232
|
+
output.writeln();
|
|
1233
|
+
// Clear instruction for Claude
|
|
1234
|
+
output.writeln(output.dim('─'.repeat(60)));
|
|
1235
|
+
output.writeln(output.bold(output.success(`[TASK_MODEL_RECOMMENDATION] Use model="${routeResult.model}" for this task`)));
|
|
1236
|
+
output.writeln(output.dim(`Complexity: ${((routeResult.complexity || 0) * 100).toFixed(0)}% | Confidence: ${(routeResult.confidence * 100).toFixed(0)}%`));
|
|
1237
|
+
output.writeln(output.dim('─'.repeat(60)));
|
|
1238
|
+
}
|
|
1239
|
+
// Add routing result for programmatic use
|
|
1240
|
+
result.routeResult = routeResult;
|
|
1241
|
+
result.recommendedModel = routeResult.model;
|
|
1242
|
+
result.modelRouting = {
|
|
1243
|
+
tier: routeResult.tier,
|
|
1244
|
+
handler: routeResult.handler,
|
|
1245
|
+
model: routeResult.model,
|
|
1246
|
+
confidence: routeResult.confidence,
|
|
1247
|
+
complexity: routeResult.complexity,
|
|
1248
|
+
reasoning: routeResult.reasoning,
|
|
1249
|
+
canSkipLLM: routeResult.canSkipLLM,
|
|
1250
|
+
agentBoosterIntent: routeResult.agentBoosterIntent
|
|
1251
|
+
};
|
|
1252
|
+
}
|
|
1253
|
+
catch {
|
|
1254
|
+
// Enhanced router not available, skip recommendation
|
|
1255
|
+
}
|
|
1209
1256
|
return { success: true, data: result };
|
|
1210
1257
|
}
|
|
1211
1258
|
catch (error) {
|
|
@@ -2979,6 +3026,194 @@ const tokenOptimizeCommand = {
|
|
|
2979
3026
|
}
|
|
2980
3027
|
}
|
|
2981
3028
|
};
|
|
3029
|
+
// Model Router command - intelligent model selection (haiku/sonnet/opus)
|
|
3030
|
+
const modelRouteCommand = {
|
|
3031
|
+
name: 'model-route',
|
|
3032
|
+
description: 'Route task to optimal Claude model (haiku/sonnet/opus) based on complexity',
|
|
3033
|
+
options: [
|
|
3034
|
+
{ name: 'task', short: 't', type: 'string', description: 'Task description to route', required: true },
|
|
3035
|
+
{ name: 'context', short: 'c', type: 'string', description: 'Additional context' },
|
|
3036
|
+
{ name: 'prefer-cost', type: 'boolean', description: 'Prefer lower cost models' },
|
|
3037
|
+
{ name: 'prefer-quality', type: 'boolean', description: 'Prefer higher quality models' },
|
|
3038
|
+
],
|
|
3039
|
+
examples: [
|
|
3040
|
+
{ command: 'claude-flow hooks model-route -t "fix typo"', description: 'Route simple task (likely haiku)' },
|
|
3041
|
+
{ command: 'claude-flow hooks model-route -t "architect auth system"', description: 'Route complex task (likely opus)' },
|
|
3042
|
+
],
|
|
3043
|
+
action: async (ctx) => {
|
|
3044
|
+
const task = ctx.args[0] || ctx.flags.task;
|
|
3045
|
+
if (!task) {
|
|
3046
|
+
output.printError('Task description required. Use --task or -t flag.');
|
|
3047
|
+
return { success: false, exitCode: 1 };
|
|
3048
|
+
}
|
|
3049
|
+
output.printInfo(`Analyzing task complexity: ${output.highlight(task.slice(0, 50))}...`);
|
|
3050
|
+
try {
|
|
3051
|
+
const result = await callMCPTool('hooks/model-route', {
|
|
3052
|
+
task,
|
|
3053
|
+
context: ctx.flags.context,
|
|
3054
|
+
preferCost: ctx.flags['prefer-cost'],
|
|
3055
|
+
preferQuality: ctx.flags['prefer-quality'],
|
|
3056
|
+
});
|
|
3057
|
+
if (ctx.flags.format === 'json') {
|
|
3058
|
+
output.printJson(result);
|
|
3059
|
+
return { success: true, data: result };
|
|
3060
|
+
}
|
|
3061
|
+
output.writeln();
|
|
3062
|
+
// Model icon based on selection
|
|
3063
|
+
const modelIcons = {
|
|
3064
|
+
haiku: '🌸',
|
|
3065
|
+
sonnet: '📜',
|
|
3066
|
+
opus: '🎭',
|
|
3067
|
+
};
|
|
3068
|
+
const model = result.model || 'sonnet';
|
|
3069
|
+
const icon = modelIcons[model] || '🤖';
|
|
3070
|
+
// Calculate cost savings compared to opus
|
|
3071
|
+
const costMultipliers = { haiku: 0.04, sonnet: 0.2, opus: 1.0 };
|
|
3072
|
+
const costSavings = model !== 'opus'
|
|
3073
|
+
? `${((1 - costMultipliers[model]) * 100).toFixed(0)}% vs opus`
|
|
3074
|
+
: undefined;
|
|
3075
|
+
// Determine complexity level
|
|
3076
|
+
const complexityScore = typeof result.complexity === 'number' ? result.complexity : 0.5;
|
|
3077
|
+
const complexityLevel = complexityScore > 0.7 ? 'high' : complexityScore > 0.4 ? 'medium' : 'low';
|
|
3078
|
+
output.printBox([
|
|
3079
|
+
`Selected Model: ${icon} ${output.bold(model.toUpperCase())}`,
|
|
3080
|
+
`Confidence: ${(result.confidence * 100).toFixed(1)}%`,
|
|
3081
|
+
`Complexity: ${complexityLevel} (${(complexityScore * 100).toFixed(0)}%)`,
|
|
3082
|
+
costSavings ? `Cost Savings: ${costSavings}` : '',
|
|
3083
|
+
].filter(Boolean).join('\n'), 'Model Routing Result');
|
|
3084
|
+
output.writeln();
|
|
3085
|
+
output.writeln(output.bold('Reasoning'));
|
|
3086
|
+
output.writeln(output.dim(result.reasoning || 'Based on task complexity analysis'));
|
|
3087
|
+
if (result.implementation) {
|
|
3088
|
+
output.writeln();
|
|
3089
|
+
output.writeln(output.dim(`Implementation: ${result.implementation}`));
|
|
3090
|
+
}
|
|
3091
|
+
return { success: true, data: result };
|
|
3092
|
+
}
|
|
3093
|
+
catch (error) {
|
|
3094
|
+
if (error instanceof MCPClientError) {
|
|
3095
|
+
output.printError(`Model routing failed: ${error.message}`);
|
|
3096
|
+
}
|
|
3097
|
+
else {
|
|
3098
|
+
output.printError(`Unexpected error: ${String(error)}`);
|
|
3099
|
+
}
|
|
3100
|
+
return { success: false, exitCode: 1 };
|
|
3101
|
+
}
|
|
3102
|
+
}
|
|
3103
|
+
};
|
|
3104
|
+
// Model Outcome command - record routing outcomes for learning
|
|
3105
|
+
const modelOutcomeCommand = {
|
|
3106
|
+
name: 'model-outcome',
|
|
3107
|
+
description: 'Record model routing outcome for learning',
|
|
3108
|
+
options: [
|
|
3109
|
+
{ name: 'task', short: 't', type: 'string', description: 'Task that was executed', required: true },
|
|
3110
|
+
{ name: 'model', short: 'm', type: 'string', description: 'Model that was used (haiku/sonnet/opus)', required: true },
|
|
3111
|
+
{ name: 'outcome', short: 'o', type: 'string', description: 'Outcome (success/failure/escalated)', required: true },
|
|
3112
|
+
{ name: 'quality', short: 'q', type: 'number', description: 'Quality score 0-1' },
|
|
3113
|
+
],
|
|
3114
|
+
examples: [
|
|
3115
|
+
{ command: 'claude-flow hooks model-outcome -t "fix typo" -m haiku -o success', description: 'Record successful haiku task' },
|
|
3116
|
+
{ command: 'claude-flow hooks model-outcome -t "auth system" -m sonnet -o escalated', description: 'Record escalation to opus' },
|
|
3117
|
+
],
|
|
3118
|
+
action: async (ctx) => {
|
|
3119
|
+
const task = ctx.flags.task;
|
|
3120
|
+
const model = ctx.flags.model;
|
|
3121
|
+
const outcome = ctx.flags.outcome;
|
|
3122
|
+
if (!task || !model || !outcome) {
|
|
3123
|
+
output.printError('Task, model, and outcome are required.');
|
|
3124
|
+
return { success: false, exitCode: 1 };
|
|
3125
|
+
}
|
|
3126
|
+
try {
|
|
3127
|
+
const result = await callMCPTool('hooks/model-outcome', {
|
|
3128
|
+
task,
|
|
3129
|
+
model,
|
|
3130
|
+
outcome,
|
|
3131
|
+
quality: ctx.flags.quality,
|
|
3132
|
+
});
|
|
3133
|
+
output.printSuccess(`Outcome recorded for ${model}: ${outcome}`);
|
|
3134
|
+
if (result.learningUpdate) {
|
|
3135
|
+
output.writeln(output.dim(result.learningUpdate));
|
|
3136
|
+
}
|
|
3137
|
+
return { success: true, data: result };
|
|
3138
|
+
}
|
|
3139
|
+
catch (error) {
|
|
3140
|
+
output.printError(`Failed to record outcome: ${String(error)}`);
|
|
3141
|
+
return { success: false, exitCode: 1 };
|
|
3142
|
+
}
|
|
3143
|
+
}
|
|
3144
|
+
};
|
|
3145
|
+
// Model Stats command - view routing statistics
|
|
3146
|
+
const modelStatsCommand = {
|
|
3147
|
+
name: 'model-stats',
|
|
3148
|
+
description: 'View model routing statistics and learning metrics',
|
|
3149
|
+
options: [
|
|
3150
|
+
{ name: 'detailed', short: 'd', type: 'boolean', description: 'Show detailed breakdown' },
|
|
3151
|
+
],
|
|
3152
|
+
examples: [
|
|
3153
|
+
{ command: 'claude-flow hooks model-stats', description: 'View routing stats' },
|
|
3154
|
+
{ command: 'claude-flow hooks model-stats --detailed', description: 'Show detailed breakdown' },
|
|
3155
|
+
],
|
|
3156
|
+
action: async (ctx) => {
|
|
3157
|
+
try {
|
|
3158
|
+
const result = await callMCPTool('hooks/model-stats', {
|
|
3159
|
+
detailed: ctx.flags.detailed,
|
|
3160
|
+
});
|
|
3161
|
+
if (ctx.flags.format === 'json') {
|
|
3162
|
+
output.printJson(result);
|
|
3163
|
+
return { success: true, data: result };
|
|
3164
|
+
}
|
|
3165
|
+
if (!result.available) {
|
|
3166
|
+
output.printWarning(result.message || 'Model router not available');
|
|
3167
|
+
return { success: true, data: result };
|
|
3168
|
+
}
|
|
3169
|
+
// Calculate cost savings based on model distribution
|
|
3170
|
+
const dist = result.modelDistribution || { haiku: 0, sonnet: 0, opus: 0 };
|
|
3171
|
+
const totalTasks = result.totalDecisions || 0;
|
|
3172
|
+
const costMultipliers = { haiku: 0.04, sonnet: 0.2, opus: 1.0 };
|
|
3173
|
+
let totalCost = 0;
|
|
3174
|
+
let maxCost = totalTasks; // If all were opus
|
|
3175
|
+
for (const [model, count] of Object.entries(dist)) {
|
|
3176
|
+
if (model !== 'inherit') {
|
|
3177
|
+
totalCost += count * (costMultipliers[model] || 1);
|
|
3178
|
+
}
|
|
3179
|
+
}
|
|
3180
|
+
const costSavings = maxCost > 0 ? ((1 - totalCost / maxCost) * 100).toFixed(1) : '0';
|
|
3181
|
+
output.writeln();
|
|
3182
|
+
output.printBox([
|
|
3183
|
+
`Total Tasks Routed: ${totalTasks}`,
|
|
3184
|
+
`Avg Complexity: ${((result.avgComplexity || 0) * 100).toFixed(1)}%`,
|
|
3185
|
+
`Avg Confidence: ${((result.avgConfidence || 0) * 100).toFixed(1)}%`,
|
|
3186
|
+
`Cost Savings: ${costSavings}% vs all-opus`,
|
|
3187
|
+
`Circuit Breaker Trips: ${result.circuitBreakerTrips || 0}`,
|
|
3188
|
+
].join('\n'), 'Model Routing Statistics');
|
|
3189
|
+
if (dist && Object.keys(dist).length > 0) {
|
|
3190
|
+
output.writeln();
|
|
3191
|
+
output.writeln(output.bold('Model Distribution'));
|
|
3192
|
+
output.printTable({
|
|
3193
|
+
columns: [
|
|
3194
|
+
{ key: 'model', header: 'Model', width: 10 },
|
|
3195
|
+
{ key: 'count', header: 'Tasks', width: 8, align: 'right' },
|
|
3196
|
+
{ key: 'percentage', header: '%', width: 8, align: 'right' },
|
|
3197
|
+
{ key: 'costMultiplier', header: 'Cost', width: 8, align: 'right' },
|
|
3198
|
+
],
|
|
3199
|
+
data: Object.entries(dist)
|
|
3200
|
+
.filter(([model]) => model !== 'inherit')
|
|
3201
|
+
.map(([model, count]) => ({
|
|
3202
|
+
model: model.toUpperCase(),
|
|
3203
|
+
count,
|
|
3204
|
+
percentage: totalTasks > 0 ? `${((count / totalTasks) * 100).toFixed(1)}%` : '0%',
|
|
3205
|
+
costMultiplier: `${costMultipliers[model] || 1}x`,
|
|
3206
|
+
})),
|
|
3207
|
+
});
|
|
3208
|
+
}
|
|
3209
|
+
return { success: true, data: result };
|
|
3210
|
+
}
|
|
3211
|
+
catch (error) {
|
|
3212
|
+
output.printError(`Failed to get stats: ${String(error)}`);
|
|
3213
|
+
return { success: false, exitCode: 1 };
|
|
3214
|
+
}
|
|
3215
|
+
}
|
|
3216
|
+
};
|
|
2982
3217
|
// Main hooks command
|
|
2983
3218
|
export const hooksCommand = {
|
|
2984
3219
|
name: 'hooks',
|
|
@@ -3009,6 +3244,10 @@ export const hooksCommand = {
|
|
|
3009
3244
|
coverageGapsCommand,
|
|
3010
3245
|
// Token optimization
|
|
3011
3246
|
tokenOptimizeCommand,
|
|
3247
|
+
// Model routing (tiny-dancer integration)
|
|
3248
|
+
modelRouteCommand,
|
|
3249
|
+
modelOutcomeCommand,
|
|
3250
|
+
modelStatsCommand,
|
|
3012
3251
|
// Backward-compatible aliases for v2
|
|
3013
3252
|
routeTaskCommand,
|
|
3014
3253
|
sessionStartCommand,
|
|
@@ -3053,7 +3292,10 @@ export const hooksCommand = {
|
|
|
3053
3292
|
`${output.highlight('coverage-route')} - Route tasks based on coverage gaps (ruvector)`,
|
|
3054
3293
|
`${output.highlight('coverage-suggest')}- Suggest coverage improvements`,
|
|
3055
3294
|
`${output.highlight('coverage-gaps')} - List all coverage gaps with agents`,
|
|
3056
|
-
`${output.highlight('token-optimize')} - Token optimization (30-50% savings)
|
|
3295
|
+
`${output.highlight('token-optimize')} - Token optimization (30-50% savings)`,
|
|
3296
|
+
`${output.highlight('model-route')} - Route to optimal model (haiku/sonnet/opus)`,
|
|
3297
|
+
`${output.highlight('model-outcome')} - Record model routing outcome`,
|
|
3298
|
+
`${output.highlight('model-stats')} - View model routing statistics`
|
|
3057
3299
|
]);
|
|
3058
3300
|
output.writeln();
|
|
3059
3301
|
output.writeln('Run "claude-flow hooks <subcommand> --help" for subcommand help');
|