claude-flow-novice 2.5.2 → 2.6.0
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/agents/CLAUDE.md +740 -978
- package/.claude/agents/core-agents/cost-savings-cfn-loop-coordinator.md +47 -2
- package/.claude/agents/custom/agent-builder.md +637 -0
- package/.claude/api-configs/config-current-zai-config.env +62 -0
- package/.claude/api-configs/config-test-zai-config.env +62 -0
- package/.claude/api-configs/env-backups/before-anthropic-20251020-025404.env +62 -0
- package/.claude/api-configs/env-backups/before-restore-20251020-025431.env +62 -0
- package/.claude/artifacts/reflection-merge-logs/cli-agent-spawning-v2.5.2-merge-report.md +61 -0
- package/.claude/commands/cfn-loop-epic.md +41 -17
- package/.claude/commands/cfn-loop.md +43 -30
- package/.claude/commands/custom-routing-activate.md +37 -123
- package/.claude/commands/custom-routing-deactivate.md +27 -124
- package/.claude/commands/switch-api.md +41 -16
- package/.claude/skills/agent-execution/execute-agent.sh +126 -0
- package/.claude/skills/redis-coordination/AGENT_LOGGING.md +280 -0
- package/.claude/skills/redis-coordination/agent-log.sh +124 -0
- package/.claude/skills/redis-coordination/init-swarm.sh +6 -1
- package/.claude/skills/redis-coordination/invoke-waiting-mode.sh +62 -5
- package/.claude/skills/redis-coordination/orchestrate-cfn-loop.sh +68 -8
- package/.claude/skills/redis-coordination/orchestrate-cfn-loop.sh.backup-1760949407 +933 -0
- package/.claude/skills/redis-coordination/store-epic-context.sh +123 -0
- package/.claude/skills/redis-coordination/test-iteration-feedback.sh +320 -0
- package/.claude/skills/skill-builder/SKILL.md +910 -0
- package/CLAUDE.md +76 -2
- package/dist/cli/agent-command.js +151 -0
- package/dist/cli/agent-command.js.map +1 -0
- package/dist/cli/agent-definition-parser.js +176 -0
- package/dist/cli/agent-definition-parser.js.map +1 -0
- package/dist/cli/agent-executor.js +176 -0
- package/dist/cli/agent-executor.js.map +1 -0
- package/dist/cli/agent-prompt-builder.js +188 -0
- package/dist/cli/agent-prompt-builder.js.map +1 -0
- package/dist/cli/agent-spawn.js +46 -1
- package/dist/cli/agent-spawn.js.map +1 -1
- package/dist/cli/anthropic-client.js +242 -0
- package/dist/cli/anthropic-client.js.map +1 -0
- package/dist/cli/cli-agent-context.js +353 -0
- package/dist/cli/cli-agent-context.js.map +1 -0
- package/dist/cli/cli-agent-context.test.js +451 -0
- package/dist/cli/cli-agent-context.test.js.map +1 -0
- package/dist/cli/index.js +115 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/iteration-history.js +188 -0
- package/dist/cli/iteration-history.js.map +1 -0
- package/package.json +3 -1
- package/scripts/switch-api.sh +233 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cli/agent-executor.ts"],"sourcesContent":["/**\r\n * Agent Executor\r\n *\r\n * Executes CLI-spawned agents by:\r\n * 1. Checking custom routing configuration (z.ai vs Anthropic)\r\n * 2. Invoking the appropriate API\r\n * 3. Managing agent lifecycle and output\r\n */\r\n\r\nimport { spawn } from 'child_process';\r\nimport { AgentDefinition } from './agent-definition-parser.js';\r\nimport { TaskContext, getAgentId } from './agent-prompt-builder.js';\r\nimport { buildCLIAgentSystemPrompt, loadContextFromEnv } from './cli-agent-context.js';\r\nimport fs from 'fs/promises';\r\nimport path from 'path';\r\nimport os from 'os';\r\n\r\nexport interface AgentExecutionResult {\r\n success: boolean;\r\n agentId: string;\r\n output?: string;\r\n error?: string;\r\n exitCode: number;\r\n}\r\n\r\n/**\r\n * Check if custom routing (z.ai) is enabled\r\n */\r\nasync function isCustomRoutingEnabled(): Promise<boolean> {\r\n // Check environment variable\r\n if (process.env.CLAUDE_API_PROVIDER === 'zai') {\r\n return true;\r\n }\r\n\r\n // Check config file (.claude/config/api-provider.json)\r\n try {\r\n const configPath = path.join('.claude', 'config', 'api-provider.json');\r\n const config = JSON.parse(await fs.readFile(configPath, 'utf-8'));\r\n return config.provider === 'zai' || config.provider === 'z.ai';\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Get API provider configuration\r\n */\r\nasync function getAPIProvider(): Promise<'anthropic' | 'zai'> {\r\n const customEnabled = await isCustomRoutingEnabled();\r\n return customEnabled ? 'zai' : 'anthropic';\r\n}\r\n\r\n/**\r\n * Execute agent using direct API calls\r\n */\r\nasync function executeViaAPI(\r\n definition: AgentDefinition,\r\n prompt: string,\r\n context: TaskContext\r\n): Promise<AgentExecutionResult> {\r\n const agentId = getAgentId(definition, context);\r\n\r\n console.log(`[agent-executor] Executing agent via API: ${definition.name}`);\r\n console.log(`[agent-executor] Agent ID: ${agentId}`);\r\n console.log(`[agent-executor] Model: ${definition.model}`);\r\n console.log('');\r\n\r\n try {\r\n // Build system prompt with natural language context (Phase 1 enhancement)\r\n console.log('[agent-executor] Building system prompt with context...');\r\n const contextOptions = loadContextFromEnv();\r\n // Override agent type with definition name\r\n contextOptions.agentType = definition.name;\r\n // Override iteration/taskId if provided in context\r\n if (context.taskId) contextOptions.taskId = context.taskId;\r\n if (context.iteration) contextOptions.iteration = context.iteration;\r\n\r\n const systemPrompt = await buildCLIAgentSystemPrompt(contextOptions);\r\n console.log('[agent-executor] System prompt built successfully');\r\n console.log('');\r\n\r\n // Dynamic import to avoid bundling issues\r\n const { executeAgentAPI } = await import('./anthropic-client.js');\r\n\r\n const result = await executeAgentAPI(\r\n definition.name,\r\n agentId,\r\n definition.model,\r\n prompt,\r\n systemPrompt\r\n );\r\n\r\n return {\r\n success: result.success,\r\n agentId,\r\n output: result.output,\r\n error: result.error,\r\n exitCode: result.success ? 0 : 1,\r\n };\r\n } catch (error) {\r\n console.error('[agent-executor] API execution failed:', error);\r\n return {\r\n success: false,\r\n agentId,\r\n error: error instanceof Error ? error.message : String(error),\r\n exitCode: 1,\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Execute agent using shell script (fallback/simulation)\r\n */\r\nasync function executeViaScript(\r\n definition: AgentDefinition,\r\n prompt: string,\r\n context: TaskContext\r\n): Promise<AgentExecutionResult> {\r\n const agentId = getAgentId(definition, context);\r\n\r\n // Write prompt to temporary file\r\n const tmpDir = os.tmpdir();\r\n const promptFile = path.join(tmpDir, `agent-${agentId}-${Date.now()}.md`);\r\n await fs.writeFile(promptFile, prompt, 'utf-8');\r\n\r\n console.log(`[agent-executor] Executing agent via script: ${definition.name}`);\r\n console.log(`[agent-executor] Agent ID: ${agentId}`);\r\n console.log(`[agent-executor] Model: ${definition.model}`);\r\n console.log(`[agent-executor] Prompt file: ${promptFile}`);\r\n\r\n return new Promise((resolve) => {\r\n const scriptPath = path.join('.claude', 'skills', 'agent-execution', 'execute-agent.sh');\r\n\r\n // Build environment variables\r\n const env = {\r\n ...process.env,\r\n AGENT_TYPE: definition.name,\r\n AGENT_ID: agentId,\r\n AGENT_MODEL: definition.model,\r\n AGENT_TOOLS: definition.tools.join(','),\r\n TASK_ID: context.taskId || '',\r\n ITERATION: String(context.iteration || 1),\r\n MODE: context.mode || 'cli',\r\n PROMPT_FILE: promptFile,\r\n };\r\n\r\n // Check if execute script exists\r\n fs.access(scriptPath)\r\n .then(() => {\r\n // Use execution script\r\n const proc = spawn('bash', [scriptPath], { env, stdio: 'inherit' });\r\n\r\n proc.on('exit', (code) => {\r\n resolve({\r\n success: code === 0,\r\n agentId,\r\n exitCode: code || 0,\r\n });\r\n });\r\n\r\n proc.on('error', (err) => {\r\n resolve({\r\n success: false,\r\n agentId,\r\n error: err.message,\r\n exitCode: 1,\r\n });\r\n });\r\n })\r\n .catch(() => {\r\n // Fallback: Print prompt\r\n console.log('\\n=== Agent Prompt ===');\r\n console.log(prompt.substring(0, 500) + '...');\r\n console.log('\\n[agent-executor] Execution script not found');\r\n console.log('[agent-executor] Using simulation mode\\n');\r\n\r\n resolve({\r\n success: true,\r\n agentId,\r\n output: prompt,\r\n exitCode: 0,\r\n });\r\n });\r\n });\r\n}\r\n\r\n/**\r\n * Main agent execution function\r\n */\r\nexport async function executeAgent(\r\n definition: AgentDefinition,\r\n prompt: string,\r\n context: TaskContext,\r\n options: {\r\n method?: 'auto' | 'api' | 'script';\r\n } = {}\r\n): Promise<AgentExecutionResult> {\r\n const method = options.method || 'auto';\r\n\r\n // Auto-select execution method\r\n if (method === 'auto') {\r\n // Try API execution first, fallback to script if API key not available\r\n try {\r\n return await executeViaAPI(definition, prompt, context);\r\n } catch (error) {\r\n if (error instanceof Error && error.message.includes('API key not found')) {\r\n console.log('[agent-executor] API key not found, using script fallback');\r\n return executeViaScript(definition, prompt, context);\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n if (method === 'api') {\r\n return executeViaAPI(definition, prompt, context);\r\n }\r\n\r\n return executeViaScript(definition, prompt, context);\r\n}\r\n\r\n/**\r\n * Write agent output to file for debugging\r\n */\r\nexport async function saveAgentOutput(\r\n agentId: string,\r\n output: string,\r\n outputDir: string = '.claude/tmp/agent-output'\r\n): Promise<string> {\r\n await fs.mkdir(outputDir, { recursive: true });\r\n\r\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\r\n const filename = `${agentId}-${timestamp}.txt`;\r\n const filepath = path.join(outputDir, filename);\r\n\r\n await fs.writeFile(filepath, output, 'utf-8');\r\n\r\n return filepath;\r\n}\r\n"],"names":["spawn","getAgentId","buildCLIAgentSystemPrompt","loadContextFromEnv","fs","path","os","isCustomRoutingEnabled","process","env","CLAUDE_API_PROVIDER","configPath","join","config","JSON","parse","readFile","provider","getAPIProvider","customEnabled","executeViaAPI","definition","prompt","context","agentId","console","log","name","model","contextOptions","agentType","taskId","iteration","systemPrompt","executeAgentAPI","result","success","output","error","exitCode","Error","message","String","executeViaScript","tmpDir","tmpdir","promptFile","Date","now","writeFile","Promise","resolve","scriptPath","AGENT_TYPE","AGENT_ID","AGENT_MODEL","AGENT_TOOLS","tools","TASK_ID","ITERATION","MODE","mode","PROMPT_FILE","access","then","proc","stdio","on","code","err","catch","substring","executeAgent","options","method","includes","saveAgentOutput","outputDir","mkdir","recursive","timestamp","toISOString","replace","filename","filepath"],"mappings":"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"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Prompt Builder
|
|
3
|
+
*
|
|
4
|
+
* Builds comprehensive prompts for CLI-spawned agents by combining:
|
|
5
|
+
* - Agent definition (YAML + markdown)
|
|
6
|
+
* - Task context (taskId, iteration, mode)
|
|
7
|
+
* - CFN Loop protocol (if applicable)
|
|
8
|
+
* - Iteration history (Sprint 3 - Phase 2)
|
|
9
|
+
* - Environment variables
|
|
10
|
+
*/ import { hasCFNLoopProtocol } from './agent-definition-parser.js';
|
|
11
|
+
import { loadIterationHistory, formatIterationHistory } from './iteration-history.js';
|
|
12
|
+
/**
|
|
13
|
+
* Build CFN Loop protocol instructions
|
|
14
|
+
*/ function buildCFNLoopProtocol(taskId, agentId) {
|
|
15
|
+
return `
|
|
16
|
+
## CFN Loop Redis Completion Protocol
|
|
17
|
+
|
|
18
|
+
You are participating in a CFN Loop workflow. Follow this protocol EXACTLY:
|
|
19
|
+
|
|
20
|
+
### Step 1: Complete Work
|
|
21
|
+
Execute your assigned task (implementation, review, testing, etc.)
|
|
22
|
+
|
|
23
|
+
### Step 2: Signal Completion
|
|
24
|
+
\`\`\`bash
|
|
25
|
+
redis-cli lpush "swarm:${taskId}:\${AGENT_ID}:done" "complete"
|
|
26
|
+
\`\`\`
|
|
27
|
+
|
|
28
|
+
### Step 3: Report Confidence Score
|
|
29
|
+
\`\`\`bash
|
|
30
|
+
./.claude/skills/redis-coordination/invoke-waiting-mode.sh report \\
|
|
31
|
+
--task-id "${taskId}" \\
|
|
32
|
+
--agent-id "\${AGENT_ID}" \\
|
|
33
|
+
--confidence [0.0-1.0] \\
|
|
34
|
+
--iteration ${taskId.includes('iteration') ? 'CURRENT_ITERATION' : '1'}
|
|
35
|
+
\`\`\`
|
|
36
|
+
|
|
37
|
+
### Step 4: Enter Waiting Mode (for potential iteration)
|
|
38
|
+
\`\`\`bash
|
|
39
|
+
./.claude/skills/redis-coordination/invoke-waiting-mode.sh enter \\
|
|
40
|
+
--task-id "${taskId}" \\
|
|
41
|
+
--agent-id "\${AGENT_ID}" \\
|
|
42
|
+
--context "iteration-complete"
|
|
43
|
+
\`\`\`
|
|
44
|
+
|
|
45
|
+
**Critical Context Variables:**
|
|
46
|
+
- TASK_ID: ${taskId}
|
|
47
|
+
- AGENT_ID: ${agentId} (your unique identifier)
|
|
48
|
+
- Confidence: Your self-assessment score (0.0-1.0)
|
|
49
|
+
|
|
50
|
+
**Why This Matters:**
|
|
51
|
+
- Zero-token blocking coordination (BLPOP waits without API calls)
|
|
52
|
+
- Orchestrator collects confidence/consensus scores automatically
|
|
53
|
+
- Supports autonomous iteration based on quality gates
|
|
54
|
+
- Agent woken instantly (<100ms) if iteration needed
|
|
55
|
+
|
|
56
|
+
**IMPORTANT:** You MUST complete all 4 steps in order. The orchestrator is waiting for your completion signal.
|
|
57
|
+
`;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Build task description from context
|
|
61
|
+
*/ function buildTaskDescription(agentType, context) {
|
|
62
|
+
let desc = '';
|
|
63
|
+
if (context.context) {
|
|
64
|
+
desc = context.context;
|
|
65
|
+
} else {
|
|
66
|
+
desc = `Execute task as ${agentType} agent`;
|
|
67
|
+
}
|
|
68
|
+
if (context.taskId) {
|
|
69
|
+
desc += `\n\n**Task ID:** ${context.taskId}`;
|
|
70
|
+
}
|
|
71
|
+
if (context.iteration) {
|
|
72
|
+
desc += `\n**Iteration:** ${context.iteration}`;
|
|
73
|
+
}
|
|
74
|
+
if (context.mode) {
|
|
75
|
+
desc += `\n**Mode:** ${context.mode}`;
|
|
76
|
+
}
|
|
77
|
+
if (context.priority) {
|
|
78
|
+
desc += `\n**Priority:** ${context.priority}`;
|
|
79
|
+
}
|
|
80
|
+
if (context.parentTaskId) {
|
|
81
|
+
desc += `\n**Parent Task:** ${context.parentTaskId}`;
|
|
82
|
+
}
|
|
83
|
+
return desc;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Build environment context section
|
|
87
|
+
*/ function buildEnvironmentContext(context) {
|
|
88
|
+
const env = [];
|
|
89
|
+
if (context.taskId) env.push(`TASK_ID=${context.taskId}`);
|
|
90
|
+
if (context.iteration) env.push(`ITERATION=${context.iteration}`);
|
|
91
|
+
if (context.mode) env.push(`MODE=${context.mode}`);
|
|
92
|
+
if (context.priority) env.push(`PRIORITY=${context.priority}`);
|
|
93
|
+
if (context.parentTaskId) env.push(`PARENT_TASK_ID=${context.parentTaskId}`);
|
|
94
|
+
if (env.length === 0) return '';
|
|
95
|
+
return `
|
|
96
|
+
## Environment Variables
|
|
97
|
+
|
|
98
|
+
\`\`\`bash
|
|
99
|
+
${env.join('\n')}
|
|
100
|
+
\`\`\`
|
|
101
|
+
`;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Build complete prompt for agent execution (async for iteration history)
|
|
105
|
+
*/ export async function buildAgentPrompt(definition, context) {
|
|
106
|
+
const agentId = `${definition.name}-${context.iteration || 1}`;
|
|
107
|
+
const sections = [];
|
|
108
|
+
// 1. Agent definition header
|
|
109
|
+
sections.push(`# Agent: ${definition.name}`);
|
|
110
|
+
sections.push('');
|
|
111
|
+
sections.push(definition.description);
|
|
112
|
+
sections.push('');
|
|
113
|
+
// 2. Task description
|
|
114
|
+
sections.push('## Task');
|
|
115
|
+
sections.push('');
|
|
116
|
+
sections.push(buildTaskDescription(definition.name, context));
|
|
117
|
+
sections.push('');
|
|
118
|
+
// 3. Iteration history (Sprint 3 - Phase 2)
|
|
119
|
+
// Load and format previous iterations if iteration > 1
|
|
120
|
+
if (context.taskId && context.iteration && context.iteration > 1) {
|
|
121
|
+
try {
|
|
122
|
+
const history = await loadIterationHistory(context.taskId, agentId, context.iteration);
|
|
123
|
+
const historyText = formatIterationHistory(history, context.iteration);
|
|
124
|
+
sections.push(historyText);
|
|
125
|
+
sections.push('');
|
|
126
|
+
} catch (err) {
|
|
127
|
+
console.warn(`[agent-prompt-builder] Failed to load iteration history:`, err);
|
|
128
|
+
// Continue without history
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// 4. Agent definition content (from markdown file)
|
|
132
|
+
sections.push('## Agent Definition');
|
|
133
|
+
sections.push('');
|
|
134
|
+
sections.push(definition.content);
|
|
135
|
+
sections.push('');
|
|
136
|
+
// 5. CFN Loop protocol (if agent supports it AND task context includes taskId)
|
|
137
|
+
if (context.taskId && hasCFNLoopProtocol(definition)) {
|
|
138
|
+
sections.push(buildCFNLoopProtocol(context.taskId, agentId));
|
|
139
|
+
sections.push('');
|
|
140
|
+
}
|
|
141
|
+
// 6. Environment context
|
|
142
|
+
const envContext = buildEnvironmentContext(context);
|
|
143
|
+
if (envContext) {
|
|
144
|
+
sections.push(envContext);
|
|
145
|
+
sections.push('');
|
|
146
|
+
}
|
|
147
|
+
// 7. Execution instructions
|
|
148
|
+
sections.push('## Execution Instructions');
|
|
149
|
+
sections.push('');
|
|
150
|
+
sections.push('1. Read and understand the task requirements');
|
|
151
|
+
if (context.iteration && context.iteration > 1) {
|
|
152
|
+
sections.push('2. Review iteration history and feedback from validators');
|
|
153
|
+
sections.push('3. Address specific feedback points from previous iteration');
|
|
154
|
+
sections.push('4. Execute your core responsibilities as defined above');
|
|
155
|
+
} else {
|
|
156
|
+
sections.push('2. Execute your core responsibilities as defined above');
|
|
157
|
+
sections.push('3. Follow any protocol steps (CFN Loop, validation hooks, etc.)');
|
|
158
|
+
}
|
|
159
|
+
sections.push('4. Provide clear, concise output');
|
|
160
|
+
sections.push('5. Report confidence score if applicable');
|
|
161
|
+
sections.push('');
|
|
162
|
+
// 8. Tool reminder
|
|
163
|
+
if (definition.tools && definition.tools.length > 0) {
|
|
164
|
+
sections.push('## Available Tools');
|
|
165
|
+
sections.push('');
|
|
166
|
+
sections.push(`You have access to: ${definition.tools.join(', ')}`);
|
|
167
|
+
sections.push('');
|
|
168
|
+
}
|
|
169
|
+
return sections.join('\n');
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Extract agent ID from context
|
|
173
|
+
*/ export function getAgentId(definition, context) {
|
|
174
|
+
return `${definition.name}-${context.iteration || 1}`;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Build system prompt for agent (optional, for structured agent behavior)
|
|
178
|
+
*/ export function buildSystemPrompt(definition) {
|
|
179
|
+
return `You are ${definition.name}, a specialized AI agent.
|
|
180
|
+
|
|
181
|
+
Type: ${definition.type || 'specialist'}
|
|
182
|
+
Model: ${definition.model}
|
|
183
|
+
Tools: ${definition.tools.join(', ')}
|
|
184
|
+
|
|
185
|
+
Follow your agent definition exactly and complete assigned tasks with high quality.`;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
//# sourceMappingURL=agent-prompt-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cli/agent-prompt-builder.ts"],"sourcesContent":["/**\r\n * Agent Prompt Builder\r\n *\r\n * Builds comprehensive prompts for CLI-spawned agents by combining:\r\n * - Agent definition (YAML + markdown)\r\n * - Task context (taskId, iteration, mode)\r\n * - CFN Loop protocol (if applicable)\r\n * - Iteration history (Sprint 3 - Phase 2)\r\n * - Environment variables\r\n */\r\n\r\nimport { AgentDefinition, hasCFNLoopProtocol } from './agent-definition-parser.js';\r\nimport { loadIterationHistory, formatIterationHistory } from './iteration-history.js';\r\n\r\nexport interface TaskContext {\r\n taskId?: string;\r\n iteration?: number;\r\n context?: string;\r\n mode?: string;\r\n priority?: number;\r\n parentTaskId?: string;\r\n}\r\n\r\n/**\r\n * Build CFN Loop protocol instructions\r\n */\r\nfunction buildCFNLoopProtocol(taskId: string, agentId: string): string {\r\n return `\r\n## CFN Loop Redis Completion Protocol\r\n\r\nYou are participating in a CFN Loop workflow. Follow this protocol EXACTLY:\r\n\r\n### Step 1: Complete Work\r\nExecute your assigned task (implementation, review, testing, etc.)\r\n\r\n### Step 2: Signal Completion\r\n\\`\\`\\`bash\r\nredis-cli lpush \"swarm:${taskId}:\\${AGENT_ID}:done\" \"complete\"\r\n\\`\\`\\`\r\n\r\n### Step 3: Report Confidence Score\r\n\\`\\`\\`bash\r\n./.claude/skills/redis-coordination/invoke-waiting-mode.sh report \\\\\r\n --task-id \"${taskId}\" \\\\\r\n --agent-id \"\\${AGENT_ID}\" \\\\\r\n --confidence [0.0-1.0] \\\\\r\n --iteration ${taskId.includes('iteration') ? 'CURRENT_ITERATION' : '1'}\r\n\\`\\`\\`\r\n\r\n### Step 4: Enter Waiting Mode (for potential iteration)\r\n\\`\\`\\`bash\r\n./.claude/skills/redis-coordination/invoke-waiting-mode.sh enter \\\\\r\n --task-id \"${taskId}\" \\\\\r\n --agent-id \"\\${AGENT_ID}\" \\\\\r\n --context \"iteration-complete\"\r\n\\`\\`\\`\r\n\r\n**Critical Context Variables:**\r\n- TASK_ID: ${taskId}\r\n- AGENT_ID: ${agentId} (your unique identifier)\r\n- Confidence: Your self-assessment score (0.0-1.0)\r\n\r\n**Why This Matters:**\r\n- Zero-token blocking coordination (BLPOP waits without API calls)\r\n- Orchestrator collects confidence/consensus scores automatically\r\n- Supports autonomous iteration based on quality gates\r\n- Agent woken instantly (<100ms) if iteration needed\r\n\r\n**IMPORTANT:** You MUST complete all 4 steps in order. The orchestrator is waiting for your completion signal.\r\n`;\r\n}\r\n\r\n/**\r\n * Build task description from context\r\n */\r\nfunction buildTaskDescription(agentType: string, context: TaskContext): string {\r\n let desc = '';\r\n\r\n if (context.context) {\r\n desc = context.context;\r\n } else {\r\n desc = `Execute task as ${agentType} agent`;\r\n }\r\n\r\n if (context.taskId) {\r\n desc += `\\n\\n**Task ID:** ${context.taskId}`;\r\n }\r\n\r\n if (context.iteration) {\r\n desc += `\\n**Iteration:** ${context.iteration}`;\r\n }\r\n\r\n if (context.mode) {\r\n desc += `\\n**Mode:** ${context.mode}`;\r\n }\r\n\r\n if (context.priority) {\r\n desc += `\\n**Priority:** ${context.priority}`;\r\n }\r\n\r\n if (context.parentTaskId) {\r\n desc += `\\n**Parent Task:** ${context.parentTaskId}`;\r\n }\r\n\r\n return desc;\r\n}\r\n\r\n/**\r\n * Build environment context section\r\n */\r\nfunction buildEnvironmentContext(context: TaskContext): string {\r\n const env: string[] = [];\r\n\r\n if (context.taskId) env.push(`TASK_ID=${context.taskId}`);\r\n if (context.iteration) env.push(`ITERATION=${context.iteration}`);\r\n if (context.mode) env.push(`MODE=${context.mode}`);\r\n if (context.priority) env.push(`PRIORITY=${context.priority}`);\r\n if (context.parentTaskId) env.push(`PARENT_TASK_ID=${context.parentTaskId}`);\r\n\r\n if (env.length === 0) return '';\r\n\r\n return `\r\n## Environment Variables\r\n\r\n\\`\\`\\`bash\r\n${env.join('\\n')}\r\n\\`\\`\\`\r\n`;\r\n}\r\n\r\n/**\r\n * Build complete prompt for agent execution (async for iteration history)\r\n */\r\nexport async function buildAgentPrompt(\r\n definition: AgentDefinition,\r\n context: TaskContext\r\n): Promise<string> {\r\n const agentId = `${definition.name}-${context.iteration || 1}`;\r\n\r\n const sections: string[] = [];\r\n\r\n // 1. Agent definition header\r\n sections.push(`# Agent: ${definition.name}`);\r\n sections.push('');\r\n sections.push(definition.description);\r\n sections.push('');\r\n\r\n // 2. Task description\r\n sections.push('## Task');\r\n sections.push('');\r\n sections.push(buildTaskDescription(definition.name, context));\r\n sections.push('');\r\n\r\n // 3. Iteration history (Sprint 3 - Phase 2)\r\n // Load and format previous iterations if iteration > 1\r\n if (context.taskId && context.iteration && context.iteration > 1) {\r\n try {\r\n const history = await loadIterationHistory(context.taskId, agentId, context.iteration);\r\n const historyText = formatIterationHistory(history, context.iteration);\r\n sections.push(historyText);\r\n sections.push('');\r\n } catch (err) {\r\n console.warn(`[agent-prompt-builder] Failed to load iteration history:`, err);\r\n // Continue without history\r\n }\r\n }\r\n\r\n // 4. Agent definition content (from markdown file)\r\n sections.push('## Agent Definition');\r\n sections.push('');\r\n sections.push(definition.content);\r\n sections.push('');\r\n\r\n // 5. CFN Loop protocol (if agent supports it AND task context includes taskId)\r\n if (context.taskId && hasCFNLoopProtocol(definition)) {\r\n sections.push(buildCFNLoopProtocol(context.taskId, agentId));\r\n sections.push('');\r\n }\r\n\r\n // 6. Environment context\r\n const envContext = buildEnvironmentContext(context);\r\n if (envContext) {\r\n sections.push(envContext);\r\n sections.push('');\r\n }\r\n\r\n // 7. Execution instructions\r\n sections.push('## Execution Instructions');\r\n sections.push('');\r\n sections.push('1. Read and understand the task requirements');\r\n if (context.iteration && context.iteration > 1) {\r\n sections.push('2. Review iteration history and feedback from validators');\r\n sections.push('3. Address specific feedback points from previous iteration');\r\n sections.push('4. Execute your core responsibilities as defined above');\r\n } else {\r\n sections.push('2. Execute your core responsibilities as defined above');\r\n sections.push('3. Follow any protocol steps (CFN Loop, validation hooks, etc.)');\r\n }\r\n sections.push('4. Provide clear, concise output');\r\n sections.push('5. Report confidence score if applicable');\r\n sections.push('');\r\n\r\n // 8. Tool reminder\r\n if (definition.tools && definition.tools.length > 0) {\r\n sections.push('## Available Tools');\r\n sections.push('');\r\n sections.push(`You have access to: ${definition.tools.join(', ')}`);\r\n sections.push('');\r\n }\r\n\r\n return sections.join('\\n');\r\n}\r\n\r\n/**\r\n * Extract agent ID from context\r\n */\r\nexport function getAgentId(definition: AgentDefinition, context: TaskContext): string {\r\n return `${definition.name}-${context.iteration || 1}`;\r\n}\r\n\r\n/**\r\n * Build system prompt for agent (optional, for structured agent behavior)\r\n */\r\nexport function buildSystemPrompt(definition: AgentDefinition): string {\r\n return `You are ${definition.name}, a specialized AI agent.\r\n\r\nType: ${definition.type || 'specialist'}\r\nModel: ${definition.model}\r\nTools: ${definition.tools.join(', ')}\r\n\r\nFollow your agent definition exactly and complete assigned tasks with high quality.`;\r\n}\r\n"],"names":["hasCFNLoopProtocol","loadIterationHistory","formatIterationHistory","buildCFNLoopProtocol","taskId","agentId","includes","buildTaskDescription","agentType","context","desc","iteration","mode","priority","parentTaskId","buildEnvironmentContext","env","push","length","join","buildAgentPrompt","definition","name","sections","description","history","historyText","err","console","warn","content","envContext","tools","getAgentId","buildSystemPrompt","type","model"],"mappings":"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"}
|
package/dist/cli/agent-spawn.js
CHANGED
|
@@ -98,6 +98,47 @@
|
|
|
98
98
|
if (parentTaskId) {
|
|
99
99
|
claudeArgs.push('--parent-task-id', parentTaskId);
|
|
100
100
|
}
|
|
101
|
+
// Fetch epic context from Redis if available
|
|
102
|
+
let epicContext = '';
|
|
103
|
+
let phaseContext = '';
|
|
104
|
+
let successCriteria = '';
|
|
105
|
+
if (taskId) {
|
|
106
|
+
try {
|
|
107
|
+
const { execSync } = await import('child_process');
|
|
108
|
+
// Try to read epic-level context from Redis
|
|
109
|
+
try {
|
|
110
|
+
epicContext = execSync(`redis-cli get "swarm:${taskId}:epic-context"`, {
|
|
111
|
+
encoding: 'utf8'
|
|
112
|
+
}).trim();
|
|
113
|
+
if (epicContext === '(nil)') epicContext = '';
|
|
114
|
+
} catch (e) {
|
|
115
|
+
// Redis not available or key doesn't exist
|
|
116
|
+
}
|
|
117
|
+
// Try to read phase-specific context
|
|
118
|
+
try {
|
|
119
|
+
phaseContext = execSync(`redis-cli get "swarm:${taskId}:phase-context"`, {
|
|
120
|
+
encoding: 'utf8'
|
|
121
|
+
}).trim();
|
|
122
|
+
if (phaseContext === '(nil)') phaseContext = '';
|
|
123
|
+
} catch (e) {
|
|
124
|
+
// Redis not available or key doesn't exist
|
|
125
|
+
}
|
|
126
|
+
// Try to read success criteria
|
|
127
|
+
try {
|
|
128
|
+
successCriteria = execSync(`redis-cli get "swarm:${taskId}:success-criteria"`, {
|
|
129
|
+
encoding: 'utf8'
|
|
130
|
+
}).trim();
|
|
131
|
+
if (successCriteria === '(nil)') successCriteria = '';
|
|
132
|
+
} catch (e) {
|
|
133
|
+
// Redis not available or key doesn't exist
|
|
134
|
+
}
|
|
135
|
+
if (epicContext) {
|
|
136
|
+
console.log(`[cfn-spawn] Epic context loaded from Redis`);
|
|
137
|
+
}
|
|
138
|
+
} catch (err) {
|
|
139
|
+
console.warn(`[cfn-spawn] Could not load epic context from Redis:`, err);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
101
142
|
// Add environment variables for agent context
|
|
102
143
|
const env = {
|
|
103
144
|
...process.env,
|
|
@@ -107,7 +148,11 @@
|
|
|
107
148
|
CONTEXT: context || '',
|
|
108
149
|
MODE: mode || 'cli',
|
|
109
150
|
PRIORITY: priority?.toString() || '5',
|
|
110
|
-
PARENT_TASK_ID: parentTaskId || ''
|
|
151
|
+
PARENT_TASK_ID: parentTaskId || '',
|
|
152
|
+
// Epic-level context from Redis
|
|
153
|
+
EPIC_CONTEXT: epicContext,
|
|
154
|
+
PHASE_CONTEXT: phaseContext,
|
|
155
|
+
SUCCESS_CRITERIA: successCriteria
|
|
111
156
|
};
|
|
112
157
|
console.log(`[cfn-spawn] Executing: npx ${claudeArgs.join(' ')}`);
|
|
113
158
|
// Spawn the claude-flow-novice agent process
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/agent-spawn.ts"],"sourcesContent":["#!/usr/bin/env node\r\n/**\r\n * Agent Spawning CLI - Direct agent process spawning\r\n *\r\n * Usage:\r\n * npx cfn-spawn agent <type> [options]\r\n * npx cfn-spawn <type> [options] (agent is implied)\r\n *\r\n * Examples:\r\n * npx cfn-spawn agent researcher --task-id task-123 --iteration 1\r\n * npx cfn-spawn researcher --task-id task-123 --iteration 1\r\n */\r\n\r\nimport { spawn } from 'child_process';\r\nimport { resolve } from 'path';\r\n\r\ninterface AgentSpawnOptions {\r\n agentType: string;\r\n taskId?: string;\r\n iteration?: number;\r\n context?: string;\r\n mode?: string;\r\n priority?: number;\r\n parentTaskId?: string;\r\n}\r\n\r\n/**\r\n * Parse command line arguments for agent spawning\r\n */\r\nfunction parseAgentArgs(args: string[]): AgentSpawnOptions | null {\r\n // Handle both \"agent <type>\" and \"<type>\" patterns\r\n let agentType: string;\r\n let optionArgs: string[];\r\n\r\n if (args[0] === 'agent') {\r\n agentType = args[1];\r\n optionArgs = args.slice(2);\r\n } else {\r\n agentType = args[0];\r\n optionArgs = args.slice(1);\r\n }\r\n\r\n if (!agentType) {\r\n console.error('Error: Agent type is required');\r\n console.error('Usage: cfn-spawn agent <type> [options]');\r\n return null;\r\n }\r\n\r\n const options: AgentSpawnOptions = { agentType };\r\n\r\n // Parse optional parameters\r\n for (let i = 0; i < optionArgs.length; i += 2) {\r\n const key = optionArgs[i];\r\n const value = optionArgs[i + 1];\r\n\r\n switch (key) {\r\n case '--task-id':\r\n options.taskId = value;\r\n break;\r\n case '--iteration':\r\n options.iteration = parseInt(value, 10);\r\n break;\r\n case '--context':\r\n options.context = value;\r\n break;\r\n case '--mode':\r\n options.mode = value;\r\n break;\r\n case '--priority':\r\n options.priority = parseInt(value, 10);\r\n break;\r\n case '--parent-task':\r\n case '--parent-task-id':\r\n options.parentTaskId = value;\r\n break;\r\n default:\r\n console.warn(`Unknown option: ${key}`);\r\n }\r\n }\r\n\r\n return options;\r\n}\r\n\r\n/**\r\n * Spawn an agent process using npx claude-flow-novice agent\r\n *\r\n * This is a wrapper/alias for the existing claude-flow-novice agent spawning mechanism\r\n * Provides the cfn-spawn naming pattern while delegating to the working implementation\r\n */\r\nasync function spawnAgent(options: AgentSpawnOptions): Promise<void> {\r\n const { agentType, taskId, iteration, context, mode, priority, parentTaskId } = options;\r\n\r\n console.log(`[cfn-spawn] Spawning agent: ${agentType}`);\r\n if (taskId) console.log(`[cfn-spawn] Task ID: ${taskId}`);\r\n if (iteration) console.log(`[cfn-spawn] Iteration: ${iteration}`);\r\n if (context) console.log(`[cfn-spawn] Context: ${context}`);\r\n if (mode) console.log(`[cfn-spawn] Mode: ${mode}`);\r\n\r\n // Build command arguments for npx claude-flow-novice agent\r\n const claudeArgs = ['claude-flow-novice', 'agent', agentType];\r\n\r\n // Add optional parameters\r\n if (taskId) {\r\n claudeArgs.push('--task-id', taskId);\r\n }\r\n if (iteration) {\r\n claudeArgs.push('--iteration', iteration.toString());\r\n }\r\n if (context) {\r\n claudeArgs.push('--context', context);\r\n }\r\n if (mode) {\r\n claudeArgs.push('--mode', mode);\r\n }\r\n if (priority) {\r\n claudeArgs.push('--priority', priority.toString());\r\n }\r\n if (parentTaskId) {\r\n claudeArgs.push('--parent-task-id', parentTaskId);\r\n }\r\n\r\n // Add environment variables for agent context\r\n const env = {\r\n ...process.env,\r\n AGENT_TYPE: agentType,\r\n TASK_ID: taskId || '',\r\n ITERATION: iteration?.toString() || '1',\r\n CONTEXT: context || '',\r\n MODE: mode || 'cli',\r\n PRIORITY: priority?.toString() || '5',\r\n PARENT_TASK_ID: parentTaskId || ''\r\n };\r\n\r\n console.log(`[cfn-spawn] Executing: npx ${claudeArgs.join(' ')}`);\r\n\r\n // Spawn the claude-flow-novice agent process\r\n const agentProcess = spawn('npx', claudeArgs, {\r\n stdio: 'inherit',\r\n env,\r\n cwd: process.cwd()\r\n });\r\n\r\n // Handle process exit\r\n agentProcess.on('exit', (code, signal) => {\r\n if (code === 0) {\r\n console.log(`[cfn-spawn] Agent ${agentType} completed successfully`);\r\n } else {\r\n console.error(`[cfn-spawn] Agent ${agentType} exited with code ${code}, signal ${signal}`);\r\n }\r\n process.exit(code || 0);\r\n });\r\n\r\n // Handle process errors\r\n agentProcess.on('error', (err) => {\r\n console.error(`[cfn-spawn] Failed to spawn agent ${agentType}:`, err.message);\r\n process.exit(1);\r\n });\r\n\r\n // Cleanup on parent exit\r\n process.on('SIGINT', () => {\r\n console.log('\\n[cfn-spawn] Received SIGINT, terminating agent...');\r\n agentProcess.kill('SIGINT');\r\n });\r\n\r\n process.on('SIGTERM', () => {\r\n console.log('\\n[cfn-spawn] Received SIGTERM, terminating agent...');\r\n agentProcess.kill('SIGTERM');\r\n });\r\n}\r\n\r\n/**\r\n * Build task description for the agent\r\n */\r\nfunction buildTaskDescription(\r\n agentType: string,\r\n taskId?: string,\r\n iteration?: number,\r\n context?: string\r\n): string {\r\n let desc = `Execute task as ${agentType} agent`;\r\n\r\n if (taskId) desc += ` for task ${taskId}`;\r\n if (iteration) desc += ` (iteration ${iteration})`;\r\n if (context) desc += `: ${context}`;\r\n\r\n return desc;\r\n}\r\n\r\n/**\r\n * Main CLI entry point\r\n */\r\nexport async function main(args: string[] = process.argv.slice(2)): Promise<void> {\r\n // Show help if requested\r\n if (args.includes('--help') || args.includes('-h')) {\r\n console.log(`\r\ncfn-spawn - Claude Flow Novice Agent Spawner\r\n\r\nUsage:\r\n cfn-spawn agent <type> [options]\r\n cfn-spawn <type> [options] (agent is implied)\r\n\r\nOptions:\r\n --task-id <id> Task identifier\r\n --iteration <n> Iteration number\r\n --context <text> Context description\r\n --mode <mode> Execution mode (cli, api, hybrid)\r\n --priority <1-10> Task priority\r\n --parent-task-id <id> Parent task identifier\r\n\r\nExamples:\r\n cfn-spawn agent researcher --task-id task-123 --iteration 1\r\n cfn-spawn coder --task-id auth-impl --context \"Implement JWT auth\"\r\n cfn-spawn reviewer --task-id auth-impl --iteration 2 --mode cli\r\n `);\r\n return;\r\n }\r\n\r\n // Parse arguments\r\n const options = parseAgentArgs(args);\r\n if (!options) {\r\n process.exit(1);\r\n }\r\n\r\n // Spawn the agent\r\n await spawnAgent(options);\r\n}\r\n\r\n// Run if called directly\r\n// ES module check - compare import.meta.url with the executed file\r\nconst isMainModule = import.meta.url.endsWith(process.argv[1]?.replace(/\\\\/g, '/') || '');\r\nif (isMainModule) {\r\n main().catch((err) => {\r\n console.error('[cfn-spawn] Fatal error:', err);\r\n process.exit(1);\r\n });\r\n}\r\n"],"names":["spawn","parseAgentArgs","args","agentType","optionArgs","slice","console","error","options","i","length","key","value","taskId","iteration","parseInt","context","mode","priority","parentTaskId","warn","spawnAgent","log","claudeArgs","push","toString","env","process","AGENT_TYPE","TASK_ID","ITERATION","CONTEXT","MODE","PRIORITY","PARENT_TASK_ID","join","agentProcess","stdio","cwd","on","code","signal","exit","err","message","kill","buildTaskDescription","desc","main","argv","includes","isMainModule","url","endsWith","replace","catch"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/agent-spawn.ts"],"sourcesContent":["#!/usr/bin/env node\r\n/**\r\n * Agent Spawning CLI - Direct agent process spawning\r\n *\r\n * Usage:\r\n * npx cfn-spawn agent <type> [options]\r\n * npx cfn-spawn <type> [options] (agent is implied)\r\n *\r\n * Examples:\r\n * npx cfn-spawn agent researcher --task-id task-123 --iteration 1\r\n * npx cfn-spawn researcher --task-id task-123 --iteration 1\r\n */\r\n\r\nimport { spawn } from 'child_process';\r\nimport { resolve } from 'path';\r\n\r\ninterface AgentSpawnOptions {\r\n agentType: string;\r\n taskId?: string;\r\n iteration?: number;\r\n context?: string;\r\n mode?: string;\r\n priority?: number;\r\n parentTaskId?: string;\r\n}\r\n\r\n/**\r\n * Parse command line arguments for agent spawning\r\n */\r\nfunction parseAgentArgs(args: string[]): AgentSpawnOptions | null {\r\n // Handle both \"agent <type>\" and \"<type>\" patterns\r\n let agentType: string;\r\n let optionArgs: string[];\r\n\r\n if (args[0] === 'agent') {\r\n agentType = args[1];\r\n optionArgs = args.slice(2);\r\n } else {\r\n agentType = args[0];\r\n optionArgs = args.slice(1);\r\n }\r\n\r\n if (!agentType) {\r\n console.error('Error: Agent type is required');\r\n console.error('Usage: cfn-spawn agent <type> [options]');\r\n return null;\r\n }\r\n\r\n const options: AgentSpawnOptions = { agentType };\r\n\r\n // Parse optional parameters\r\n for (let i = 0; i < optionArgs.length; i += 2) {\r\n const key = optionArgs[i];\r\n const value = optionArgs[i + 1];\r\n\r\n switch (key) {\r\n case '--task-id':\r\n options.taskId = value;\r\n break;\r\n case '--iteration':\r\n options.iteration = parseInt(value, 10);\r\n break;\r\n case '--context':\r\n options.context = value;\r\n break;\r\n case '--mode':\r\n options.mode = value;\r\n break;\r\n case '--priority':\r\n options.priority = parseInt(value, 10);\r\n break;\r\n case '--parent-task':\r\n case '--parent-task-id':\r\n options.parentTaskId = value;\r\n break;\r\n default:\r\n console.warn(`Unknown option: ${key}`);\r\n }\r\n }\r\n\r\n return options;\r\n}\r\n\r\n/**\r\n * Spawn an agent process using npx claude-flow-novice agent\r\n *\r\n * This is a wrapper/alias for the existing claude-flow-novice agent spawning mechanism\r\n * Provides the cfn-spawn naming pattern while delegating to the working implementation\r\n */\r\nasync function spawnAgent(options: AgentSpawnOptions): Promise<void> {\r\n const { agentType, taskId, iteration, context, mode, priority, parentTaskId } = options;\r\n\r\n console.log(`[cfn-spawn] Spawning agent: ${agentType}`);\r\n if (taskId) console.log(`[cfn-spawn] Task ID: ${taskId}`);\r\n if (iteration) console.log(`[cfn-spawn] Iteration: ${iteration}`);\r\n if (context) console.log(`[cfn-spawn] Context: ${context}`);\r\n if (mode) console.log(`[cfn-spawn] Mode: ${mode}`);\r\n\r\n // Build command arguments for npx claude-flow-novice agent\r\n const claudeArgs = ['claude-flow-novice', 'agent', agentType];\r\n\r\n // Add optional parameters\r\n if (taskId) {\r\n claudeArgs.push('--task-id', taskId);\r\n }\r\n if (iteration) {\r\n claudeArgs.push('--iteration', iteration.toString());\r\n }\r\n if (context) {\r\n claudeArgs.push('--context', context);\r\n }\r\n if (mode) {\r\n claudeArgs.push('--mode', mode);\r\n }\r\n if (priority) {\r\n claudeArgs.push('--priority', priority.toString());\r\n }\r\n if (parentTaskId) {\r\n claudeArgs.push('--parent-task-id', parentTaskId);\r\n }\r\n\r\n // Fetch epic context from Redis if available\r\n let epicContext = '';\r\n let phaseContext = '';\r\n let successCriteria = '';\r\n\r\n if (taskId) {\r\n try {\r\n const { execSync } = await import('child_process');\r\n\r\n // Try to read epic-level context from Redis\r\n try {\r\n epicContext = execSync(`redis-cli get \"swarm:${taskId}:epic-context\"`, { encoding: 'utf8' }).trim();\r\n if (epicContext === '(nil)') epicContext = '';\r\n } catch (e) {\r\n // Redis not available or key doesn't exist\r\n }\r\n\r\n // Try to read phase-specific context\r\n try {\r\n phaseContext = execSync(`redis-cli get \"swarm:${taskId}:phase-context\"`, { encoding: 'utf8' }).trim();\r\n if (phaseContext === '(nil)') phaseContext = '';\r\n } catch (e) {\r\n // Redis not available or key doesn't exist\r\n }\r\n\r\n // Try to read success criteria\r\n try {\r\n successCriteria = execSync(`redis-cli get \"swarm:${taskId}:success-criteria\"`, { encoding: 'utf8' }).trim();\r\n if (successCriteria === '(nil)') successCriteria = '';\r\n } catch (e) {\r\n // Redis not available or key doesn't exist\r\n }\r\n\r\n if (epicContext) {\r\n console.log(`[cfn-spawn] Epic context loaded from Redis`);\r\n }\r\n } catch (err) {\r\n console.warn(`[cfn-spawn] Could not load epic context from Redis:`, err);\r\n }\r\n }\r\n\r\n // Add environment variables for agent context\r\n const env = {\r\n ...process.env,\r\n AGENT_TYPE: agentType,\r\n TASK_ID: taskId || '',\r\n ITERATION: iteration?.toString() || '1',\r\n CONTEXT: context || '',\r\n MODE: mode || 'cli',\r\n PRIORITY: priority?.toString() || '5',\r\n PARENT_TASK_ID: parentTaskId || '',\r\n // Epic-level context from Redis\r\n EPIC_CONTEXT: epicContext,\r\n PHASE_CONTEXT: phaseContext,\r\n SUCCESS_CRITERIA: successCriteria\r\n };\r\n\r\n console.log(`[cfn-spawn] Executing: npx ${claudeArgs.join(' ')}`);\r\n\r\n // Spawn the claude-flow-novice agent process\r\n const agentProcess = spawn('npx', claudeArgs, {\r\n stdio: 'inherit',\r\n env,\r\n cwd: process.cwd()\r\n });\r\n\r\n // Handle process exit\r\n agentProcess.on('exit', (code, signal) => {\r\n if (code === 0) {\r\n console.log(`[cfn-spawn] Agent ${agentType} completed successfully`);\r\n } else {\r\n console.error(`[cfn-spawn] Agent ${agentType} exited with code ${code}, signal ${signal}`);\r\n }\r\n process.exit(code || 0);\r\n });\r\n\r\n // Handle process errors\r\n agentProcess.on('error', (err) => {\r\n console.error(`[cfn-spawn] Failed to spawn agent ${agentType}:`, err.message);\r\n process.exit(1);\r\n });\r\n\r\n // Cleanup on parent exit\r\n process.on('SIGINT', () => {\r\n console.log('\\n[cfn-spawn] Received SIGINT, terminating agent...');\r\n agentProcess.kill('SIGINT');\r\n });\r\n\r\n process.on('SIGTERM', () => {\r\n console.log('\\n[cfn-spawn] Received SIGTERM, terminating agent...');\r\n agentProcess.kill('SIGTERM');\r\n });\r\n}\r\n\r\n/**\r\n * Build task description for the agent\r\n */\r\nfunction buildTaskDescription(\r\n agentType: string,\r\n taskId?: string,\r\n iteration?: number,\r\n context?: string\r\n): string {\r\n let desc = `Execute task as ${agentType} agent`;\r\n\r\n if (taskId) desc += ` for task ${taskId}`;\r\n if (iteration) desc += ` (iteration ${iteration})`;\r\n if (context) desc += `: ${context}`;\r\n\r\n return desc;\r\n}\r\n\r\n/**\r\n * Main CLI entry point\r\n */\r\nexport async function main(args: string[] = process.argv.slice(2)): Promise<void> {\r\n // Show help if requested\r\n if (args.includes('--help') || args.includes('-h')) {\r\n console.log(`\r\ncfn-spawn - Claude Flow Novice Agent Spawner\r\n\r\nUsage:\r\n cfn-spawn agent <type> [options]\r\n cfn-spawn <type> [options] (agent is implied)\r\n\r\nOptions:\r\n --task-id <id> Task identifier\r\n --iteration <n> Iteration number\r\n --context <text> Context description\r\n --mode <mode> Execution mode (cli, api, hybrid)\r\n --priority <1-10> Task priority\r\n --parent-task-id <id> Parent task identifier\r\n\r\nExamples:\r\n cfn-spawn agent researcher --task-id task-123 --iteration 1\r\n cfn-spawn coder --task-id auth-impl --context \"Implement JWT auth\"\r\n cfn-spawn reviewer --task-id auth-impl --iteration 2 --mode cli\r\n `);\r\n return;\r\n }\r\n\r\n // Parse arguments\r\n const options = parseAgentArgs(args);\r\n if (!options) {\r\n process.exit(1);\r\n }\r\n\r\n // Spawn the agent\r\n await spawnAgent(options);\r\n}\r\n\r\n// Run if called directly\r\n// ES module check - compare import.meta.url with the executed file\r\nconst isMainModule = import.meta.url.endsWith(process.argv[1]?.replace(/\\\\/g, '/') || '');\r\nif (isMainModule) {\r\n main().catch((err) => {\r\n console.error('[cfn-spawn] Fatal error:', err);\r\n process.exit(1);\r\n });\r\n}\r\n"],"names":["spawn","parseAgentArgs","args","agentType","optionArgs","slice","console","error","options","i","length","key","value","taskId","iteration","parseInt","context","mode","priority","parentTaskId","warn","spawnAgent","log","claudeArgs","push","toString","epicContext","phaseContext","successCriteria","execSync","encoding","trim","e","err","env","process","AGENT_TYPE","TASK_ID","ITERATION","CONTEXT","MODE","PRIORITY","PARENT_TASK_ID","EPIC_CONTEXT","PHASE_CONTEXT","SUCCESS_CRITERIA","join","agentProcess","stdio","cwd","on","code","signal","exit","message","kill","buildTaskDescription","desc","main","argv","includes","isMainModule","url","endsWith","replace","catch"],"mappings":"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"}
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anthropic API Client
|
|
3
|
+
*
|
|
4
|
+
* Handles communication with Claude API (Anthropic or z.ai provider).
|
|
5
|
+
* Supports streaming responses and tool execution.
|
|
6
|
+
*/ import Anthropic from '@anthropic-ai/sdk';
|
|
7
|
+
import fs from 'fs/promises';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
/**
|
|
10
|
+
* Get API configuration from environment and config files
|
|
11
|
+
*/ export async function getAPIConfig() {
|
|
12
|
+
// Check environment variable
|
|
13
|
+
const envProvider = process.env.CLAUDE_API_PROVIDER;
|
|
14
|
+
if (envProvider === 'zai') {
|
|
15
|
+
return {
|
|
16
|
+
provider: 'zai',
|
|
17
|
+
apiKey: process.env.ZAI_API_KEY || process.env.ANTHROPIC_API_KEY,
|
|
18
|
+
baseURL: process.env.ZAI_BASE_URL || 'https://api.z.ai/api/anthropic'
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
// Check config file
|
|
22
|
+
try {
|
|
23
|
+
const configPath = path.join('.claude', 'config', 'api-provider.json');
|
|
24
|
+
const config = JSON.parse(await fs.readFile(configPath, 'utf-8'));
|
|
25
|
+
if (config.provider === 'zai' || config.provider === 'z.ai') {
|
|
26
|
+
return {
|
|
27
|
+
provider: 'zai',
|
|
28
|
+
apiKey: config.apiKey || process.env.ZAI_API_KEY || process.env.ANTHROPIC_API_KEY,
|
|
29
|
+
baseURL: config.baseURL || process.env.ZAI_BASE_URL || 'https://api.z.ai/api/anthropic'
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
} catch {
|
|
33
|
+
// Config file doesn't exist, use defaults
|
|
34
|
+
}
|
|
35
|
+
// Default to Anthropic
|
|
36
|
+
return {
|
|
37
|
+
provider: 'anthropic',
|
|
38
|
+
apiKey: process.env.ANTHROPIC_API_KEY
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Create Anthropic client with appropriate configuration
|
|
43
|
+
*/ export async function createClient() {
|
|
44
|
+
const config = await getAPIConfig();
|
|
45
|
+
if (!config.apiKey) {
|
|
46
|
+
throw new Error(`API key not found. Set ${config.provider === 'zai' ? 'ZAI_API_KEY' : 'ANTHROPIC_API_KEY'} environment variable.`);
|
|
47
|
+
}
|
|
48
|
+
const clientOptions = {
|
|
49
|
+
apiKey: config.apiKey,
|
|
50
|
+
timeout: 120000,
|
|
51
|
+
maxRetries: 2
|
|
52
|
+
};
|
|
53
|
+
if (config.provider === 'zai' && config.baseURL) {
|
|
54
|
+
clientOptions.baseURL = config.baseURL;
|
|
55
|
+
}
|
|
56
|
+
return new Anthropic(clientOptions);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Map agent model name to API model ID (provider-specific)
|
|
60
|
+
*/ export function mapModelName(agentModel, provider = 'anthropic') {
|
|
61
|
+
// Z.ai uses GLM models - try glm-4.6 first for all models
|
|
62
|
+
if (provider === 'zai') {
|
|
63
|
+
const zaiModelMap = {
|
|
64
|
+
haiku: 'glm-4.6',
|
|
65
|
+
sonnet: 'glm-4.6',
|
|
66
|
+
opus: 'glm-4.6'
|
|
67
|
+
};
|
|
68
|
+
return zaiModelMap[agentModel] || 'glm-4.6';
|
|
69
|
+
}
|
|
70
|
+
// Anthropic uses Claude models
|
|
71
|
+
const modelMap = {
|
|
72
|
+
haiku: 'claude-3-5-haiku-20241022',
|
|
73
|
+
sonnet: 'claude-3-5-sonnet-20241022',
|
|
74
|
+
opus: 'claude-3-opus-20240229'
|
|
75
|
+
};
|
|
76
|
+
return modelMap[agentModel] || modelMap.haiku;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Get fallback model for Z.ai (glm-4.6 -> glm-4.5-air)
|
|
80
|
+
*/ function getFallbackModel(model) {
|
|
81
|
+
if (model === 'glm-4.6') {
|
|
82
|
+
return 'glm-4.5-air';
|
|
83
|
+
}
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Send message to Claude API with streaming support and automatic fallback
|
|
88
|
+
*/ export async function sendMessage(options, onChunk) {
|
|
89
|
+
const client = await createClient();
|
|
90
|
+
const config = await getAPIConfig();
|
|
91
|
+
// Primary model (glm-4.6 for Z.ai, Claude for Anthropic)
|
|
92
|
+
let model = mapModelName(options.model, config.provider);
|
|
93
|
+
const maxTokens = options.maxTokens || 4096;
|
|
94
|
+
const temperature = options.temperature ?? 1.0;
|
|
95
|
+
// Disable streaming for Z.ai (compatibility issue)
|
|
96
|
+
const enableStreaming = options.stream && config.provider !== 'zai';
|
|
97
|
+
console.log(`[anthropic-client] Provider: ${config.provider}`);
|
|
98
|
+
console.log(`[anthropic-client] Model: ${model}`);
|
|
99
|
+
console.log(`[anthropic-client] Max tokens: ${maxTokens}`);
|
|
100
|
+
console.log(`[anthropic-client] Stream: ${enableStreaming ? 'enabled' : 'disabled'}`);
|
|
101
|
+
console.log('');
|
|
102
|
+
const messages = [
|
|
103
|
+
{
|
|
104
|
+
role: 'user',
|
|
105
|
+
content: options.prompt
|
|
106
|
+
}
|
|
107
|
+
];
|
|
108
|
+
// Retry logic: Try primary model (glm-4.6), fall back to glm-4.5 on error
|
|
109
|
+
let lastError = null;
|
|
110
|
+
let attempts = 0;
|
|
111
|
+
const maxAttempts = 2; // Primary + fallback
|
|
112
|
+
while(attempts < maxAttempts){
|
|
113
|
+
const currentModel = attempts === 0 ? model : getFallbackModel(model);
|
|
114
|
+
if (!currentModel) {
|
|
115
|
+
// No fallback available, throw last error
|
|
116
|
+
throw lastError || new Error('No model available');
|
|
117
|
+
}
|
|
118
|
+
attempts++;
|
|
119
|
+
if (attempts > 1) {
|
|
120
|
+
console.log(`[anthropic-client] Retrying with fallback model: ${currentModel}`);
|
|
121
|
+
}
|
|
122
|
+
const requestParams = {
|
|
123
|
+
model: currentModel,
|
|
124
|
+
max_tokens: maxTokens,
|
|
125
|
+
temperature,
|
|
126
|
+
messages
|
|
127
|
+
};
|
|
128
|
+
if (options.systemPrompt) {
|
|
129
|
+
requestParams.system = options.systemPrompt;
|
|
130
|
+
}
|
|
131
|
+
if (options.tools && options.tools.length > 0) {
|
|
132
|
+
requestParams.tools = options.tools;
|
|
133
|
+
}
|
|
134
|
+
try {
|
|
135
|
+
// Streaming response
|
|
136
|
+
if (enableStreaming) {
|
|
137
|
+
let fullContent = '';
|
|
138
|
+
let inputTokens = 0;
|
|
139
|
+
let outputTokens = 0;
|
|
140
|
+
let stopReason = 'end_turn';
|
|
141
|
+
console.log('[anthropic-client] Creating streaming request...');
|
|
142
|
+
const stream = await client.messages.create({
|
|
143
|
+
...requestParams,
|
|
144
|
+
stream: true
|
|
145
|
+
});
|
|
146
|
+
console.log('[anthropic-client] Stream created, processing events...');
|
|
147
|
+
for await (const event of stream){
|
|
148
|
+
console.log('[anthropic-client] Event type:', event.type);
|
|
149
|
+
if (event.type === 'message_start') {
|
|
150
|
+
// @ts-ignore - usage exists on message_start
|
|
151
|
+
inputTokens = event.message.usage?.input_tokens || 0;
|
|
152
|
+
} else if (event.type === 'content_block_delta') {
|
|
153
|
+
// @ts-ignore - text exists on delta
|
|
154
|
+
const text = event.delta?.text || '';
|
|
155
|
+
fullContent += text;
|
|
156
|
+
if (onChunk) {
|
|
157
|
+
onChunk(text);
|
|
158
|
+
}
|
|
159
|
+
} else if (event.type === 'message_delta') {
|
|
160
|
+
// @ts-ignore - usage exists on message_delta
|
|
161
|
+
outputTokens = event.usage?.output_tokens || 0;
|
|
162
|
+
// @ts-ignore - stop_reason exists on delta
|
|
163
|
+
stopReason = event.delta?.stop_reason || 'end_turn';
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return {
|
|
167
|
+
content: fullContent,
|
|
168
|
+
usage: {
|
|
169
|
+
inputTokens,
|
|
170
|
+
outputTokens
|
|
171
|
+
},
|
|
172
|
+
stopReason
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
// Non-streaming response
|
|
176
|
+
const response = await client.messages.create(requestParams);
|
|
177
|
+
const content = response.content.filter((block)=>block.type === 'text').map((block)=>block.text).join('\n') || '';
|
|
178
|
+
return {
|
|
179
|
+
content,
|
|
180
|
+
usage: {
|
|
181
|
+
inputTokens: response.usage.input_tokens,
|
|
182
|
+
outputTokens: response.usage.output_tokens
|
|
183
|
+
},
|
|
184
|
+
stopReason: response.stop_reason || 'end_turn'
|
|
185
|
+
};
|
|
186
|
+
} catch (error) {
|
|
187
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
188
|
+
console.error(`[anthropic-client] Error with model ${currentModel}:`, lastError.message);
|
|
189
|
+
// If this was the last attempt, throw the error
|
|
190
|
+
if (attempts >= maxAttempts) {
|
|
191
|
+
throw lastError;
|
|
192
|
+
}
|
|
193
|
+
// Continue to next attempt with fallback model
|
|
194
|
+
console.log('[anthropic-client] Will retry with fallback model...');
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
// Should never reach here
|
|
198
|
+
throw lastError || new Error('All retry attempts failed');
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Execute agent via API with full lifecycle
|
|
202
|
+
*/ export async function executeAgentAPI(agentType, agentId, model, prompt, systemPrompt) {
|
|
203
|
+
try {
|
|
204
|
+
console.log(`[anthropic-client] Executing agent: ${agentType}`);
|
|
205
|
+
console.log(`[anthropic-client] Agent ID: ${agentId}`);
|
|
206
|
+
console.log('');
|
|
207
|
+
let fullOutput = '';
|
|
208
|
+
const response = await sendMessage({
|
|
209
|
+
model,
|
|
210
|
+
prompt,
|
|
211
|
+
systemPrompt,
|
|
212
|
+
stream: true
|
|
213
|
+
}, (chunk)=>{
|
|
214
|
+
// Stream output in real-time
|
|
215
|
+
process.stdout.write(chunk);
|
|
216
|
+
fullOutput += chunk;
|
|
217
|
+
});
|
|
218
|
+
console.log('\n');
|
|
219
|
+
console.log('=== Agent Execution Complete ===');
|
|
220
|
+
console.log(`Input tokens: ${response.usage.inputTokens}`);
|
|
221
|
+
console.log(`Output tokens: ${response.usage.outputTokens}`);
|
|
222
|
+
console.log(`Stop reason: ${response.stopReason}`);
|
|
223
|
+
return {
|
|
224
|
+
success: true,
|
|
225
|
+
output: response.content,
|
|
226
|
+
usage: response.usage
|
|
227
|
+
};
|
|
228
|
+
} catch (error) {
|
|
229
|
+
console.error('[anthropic-client] Error:', error);
|
|
230
|
+
return {
|
|
231
|
+
success: false,
|
|
232
|
+
output: '',
|
|
233
|
+
usage: {
|
|
234
|
+
inputTokens: 0,
|
|
235
|
+
outputTokens: 0
|
|
236
|
+
},
|
|
237
|
+
error: error instanceof Error ? error.message : String(error)
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
//# sourceMappingURL=anthropic-client.js.map
|