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
package/CLAUDE.md CHANGED
@@ -6,6 +6,35 @@
6
6
 
7
7
  ## 1) Critical Rules (Single Source of Truth)
8
8
 
9
+ ### Core Operational Rules
10
+ * **Use agents for all non-trivial work** (≥4 steps or any multi-file / research / testing / architecture / security / integration / refactor / feature)
11
+ * **Initialize swarm before any multi-agent work**
12
+ * **Batch operations**: one message per related batch (spawn, file edits, bash, todos, memory ops)
13
+ * **Run post-edit hook after every file edit** inclusive of .md files and await the response
14
+ * **Never work solo** on multi-step tasks. Spawn parallel specialists
15
+ * **Never mix implementers and validators in the same message**
16
+ * **Never run tests inside agents.** Execute once; agents read results
17
+ * **Never save to project root.** Use proper subdirs
18
+ * **No guides/summaries/reports** unless explicitly asked
19
+ * **Use spartan language and give answers in plain english**
20
+ * **Concise summaries only** - no code examples unless requested
21
+ * **Redis persistence enables swarm recovery** - swarm state survives interruptions
22
+ * **ALL agent communication MUST use Redis pub/sub** - no direct file coordination
23
+
24
+ **Consensus thresholds:**
25
+ * Gate (agent self-confidence): **≥0.75 each**
26
+ * Validators consensus: **≥0.90**
27
+
28
+ ### CTO Delegation Persona
29
+ * **Act as a busy CTO** who delegates all non-trivial work to specialized agents
30
+ * **Define clear success criteria** for implementation (working code, passing tests, documented features)
31
+ * **Never define adoption criteria** (user engagement, rollout strategy, training plans)
32
+ * **Ruthlessly delegate** - if task requires >3 steps, spawn agents immediately
33
+ * **Provide context, not solutions** - agents figure out implementation details
34
+ * **Success = implementation complete** - not "users love it" or "team adopts it"
35
+
36
+ ---
37
+
9
38
  ### Skills-Based Coordination
10
39
  **Core Skills:**
11
40
  - Redis Coordination (`.claude/skills/redis-coordination/SKILL.md`)
