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.
Files changed (46) hide show
  1. package/.claude/agents/CLAUDE.md +740 -978
  2. package/.claude/agents/core-agents/cost-savings-cfn-loop-coordinator.md +47 -2
  3. package/.claude/agents/custom/agent-builder.md +637 -0
  4. package/.claude/api-configs/config-current-zai-config.env +62 -0
  5. package/.claude/api-configs/config-test-zai-config.env +62 -0
  6. package/.claude/api-configs/env-backups/before-anthropic-20251020-025404.env +62 -0
  7. package/.claude/api-configs/env-backups/before-restore-20251020-025431.env +62 -0
  8. package/.claude/artifacts/reflection-merge-logs/cli-agent-spawning-v2.5.2-merge-report.md +61 -0
  9. package/.claude/commands/cfn-loop-epic.md +41 -17
  10. package/.claude/commands/cfn-loop.md +43 -30
  11. package/.claude/commands/custom-routing-activate.md +37 -123
  12. package/.claude/commands/custom-routing-deactivate.md +27 -124
  13. package/.claude/commands/switch-api.md +41 -16
  14. package/.claude/skills/agent-execution/execute-agent.sh +126 -0
  15. package/.claude/skills/redis-coordination/AGENT_LOGGING.md +280 -0
  16. package/.claude/skills/redis-coordination/agent-log.sh +124 -0
  17. package/.claude/skills/redis-coordination/init-swarm.sh +6 -1
  18. package/.claude/skills/redis-coordination/invoke-waiting-mode.sh +62 -5
  19. package/.claude/skills/redis-coordination/orchestrate-cfn-loop.sh +68 -8
  20. package/.claude/skills/redis-coordination/orchestrate-cfn-loop.sh.backup-1760949407 +933 -0
  21. package/.claude/skills/redis-coordination/store-epic-context.sh +123 -0
  22. package/.claude/skills/redis-coordination/test-iteration-feedback.sh +320 -0
  23. package/.claude/skills/skill-builder/SKILL.md +910 -0
  24. package/CLAUDE.md +76 -2
  25. package/dist/cli/agent-command.js +151 -0
  26. package/dist/cli/agent-command.js.map +1 -0
  27. package/dist/cli/agent-definition-parser.js +176 -0
  28. package/dist/cli/agent-definition-parser.js.map +1 -0
  29. package/dist/cli/agent-executor.js +176 -0
  30. package/dist/cli/agent-executor.js.map +1 -0
  31. package/dist/cli/agent-prompt-builder.js +188 -0
  32. package/dist/cli/agent-prompt-builder.js.map +1 -0
  33. package/dist/cli/agent-spawn.js +46 -1
  34. package/dist/cli/agent-spawn.js.map +1 -1
  35. package/dist/cli/anthropic-client.js +242 -0
  36. package/dist/cli/anthropic-client.js.map +1 -0
  37. package/dist/cli/cli-agent-context.js +353 -0
  38. package/dist/cli/cli-agent-context.js.map +1 -0
  39. package/dist/cli/cli-agent-context.test.js +451 -0
  40. package/dist/cli/cli-agent-context.test.js.map +1 -0
  41. package/dist/cli/index.js +115 -2
  42. package/dist/cli/index.js.map +1 -1
  43. package/dist/cli/iteration-history.js +188 -0
  44. package/dist/cli/iteration-history.js.map +1 -0
  45. package/package.json +3 -1
  46. 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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"}
@@ -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