@@ -120,7 +149,11 @@ Task("cost-savings-cfn-loop-coordinator", `
120
149
  **Config:** `.claude/hooks/post-edit.config.json`
121
150
  **Skill:** `.claude/skills/hook-pipeline/SKILL.md`
122
151
 
123
- ## 2) Skill-Driven Agent Execution
152
+ ## 2) When Agents Are Mandatory (Triggers)
153
+
154
+ If **any** apply, spawn agents:
155
+
156
+ * > 3 distinct steps • multiple files • research+implement+test • design decisions • code review/quality • security/performance/compliance • system integration • docs generation • refactor/optimize • any feature work
124
157
 
125
158
  ### Skill Selection Criteria
126
159
  **Mandatory Skill Spawning Triggers:**
@@ -140,6 +173,19 @@ npx claude-flow-novice swarm "Task Description" \
140
173
  --strategy development
141
174
  ```
142
175
 
176
+ ### Single Agent vs Coordinator
177
+
178
+ **Use Single Agent:**
179
+ * 1 specialized task (coding, reviewing, testing)
180
+ * No dependencies on other agents
181
+ * Straightforward execution
182
+
183
+ **Use Coordinator:**
184
+ * Multiple agents needed (2+)
185
+ * Sequential dependencies (Loop 3 → Loop 2 → Product Owner)
186
+ * Iteration/consensus required
187
+ * CFN Loop workflows
188
+
143
189
  ## 3) Coordination Patterns
144
190
 
145
191
  **Redis Coordination Patterns**
@@ -425,4 +471,32 @@ Implement comprehensive test suites that validate both functional requirements a
425
471
  - Maintenance Schedule: `planning/skills/MAINTENANCE_SCHEDULE.md`
426
472
 
427
473
  **Migration Analytics:**
428
- See `.artifacts/analytics/context-reduction-report.json`
474
+ See `.artifacts/analytics/context-reduction-report.json`
475
+ ## Adaptive Context Extensions: CLI Agent Spawning Insights (v2.5.2)
476
+
477
+ ### Strategy Patterns
478
+
479
+ #### PATTERN-001: Environment Configuration
480
+ - **Context**: CLI Entrypoints
481
+ - **Insight**: Always explicitly load environment configurations using 'import dotenv/config' to ensure provider-specific settings are correctly read and applied across different execution contexts.
482
+ - **Tags**: environment, configuration, cli, dotenv
483
+ - **Confidence**: 0.95
484
+ - **Priority**: 9/10
485
+
486
+ ### Domain Insights
487
+
488
+ #### PATTERN-002: Multi-Provider API Integration
489
+ - **Context**: API Provider Configuration
490
+ - **Insight**: Create explicit provider-specific mappings that account for endpoint differences, model naming conventions, and protocol variations to ensure robust cross-provider compatibility.
491
+ - **Tags**: api-integration, provider-mapping, resilience, configuration
492
+ - **Confidence**: 0.92
493
+ - **Priority**: 8/10
494
+
495
+ ### Edge Case Handling
496
+
497
+ #### PATTERN-004: Resilient API Call Mechanisms
498
+ - **Context**: Error Handling and Timeout Management
499
+ - **Insight**: Configure explicit timeouts and retry mechanisms for API calls to prevent indefinite hanging and provide built-in resilience, with provider-specific timeout and retry configurations.
500
+ - **Tags**: error-handling, timeout, resilience, api-calls
501
+ - **Confidence**: 0.90
502
+ - **Priority**: 9/10
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Agent Command Handler
3
+ *
4
+ * Handles `npx claude-flow-novice agent <type> [options]` commands.
5
+ * Orchestrates agent definition parsing, prompt building, and execution.
6
+ */ import { parseAgentDefinition, listAgentDefinitions } from './agent-definition-parser.js';
7
+ import { buildAgentPrompt } from './agent-prompt-builder.js';
8
+ import { executeAgent } from './agent-executor.js';
9
+ /**
10
+ * Display agent command help
11
+ */ export function displayAgentHelp() {
12
+ console.log(`
13
+ Claude Flow Novice - Agent Spawning
14
+
15
+ Usage:
16
+ npx claude-flow-novice agent <type> [options]
17
+
18
+ Arguments:
19
+ <type> Agent type (e.g., rust-enterprise-developer, coder, reviewer)
20
+
21
+ Options:
22
+ --task-id <id> Task identifier for CFN Loop coordination
23
+ --iteration <n> Iteration number (default: 1)
24
+ --context <text> Task context/description
25
+ --mode <mode> Execution mode (cli, api, hybrid)
26
+ --priority <n> Task priority (1-10)
27
+ --parent-task-id <id> Parent task identifier
28
+ --list List all available agents
29
+ --help Show this help message
30
+
31
+ Examples:
32
+ # Simple agent spawn
33
+ npx claude-flow-novice agent coder --context "Implement JWT auth"
34
+
35
+ # CFN Loop agent
36
+ npx claude-flow-novice agent rust-enterprise-developer \\
37
+ --task-id task-123 \\
38
+ --iteration 1 \\
39
+ --mode standard
40
+
41
+ # List available agents
42
+ npx claude-flow-novice agent --list
43
+
44
+ Available Agents:
45
+ Agents are defined in .claude/agents/ directory:
46
+ - core-agents/ Production-ready core agents
47
+ - specialized/ Domain-specific specialists
48
+ - development/ Development-focused agents
49
+ - security/ Security-focused agents
50
+ - custom/ Your custom agents
51
+
52
+ Documentation:
53
+ See .claude/agents/CLAUDE.md for agent creation guide
54
+ `);
55
+ }
56
+ /**
57
+ * List all available agent definitions
58
+ */ export async function listAgents() {
59
+ console.log('Searching for agent definitions...\n');
60
+ const agents = await listAgentDefinitions();
61
+ if (agents.length === 0) {
62
+ console.log('No agent definitions found in .claude/agents/');
63
+ console.log('\nTo create agents, see: .claude/agents/CLAUDE.md');
64
+ return;
65
+ }
66
+ console.log(`Found ${agents.length} agent(s):\n`);
67
+ // Group by category
68
+ const grouped = {};
69
+ for (const agent of agents){
70
+ const parts = agent.split('/');
71
+ const category = parts.length > 1 ? parts[0] : 'root';
72
+ const name = parts.length > 1 ? parts.slice(1).join('/') : parts[0];
73
+ if (!grouped[category]) {
74
+ grouped[category] = [];
75
+ }
76
+ grouped[category].push(name);
77
+ }
78
+ // Display grouped agents
79
+ for (const [category, names] of Object.entries(grouped).sort()){
80
+ console.log(`${category}/`);
81
+ for (const name of names.sort()){
82
+ console.log(` - ${name}`);
83
+ }
84
+ console.log('');
85
+ }
86
+ console.log('Usage:');
87
+ console.log(' npx claude-flow-novice agent <name> [options]');
88
+ }
89
+ /**
90
+ * Execute agent command
91
+ */ export async function agentCommand(agentType, options) {
92
+ // Handle --list flag
93
+ if (options.list) {
94
+ await listAgents();
95
+ return;
96
+ }
97
+ // Handle --help flag
98
+ if (options.help || !agentType) {
99
+ displayAgentHelp();
100
+ return;
101
+ }
102
+ try {
103
+ console.log(`[agent-command] Spawning agent: ${agentType}`);
104
+ console.log('');
105
+ // Step 1: Parse agent definition
106
+ console.log('[1/3] Parsing agent definition...');
107
+ const definition = await parseAgentDefinition(agentType);
108
+ console.log(` ✓ Found: ${definition.name}`);
109
+ console.log(` ✓ Type: ${definition.type || 'specialist'}`);
110
+ console.log(` ✓ Model: ${definition.model}`);
111
+ console.log(` ✓ Tools: ${definition.tools.join(', ')}`);
112
+ console.log('');
113
+ // Step 2: Build agent prompt
114
+ console.log('[2/3] Building agent prompt...');
115
+ const taskContext = {
116
+ taskId: options.taskId,
117
+ iteration: options.iteration,
118
+ context: options.context,
119
+ mode: options.mode,
120
+ priority: options.priority,
121
+ parentTaskId: options.parentTaskId
122
+ };
123
+ const prompt = await buildAgentPrompt(definition, taskContext);
124
+ console.log(` ✓ Prompt size: ${prompt.length} characters`);
125
+ console.log(` ✓ CFN Loop protocol: ${prompt.includes('CFN Loop Redis Completion Protocol') ? 'included' : 'not applicable'}`);
126
+ console.log(` ✓ Iteration history: ${prompt.includes('## Iteration History') ? 'included' : 'not applicable'}`);
127
+ console.log('');
128
+ // Step 3: Execute agent
129
+ console.log('[3/3] Executing agent...');
130
+ const result = await executeAgent(definition, prompt, taskContext);
131
+ console.log('');
132
+ console.log('=== Execution Result ===');
133
+ console.log(`Agent ID: ${result.agentId}`);
134
+ console.log(`Status: ${result.success ? '✓ Success' : '✗ Failed'}`);
135
+ console.log(`Exit Code: ${result.exitCode}`);
136
+ if (result.error) {
137
+ console.error(`Error: ${result.error}`);
138
+ process.exit(1);
139
+ }
140
+ if (result.output) {
141
+ console.log('\nOutput:');
142
+ console.log(result.output);
143
+ }
144
+ process.exit(result.exitCode);
145
+ } catch (error) {
146
+ console.error('\n[agent-command] Error:', error instanceof Error ? error.message : String(error));
147
+ process.exit(1);
148
+ }
149
+ }
150
+
151
+ //# sourceMappingURL=agent-command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/cli/agent-command.ts"],"sourcesContent":["/**\r\n * Agent Command Handler\r\n *\r\n * Handles `npx claude-flow-novice agent <type> [options]` commands.\r\n * Orchestrates agent definition parsing, prompt building, and execution.\r\n */\r\n\r\nimport { parseAgentDefinition, listAgentDefinitions } from './agent-definition-parser.js';\r\nimport { buildAgentPrompt, TaskContext } from './agent-prompt-builder.js';\r\nimport { executeAgent } from './agent-executor.js';\r\n\r\nexport interface AgentCommandOptions {\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 list?: boolean;\r\n help?: boolean;\r\n}\r\n\r\n/**\r\n * Display agent command help\r\n */\r\nexport function displayAgentHelp(): void {\r\n console.log(`\r\nClaude Flow Novice - Agent Spawning\r\n\r\nUsage:\r\n npx claude-flow-novice agent <type> [options]\r\n\r\nArguments:\r\n <type> Agent type (e.g., rust-enterprise-developer, coder, reviewer)\r\n\r\nOptions:\r\n --task-id <id> Task identifier for CFN Loop coordination\r\n --iteration <n> Iteration number (default: 1)\r\n --context <text> Task context/description\r\n --mode <mode> Execution mode (cli, api, hybrid)\r\n --priority <n> Task priority (1-10)\r\n --parent-task-id <id> Parent task identifier\r\n --list List all available agents\r\n --help Show this help message\r\n\r\nExamples:\r\n # Simple agent spawn\r\n npx claude-flow-novice agent coder --context \"Implement JWT auth\"\r\n\r\n # CFN Loop agent\r\n npx claude-flow-novice agent rust-enterprise-developer \\\\\r\n --task-id task-123 \\\\\r\n --iteration 1 \\\\\r\n --mode standard\r\n\r\n # List available agents\r\n npx claude-flow-novice agent --list\r\n\r\nAvailable Agents:\r\n Agents are defined in .claude/agents/ directory:\r\n - core-agents/ Production-ready core agents\r\n - specialized/ Domain-specific specialists\r\n - development/ Development-focused agents\r\n - security/ Security-focused agents\r\n - custom/ Your custom agents\r\n\r\nDocumentation:\r\n See .claude/agents/CLAUDE.md for agent creation guide\r\n`);\r\n}\r\n\r\n/**\r\n * List all available agent definitions\r\n */\r\nexport async function listAgents(): Promise<void> {\r\n console.log('Searching for agent definitions...\\n');\r\n\r\n const agents = await listAgentDefinitions();\r\n\r\n if (agents.length === 0) {\r\n console.log('No agent definitions found in .claude/agents/');\r\n console.log('\\nTo create agents, see: .claude/agents/CLAUDE.md');\r\n return;\r\n }\r\n\r\n console.log(`Found ${agents.length} agent(s):\\n`);\r\n\r\n // Group by category\r\n const grouped: Record<string, string[]> = {};\r\n\r\n for (const agent of agents) {\r\n const parts = agent.split('/');\r\n const category = parts.length > 1 ? parts[0] : 'root';\r\n const name = parts.length > 1 ? parts.slice(1).join('/') : parts[0];\r\n\r\n if (!grouped[category]) {\r\n grouped[category] = [];\r\n }\r\n grouped[category].push(name);\r\n }\r\n\r\n // Display grouped agents\r\n for (const [category, names] of Object.entries(grouped).sort()) {\r\n console.log(`${category}/`);\r\n for (const name of names.sort()) {\r\n console.log(` - ${name}`);\r\n }\r\n console.log('');\r\n }\r\n\r\n console.log('Usage:');\r\n console.log(' npx claude-flow-novice agent <name> [options]');\r\n}\r\n\r\n/**\r\n * Execute agent command\r\n */\r\nexport async function agentCommand(\r\n agentType: string | undefined,\r\n options: AgentCommandOptions\r\n): Promise<void> {\r\n // Handle --list flag\r\n if (options.list) {\r\n await listAgents();\r\n return;\r\n }\r\n\r\n // Handle --help flag\r\n if (options.help || !agentType) {\r\n displayAgentHelp();\r\n return;\r\n }\r\n\r\n try {\r\n console.log(`[agent-command] Spawning agent: ${agentType}`);\r\n console.log('');\r\n\r\n // Step 1: Parse agent definition\r\n console.log('[1/3] Parsing agent definition...');\r\n const definition = await parseAgentDefinition(agentType);\r\n console.log(` ✓ Found: ${definition.name}`);\r\n console.log(` ✓ Type: ${definition.type || 'specialist'}`);\r\n console.log(` ✓ Model: ${definition.model}`);\r\n console.log(` ✓ Tools: ${definition.tools.join(', ')}`);\r\n console.log('');\r\n\r\n // Step 2: Build agent prompt\r\n console.log('[2/3] Building agent prompt...');\r\n const taskContext: TaskContext = {\r\n taskId: options.taskId,\r\n iteration: options.iteration,\r\n context: options.context,\r\n mode: options.mode,\r\n priority: options.priority,\r\n parentTaskId: options.parentTaskId,\r\n };\r\n\r\n const prompt = await buildAgentPrompt(definition, taskContext);\r\n console.log(` ✓ Prompt size: ${prompt.length} characters`);\r\n console.log(` ✓ CFN Loop protocol: ${prompt.includes('CFN Loop Redis Completion Protocol') ? 'included' : 'not applicable'}`);\r\n console.log(` ✓ Iteration history: ${prompt.includes('## Iteration History') ? 'included' : 'not applicable'}`);\r\n console.log('');\r\n\r\n // Step 3: Execute agent\r\n console.log('[3/3] Executing agent...');\r\n const result = await executeAgent(definition, prompt, taskContext);\r\n\r\n console.log('');\r\n console.log('=== Execution Result ===');\r\n console.log(`Agent ID: ${result.agentId}`);\r\n console.log(`Status: ${result.success ? '✓ Success' : '✗ Failed'}`);\r\n console.log(`Exit Code: ${result.exitCode}`);\r\n\r\n if (result.error) {\r\n console.error(`Error: ${result.error}`);\r\n process.exit(1);\r\n }\r\n\r\n if (result.output) {\r\n console.log('\\nOutput:');\r\n console.log(result.output);\r\n }\r\n\r\n process.exit(result.exitCode);\r\n } catch (error) {\r\n console.error('\\n[agent-command] Error:', error instanceof Error ? error.message : String(error));\r\n process.exit(1);\r\n }\r\n}\r\n"],"names":["parseAgentDefinition","listAgentDefinitions","buildAgentPrompt","executeAgent","displayAgentHelp","console","log","listAgents","agents","length","grouped","agent","parts","split","category","name","slice","join","push","names","Object","entries","sort","agentCommand","agentType","options","list","help","definition","type","model","tools","taskContext","taskId","iteration","context","mode","priority","parentTaskId","prompt","includes","result","agentId","success","exitCode","error","process","exit","output","Error","message","String"],"mappings":"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"}
@@ -0,0 +1,176 @@
1
+ /**
2
+ * Agent Definition Parser
3
+ *
4
+ * Parses agent definition files (.md) with YAML frontmatter and markdown content.
5
+ * Supports agent definitions in .claude/agents/ directory structure.
6
+ */ import fs from 'fs/promises';
7
+ import path from 'path';
8
+ import { glob } from 'glob';
9
+ /**
10
+ * Parse YAML frontmatter from markdown content
11
+ */ function parseFrontmatter(content) {
12
+ const frontmatterRegex = /^---\n([\s\S]*?)\n---\n([\s\S]*)$/;
13
+ const match = content.match(frontmatterRegex);
14
+ if (!match) {
15
+ return {
16
+ frontmatter: {},
17
+ body: content
18
+ };
19
+ }
20
+ const [, yamlContent, body] = match;
21
+ // Simple YAML parser (handles basic key-value pairs, arrays, and objects)
22
+ const frontmatter = {};
23
+ const lines = yamlContent.split('\n');
24
+ let currentKey = '';
25
+ let currentArray = [];
26
+ let isInArray = false;
27
+ let isInObject = false;
28
+ let currentObject = {};
29
+ let objectKey = '';
30
+ for (const line of lines){
31
+ const trimmed = line.trim();
32
+ if (!trimmed || trimmed.startsWith('#')) continue;
33
+ // Array item
34
+ if (trimmed.startsWith('- ')) {
35
+ if (!isInArray) {
36
+ isInArray = true;
37
+ currentArray = [];
38
+ }
39
+ currentArray.push(trimmed.substring(2).trim());
40
+ continue;
41
+ }
42
+ // End of array
43
+ if (isInArray && !trimmed.startsWith('- ')) {
44
+ frontmatter[currentKey] = currentArray;
45
+ isInArray = false;
46
+ currentArray = [];
47
+ }
48
+ // Object field (indented key-value)
49
+ if (trimmed.match(/^\s+\w+:/) && isInObject) {
50
+ const [objKey, ...objValueParts] = trimmed.split(':');
51
+ const objValue = objValueParts.join(':').trim().replace(/^["']|["']$/g, '');
52
+ currentObject[objKey.trim()] = objValue;
53
+ continue;
54
+ }
55
+ // Key-value pair
56
+ const colonIndex = trimmed.indexOf(':');
57
+ if (colonIndex !== -1) {
58
+ const key = trimmed.substring(0, colonIndex).trim();
59
+ const value = trimmed.substring(colonIndex + 1).trim();
60
+ // Check if this starts an object
61
+ if (value === '') {
62
+ isInObject = true;
63
+ currentObject = {};
64
+ objectKey = key;
65
+ continue;
66
+ }
67
+ // End previous object if any
68
+ if (isInObject && !trimmed.match(/^\s+/)) {
69
+ frontmatter[objectKey] = currentObject;
70
+ isInObject = false;
71
+ currentObject = {};
72
+ }
73
+ currentKey = key;
74
+ // Multi-line string (starts with |)
75
+ if (value === '|') {
76
+ continue; // Will be handled by next lines
77
+ }
78
+ // Remove quotes
79
+ const cleanValue = value.replace(/^["']|["']$/g, '');
80
+ frontmatter[key] = cleanValue;
81
+ } else if (currentKey && trimmed && !isInArray && !isInObject) {
82
+ // Continuation of multi-line string
83
+ const existingValue = frontmatter[currentKey];
84
+ frontmatter[currentKey] = existingValue ? `${existingValue}\n${trimmed}` : trimmed;
85
+ }
86
+ }
87
+ // Handle trailing array or object
88
+ if (isInArray) {
89
+ frontmatter[currentKey] = currentArray;
90
+ }
91
+ if (isInObject) {
92
+ frontmatter[objectKey] = currentObject;
93
+ }
94
+ return {
95
+ frontmatter,
96
+ body: body.trim()
97
+ };
98
+ }
99
+ /**
100
+ * Find agent definition file by agent type/name
101
+ */ async function findAgentFile(agentType, baseDir = '.claude/agents') {
102
+ // Normalize agent type (handle both kebab-case and underscores)
103
+ const normalizedType = agentType.toLowerCase().replace(/_/g, '-');
104
+ // Search patterns (in order of priority)
105
+ const patterns = [
106
+ // Exact match in any subdirectory
107
+ `${baseDir}/**/${normalizedType}.md`,
108
+ // Match with different casing
109
+ `${baseDir}/**/*${normalizedType}*.md`
110
+ ];
111
+ for (const pattern of patterns){
112
+ const files = await glob(pattern, {
113
+ nodir: true,
114
+ absolute: true
115
+ });
116
+ if (files.length > 0) {
117
+ // Prefer exact match over partial match
118
+ const exactMatch = files.find((f)=>{
119
+ const basename = path.basename(f, '.md').toLowerCase();
120
+ return basename === normalizedType;
121
+ });
122
+ return exactMatch || files[0];
123
+ }
124
+ }
125
+ return null;
126
+ }
127
+ /**
128
+ * Parse agent definition from file
129
+ */ export async function parseAgentDefinition(agentType) {
130
+ // Find agent file
131
+ const filePath = await findAgentFile(agentType);
132
+ if (!filePath) {
133
+ throw new Error(`Agent definition not found: ${agentType}`);
134
+ }
135
+ // Read file content
136
+ const content = await fs.readFile(filePath, 'utf-8');
137
+ // Parse frontmatter and body
138
+ const { frontmatter, body } = parseFrontmatter(content);
139
+ // Extract category from path
140
+ const relativePath = path.relative('.claude/agents', filePath);
141
+ const category = relativePath.includes('/') ? relativePath.split('/')[0] : undefined;
142
+ // Build agent definition
143
+ const definition = {
144
+ name: frontmatter.name || agentType,
145
+ description: frontmatter.description || '',
146
+ tools: Array.isArray(frontmatter.tools) ? frontmatter.tools : [],
147
+ model: frontmatter.model || 'haiku',
148
+ type: frontmatter.type,
149
+ color: frontmatter.color,
150
+ acl_level: frontmatter.acl_level ? parseInt(String(frontmatter.acl_level), 10) : undefined,
151
+ capabilities: frontmatter.capabilities,
152
+ validation_hooks: frontmatter.validation_hooks,
153
+ lifecycle: frontmatter.lifecycle,
154
+ content: body,
155
+ filePath,
156
+ category
157
+ };
158
+ return definition;
159
+ }
160
+ /**
161
+ * List all available agent definitions
162
+ */ export async function listAgentDefinitions(baseDir = '.claude/agents') {
163
+ const pattern = `${baseDir}/**/*.md`;
164
+ const files = await glob(pattern, {
165
+ nodir: true
166
+ });
167
+ return files.map((f)=>path.basename(f, '.md'));
168
+ }
169
+ /**
170
+ * Check if agent definition includes CFN Loop protocol
171
+ */ export function hasCFNLoopProtocol(definition) {
172
+ const content = definition.content.toLowerCase();
173
+ return content.includes('cfn loop') && content.includes('redis completion protocol') || content.includes('invoke-waiting-mode.sh');
174
+ }
175
+
176
+ //# sourceMappingURL=agent-definition-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/cli/agent-definition-parser.ts"],"sourcesContent":["/**\r\n * Agent Definition Parser\r\n *\r\n * Parses agent definition files (.md) with YAML frontmatter and markdown content.\r\n * Supports agent definitions in .claude/agents/ directory structure.\r\n */\r\n\r\nimport fs from 'fs/promises';\r\nimport path from 'path';\r\nimport { glob } from 'glob';\r\n\r\nexport interface AgentDefinition {\r\n // YAML frontmatter fields\r\n name: string;\r\n description: string;\r\n tools: string[];\r\n model: 'haiku' | 'sonnet' | 'opus';\r\n type?: string;\r\n color?: string;\r\n acl_level?: number;\r\n capabilities?: string[];\r\n validation_hooks?: string[];\r\n lifecycle?: {\r\n pre_task?: string;\r\n post_task?: string;\r\n };\r\n\r\n // Parsed markdown content\r\n content: string;\r\n\r\n // File metadata\r\n filePath: string;\r\n category?: string; // e.g., 'core-agents', 'specialized', 'custom'\r\n}\r\n\r\n/**\r\n * Parse YAML frontmatter from markdown content\r\n */\r\nfunction parseFrontmatter(content: string): { frontmatter: Record<string, any>; body: string } {\r\n const frontmatterRegex = /^---\\n([\\s\\S]*?)\\n---\\n([\\s\\S]*)$/;\r\n const match = content.match(frontmatterRegex);\r\n\r\n if (!match) {\r\n return { frontmatter: {}, body: content };\r\n }\r\n\r\n const [, yamlContent, body] = match;\r\n\r\n // Simple YAML parser (handles basic key-value pairs, arrays, and objects)\r\n const frontmatter: Record<string, any> = {};\r\n const lines = yamlContent.split('\\n');\r\n let currentKey = '';\r\n let currentArray: string[] = [];\r\n let isInArray = false;\r\n let isInObject = false;\r\n let currentObject: Record<string, string> = {};\r\n let objectKey = '';\r\n\r\n for (const line of lines) {\r\n const trimmed = line.trim();\r\n if (!trimmed || trimmed.startsWith('#')) continue;\r\n\r\n // Array item\r\n if (trimmed.startsWith('- ')) {\r\n if (!isInArray) {\r\n isInArray = true;\r\n currentArray = [];\r\n }\r\n currentArray.push(trimmed.substring(2).trim());\r\n continue;\r\n }\r\n\r\n // End of array\r\n if (isInArray && !trimmed.startsWith('- ')) {\r\n frontmatter[currentKey] = currentArray;\r\n isInArray = false;\r\n currentArray = [];\r\n }\r\n\r\n // Object field (indented key-value)\r\n if (trimmed.match(/^\\s+\\w+:/) && isInObject) {\r\n const [objKey, ...objValueParts] = trimmed.split(':');\r\n const objValue = objValueParts.join(':').trim().replace(/^[\"']|[\"']$/g, '');\r\n currentObject[objKey.trim()] = objValue;\r\n continue;\r\n }\r\n\r\n // Key-value pair\r\n const colonIndex = trimmed.indexOf(':');\r\n if (colonIndex !== -1) {\r\n const key = trimmed.substring(0, colonIndex).trim();\r\n const value = trimmed.substring(colonIndex + 1).trim();\r\n\r\n // Check if this starts an object\r\n if (value === '') {\r\n isInObject = true;\r\n currentObject = {};\r\n objectKey = key;\r\n continue;\r\n }\r\n\r\n // End previous object if any\r\n if (isInObject && !trimmed.match(/^\\s+/)) {\r\n frontmatter[objectKey] = currentObject;\r\n isInObject = false;\r\n currentObject = {};\r\n }\r\n\r\n currentKey = key;\r\n\r\n // Multi-line string (starts with |)\r\n if (value === '|') {\r\n continue; // Will be handled by next lines\r\n }\r\n\r\n // Remove quotes\r\n const cleanValue = value.replace(/^[\"']|[\"']$/g, '');\r\n frontmatter[key] = cleanValue;\r\n } else if (currentKey && trimmed && !isInArray && !isInObject) {\r\n // Continuation of multi-line string\r\n const existingValue = frontmatter[currentKey];\r\n frontmatter[currentKey] = existingValue\r\n ? `${existingValue}\\n${trimmed}`\r\n : trimmed;\r\n }\r\n }\r\n\r\n // Handle trailing array or object\r\n if (isInArray) {\r\n frontmatter[currentKey] = currentArray;\r\n }\r\n if (isInObject) {\r\n frontmatter[objectKey] = currentObject;\r\n }\r\n\r\n return { frontmatter, body: body.trim() };\r\n}\r\n\r\n/**\r\n * Find agent definition file by agent type/name\r\n */\r\nasync function findAgentFile(agentType: string, baseDir: string = '.claude/agents'): Promise<string | null> {\r\n // Normalize agent type (handle both kebab-case and underscores)\r\n const normalizedType = agentType.toLowerCase().replace(/_/g, '-');\r\n\r\n // Search patterns (in order of priority)\r\n const patterns = [\r\n // Exact match in any subdirectory\r\n `${baseDir}/**/${normalizedType}.md`,\r\n // Match with different casing\r\n `${baseDir}/**/*${normalizedType}*.md`,\r\n ];\r\n\r\n for (const pattern of patterns) {\r\n const files = await glob(pattern, { nodir: true, absolute: true });\r\n if (files.length > 0) {\r\n // Prefer exact match over partial match\r\n const exactMatch = files.find(f => {\r\n const basename = path.basename(f, '.md').toLowerCase();\r\n return basename === normalizedType;\r\n });\r\n return exactMatch || files[0];\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Parse agent definition from file\r\n */\r\nexport async function parseAgentDefinition(agentType: string): Promise<AgentDefinition> {\r\n // Find agent file\r\n const filePath = await findAgentFile(agentType);\r\n\r\n if (!filePath) {\r\n throw new Error(`Agent definition not found: ${agentType}`);\r\n }\r\n\r\n // Read file content\r\n const content = await fs.readFile(filePath, 'utf-8');\r\n\r\n // Parse frontmatter and body\r\n const { frontmatter, body } = parseFrontmatter(content);\r\n\r\n // Extract category from path\r\n const relativePath = path.relative('.claude/agents', filePath);\r\n const category = relativePath.includes('/')\r\n ? relativePath.split('/')[0]\r\n : undefined;\r\n\r\n // Build agent definition\r\n const definition: AgentDefinition = {\r\n name: frontmatter.name || agentType,\r\n description: frontmatter.description || '',\r\n tools: Array.isArray(frontmatter.tools) ? frontmatter.tools : [],\r\n model: frontmatter.model || 'haiku',\r\n type: frontmatter.type,\r\n color: frontmatter.color,\r\n acl_level: frontmatter.acl_level ? parseInt(String(frontmatter.acl_level), 10) : undefined,\r\n capabilities: frontmatter.capabilities,\r\n validation_hooks: frontmatter.validation_hooks,\r\n lifecycle: frontmatter.lifecycle,\r\n content: body,\r\n filePath,\r\n category,\r\n };\r\n\r\n return definition;\r\n}\r\n\r\n/**\r\n * List all available agent definitions\r\n */\r\nexport async function listAgentDefinitions(baseDir: string = '.claude/agents'): Promise<string[]> {\r\n const pattern = `${baseDir}/**/*.md`;\r\n const files = await glob(pattern, { nodir: true });\r\n\r\n return files.map(f => path.basename(f, '.md'));\r\n}\r\n\r\n/**\r\n * Check if agent definition includes CFN Loop protocol\r\n */\r\nexport function hasCFNLoopProtocol(definition: AgentDefinition): boolean {\r\n const content = definition.content.toLowerCase();\r\n return (\r\n content.includes('cfn loop') &&\r\n content.includes('redis completion protocol') ||\r\n content.includes('invoke-waiting-mode.sh')\r\n );\r\n}\r\n"],"names":["fs","path","glob","parseFrontmatter","content","frontmatterRegex","match","frontmatter","body","yamlContent","lines","split","currentKey","currentArray","isInArray","isInObject","currentObject","objectKey","line","trimmed","trim","startsWith","push","substring","objKey","objValueParts","objValue","join","replace","colonIndex","indexOf","key","value","cleanValue","existingValue","findAgentFile","agentType","baseDir","normalizedType","toLowerCase","patterns","pattern","files","nodir","absolute","length","exactMatch","find","f","basename","parseAgentDefinition","filePath","Error","readFile","relativePath","relative","category","includes","undefined","definition","name","description","tools","Array","isArray","model","type","color","acl_level","parseInt","String","capabilities","validation_hooks","lifecycle","listAgentDefinitions","map","hasCFNLoopProtocol"],"mappings":"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"}
@@ -0,0 +1,176 @@
1
+ /**
2
+ * Agent Executor
3
+ *
4
+ * Executes CLI-spawned agents by:
5
+ * 1. Checking custom routing configuration (z.ai vs Anthropic)
6
+ * 2. Invoking the appropriate API
7
+ * 3. Managing agent lifecycle and output
8
+ */ import { spawn } from 'child_process';
9
+ import { getAgentId } from './agent-prompt-builder.js';
10
+ import { buildCLIAgentSystemPrompt, loadContextFromEnv } from './cli-agent-context.js';
11
+ import fs from 'fs/promises';
12
+ import path from 'path';
13
+ import os from 'os';
14
+ /**
15
+ * Check if custom routing (z.ai) is enabled
16
+ */ async function isCustomRoutingEnabled() {
17
+ // Check environment variable
18
+ if (process.env.CLAUDE_API_PROVIDER === 'zai') {
19
+ return true;
20
+ }
21
+ // Check config file (.claude/config/api-provider.json)
22
+ try {
23
+ const configPath = path.join('.claude', 'config', 'api-provider.json');
24
+ const config = JSON.parse(await fs.readFile(configPath, 'utf-8'));
25
+ return config.provider === 'zai' || config.provider === 'z.ai';
26
+ } catch {
27
+ return false;
28
+ }
29
+ }
30
+ /**
31
+ * Get API provider configuration
32
+ */ async function getAPIProvider() {
33
+ const customEnabled = await isCustomRoutingEnabled();
34
+ return customEnabled ? 'zai' : 'anthropic';
35
+ }
36
+ /**
37
+ * Execute agent using direct API calls
38
+ */ async function executeViaAPI(definition, prompt, context) {
39
+ const agentId = getAgentId(definition, context);
40
+ console.log(`[agent-executor] Executing agent via API: ${definition.name}`);
41
+ console.log(`[agent-executor] Agent ID: ${agentId}`);
42
+ console.log(`[agent-executor] Model: ${definition.model}`);
43
+ console.log('');
44
+ try {
45
+ // Build system prompt with natural language context (Phase 1 enhancement)
46
+ console.log('[agent-executor] Building system prompt with context...');
47
+ const contextOptions = loadContextFromEnv();
48
+ // Override agent type with definition name
49
+ contextOptions.agentType = definition.name;
50
+ // Override iteration/taskId if provided in context
51
+ if (context.taskId) contextOptions.taskId = context.taskId;
52
+ if (context.iteration) contextOptions.iteration = context.iteration;
53
+ const systemPrompt = await buildCLIAgentSystemPrompt(contextOptions);
54
+ console.log('[agent-executor] System prompt built successfully');
55
+ console.log('');
56
+ // Dynamic import to avoid bundling issues
57
+ const { executeAgentAPI } = await import('./anthropic-client.js');
58
+ const result = await executeAgentAPI(definition.name, agentId, definition.model, prompt, systemPrompt);
59
+ return {
60
+ success: result.success,
61
+ agentId,
62
+ output: result.output,
63
+ error: result.error,
64
+ exitCode: result.success ? 0 : 1
65
+ };
66
+ } catch (error) {
67
+ console.error('[agent-executor] API execution failed:', error);
68
+ return {
69
+ success: false,
70
+ agentId,
71
+ error: error instanceof Error ? error.message : String(error),
72
+ exitCode: 1
73
+ };
74
+ }
75
+ }
76
+ /**
77
+ * Execute agent using shell script (fallback/simulation)
78
+ */ async function executeViaScript(definition, prompt, context) {
79
+ const agentId = getAgentId(definition, context);
80
+ // Write prompt to temporary file
81
+ const tmpDir = os.tmpdir();
82
+ const promptFile = path.join(tmpDir, `agent-${agentId}-${Date.now()}.md`);
83
+ await fs.writeFile(promptFile, prompt, 'utf-8');
84
+ console.log(`[agent-executor] Executing agent via script: ${definition.name}`);
85
+ console.log(`[agent-executor] Agent ID: ${agentId}`);
86
+ console.log(`[agent-executor] Model: ${definition.model}`);
87
+ console.log(`[agent-executor] Prompt file: ${promptFile}`);
88
+ return new Promise((resolve)=>{
89
+ const scriptPath = path.join('.claude', 'skills', 'agent-execution', 'execute-agent.sh');
90
+ // Build environment variables
91
+ const env = {
92
+ ...process.env,
93
+ AGENT_TYPE: definition.name,
94
+ AGENT_ID: agentId,
95
+ AGENT_MODEL: definition.model,
96
+ AGENT_TOOLS: definition.tools.join(','),
97
+ TASK_ID: context.taskId || '',
98
+ ITERATION: String(context.iteration || 1),
99
+ MODE: context.mode || 'cli',
100
+ PROMPT_FILE: promptFile
101
+ };
102
+ // Check if execute script exists
103
+ fs.access(scriptPath).then(()=>{
104
+ // Use execution script
105
+ const proc = spawn('bash', [
106
+ scriptPath
107
+ ], {
108
+ env,
109
+ stdio: 'inherit'
110
+ });
111
+ proc.on('exit', (code)=>{
112
+ resolve({
113
+ success: code === 0,
114
+ agentId,
115
+ exitCode: code || 0
116
+ });
117
+ });
118
+ proc.on('error', (err)=>{
119
+ resolve({
120
+ success: false,
121
+ agentId,
122
+ error: err.message,
123
+ exitCode: 1
124
+ });
125
+ });
126
+ }).catch(()=>{
127
+ // Fallback: Print prompt
128
+ console.log('\n=== Agent Prompt ===');
129
+ console.log(prompt.substring(0, 500) + '...');
130
+ console.log('\n[agent-executor] Execution script not found');
131
+ console.log('[agent-executor] Using simulation mode\n');
132
+ resolve({
133
+ success: true,
134
+ agentId,
135
+ output: prompt,
136
+ exitCode: 0
137
+ });
138
+ });
139
+ });
140
+ }
141
+ /**
142
+ * Main agent execution function
143
+ */ export async function executeAgent(definition, prompt, context, options = {}) {
144
+ const method = options.method || 'auto';
145
+ // Auto-select execution method
146
+ if (method === 'auto') {
147
+ // Try API execution first, fallback to script if API key not available
148
+ try {
149
+ return await executeViaAPI(definition, prompt, context);
150
+ } catch (error) {
151
+ if (error instanceof Error && error.message.includes('API key not found')) {
152
+ console.log('[agent-executor] API key not found, using script fallback');
153
+ return executeViaScript(definition, prompt, context);
154
+ }
155
+ throw error;
156
+ }
157
+ }
158
+ if (method === 'api') {
159
+ return executeViaAPI(definition, prompt, context);
160
+ }
161
+ return executeViaScript(definition, prompt, context);
162
+ }
163
+ /**
164
+ * Write agent output to file for debugging
165
+ */ export async function saveAgentOutput(agentId, output, outputDir = '.claude/tmp/agent-output') {
166
+ await fs.mkdir(outputDir, {
167
+ recursive: true
168
+ });
169
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
170
+ const filename = `${agentId}-${timestamp}.txt`;
171
+ const filepath = path.join(outputDir, filename);
172
+ await fs.writeFile(filepath, output, 'utf-8');
173
+ return filepath;
174
+ }
175
+
176
+ //# sourceMappingURL=agent-executor.js.map