claude-flow-novice 2.16.0 → 2.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/cfn-extras/skills/GOOGLE_SHEETS_SKILLS_README.md +1 -1
- package/.claude/cfn-extras/skills/google-sheets-api-coordinator/SKILL.md +1 -1
- package/.claude/cfn-extras/skills/google-sheets-formula-builder/SKILL.md +1 -1
- package/.claude/cfn-extras/skills/google-sheets-progress/SKILL.md +1 -1
- package/.claude/commands/CFN_LOOP_FRONTEND.md +1 -1
- package/.claude/commands/cfn-loop-cli.md +124 -46
- package/.claude/commands/cfn-loop-frontend.md +1 -1
- package/.claude/commands/cfn-loop-task.md +2 -2
- package/.claude/commands/deprecated/cfn-loop.md +2 -2
- package/.claude/hooks/cfn-invoke-post-edit.sh +31 -5
- package/.claude/hooks/cfn-post-edit.config.json +9 -2
- package/.claude/root-claude-distribute/CFN-CLAUDE.md +1 -1
- package/.claude/skills/cfn-backlog-management/SKILL.md +1 -1
- package/.claude/skills/cfn-loop-orchestration/NORTH_STAR_INDEX.md +1 -1
- package/claude-assets/agents/cfn-dev-team/analysts/root-cause-analyst.md +2 -2
- package/claude-assets/agents/cfn-dev-team/architecture/base-template-generator.md +1 -1
- package/claude-assets/agents/cfn-dev-team/coordinators/cfn-frontend-coordinator.md +2 -2
- package/claude-assets/agents/cfn-dev-team/coordinators/handoff-coordinator.md +1 -1
- package/claude-assets/agents/cfn-dev-team/dev-ops/devops-engineer.md +1 -1
- package/claude-assets/agents/cfn-dev-team/dev-ops/docker-specialist.md +2 -2
- package/claude-assets/agents/cfn-dev-team/dev-ops/github-commit-agent.md +2 -2
- package/claude-assets/agents/cfn-dev-team/dev-ops/kubernetes-specialist.md +1 -1
- package/claude-assets/agents/cfn-dev-team/developers/api-gateway-specialist.md +1 -1
- package/claude-assets/agents/cfn-dev-team/developers/data/data-engineer.md +1 -1
- package/claude-assets/agents/cfn-dev-team/developers/database/database-architect.md +1 -1
- package/claude-assets/agents/cfn-dev-team/developers/frontend/typescript-specialist.md +1 -1
- package/claude-assets/agents/cfn-dev-team/developers/frontend/ui-designer.md +1 -1
- package/claude-assets/agents/cfn-dev-team/developers/graphql-specialist.md +1 -1
- package/claude-assets/agents/cfn-dev-team/documentation/pseudocode.md +1 -1
- package/claude-assets/agents/cfn-dev-team/product-owners/accessibility-advocate-persona.md +1 -1
- package/claude-assets/agents/cfn-dev-team/product-owners/cto-agent.md +1 -1
- package/claude-assets/agents/cfn-dev-team/product-owners/power-user-persona.md +1 -1
- package/claude-assets/agents/cfn-dev-team/reviewers/quality/security-specialist.md +1 -1
- package/claude-assets/agents/cfn-dev-team/testers/api-testing-specialist.md +1 -1
- package/claude-assets/agents/cfn-dev-team/testers/chaos-engineering-specialist.md +1 -1
- package/claude-assets/agents/cfn-dev-team/testers/contract-tester.md +1 -1
- package/claude-assets/agents/cfn-dev-team/testers/e2e/playwright-tester.md +1 -1
- package/claude-assets/agents/cfn-dev-team/testers/integration-tester.md +1 -1
- package/claude-assets/agents/cfn-dev-team/testers/load-testing-specialist.md +1 -1
- package/claude-assets/agents/cfn-dev-team/testers/mutation-testing-specialist.md +1 -1
- package/claude-assets/agents/cfn-dev-team/testers/unit/tdd-london-unit-swarm.md +1 -1
- package/claude-assets/agents/cfn-dev-team/utility/agent-builder.md +11 -0
- package/claude-assets/agents/cfn-dev-team/utility/analyst.md +1 -1
- package/claude-assets/agents/cfn-dev-team/utility/claude-code-expert.md +1 -1
- package/claude-assets/agents/cfn-dev-team/utility/epic-creator.md +1 -1
- package/claude-assets/agents/cfn-dev-team/utility/memory-leak-specialist.md +1 -1
- package/claude-assets/agents/cfn-dev-team/utility/researcher.md +1 -1
- package/claude-assets/agents/cfn-dev-team/utility/z-ai-specialist.md +1 -1
- package/claude-assets/agents/custom/cfn-docker-expert.md +1 -0
- package/claude-assets/agents/custom/cfn-loops-cli-expert.md +326 -17
- package/claude-assets/agents/custom/cfn-redis-operations.md +529 -529
- package/claude-assets/agents/custom/cfn-system-expert.md +1 -1
- package/claude-assets/agents/custom/trigger-dev-expert.md +369 -0
- package/claude-assets/agents/docker-team/micro-sprint-planner.md +747 -747
- package/claude-assets/agents/project-only-agents/npm-package-specialist.md +1 -1
- package/claude-assets/cfn-extras/skills/GOOGLE_SHEETS_SKILLS_README.md +1 -1
- package/claude-assets/cfn-extras/skills/google-sheets-api-coordinator/SKILL.md +1 -1
- package/claude-assets/cfn-extras/skills/google-sheets-formula-builder/SKILL.md +1 -1
- package/claude-assets/cfn-extras/skills/google-sheets-progress/SKILL.md +1 -1
- package/claude-assets/commands/CFN_LOOP_FRONTEND.md +1 -1
- package/claude-assets/commands/cfn-loop-cli.md +124 -46
- package/claude-assets/commands/cfn-loop-frontend.md +1 -1
- package/claude-assets/commands/cfn-loop-task.md +2 -2
- package/claude-assets/commands/deprecated/cfn-loop.md +2 -2
- package/claude-assets/hooks/GIT-HOOKS-USAGE-EXAMPLES.md +116 -0
- package/claude-assets/hooks/README-GIT-HOOKS.md +443 -0
- package/claude-assets/hooks/cfn-invoke-post-edit.sh +31 -5
- package/claude-assets/hooks/cfn-post-edit.config.json +9 -2
- package/claude-assets/hooks/install-git-hooks.sh +243 -0
- package/claude-assets/hooks/subagent-start.sh +98 -0
- package/claude-assets/hooks/subagent-stop.sh +93 -0
- package/claude-assets/hooks/validators/credential-scanner.sh +172 -0
- package/claude-assets/root-claude-distribute/CFN-CLAUDE.md +1 -1
- package/claude-assets/skills/cfn-backlog-management/SKILL.md +1 -1
- package/claude-assets/skills/cfn-dependency-ingestion/SKILL.md +41 -13
- package/claude-assets/skills/cfn-dependency-ingestion/ingest.sh +237 -0
- package/claude-assets/skills/cfn-dependency-ingestion/manifests/cli-mode-dependencies.txt +73 -0
- package/claude-assets/skills/cfn-dependency-ingestion/manifests/shared-dependencies.txt +57 -0
- package/claude-assets/skills/cfn-dependency-ingestion/manifests/trigger-dev-dependencies.txt +82 -0
- package/claude-assets/skills/cfn-dependency-ingestion/manifests/trigger-mode-dependencies.txt +80 -0
- package/claude-assets/skills/cfn-environment-sanitization/sanitize-environment.sh +14 -4
- package/claude-assets/skills/cfn-loop-orchestration/NORTH_STAR_INDEX.md +1 -1
- package/claude-assets/skills/cfn-provider-routing/SKILL.md +23 -0
- package/claude-assets/skills/docker-build/build.sh +1 -1
- package/dist/agent/skill-mcp-selector.js +2 -1
- package/dist/agent/skill-mcp-selector.js.map +1 -1
- package/dist/agents/agent-loader.js +165 -146
- package/dist/agents/agent-loader.js.map +1 -1
- package/dist/cli/agent-executor.js +470 -26
- package/dist/cli/agent-executor.js.map +1 -1
- package/dist/cli/agent-prompt-builder.js +2 -2
- package/dist/cli/agent-prompt-builder.js.map +1 -1
- package/dist/cli/agent-spawn.js +7 -4
- package/dist/cli/agent-spawn.js.map +1 -1
- package/dist/cli/agent-spawner.js +51 -4
- package/dist/cli/agent-spawner.js.map +1 -1
- package/dist/cli/agent-token-manager.js +2 -1
- package/dist/cli/agent-token-manager.js.map +1 -1
- package/dist/cli/anthropic-client.js +117 -11
- package/dist/cli/anthropic-client.js.map +1 -1
- package/dist/cli/cfn-context.js +2 -1
- package/dist/cli/cfn-context.js.map +1 -1
- package/dist/cli/cfn-metrics.js +2 -1
- package/dist/cli/cfn-metrics.js.map +1 -1
- package/dist/cli/cfn-redis.js +2 -1
- package/dist/cli/cfn-redis.js.map +1 -1
- package/dist/cli/cli-agent-context.js +2 -0
- package/dist/cli/cli-agent-context.js.map +1 -1
- package/dist/cli/config-manager.js +4 -252
- package/dist/cli/config-manager.js.map +1 -1
- package/dist/cli/conversation-fork-cleanup.js +2 -1
- package/dist/cli/conversation-fork-cleanup.js.map +1 -1
- package/dist/cli/conversation-fork.js +2 -1
- package/dist/cli/conversation-fork.js.map +1 -1
- package/dist/cli/coordination/agent-messaging.js +415 -0
- package/dist/cli/coordination/agent-messaging.js.map +1 -0
- package/dist/cli/coordination/wait-for-threshold.js +232 -0
- package/dist/cli/coordination/wait-for-threshold.js.map +1 -0
- package/dist/cli/iteration-history.js +2 -1
- package/dist/cli/iteration-history.js.map +1 -1
- package/dist/cli/process-lifecycle.js +5 -1
- package/dist/cli/process-lifecycle.js.map +1 -1
- package/dist/cli/spawn-agent-cli.js +41 -6
- package/dist/cli/spawn-agent-cli.js.map +1 -1
- package/dist/coordination/redis-waiting-mode.js +4 -0
- package/dist/coordination/redis-waiting-mode.js.map +1 -1
- package/dist/lib/artifact-registry.js +4 -0
- package/dist/lib/artifact-registry.js.map +1 -1
- package/dist/lib/connection-pool.js +390 -0
- package/dist/lib/connection-pool.js.map +1 -0
- package/dist/lib/environment-contract.js +258 -0
- package/dist/lib/environment-contract.js.map +1 -0
- package/dist/lib/query-optimizer.js +388 -0
- package/dist/lib/query-optimizer.js.map +1 -0
- package/dist/lib/result-cache.js +285 -0
- package/dist/lib/result-cache.js.map +1 -0
- package/dist/mcp/auth-middleware.js +2 -1
- package/dist/mcp/auth-middleware.js.map +1 -1
- package/dist/mcp/playwright-mcp-server-auth.js +2 -1
- package/dist/mcp/playwright-mcp-server-auth.js.map +1 -1
- package/package.json +3 -1
- package/scripts/build-agent-image.sh +1 -1
- package/scripts/cost-allocation-tracker.sh +632 -0
- package/scripts/docker-rebuild-all-agents.sh +2 -2
- package/scripts/reorganize-tests.sh +280 -0
- package/scripts/trigger-dev-setup.sh +12 -0
- package/tests/README.md +45 -0
- package/.claude/commands/cost-savings-status.md +0 -34
- package/.claude/commands/metrics-summary.md +0 -58
- package/claude-assets/agents/cfn-dev-team/dev-ops/monitoring-specialist.md +0 -768
- package/claude-assets/agents/custom/test-mcp-access.md +0 -24
- package/claude-assets/commands/cost-savings-status.md +0 -34
- package/claude-assets/commands/metrics-summary.md +0 -58
- package/tests/test-memory-leak-task-mode.sh +0 -435
|
@@ -1 +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 { exec } from 'child_process';\r\nimport { promisify } from 'util';\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 {\r\n loadMessages,\r\n storeMessage,\r\n getCurrentFork,\r\n formatMessagesForAPI,\r\n type Message\r\n} from './conversation-fork.js';\r\nimport { convertToolNames } from './tool-definitions.js';\r\nimport fs from 'fs/promises';\r\nimport path from 'path';\r\nimport os from 'os';\r\nimport { execSync } from 'child_process';\r\n\r\nconst execAsync = promisify(exec);\r\n\r\n/**\r\n * Detect project root dynamically\r\n * Uses PROJECT_ROOT env var if set, otherwise tries git, falls back to cwd\r\n */\r\nfunction getProjectRoot(): string {\r\n // 1. Check environment variable\r\n if (process.env.PROJECT_ROOT) {\r\n return process.env.PROJECT_ROOT;\r\n }\r\n\r\n // 2. Try git rev-parse (most reliable)\r\n try {\r\n const gitRoot = execSync('git rev-parse --show-toplevel', {\r\n encoding: 'utf-8',\r\n cwd: process.cwd(),\r\n stdio: ['pipe', 'pipe', 'ignore']\r\n }).trim();\r\n if (gitRoot) {\r\n return gitRoot;\r\n }\r\n } catch {\r\n // Fall through to next method\r\n }\r\n\r\n // 3. Fall back to current working directory\r\n return process.cwd();\r\n}\r\n\r\nconst projectRoot = getProjectRoot();\r\n\r\n// Bug #6 Fix: Read Redis connection parameters from process.env\r\n// ENV-001: Standardized environment variable naming (REDIS_PASSWORD for all deployments)\r\nconst redisHost = process.env.CFN_REDIS_HOST || 'cfn-redis';\r\nconst redisPort = process.env.CFN_REDIS_PORT || '6379';\r\nconst redisPassword = process.env.CFN_REDIS_PASSWORD || process.env.REDIS_PASSWORD || '';\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 * Parse context string into environment variables\r\n *\r\n * Parses context string like \"TASK_ID='xyz' MODE='mvp' MAX_ITERATIONS=5\"\r\n * and sets the values as environment variables.\r\n *\r\n * Supports:\r\n * - Single quoted: KEY='value with spaces'\r\n * - Double quoted: KEY=\"value with spaces\"\r\n * - Unquoted: KEY=value (no spaces in value)\r\n *\r\n * @param contextString - Context string from --context parameter\r\n * @returns Object with parsed key-value pairs\r\n */\r\nfunction parseContextToEnv(contextString: string | undefined): Record<string, string> {\r\n if (!contextString) return {};\r\n\r\n const envVars: Record<string, string> = {};\r\n\r\n // Match KEY='value' or KEY=\"value\" or KEY=value patterns\r\n // For quoted values: capture everything between quotes\r\n // For unquoted values: capture until next space or end of string\r\n const regex = /(\\w+)=(?:(['\"])([^\\2]*?)\\2|([^\\s]+))/g;\r\n let match;\r\n\r\n while ((match = regex.exec(contextString)) !== null) {\r\n const [, key, , quotedValue, unquotedValue] = match;\r\n const value = quotedValue !== undefined ? quotedValue : unquotedValue;\r\n envVars[key] = value;\r\n // Also set in process.env for current process\r\n process.env[key] = value;\r\n }\r\n\r\n return envVars;\r\n}\r\n\r\n/**\r\n * Extract confidence score from agent output\r\n * Looks for patterns like:\r\n * - \"confidence: 0.85\"\r\n * - \"Confidence: 0.90\"\r\n * - \"confidence score: 0.95\"\r\n * - \"self-confidence: 0.88\"\r\n */\r\nfunction extractConfidence(output: string | undefined): number {\r\n if (!output) return 0.85;\r\n\r\n // Try multiple patterns\r\n const patterns = [\r\n /confidence:\\s*([0-9.]+)/i,\r\n /confidence\\s+score:\\s*([0-9.]+)/i,\r\n /self-confidence:\\s*([0-9.]+)/i,\r\n /my\\s+confidence:\\s*([0-9.]+)/i,\r\n ];\r\n\r\n for (const pattern of patterns) {\r\n const match = output.match(pattern);\r\n if (match && match[1]) {\r\n const score = parseFloat(match[1]);\r\n if (score >= 0 && score <= 1) {\r\n return score;\r\n }\r\n }\r\n }\r\n\r\n // Default to 0.85 if not found\r\n return 0.85;\r\n}\r\n\r\n/**\r\n * Execute CFN Loop protocol after agent completes work\r\n *\r\n * Steps:\r\n * 1. Signal completion to orchestrator\r\n * 2. Report confidence score\r\n * 3. Enter waiting mode (if iterations enabled)\r\n */\r\nasync function executeCFNProtocol(\r\n taskId: string,\r\n agentId: string,\r\n output: string | undefined,\r\n iteration: number,\r\n enableIterations: boolean = false,\r\n maxIterations: number = 10\r\n): Promise<void> {\r\n console.log(`\\n[CFN Protocol] Starting for agent ${agentId}`);\r\n console.log(`[CFN Protocol] Task ID: ${taskId}, Iteration: ${iteration}`);\r\n\r\n try {\r\n // Step 1: Signal completion\r\n console.log('[CFN Protocol] Step 1: Signaling completion...');\r\n const authFlag = redisPassword ? `-a \"${redisPassword}\"` : '';\r\n await execAsync(`redis-cli -h \"${redisHost}\" -p \"${redisPort}\" ${authFlag} lpush \"swarm:${taskId}:${agentId}:done\" \"complete\"`);\r\n console.log('[CFN Protocol] ✓ Completion signaled');\r\n\r\n // Step 2: Extract and report confidence\r\n const confidence = extractConfidence(output);\r\n console.log(`[CFN Protocol] Step 2: Reporting confidence (${confidence})...`);\r\n\r\n const reportCmd = `./.claude/skills/cfn-redis-coordination/report-completion.sh \\\r\n --task-id \"${taskId}\" \\\r\n --agent-id \"${agentId}\" \\\r\n --confidence ${confidence} \\\r\n --iteration ${iteration}`;\r\n\r\n await execAsync(reportCmd);\r\n console.log('[CFN Protocol] ✓ Confidence reported');\r\n\r\n // Step 3: Exit cleanly (BUG #18 FIX - removed waiting mode)\r\n // Orchestrator will spawn appropriate specialist agent for next iteration\r\n // This enables adaptive agent specialization based on feedback type\r\n console.log('[CFN Protocol] Step 3: Exiting cleanly (iteration complete)');\r\n console.log('[CFN Protocol] Protocol complete\\n');\r\n } catch (error) {\r\n console.error('[CFN Protocol] Error:', error);\r\n throw error;\r\n }\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(projectRoot, '.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 // BUG #24 FIX: Parse and inject context environment variables\r\n // This enables CLI-spawned agents to access TASK_ID, MODE, etc. in Bash tool\r\n if (context.context) {\r\n console.log(`[agent-executor] Parsing context: ${context.context}`);\r\n const contextEnv = parseContextToEnv(context.context);\r\n console.log(`[agent-executor] Injected env vars: ${Object.keys(contextEnv).join(', ')}`);\r\n }\r\n\r\n try {\r\n // Check for conversation fork (Sprint 4 enhancement)\r\n const forkId = process.env.FORK_ID || await getCurrentFork(context.taskId || '', agentId);\r\n const iteration = context.iteration || 1;\r\n\r\n let systemPrompt: string;\r\n let messages: Array<{role: string, content: string}> = [];\r\n\r\n if (forkId && iteration > 1) {\r\n // Continue from fork (iterations 2+)\r\n console.log(`[agent-executor] Continuing from fork: ${forkId}`);\r\n\r\n // Load fork messages\r\n const forkMessages = await loadMessages(context.taskId || '', agentId, forkId);\r\n console.log(`[agent-executor] Loaded ${forkMessages.length} messages from fork`);\r\n\r\n // Extract system prompt from first message (it's always the system message)\r\n // The fork messages are assistant/user pairs, we need to add system separately\r\n systemPrompt = forkMessages[0]?.content || '';\r\n\r\n // Format remaining messages for API\r\n messages = formatMessagesForAPI(forkMessages.slice(1));\r\n\r\n // Add new user message with feedback\r\n messages.push({\r\n role: 'user',\r\n content: prompt\r\n });\r\n\r\n console.log(`[agent-executor] Fork continuation: ${messages.length} messages`);\r\n } else {\r\n // New conversation (iteration 1)\r\n console.log('[agent-executor] Starting new conversation');\r\n console.log('[agent-executor] Building system prompt with context...');\r\n\r\n const contextOptions = loadContextFromEnv();\r\n contextOptions.agentType = definition.name;\r\n if (context.taskId) contextOptions.taskId = context.taskId;\r\n if (context.iteration) contextOptions.iteration = context.iteration;\r\n\r\n systemPrompt = await buildCLIAgentSystemPrompt(contextOptions);\r\n console.log('[agent-executor] System prompt built successfully');\r\n\r\n // Initial user message\r\n messages = [{\r\n role: 'user',\r\n content: prompt\r\n }];\r\n }\r\n\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 // Convert agent tool names to Anthropic API format\r\n const tools = definition.tools && definition.tools.length > 0\r\n ? convertToolNames(definition.tools)\r\n : undefined;\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 messages.length > 1 ? messages : undefined,\r\n undefined, // maxTokens (use default)\r\n tools // Pass converted tools\r\n );\r\n\r\n // Store messages in conversation history (for future forking)\r\n if (context.taskId) {\r\n // Store user message\r\n const userMessage: Message = {\r\n role: 'user',\r\n content: prompt,\r\n iteration,\r\n timestamp: new Date().toISOString()\r\n };\r\n await storeMessage(context.taskId, agentId, userMessage);\r\n\r\n // Store assistant response\r\n if (result.output) {\r\n const assistantMessage: Message = {\r\n role: 'assistant',\r\n content: result.output,\r\n iteration,\r\n timestamp: new Date().toISOString()\r\n };\r\n await storeMessage(context.taskId, agentId, assistantMessage);\r\n }\r\n\r\n console.log(`[agent-executor] Stored messages for iteration ${iteration}`);\r\n\r\n // Execute CFN Loop protocol (signal completion, report confidence, enter waiting mode)\r\n // Iterations are enabled for CFN Loop tasks (indicated by presence of taskId)\r\n try {\r\n const maxIterations = 10; // Default max iterations\r\n const enableIterations = true; // Enable iterations for all CFN Loop tasks\r\n\r\n await executeCFNProtocol(\r\n context.taskId,\r\n agentId,\r\n result.output,\r\n iteration,\r\n enableIterations,\r\n maxIterations\r\n );\r\n } catch (error) {\r\n console.error('[agent-executor] CFN Protocol execution failed:', error);\r\n // Don't fail the entire agent execution if CFN protocol fails\r\n // This allows agents to complete even if Redis coordination has issues\r\n }\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 // BUG #24 FIX: Parse and inject context environment variables\r\n if (context.context) {\r\n console.log(`[agent-executor] Parsing context: ${context.context}`);\r\n const contextEnv = parseContextToEnv(context.context);\r\n console.log(`[agent-executor] Injected env vars: ${Object.keys(contextEnv).join(', ')}`);\r\n }\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(projectRoot, '.claude', 'skills', 'agent-execution', 'execute-agent.sh');\r\n\r\n // Build environment variables - WHITELIST ONLY APPROACH\r\n // SECURITY FIX: Do not use ...process.env spread which exposes ALL variables including secrets\r\n // Instead, explicitly whitelist safe variables to pass to spawned process\r\n const safeEnvVars = [\r\n 'CFN_REDIS_HOST',\r\n 'CFN_REDIS_PORT',\r\n 'CFN_REDIS_PASSWORD', // CRITICAL: Required for Redis authentication\r\n 'CFN_REDIS_URL',\r\n 'REDIS_PASSWORD', // Fallback for Redis password\r\n 'CFN_MEMORY_BUDGET',\r\n 'CFN_API_HOST',\r\n 'CFN_API_PORT',\r\n 'CFN_LOG_LEVEL',\r\n 'CFN_LOG_FORMAT',\r\n 'CFN_CONTAINER_MODE',\r\n 'CFN_DOCKER_SOCKET',\r\n 'CFN_NETWORK_NAME',\r\n 'CFN_CUSTOM_ROUTING',\r\n 'CFN_DEFAULT_PROVIDER',\r\n 'NODE_ENV',\r\n 'PATH',\r\n 'HOME',\r\n 'PWD' // Required for working directory context\r\n ];\r\n\r\n const env: Record<string, string> = {};\r\n\r\n // Add whitelisted variables\r\n for (const key of safeEnvVars) {\r\n const value = process.env[key];\r\n if (value !== undefined) {\r\n env[key] = value;\r\n }\r\n }\r\n\r\n // Add API key only when explicitly needed (with strict validation)\r\n if (process.env.ANTHROPIC_API_KEY) {\r\n if (process.env.ANTHROPIC_API_KEY.match(/^sk-[a-zA-Z0-9-]+$/)) {\r\n env.ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY;\r\n }\r\n }\r\n\r\n // Add agent execution context (safe values)\r\n env.AGENT_TYPE = definition.name;\r\n env.AGENT_ID = agentId;\r\n env.AGENT_MODEL = definition.model;\r\n env.AGENT_TOOLS = definition.tools.join(',');\r\n env.TASK_ID = context.taskId || '';\r\n env.ITERATION = String(context.iteration || 1);\r\n env.MODE = context.mode || 'cli';\r\n env.PROMPT_FILE = promptFile;\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","exec","promisify","getAgentId","buildCLIAgentSystemPrompt","loadContextFromEnv","loadMessages","storeMessage","getCurrentFork","formatMessagesForAPI","convertToolNames","fs","path","os","execSync","execAsync","getProjectRoot","process","env","PROJECT_ROOT","gitRoot","encoding","cwd","stdio","trim","projectRoot","redisHost","CFN_REDIS_HOST","redisPort","CFN_REDIS_PORT","redisPassword","CFN_REDIS_PASSWORD","REDIS_PASSWORD","parseContextToEnv","contextString","envVars","regex","match","key","quotedValue","unquotedValue","value","undefined","extractConfidence","output","patterns","pattern","score","parseFloat","executeCFNProtocol","taskId","agentId","iteration","enableIterations","maxIterations","console","log","authFlag","confidence","reportCmd","error","isCustomRoutingEnabled","CLAUDE_API_PROVIDER","configPath","join","config","JSON","parse","readFile","provider","getAPIProvider","customEnabled","executeViaAPI","definition","prompt","context","name","model","contextEnv","Object","keys","forkId","FORK_ID","systemPrompt","messages","forkMessages","length","content","slice","push","role","contextOptions","agentType","executeAgentAPI","tools","result","userMessage","timestamp","Date","toISOString","assistantMessage","success","exitCode","Error","message","String","executeViaScript","tmpDir","tmpdir","promptFile","now","writeFile","Promise","resolve","scriptPath","safeEnvVars","ANTHROPIC_API_KEY","AGENT_TYPE","AGENT_ID","AGENT_MODEL","AGENT_TOOLS","TASK_ID","ITERATION","MODE","mode","PROMPT_FILE","access","then","proc","on","code","err","catch","substring","executeAgent","options","method","includes","saveAgentOutput","outputDir","mkdir","recursive","replace","filename","filepath"],"mappings":"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"}
|
|
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 { exec } from 'child_process';\r\nimport { promisify } from 'util';\r\nimport { createClient, RedisClientType } from 'redis';\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 {\r\n loadMessages,\r\n storeMessage,\r\n getCurrentFork,\r\n formatMessagesForAPI,\r\n type Message\r\n} from './conversation-fork.js';\r\nimport { convertToolNames } from './tool-definitions.js';\r\nimport { AgentCommandProcessor, type AgentCommand } from './coordination/agent-messaging.js';\r\nimport fs from 'fs/promises';\r\nimport fsSync from 'fs';\r\nimport path from 'path';\r\nimport os from 'os';\r\nimport { execSync } from 'child_process';\r\n\r\nconst execAsync = promisify(exec);\r\n\r\n// DEBUG: File-based logging for background agents (stdio: 'ignore' masks errors)\r\nconst AGENT_ID = process.env.AGENT_ID || 'unknown';\r\nconst LOG_FILE = `/tmp/cfn-agent-${AGENT_ID}.log`;\r\nfunction debugLog(message: string, data?: any) {\r\n const timestamp = new Date().toISOString();\r\n const logEntry = data\r\n ? `${timestamp} [${AGENT_ID}] ${message} ${JSON.stringify(data)}\\n`\r\n : `${timestamp} [${AGENT_ID}] ${message}\\n`;\r\n try {\r\n fsSync.appendFileSync(LOG_FILE, logEntry);\r\n } catch (err) {\r\n // Ignore logging errors\r\n }\r\n}\r\n\r\ndebugLog('=== Agent Executor Started ===');\r\n\r\n/**\r\n * Detect project root dynamically\r\n * Uses PROJECT_ROOT env var if set, otherwise tries git, falls back to cwd\r\n */\r\nfunction getProjectRoot(): string {\r\n // 1. Check environment variable\r\n if (process.env.PROJECT_ROOT) {\r\n return process.env.PROJECT_ROOT;\r\n }\r\n\r\n // 2. Try git rev-parse (most reliable)\r\n try {\r\n const gitRoot = execSync('git rev-parse --show-toplevel', {\r\n encoding: 'utf-8',\r\n cwd: process.cwd(),\r\n stdio: ['pipe', 'pipe', 'ignore']\r\n }).trim();\r\n if (gitRoot) {\r\n return gitRoot;\r\n }\r\n } catch {\r\n // Fall through to next method\r\n }\r\n\r\n // 3. Fall back to current working directory\r\n return process.cwd();\r\n}\r\n\r\nconst projectRoot = getProjectRoot();\r\n\r\n// Bug #6 Fix: Read Redis connection parameters from process.env\r\n// ENV-001: Standardized environment variable naming (REDIS_PASSWORD for all deployments)\r\n// ROOT CAUSE #2 FIX: Don't fall back to REDIS_PASSWORD from parent env (CLI mode has no password)\r\n// FIX: Default to 'localhost' for CLI mode (host execution), not 'cfn-redis' (Docker)\r\n// CLI agents run on the host and connect to Redis at localhost:6379\r\n// Docker agents should have CFN_REDIS_HOST explicitly set to their container network hostname\r\nconst redisHost = process.env.CFN_REDIS_HOST || 'localhost';\r\nconst redisPort = process.env.CFN_REDIS_PORT || '6379';\r\nconst redisPassword = process.env.CFN_REDIS_PASSWORD || '';\r\n\r\n/**\r\n * Validate task ID format to prevent command injection\r\n * Allows: optional namespace prefix (e.g., \"cli:\", \"task:\"), alphanumeric, hyphens, underscores, dots\r\n * Pattern: /^([a-z]+:)?[a-zA-Z0-9_.-]+$/\r\n * - Optional prefix: lowercase letters followed by colon\r\n * - Main ID: alphanumeric, hyphens, underscores, dots\r\n * @param taskId - The task ID to validate\r\n * @throws Error if taskId is invalid\r\n */\r\nfunction validateTaskId(taskId: string): void {\r\n if (!taskId || !/^([a-z]+:)?[a-zA-Z0-9_.-]+$/.test(taskId)) {\r\n throw new Error(`Invalid task ID format: \"${taskId}\". Must contain optional namespace prefix (e.g., \"cli:\") and alphanumeric characters, hyphens, underscores, or dots.`);\r\n }\r\n}\r\n\r\n/**\r\n * Validate agent ID format to prevent command injection\r\n * Allows: alphanumeric, hyphens, underscores\r\n * @param agentId - The agent ID to validate\r\n * @throws Error if agentId is invalid\r\n */\r\nfunction validateAgentId(agentId: string): void {\r\n if (!agentId || !/^[a-zA-Z0-9_-]+$/.test(agentId)) {\r\n throw new Error(`Invalid agent ID format: \"${agentId}\". Must contain only alphanumeric characters, hyphens, and underscores.`);\r\n }\r\n}\r\n\r\n/**\r\n * Create a Redis client with proper connection handling\r\n * Uses environment variables for connection configuration\r\n * @returns Promise<RedisClientType> - Connected Redis client\r\n */\r\nasync function createRedisClient(): Promise<RedisClientType> {\r\n debugLog('createRedisClient: Starting Redis connection attempt');\r\n debugLog('Redis config', { host: redisHost, port: redisPort, hasPassword: !!redisPassword });\r\n console.error('[DEBUG] createRedisClient: Starting Redis connection...');\r\n console.error(`[DEBUG] Redis config: host=${redisHost}, port=${redisPort}, hasPassword=${!!redisPassword}`);\r\n\r\n const portNum = parseInt(redisPort, 10);\r\n debugLog(`createRedisClient: Creating client for ${redisHost}:${portNum}`);\r\n\r\n const client = createClient({\r\n socket: {\r\n host: redisHost,\r\n port: portNum,\r\n reconnectStrategy: (retries) => Math.min(retries * 50, 500),\r\n connectTimeout: 5000,\r\n },\r\n password: redisPassword || undefined,\r\n });\r\n\r\n client.on('error', (err: Error) => {\r\n debugLog('Redis Client Error event triggered', { error: err.message, stack: err.stack });\r\n console.error('[DEBUG] Redis Client Error:', err);\r\n });\r\n\r\n debugLog('createRedisClient: Client created, calling connect()');\r\n console.error('[DEBUG] createRedisClient: Client created, attempting connection...');\r\n\r\n await client.connect();\r\n\r\n debugLog('createRedisClient: ✓ Connected successfully');\r\n console.error('[DEBUG] createRedisClient: ✓ Connected successfully');\r\n return client;\r\n}\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 * Parse context string into environment variables\r\n *\r\n * Parses context string like \"TASK_ID='xyz' MODE='mvp' MAX_ITERATIONS=5\"\r\n * and sets the values as environment variables.\r\n *\r\n * Supports:\r\n * - Single quoted: KEY='value with spaces'\r\n * - Double quoted: KEY=\"value with spaces\"\r\n * - Unquoted: KEY=value (no spaces in value)\r\n *\r\n * @param contextString - Context string from --context parameter\r\n * @returns Object with parsed key-value pairs\r\n */\r\nfunction parseContextToEnv(contextString: string | undefined): Record<string, string> {\r\n if (!contextString) return {};\r\n\r\n const envVars: Record<string, string> = {};\r\n\r\n // Match KEY='value' or KEY=\"value\" or KEY=value patterns\r\n // For quoted values: capture everything between quotes\r\n // For unquoted values: capture until next space or end of string\r\n const regex = /(\\w+)=(?:(['\"])([^\\2]*?)\\2|([^\\s]+))/g;\r\n let match;\r\n\r\n while ((match = regex.exec(contextString)) !== null) {\r\n const [, key, , quotedValue, unquotedValue] = match;\r\n const value = quotedValue !== undefined ? quotedValue : unquotedValue;\r\n envVars[key] = value;\r\n // Also set in process.env for current process\r\n process.env[key] = value;\r\n }\r\n\r\n return envVars;\r\n}\r\n\r\n/**\r\n * Extract confidence score from agent output\r\n * Looks for patterns like:\r\n * - \"confidence: 0.85\"\r\n * - \"Confidence: 0.90\"\r\n * - \"confidence score: 0.95\"\r\n * - \"self-confidence: 0.88\"\r\n */\r\nfunction extractConfidence(output: string | undefined): number {\r\n if (!output) return 0.85;\r\n\r\n // Try multiple patterns\r\n const patterns = [\r\n /confidence:\\s*([0-9.]+)/i,\r\n /confidence\\s+score:\\s*([0-9.]+)/i,\r\n /self-confidence:\\s*([0-9.]+)/i,\r\n /my\\s+confidence:\\s*([0-9.]+)/i,\r\n ];\r\n\r\n for (const pattern of patterns) {\r\n const match = output.match(pattern);\r\n if (match && match[1]) {\r\n const score = parseFloat(match[1]);\r\n if (score >= 0 && score <= 1) {\r\n return score;\r\n }\r\n }\r\n }\r\n\r\n // Default to 0.85 if not found\r\n return 0.85;\r\n}\r\n\r\n/**\r\n * Execute CFN Loop protocol after agent completes work\r\n *\r\n * Steps:\r\n * 1. Signal completion to orchestrator and Main Chat via Redis (includes confidence)\r\n * 2. Exit cleanly (orchestrator spawns next agent if needed)\r\n *\r\n * Note: Confidence is included in the completion signal JSON payload.\r\n * The deprecated report-completion.sh script has been removed (Bug #4 fix).\r\n */\r\nasync function executeCFNProtocol(\r\n taskId: string,\r\n agentId: string,\r\n output: string | undefined,\r\n iteration: number,\r\n enableIterations: boolean = false,\r\n maxIterations: number = 10\r\n): Promise<void> {\r\n console.error('[DEBUG] executeCFNProtocol: ENTRY POINT REACHED');\r\n console.log(`\\n[CFN Protocol] Starting for agent ${agentId}`);\r\n console.log(`[CFN Protocol] Task ID: ${taskId}, Iteration: ${iteration}`);\r\n\r\n // SECURITY FIX: Validate inputs to prevent command injection\r\n console.error('[DEBUG] executeCFNProtocol: Validating taskId and agentId...');\r\n validateTaskId(taskId);\r\n validateAgentId(agentId);\r\n console.error('[DEBUG] executeCFNProtocol: Validation passed');\r\n\r\n let redisClient: RedisClientType | null = null;\r\n\r\n try {\r\n // Step 1: Signal completion using Redis client (NOT shell commands)\r\n debugLog('executeCFNProtocol: Starting Step 1 (Redis signaling)', { taskId, agentId, iteration });\r\n console.error('[DEBUG] executeCFNProtocol: Starting Step 1 (Redis signaling)...');\r\n console.log('[CFN Protocol] Step 1: Signaling completion...');\r\n\r\n debugLog('executeCFNProtocol: Calling createRedisClient()');\r\n redisClient = await createRedisClient();\r\n debugLog('executeCFNProtocol: Redis client obtained successfully');\r\n console.error('[DEBUG] executeCFNProtocol: Redis client obtained');\r\n\r\n // Signal to orchestrator (CFN Loop coordination) - using parameterized Redis call\r\n const orchestratorKey = `swarm:${taskId}:${agentId}:done`;\r\n debugLog('executeCFNProtocol: Sending orchestrator signal', { key: orchestratorKey });\r\n console.error(`[DEBUG] executeCFNProtocol: Sending orchestrator signal to key: swarm:${taskId}:${agentId}:done`);\r\n\r\n await redisClient.lPush(orchestratorKey, 'complete');\r\n\r\n debugLog('executeCFNProtocol: Orchestrator signal sent successfully');\r\n console.error('[DEBUG] executeCFNProtocol: Orchestrator signal sent successfully');\r\n console.log('[CFN Protocol] ✓ Orchestrator signal sent');\r\n\r\n // Signal to Main Chat (CLI mode coordination - correct key format) - using parameterized Redis call\r\n const mainChatKey = `cfn:cli:${taskId}:completion`;\r\n debugLog('executeCFNProtocol: Preparing Main Chat signal', { key: mainChatKey });\r\n console.error(`[DEBUG] executeCFNProtocol: Preparing Main Chat signal for key: cfn:cli:${taskId}:completion`);\r\n\r\n const confidence = extractConfidence(output);\r\n const agentMetadata = JSON.stringify({\r\n agentId,\r\n taskId,\r\n status: 'completed',\r\n iteration,\r\n confidence,\r\n });\r\n debugLog('executeCFNProtocol: Agent metadata prepared', { metadata: agentMetadata, confidence });\r\n\r\n await redisClient.lPush(mainChatKey, agentMetadata);\r\n\r\n debugLog('executeCFNProtocol: Main Chat signal sent successfully');\r\n console.error('[DEBUG] executeCFNProtocol: Main Chat signal sent successfully');\r\n console.log('[CFN Protocol] ✓ Main Chat signal sent');\r\n console.log(`[CFN Protocol] ✓ Confidence reported: ${confidence}`);\r\n\r\n // Step 2: Exit cleanly (BUG #18 FIX - removed waiting mode)\r\n // Orchestrator will spawn appropriate specialist agent for next iteration\r\n // This enables adaptive agent specialization based on feedback type\r\n debugLog('executeCFNProtocol: Step 2 - Exiting cleanly');\r\n console.error('[DEBUG] executeCFNProtocol: Step 2 - Exiting cleanly...');\r\n console.log('[CFN Protocol] Step 2: Exiting cleanly (iteration complete)');\r\n console.log('[CFN Protocol] Protocol complete\\n');\r\n debugLog('executeCFNProtocol: ✓ PROTOCOL COMPLETED SUCCESSFULLY');\r\n console.error('[DEBUG] executeCFNProtocol: ✓ PROTOCOL COMPLETED SUCCESSFULLY');\r\n } catch (error) {\r\n const errorDetails = error instanceof Error ? {\r\n message: error.message,\r\n stack: error.stack,\r\n name: error.name\r\n } : { error: String(error) };\r\n debugLog('executeCFNProtocol: ERROR CAUGHT', errorDetails);\r\n console.error('[DEBUG] executeCFNProtocol: ERROR CAUGHT:', error);\r\n console.error('[CFN Protocol] Error:', error);\r\n throw error;\r\n } finally {\r\n // Always close the Redis connection\r\n debugLog('executeCFNProtocol: FINALLY block - cleaning up Redis client');\r\n console.error('[DEBUG] executeCFNProtocol: FINALLY block - cleaning up Redis client...');\r\n if (redisClient) {\r\n await redisClient.quit();\r\n debugLog('executeCFNProtocol: Redis client closed successfully');\r\n console.error('[DEBUG] executeCFNProtocol: Redis client closed');\r\n } else {\r\n debugLog('executeCFNProtocol: No Redis client to close');\r\n }\r\n debugLog('executeCFNProtocol: FINALLY block complete');\r\n console.error('[DEBUG] executeCFNProtocol: FINALLY block complete');\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Bidirectional Messaging Support (v2.0)\r\n// ============================================================================\r\n\r\n/**\r\n * Agent state that can be modified by Main Chat commands\r\n */\r\ninterface AgentRuntimeState {\r\n paused: boolean;\r\n abortRequested: boolean;\r\n redirectContext?: string;\r\n lastCommandTime?: string;\r\n}\r\n\r\n/**\r\n * Start command processor for bidirectional messaging with Main Chat\r\n *\r\n * Enables Main Chat to send commands to running agents:\r\n * - status: Request agent status update\r\n * - redirect: Redirect agent to new task context\r\n * - abort: Request clean agent abort\r\n * - pause: Pause agent for N seconds\r\n */\r\nfunction startCommandProcessor(\r\n taskId: string,\r\n agentId: string,\r\n state: AgentRuntimeState\r\n): AgentCommandProcessor | null {\r\n // Only start if Redis is available and we have valid IDs\r\n if (!taskId || !agentId) {\r\n debugLog('startCommandProcessor: Skipping - missing taskId or agentId');\r\n return null;\r\n }\r\n\r\n try {\r\n debugLog('startCommandProcessor: Creating processor', { taskId, agentId });\r\n\r\n const processor = new AgentCommandProcessor({\r\n taskId,\r\n agentId,\r\n redisHost: redisHost,\r\n redisPort: parseInt(redisPort, 10),\r\n redisPassword: redisPassword || undefined\r\n });\r\n\r\n // Register redirect handler - updates agent context\r\n processor.onCommand('redirect', async (command: AgentCommand) => {\r\n debugLog('Command received: redirect', command.payload);\r\n console.log(`[agent-msg] Received redirect command`);\r\n\r\n if (command.payload?.newTask) {\r\n state.redirectContext = command.payload.newTask as string;\r\n state.lastCommandTime = new Date().toISOString();\r\n console.log(`[agent-msg] New context: ${state.redirectContext}`);\r\n }\r\n\r\n return {\r\n agentId,\r\n taskId,\r\n status: 'running',\r\n timestamp: new Date().toISOString(),\r\n currentStep: 'Acknowledged redirect',\r\n metadata: { redirectedTo: state.redirectContext }\r\n };\r\n });\r\n\r\n // Register custom status handler with more detail\r\n processor.onCommand('status', async (_command: AgentCommand) => {\r\n debugLog('Command received: status request');\r\n console.log(`[agent-msg] Received status request`);\r\n\r\n return {\r\n agentId,\r\n taskId,\r\n status: state.paused ? 'paused' : (state.abortRequested ? 'aborting' : 'running'),\r\n timestamp: new Date().toISOString(),\r\n metadata: {\r\n paused: state.paused,\r\n abortRequested: state.abortRequested,\r\n redirectContext: state.redirectContext,\r\n lastCommandTime: state.lastCommandTime\r\n }\r\n };\r\n });\r\n\r\n // Register abort handler\r\n processor.onCommand('abort', async (_command: AgentCommand) => {\r\n debugLog('Command received: abort request');\r\n console.log(`[agent-msg] Received abort request - will exit after current task`);\r\n state.abortRequested = true;\r\n state.lastCommandTime = new Date().toISOString();\r\n\r\n return {\r\n agentId,\r\n taskId,\r\n status: 'aborting',\r\n timestamp: new Date().toISOString()\r\n };\r\n });\r\n\r\n // Start processor in background (non-blocking)\r\n processor.start(3).catch(err => {\r\n debugLog('Command processor error', { error: err.message });\r\n console.error('[agent-msg] Command processor error:', err);\r\n });\r\n\r\n debugLog('startCommandProcessor: Started successfully');\r\n console.log(`[agent-msg] Command processor started for ${agentId}`);\r\n\r\n return processor;\r\n } catch (err) {\r\n debugLog('startCommandProcessor: Failed to start', { error: err instanceof Error ? err.message : String(err) });\r\n console.error('[agent-msg] Failed to start command processor:', err);\r\n return null;\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Provider Configuration\r\n// ============================================================================\r\n\r\n/**\r\n * Supported provider types for API routing\r\n */\r\ntype ProviderType = 'anthropic' | 'zai' | 'kimi' | 'openrouter';\r\n\r\n/**\r\n * Check if custom routing (non-Anthropic) is enabled\r\n *\r\n * BUG FIX: Now checks both CLAUDE_API_PROVIDER (legacy) and PROVIDER (from --provider flag)\r\n */\r\nasync function isCustomRoutingEnabled(): Promise<boolean> {\r\n // Check environment variables - support both conventions\r\n const envProvider = process.env.CLAUDE_API_PROVIDER || process.env.PROVIDER;\r\n\r\n if (envProvider && envProvider !== 'anthropic') {\r\n debugLog('isCustomRoutingEnabled: Custom provider from env', { provider: envProvider });\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(projectRoot, '.claude', 'config', 'api-provider.json');\r\n const config = JSON.parse(await fs.readFile(configPath, 'utf-8'));\r\n const isCustom = config.provider && config.provider !== 'anthropic';\r\n debugLog('isCustomRoutingEnabled: Config file result', { provider: config.provider, isCustom });\r\n return isCustom;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Get API provider configuration\r\n *\r\n * Resolution order:\r\n * 1. CLAUDE_API_PROVIDER env var (legacy)\r\n * 2. PROVIDER env var (from CLI --provider flag)\r\n * 3. Config file\r\n * 4. Default to Z.ai (cost-effective fallback)\r\n *\r\n * BUG FIX: Previously only returned 'anthropic' | 'zai', now supports all providers\r\n * BUG FIX: Previously defaulted to Anthropic, now defaults to Z.ai\r\n */\r\nasync function getAPIProvider(): Promise<ProviderType> {\r\n // Check environment variables\r\n const envProvider = process.env.CLAUDE_API_PROVIDER || process.env.PROVIDER;\r\n\r\n if (envProvider) {\r\n const normalized = envProvider.toLowerCase() as ProviderType;\r\n if (['anthropic', 'zai', 'z.ai', 'kimi', 'openrouter'].includes(normalized)) {\r\n const result = normalized === 'z.ai' ? 'zai' : normalized;\r\n debugLog('getAPIProvider: Resolved from env', { envProvider, result });\r\n console.error(`[agent-executor] Provider from env: ${result}`);\r\n return result as ProviderType;\r\n }\r\n }\r\n\r\n // Check config file\r\n try {\r\n const configPath = path.join(projectRoot, '.claude', 'config', 'api-provider.json');\r\n const config = JSON.parse(await fs.readFile(configPath, 'utf-8'));\r\n if (config.provider) {\r\n const normalized = config.provider.toLowerCase();\r\n if (['anthropic', 'zai', 'z.ai', 'kimi', 'openrouter'].includes(normalized)) {\r\n const result = normalized === 'z.ai' ? 'zai' : normalized;\r\n debugLog('getAPIProvider: Resolved from config', { configProvider: config.provider, result });\r\n console.error(`[agent-executor] Provider from config: ${result}`);\r\n return result as ProviderType;\r\n }\r\n }\r\n } catch {\r\n // Config file doesn't exist, use default\r\n }\r\n\r\n // Default to Z.ai (cost-effective fallback)\r\n debugLog('getAPIProvider: Using default', { result: 'zai' });\r\n console.error('[agent-executor] Provider defaulting to: zai');\r\n return 'zai';\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 debugLog('executeViaAPI: FUNCTION ENTRY', { agentType: definition.name });\r\n console.error('[DEBUG] executeViaAPI: FUNCTION ENTRY');\r\n const agentId = getAgentId(definition, context);\r\n\r\n debugLog('executeViaAPI: Agent initialized', {\r\n agentId,\r\n taskId: context.taskId,\r\n iteration: context.iteration,\r\n hasContext: !!context.context\r\n });\r\n console.error(`[DEBUG] executeViaAPI: Generated agentId=${agentId}`);\r\n console.error(`[DEBUG] executeViaAPI: context.taskId=${context.taskId}, context.iteration=${context.iteration}`);\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 // BUG #24 FIX: Parse and inject context environment variables\r\n // This enables CLI-spawned agents to access TASK_ID, MODE, etc. in Bash tool\r\n if (context.context) {\r\n console.log(`[agent-executor] Parsing context: ${context.context}`);\r\n const contextEnv = parseContextToEnv(context.context);\r\n console.log(`[agent-executor] Injected env vars: ${Object.keys(contextEnv).join(', ')}`);\r\n }\r\n\r\n // v2.0: Initialize runtime state for bidirectional messaging\r\n const runtimeState: AgentRuntimeState = {\r\n paused: false,\r\n abortRequested: false\r\n };\r\n\r\n // v2.0: Start command processor for Main Chat communication\r\n let commandProcessor: AgentCommandProcessor | null = null;\r\n if (context.taskId) {\r\n commandProcessor = startCommandProcessor(context.taskId, agentId, runtimeState);\r\n }\r\n\r\n try {\r\n // Check for conversation fork (Sprint 4 enhancement)\r\n const forkId = process.env.FORK_ID || await getCurrentFork(context.taskId || '', agentId);\r\n const iteration = context.iteration || 1;\r\n\r\n let systemPrompt: string;\r\n let messages: Array<{role: string, content: string}> = [];\r\n\r\n if (forkId && iteration > 1) {\r\n // Continue from fork (iterations 2+)\r\n console.log(`[agent-executor] Continuing from fork: ${forkId}`);\r\n\r\n // Load fork messages\r\n const forkMessages = await loadMessages(context.taskId || '', agentId, forkId);\r\n console.log(`[agent-executor] Loaded ${forkMessages.length} messages from fork`);\r\n\r\n // Extract system prompt from first message (it's always the system message)\r\n // The fork messages are assistant/user pairs, we need to add system separately\r\n systemPrompt = forkMessages[0]?.content || '';\r\n\r\n // Format remaining messages for API\r\n messages = formatMessagesForAPI(forkMessages.slice(1));\r\n\r\n // Add new user message with feedback\r\n messages.push({\r\n role: 'user',\r\n content: prompt\r\n });\r\n\r\n console.log(`[agent-executor] Fork continuation: ${messages.length} messages`);\r\n } else {\r\n // New conversation (iteration 1)\r\n console.log('[agent-executor] Starting new conversation');\r\n console.log('[agent-executor] Building system prompt with context...');\r\n\r\n const contextOptions = loadContextFromEnv();\r\n contextOptions.agentType = definition.name;\r\n if (context.taskId) contextOptions.taskId = context.taskId;\r\n if (context.iteration) contextOptions.iteration = context.iteration;\r\n\r\n systemPrompt = await buildCLIAgentSystemPrompt(contextOptions);\r\n console.log('[agent-executor] System prompt built successfully');\r\n\r\n // Initial user message\r\n messages = [{\r\n role: 'user',\r\n content: prompt\r\n }];\r\n }\r\n\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 // Convert agent tool names to Anthropic API format\r\n debugLog('[TOOL DEBUG] definition.tools check', {\r\n hasTools: !!definition.tools,\r\n toolsLength: definition.tools?.length || 0,\r\n toolNames: definition.tools || []\r\n });\r\n console.error(`[TOOL DEBUG] definition.tools: ${JSON.stringify(definition.tools)}`);\r\n\r\n const tools = definition.tools && definition.tools.length > 0\r\n ? convertToolNames(definition.tools)\r\n : undefined;\r\n\r\n debugLog('[TOOL DEBUG] converted tools', {\r\n hasConvertedTools: !!tools,\r\n convertedToolsCount: tools?.length || 0,\r\n convertedToolNames: tools?.map(t => t.name) || []\r\n });\r\n console.error(`[TOOL DEBUG] Converted tools: ${tools?.map(t => t.name).join(', ') || 'NONE'}`);\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 messages.length > 1 ? messages : undefined,\r\n undefined, // maxTokens (use default)\r\n tools // Pass converted tools\r\n );\r\n\r\n // Store messages in conversation history (for future forking)\r\n if (context.taskId) {\r\n // Store user message\r\n const userMessage: Message = {\r\n role: 'user',\r\n content: prompt,\r\n iteration,\r\n timestamp: new Date().toISOString()\r\n };\r\n await storeMessage(context.taskId, agentId, userMessage);\r\n\r\n // Store assistant response\r\n if (result.output) {\r\n const assistantMessage: Message = {\r\n role: 'assistant',\r\n content: result.output,\r\n iteration,\r\n timestamp: new Date().toISOString()\r\n };\r\n await storeMessage(context.taskId, agentId, assistantMessage);\r\n }\r\n\r\n console.log(`[agent-executor] Stored messages for iteration ${iteration}`);\r\n\r\n // Execute CFN Loop protocol (signal completion, report confidence, enter waiting mode)\r\n // Iterations are enabled for CFN Loop tasks (indicated by presence of taskId)\r\n debugLog('agent-executor: About to execute CFN Protocol', {\r\n taskId: context.taskId,\r\n agentId,\r\n iteration,\r\n outputLength: result.output.length\r\n });\r\n console.error('[DEBUG] agent-executor: About to execute CFN Protocol...');\r\n console.error(`[DEBUG] agent-executor: taskId=${context.taskId}, agentId=${agentId}, iteration=${iteration}`);\r\n try {\r\n const maxIterations = 10; // Default max iterations\r\n const enableIterations = true; // Enable iterations for all CFN Loop tasks\r\n\r\n debugLog('agent-executor: Calling executeCFNProtocol', { maxIterations, enableIterations });\r\n console.error('[DEBUG] agent-executor: Calling executeCFNProtocol...');\r\n await executeCFNProtocol(\r\n context.taskId,\r\n agentId,\r\n result.output,\r\n iteration,\r\n enableIterations,\r\n maxIterations\r\n );\r\n debugLog('agent-executor: ✓ executeCFNProtocol returned successfully');\r\n console.error('[DEBUG] agent-executor: ✓ executeCFNProtocol returned successfully');\r\n } catch (error) {\r\n const errorDetails = error instanceof Error ? {\r\n message: error.message,\r\n stack: error.stack\r\n } : { error: String(error) };\r\n debugLog('agent-executor: ✗ executeCFNProtocol threw error', errorDetails);\r\n console.error('[DEBUG] agent-executor: ✗ executeCFNProtocol threw error:', error);\r\n console.error('[agent-executor] CFN Protocol execution failed:', error);\r\n // Don't fail the entire agent execution if CFN protocol fails\r\n // This allows agents to complete even if Redis coordination has issues\r\n }\r\n console.error('[DEBUG] agent-executor: CFN Protocol section complete');\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 } finally {\r\n // v2.0: Clean up command processor\r\n if (commandProcessor) {\r\n debugLog('executeViaAPI: Stopping command processor');\r\n console.log('[agent-msg] Stopping command processor');\r\n await commandProcessor.stop();\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 // BUG #24 FIX: Parse and inject context environment variables\r\n if (context.context) {\r\n console.log(`[agent-executor] Parsing context: ${context.context}`);\r\n const contextEnv = parseContextToEnv(context.context);\r\n console.log(`[agent-executor] Injected env vars: ${Object.keys(contextEnv).join(', ')}`);\r\n }\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(projectRoot, '.claude', 'skills', 'agent-execution', 'execute-agent.sh');\r\n\r\n // Build environment variables - WHITELIST ONLY APPROACH\r\n // SECURITY FIX: Do not use ...process.env spread which exposes ALL variables including secrets\r\n // Instead, explicitly whitelist safe variables to pass to spawned process\r\n const safeEnvVars = [\r\n 'CFN_REDIS_HOST',\r\n 'CFN_REDIS_PORT',\r\n 'CFN_REDIS_PASSWORD', // CRITICAL: Required for Redis authentication\r\n 'CFN_REDIS_URL',\r\n 'REDIS_PASSWORD', // Fallback for Redis password\r\n 'CFN_MEMORY_BUDGET',\r\n 'CFN_API_HOST',\r\n 'CFN_API_PORT',\r\n 'CFN_LOG_LEVEL',\r\n 'CFN_LOG_FORMAT',\r\n 'CFN_CONTAINER_MODE',\r\n 'CFN_DOCKER_SOCKET',\r\n 'CFN_NETWORK_NAME',\r\n 'CFN_CUSTOM_ROUTING',\r\n 'CFN_DEFAULT_PROVIDER',\r\n 'NODE_ENV',\r\n 'PATH',\r\n 'HOME',\r\n 'PWD' // Required for working directory context\r\n ];\r\n\r\n const env: Record<string, string> = {};\r\n\r\n // Add whitelisted variables\r\n for (const key of safeEnvVars) {\r\n const value = process.env[key];\r\n if (value !== undefined) {\r\n env[key] = value;\r\n }\r\n }\r\n\r\n // Add API key only when explicitly needed (with strict validation)\r\n if (process.env.ANTHROPIC_API_KEY) {\r\n if (process.env.ANTHROPIC_API_KEY.match(/^sk-[a-zA-Z0-9-]+$/)) {\r\n env.ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY;\r\n }\r\n }\r\n\r\n // Add agent execution context (safe values)\r\n env.AGENT_TYPE = definition.name;\r\n env.AGENT_ID = agentId;\r\n env.AGENT_MODEL = definition.model;\r\n env.AGENT_TOOLS = definition.tools.join(',');\r\n env.TASK_ID = context.taskId || '';\r\n env.ITERATION = String(context.iteration || 1);\r\n env.MODE = context.mode || 'cli';\r\n env.PROMPT_FILE = promptFile;\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 debugLog('executeAgent: Starting execution', {\r\n agentType: definition.name,\r\n method,\r\n taskId: context.taskId,\r\n iteration: context.iteration,\r\n agentId: context.agentId || 'not-set'\r\n });\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 debugLog('executeAgent: Attempting API execution');\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 debugLog('executeAgent: API key not found, falling back to script');\r\n console.log('[agent-executor] API key not found, using script fallback');\r\n return executeViaScript(definition, prompt, context);\r\n }\r\n debugLog('executeAgent: API execution error', { error: error instanceof Error ? error.message : String(error) });\r\n throw error;\r\n }\r\n }\r\n\r\n if (method === 'api') {\r\n debugLog('executeAgent: Using API method');\r\n return executeViaAPI(definition, prompt, context);\r\n }\r\n\r\n debugLog('executeAgent: Using script method');\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\r\n/**\r\n * Main entry point when run as a script via tsx\r\n */\r\nasync function main() {\r\n // Parse command line arguments\r\n const args = process.argv.slice(2);\r\n let agentType: string | undefined;\r\n\r\n for (let i = 0; i < args.length; i++) {\r\n if (args[i] === '--agent-type' && i + 1 < args.length) {\r\n agentType = args[i + 1];\r\n break;\r\n }\r\n }\r\n\r\n if (!agentType) {\r\n console.error('[agent-executor] ERROR: --agent-type is required');\r\n process.exit(1);\r\n }\r\n\r\n // Load agent definition\r\n const { parseAgentDefinition } = await import('./agent-definition-parser.js');\r\n const definition = await parseAgentDefinition(agentType);\r\n\r\n if (!definition) {\r\n console.error(`[agent-executor] ERROR: Agent type not found: ${agentType}`);\r\n process.exit(1);\r\n }\r\n\r\n // Build task context from environment variables\r\n const context: TaskContext = {\r\n taskId: process.env.TASK_ID,\r\n iteration: process.env.ITERATION ? parseInt(process.env.ITERATION, 10) : 1,\r\n mode: process.env.MODE || 'cli',\r\n agentId: process.env.AGENT_ID,\r\n context: process.env.CONTEXT\r\n };\r\n\r\n // Get prompt from environment variable or use default\r\n const prompt = process.env.PROMPT || `Execute your assigned task for ${agentType}.\r\n\r\nYou are part of a CFN Loop workflow. Review any broadcast messages, complete your work, and report your confidence score.`;\r\n\r\n console.log(`[agent-executor] Starting agent: ${agentType}`);\r\n console.log(`[agent-executor] Task ID: ${context.taskId || 'none'}`);\r\n console.log(`[agent-executor] Iteration: ${context.iteration}`);\r\n console.log(`[agent-executor] Prompt source: ${process.env.PROMPT ? 'PROMPT env var' : 'default'}`);\r\n\r\n // Execute agent\r\n const result = await executeAgent(definition, prompt, context);\r\n\r\n // Exit with appropriate code\r\n if (!result.success) {\r\n console.error(`[agent-executor] Agent execution failed: ${result.error || 'unknown error'}`);\r\n process.exit(result.exitCode || 1);\r\n }\r\n\r\n console.log('[agent-executor] Agent execution completed successfully');\r\n process.exit(0);\r\n}\r\n\r\n// Run main if executed as a script\r\nif (import.meta.url === `file://${process.argv[1]}`) {\r\n main().catch((error) => {\r\n console.error('[agent-executor] Fatal error:', error);\r\n process.exit(1);\r\n });\r\n}\r\n"],"names":["spawn","exec","promisify","createClient","getAgentId","buildCLIAgentSystemPrompt","loadContextFromEnv","loadMessages","storeMessage","getCurrentFork","formatMessagesForAPI","convertToolNames","AgentCommandProcessor","fs","fsSync","path","os","execSync","execAsync","AGENT_ID","process","env","LOG_FILE","debugLog","message","data","timestamp","Date","toISOString","logEntry","JSON","stringify","appendFileSync","err","getProjectRoot","PROJECT_ROOT","gitRoot","encoding","cwd","stdio","trim","projectRoot","redisHost","CFN_REDIS_HOST","redisPort","CFN_REDIS_PORT","redisPassword","CFN_REDIS_PASSWORD","validateTaskId","taskId","test","Error","validateAgentId","agentId","createRedisClient","host","port","hasPassword","console","error","portNum","parseInt","client","socket","reconnectStrategy","retries","Math","min","connectTimeout","password","undefined","on","stack","connect","parseContextToEnv","contextString","envVars","regex","match","key","quotedValue","unquotedValue","value","extractConfidence","output","patterns","pattern","score","parseFloat","executeCFNProtocol","iteration","enableIterations","maxIterations","log","redisClient","orchestratorKey","lPush","mainChatKey","confidence","agentMetadata","status","metadata","errorDetails","name","String","quit","startCommandProcessor","state","processor","onCommand","command","payload","newTask","redirectContext","lastCommandTime","currentStep","redirectedTo","_command","paused","abortRequested","start","catch","isCustomRoutingEnabled","envProvider","CLAUDE_API_PROVIDER","PROVIDER","provider","configPath","join","config","parse","readFile","isCustom","getAPIProvider","normalized","toLowerCase","includes","result","configProvider","executeViaAPI","definition","prompt","context","agentType","hasContext","model","contextEnv","Object","keys","runtimeState","commandProcessor","forkId","FORK_ID","systemPrompt","messages","forkMessages","length","content","slice","push","role","contextOptions","executeAgentAPI","hasTools","tools","toolsLength","toolNames","hasConvertedTools","convertedToolsCount","convertedToolNames","map","t","userMessage","assistantMessage","outputLength","success","exitCode","stop","executeViaScript","tmpDir","tmpdir","promptFile","now","writeFile","Promise","resolve","scriptPath","safeEnvVars","ANTHROPIC_API_KEY","AGENT_TYPE","AGENT_MODEL","AGENT_TOOLS","TASK_ID","ITERATION","MODE","mode","PROMPT_FILE","access","then","proc","code","substring","executeAgent","options","method","saveAgentOutput","outputDir","mkdir","recursive","replace","filename","filepath","main","args","argv","i","exit","parseAgentDefinition","CONTEXT","PROMPT","url"],"mappings":"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"}
|
|
@@ -46,7 +46,7 @@ const signal = {
|
|
|
46
46
|
const client = createClient({ url: 'redis://localhost:6379' });
|
|
47
47
|
await client.connect();
|
|
48
48
|
|
|
49
|
-
const signalKey = \`cfn:
|
|
49
|
+
const signalKey = \`cfn:cli:\${process.env.TASK_ID}:completion\`;
|
|
50
50
|
await client.lPush(signalKey, JSON.stringify(signal));
|
|
51
51
|
|
|
52
52
|
console.log(\`✅ Completion signal sent to Main Chat via Redis\`);
|
|
@@ -74,7 +74,7 @@ After sending the signal, exit immediately. Main Chat is waiting for your Redis
|
|
|
74
74
|
|
|
75
75
|
**Main Chat Workflow:**
|
|
76
76
|
1. Spawns you via CLI with specific provider/model
|
|
77
|
-
2. Waits via \`redis-cli BLPOP cfn:
|
|
77
|
+
2. Waits via \`redis-cli BLPOP cfn:cli:${taskId}:completion\`
|
|
78
78
|
3. Processes your completion signal when received
|
|
79
79
|
4. Continues with next task or spawns additional agents
|
|
80
80
|
|
|
@@ -1 +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 * - Skills (Phase 5 - Skills Database integration)\r\n */\r\n\r\nimport { AgentDefinition, hasCFNLoopProtocol } from './agent-definition-parser.js';\r\nimport { loadIterationHistory, formatIterationHistory } from './iteration-history.js';\r\nimport { SkillLoader, Skill } from './skill-loader.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 agentId?: string;\r\n keywords?: string; // Phase 5: For skill filtering\r\n phase?: string; // Phase 5: CFN Loop phase (loop1, loop2, loop3)\r\n}\r\n\r\n/**\r\n * Build CLI Mode Redis Completion Protocol for CLI Mode\r\n */\r\nfunction buildCLIModeProtocol(taskId: string, agentId: string): string {\r\n return `\r\n## CLI Mode Redis Completion Protocol\r\n\r\nYou are running in CLI Mode with Main Chat coordination. Follow this protocol EXACTLY:\r\n\r\n### Step 1: Complete Your Work\r\nExecute your assigned task (implementation, review, testing, etc.)\r\n\r\n### Step 2: Signal Completion to Main Chat\r\nSend a Redis signal to notify Main Chat that you're finished:\r\n\r\n\\`\\`\\`bash\r\n# Use Node.js for Redis communication\r\nnode -e \"\r\nconst { createClient } = require('redis');\r\nconst signal = {\r\n agentId: '${agentId}',\r\n taskId: '${taskId}',\r\n status: 'completed',\r\n timestamp: new Date().toISOString(),\r\n provider: process.env.PROVIDER || 'unknown',\r\n model: process.env.MODEL || 'unknown',\r\n confidence: 0.90, // Replace with your actual confidence\r\n metadata: {\r\n iteration: process.env.ITERATION || 1,\r\n mode: process.env.MODE || 'standard'\r\n }\r\n};\r\n\r\n(async () => {\r\n const client = createClient({ url: 'redis://localhost:6379' });\r\n await client.connect();\r\n\r\n const signalKey = \\`cfn:mainchat:signal:\\${process.env.TASK_ID}\\`;\r\n await client.lPush(signalKey, JSON.stringify(signal));\r\n\r\n console.log(\\`✅ Completion signal sent to Main Chat via Redis\\`);\r\n await client.disconnect();\r\n})();\r\n\"\r\n\\`\\`\\`\r\n\r\n### Step 3: Exit Cleanly\r\nAfter sending the signal, exit immediately. Main Chat is waiting for your Redis signal.\r\n\r\n**Why This Protocol:**\r\n- Main Chat uses Redis BLPOP to wait for your completion signal\r\n- Enables simple 2-layer coordination (Main Chat → CLI agents)\r\n- No complex orchestrator needed for CLI mode\r\n- Supports different AI providers via environment variables\r\n\r\n**Environment Variables Available:**\r\n- TASK_ID: ${taskId}\r\n- AGENT_ID: ${agentId}\r\n- PROVIDER: AI provider (zai, kimi, anthropic, etc.)\r\n- MODEL: Specific model being used\r\n- ITERATION: Current iteration number\r\n- MODE: Execution mode (mvp, standard, enterprise)\r\n\r\n**Main Chat Workflow:**\r\n1. Spawns you via CLI with specific provider/model\r\n2. Waits via \\`redis-cli BLPOP cfn:mainchat:signal:${taskId}\\`\r\n3. Processes your completion signal when received\r\n4. Continues with next task or spawns additional agents\r\n\r\n**CRITICAL:** Send Redis signal before exiting. Main Chat cannot proceed without your completion signal.\r\n`;\r\n}\r\n\r\n/**\r\n * Parse shell variable format into JSON object\r\n * Example: \"WORKSPACE='/tmp/test' MODE='standard'\" -> {WORKSPACE: '/tmp/test', MODE: 'standard'}\r\n */\r\nfunction parseShellVariables(shellContext: string): any {\r\n const jsonObj: any = {};\r\n const regex = /([A-Z_]+)='([^']*)'/g;\r\n let match;\r\n while ((match = regex.exec(shellContext)) !== null) {\r\n jsonObj[match[1]] = match[2];\r\n }\r\n return jsonObj;\r\n}\r\n\r\n/**\r\n * Parse and enrich JSON context into natural language instructions\r\n */\r\nfunction enrichJSONContext(jsonObj: any): string {\r\n const sections: string[] = [];\r\n\r\n // Extract task description (support both 'task' and 'taskDescription' keys)\r\n const taskText = jsonObj.task || jsonObj.taskDescription;\r\n if (taskText) {\r\n sections.push(`**Task:** ${taskText}`);\r\n }\r\n\r\n // Parse files - convert comma-separated string to bullet list\r\n if (jsonObj.files) {\r\n const fileList = typeof jsonObj.files === 'string'\r\n ? jsonObj.files.split(',').map(f => f.trim()).filter(f => f)\r\n : Array.isArray(jsonObj.files) ? jsonObj.files : [];\r\n\r\n if (fileList.length > 0) {\r\n sections.push('\\n**Files to process:**');\r\n fileList.forEach(file => sections.push(`- ${file}`));\r\n }\r\n }\r\n\r\n // Add requirements/deliverables\r\n if (jsonObj.requirements) {\r\n const reqs = Array.isArray(jsonObj.requirements) ? jsonObj.requirements : [jsonObj.requirements];\r\n sections.push('\\n**Requirements:**');\r\n reqs.forEach((req, i) => sections.push(`${i + 1}. ${req}`));\r\n }\r\n\r\n if (jsonObj.deliverables) {\r\n const delivs = Array.isArray(jsonObj.deliverables) ? jsonObj.deliverables : [jsonObj.deliverables];\r\n sections.push('\\n**Deliverables:**');\r\n delivs.forEach(deliv => sections.push(`- ${deliv}`));\r\n }\r\n\r\n // Add batch information\r\n if (jsonObj.batch) {\r\n sections.push(`\\n**Batch:** ${jsonObj.batch}`);\r\n }\r\n\r\n // Add directory context - support 'directory', 'WORKSPACE', and 'workspace' keys\r\n const workspacePath = jsonObj.directory || jsonObj.WORKSPACE || jsonObj.workspace;\r\n if (workspacePath) {\r\n sections.push(`\\n**Working Directory:** ${workspacePath}`);\r\n }\r\n\r\n // Add acceptance criteria\r\n if (jsonObj.acceptanceCriteria) {\r\n const criteria = Array.isArray(jsonObj.acceptanceCriteria)\r\n ? jsonObj.acceptanceCriteria\r\n : [jsonObj.acceptanceCriteria];\r\n sections.push('\\n**Acceptance Criteria:**');\r\n criteria.forEach(criterion => sections.push(`- ${criterion}`));\r\n }\r\n\r\n // Add explicit instructions if present\r\n if (jsonObj.instructions) {\r\n sections.push('\\n**Instructions:**');\r\n const instrs = Array.isArray(jsonObj.instructions) ? jsonObj.instructions : [jsonObj.instructions];\r\n instrs.forEach((instr, i) => sections.push(`${i + 1}. ${instr}`));\r\n }\r\n\r\n return sections.join('\\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 // Try to parse context in multiple formats\r\n let contextStr = context.context.trim();\r\n\r\n // Parse shell variables BEFORE attempting JSON parse\r\n if (contextStr.includes('=') && !contextStr.startsWith('{')) {\r\n const jsonObj = parseShellVariables(contextStr);\r\n desc = enrichJSONContext(jsonObj);\r\n\r\n // Add instruction footer for structured tasks\r\n if (jsonObj.files || jsonObj.deliverables) {\r\n desc += '\\n\\n**Process each item systematically and report confidence when complete.**';\r\n }\r\n }\r\n // Check if context looks like JSON\r\n else if ((contextStr.startsWith('{') && contextStr.endsWith('}')) ||\r\n (contextStr.startsWith('[') && contextStr.endsWith(']'))) {\r\n try {\r\n const jsonObj = JSON.parse(contextStr);\r\n desc = enrichJSONContext(jsonObj);\r\n\r\n // Add instruction footer for structured tasks\r\n if (jsonObj.files || jsonObj.deliverables) {\r\n desc += '\\n\\n**Process each item systematically and report confidence when complete.**';\r\n }\r\n } catch (e) {\r\n // Not valid JSON, treat as plain text\r\n desc = context.context;\r\n }\r\n } else {\r\n // Plain text context\r\n desc = context.context;\r\n }\r\n } else {\r\n desc = `Execute task as ${agentType} agent`;\r\n }\r\n\r\n // Add metadata fields\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 // Docker workspace detection\r\n const isDockerEnv = process.env.DOCKER_AGENT === 'true' || process.env.WORKSPACE_ROOT;\r\n const workspaceRoot = process.env.WORKSPACE_ROOT || '/workspace';\r\n\r\n if (isDockerEnv) {\r\n env.push(`WORKSPACE_ROOT=${workspaceRoot}`);\r\n }\r\n\r\n // Always include Docker context if detected, even if env array is empty\r\n if (isDockerEnv && env.length === 0) {\r\n env.push(`WORKSPACE_ROOT=${workspaceRoot}`);\r\n }\r\n\r\n if (env.length === 0 && !isDockerEnv) return '';\r\n\r\n let contextText = `\r\n## Environment Variables\r\n\r\n\\`\\`\\`bash\r\n${env.join('\\n')}\r\n\\`\\`\\`\r\n`;\r\n\r\n // Add Docker workspace notice if detected\r\n if (isDockerEnv) {\r\n contextText += `\r\n\r\n## Docker Container Environment\r\n\r\n**CRITICAL:** You are running inside a Docker container.\r\n\r\n- **Working Directory:** \\`${workspaceRoot}\\`\r\n- **File Paths:** All file operations use \\`${workspaceRoot}/\\` prefix\r\n- **Example:** To read \\`src/file.ts\\`, use \\`${workspaceRoot}/src/file.ts\\`\r\n\r\n**DO NOT** use paths from your training data or Main Chat context. Use \\`${workspaceRoot}/\\` for all file operations.\r\n`;\r\n }\r\n\r\n return contextText;\r\n}\r\n\r\n/**\r\n * Load skills for agent (Phase 5: Skills Database Integration)\r\n */\r\nasync function loadSkillsForAgent(\r\n agentType: string,\r\n context: TaskContext\r\n): Promise<Skill[]> {\r\n // Feature flag check\r\n if (process.env.CFN_SKILLS_DATABASE !== 'true') {\r\n return [];\r\n }\r\n\r\n try {\r\n const dbPath = process.env.CFN_SKILLS_DB_PATH || './.claude/skills-database/skills.db';\r\n const skillLoader = new SkillLoader(dbPath, {\r\n enableCache: true,\r\n cacheMaxSize: 100,\r\n cacheTTL: 60000 // 1 minute\r\n });\r\n\r\n // Extract keywords from context for filtering\r\n const keywords = context.keywords || context.context?.toLowerCase() || '';\r\n\r\n const skills = await skillLoader.loadSkillsForAgent(agentType, {\r\n taskId: context.taskId,\r\n keywords,\r\n phase: context.phase,\r\n mode: context.mode,\r\n iteration: context.iteration\r\n });\r\n\r\n skillLoader.close();\r\n return skills;\r\n } catch (error) {\r\n console.warn(`[agent-prompt-builder] Failed to load skills: ${error}`);\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * Format skills for prompt injection\r\n */\r\nfunction formatSkillsForPrompt(skills: Skill[]): string {\r\n if (skills.length === 0) {\r\n return '';\r\n }\r\n\r\n const sections: string[] = [];\r\n\r\n sections.push('## Applicable Skills');\r\n sections.push('');\r\n sections.push('The following skills have been loaded based on your agent type and task context:');\r\n sections.push('');\r\n\r\n for (const skill of skills) {\r\n const approvalBadge = skill.approvalLevel === 'auto' ? '✓' :\r\n skill.approvalLevel === 'escalate' ? '⚠' : '✋';\r\n sections.push(`### ${skill.name} (v${skill.version}) [${approvalBadge} ${skill.approvalLevel}]`);\r\n sections.push('');\r\n if (skill.content) {\r\n sections.push(skill.content);\r\n } else {\r\n sections.push(`*Skill content not available*`);\r\n }\r\n sections.push('');\r\n }\r\n\r\n return sections.join('\\n');\r\n}\r\n\r\n/**\r\n * Build complete prompt for agent execution (async for iteration history + skills)\r\n */\r\nexport async function buildAgentPrompt(\r\n definition: AgentDefinition,\r\n context: TaskContext\r\n): Promise<string> {\r\n // Use explicit agent ID if provided, otherwise generate from name + iteration\r\n const agentId = context.agentId || `${definition.name}-${context.iteration || 1}`;\r\n const startTime = Date.now();\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 // 4a. Load and inject skills (Phase 5: Skills Database Integration)\r\n try {\r\n const skills = await loadSkillsForAgent(definition.type || definition.name, context);\r\n\r\n if (skills.length > 0) {\r\n const skillsText = formatSkillsForPrompt(skills);\r\n sections.push(skillsText);\r\n sections.push('');\r\n\r\n // Log skill usage for analytics (Phase 5)\r\n if (process.env.CFN_SKILLS_DATABASE === 'true' && context.taskId) {\r\n try {\r\n const dbPath = process.env.CFN_SKILLS_DB_PATH || './.claude/skills-database/skills.db';\r\n const skillLoader = new SkillLoader(dbPath);\r\n\r\n await skillLoader.logSkillUsage({\r\n agentId: agentId,\r\n agentType: definition.type || definition.name,\r\n skillIds: skills.map(s => s.id).filter(id => id > 0), // Exclude bootstrap skills (negative IDs)\r\n taskId: context.taskId,\r\n phase: context.phase,\r\n loadedAt: new Date(),\r\n executionTimeMs: Date.now() - startTime\r\n });\r\n\r\n skillLoader.close();\r\n } catch (logError) {\r\n console.warn(`[agent-prompt-builder] Failed to log skill usage: ${logError}`);\r\n }\r\n }\r\n }\r\n } catch (skillError) {\r\n console.warn(`[agent-prompt-builder] Skill loading failed: ${skillError}`);\r\n // Continue without skills\r\n }\r\n\r\n // 5. CLI Mode protocol (ALWAYS inject when taskId present - enables Redis coordination)\r\n if (context.taskId && agentId) {\r\n sections.push(buildCLIModeProtocol(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 // 7a. Pre-edit backup requirement (MANDATORY)\r\n sections.push('## Pre-Edit Backup Protocol (MANDATORY)');\r\n sections.push('');\r\n sections.push('**BEFORE ANY Edit/Write/MultiEdit operation, you MUST create a backup:**');\r\n sections.push('');\r\n sections.push('```bash');\r\n sections.push(`BACKUP_PATH=$(./.claude/hooks/cfn-invoke-pre-edit.sh \"$FILE_TO_EDIT\" --agent-id \"${agentId}\")`);\r\n sections.push('```');\r\n sections.push('');\r\n sections.push('**Why:** Enables safe file revert without git operations during parallel sessions.');\r\n sections.push('**Location:** `.backups/[agent-id]/[timestamp]_[hash]/`');\r\n sections.push('**Retention:** 24h TTL (configurable)');\r\n sections.push('');\r\n sections.push('**Complete Edit Workflow:**');\r\n sections.push('```bash');\r\n sections.push('# 1. Pre-Edit: Create backup');\r\n sections.push(`BACKUP_PATH=$(./.claude/hooks/cfn-invoke-pre-edit.sh \"src/file.ts\" --agent-id \"${agentId}\")`);\r\n sections.push('');\r\n sections.push('# 2. Edit: Perform file modification');\r\n sections.push('Edit: file_path=\"src/file.ts\" old_string=\"...\" new_string=\"...\"');\r\n sections.push('');\r\n sections.push('# 3. Post-Edit: Validate changes');\r\n sections.push(`./.claude/hooks/cfn-invoke-post-edit.sh \"src/file.ts\" --agent-id \"${agentId}\"`);\r\n sections.push('```');\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 * If agentId is explicitly provided in context, use it; otherwise generate from name + iteration\r\n */\r\nexport function getAgentId(definition: AgentDefinition, context: TaskContext): string {\r\n if (context.agentId) {\r\n return context.agentId;\r\n }\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":["loadIterationHistory","formatIterationHistory","SkillLoader","buildCLIModeProtocol","taskId","agentId","parseShellVariables","shellContext","jsonObj","regex","match","exec","enrichJSONContext","sections","taskText","task","taskDescription","push","files","fileList","split","map","f","trim","filter","Array","isArray","length","forEach","file","requirements","reqs","req","i","deliverables","delivs","deliv","batch","workspacePath","directory","WORKSPACE","workspace","acceptanceCriteria","criteria","criterion","instructions","instrs","instr","join","buildTaskDescription","agentType","context","desc","contextStr","includes","startsWith","endsWith","JSON","parse","e","iteration","mode","priority","parentTaskId","buildEnvironmentContext","env","isDockerEnv","process","DOCKER_AGENT","WORKSPACE_ROOT","workspaceRoot","contextText","loadSkillsForAgent","CFN_SKILLS_DATABASE","dbPath","CFN_SKILLS_DB_PATH","skillLoader","enableCache","cacheMaxSize","cacheTTL","keywords","toLowerCase","skills","phase","close","error","console","warn","formatSkillsForPrompt","skill","approvalBadge","approvalLevel","name","version","content","buildAgentPrompt","definition","startTime","Date","now","description","history","historyText","err","type","skillsText","logSkillUsage","skillIds","s","id","loadedAt","executionTimeMs","logError","skillError","envContext","tools","getAgentId","buildSystemPrompt","model"],"mappings":"AAAA;;;;;;;;;;CAUC,GAGD,SAASA,oBAAoB,EAAEC,sBAAsB,QAAQ,yBAAyB;AACtF,SAASC,WAAW,QAAe,oBAAoB;AAcvD;;CAEC,GACD,SAASC,qBAAqBC,MAAc,EAAEC,OAAe;IAC3D,OAAO,CAAC;;;;;;;;;;;;;;;;YAgBE,EAAEA,QAAQ;WACX,EAAED,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAmCT,EAAEA,OAAO;YACR,EAAEC,QAAQ;;;;;;;;mDAQ6B,EAAED,OAAO;;;;;AAK5D,CAAC;AACD;AAEA;;;CAGC,GACD,SAASE,oBAAoBC,YAAoB;IAC/C,MAAMC,UAAe,CAAC;IACtB,MAAMC,QAAQ;IACd,IAAIC;IACJ,MAAO,AAACA,CAAAA,QAAQD,MAAME,IAAI,CAACJ,aAAY,MAAO,KAAM;QAClDC,OAAO,CAACE,KAAK,CAAC,EAAE,CAAC,GAAGA,KAAK,CAAC,EAAE;IAC9B;IACA,OAAOF;AACT;AAEA;;CAEC,GACD,SAASI,kBAAkBJ,OAAY;IACrC,MAAMK,WAAqB,EAAE;IAE7B,4EAA4E;IAC5E,MAAMC,WAAWN,QAAQO,IAAI,IAAIP,QAAQQ,eAAe;IACxD,IAAIF,UAAU;QACZD,SAASI,IAAI,CAAC,CAAC,UAAU,EAAEH,UAAU;IACvC;IAEA,8DAA8D;IAC9D,IAAIN,QAAQU,KAAK,EAAE;QACjB,MAAMC,WAAW,OAAOX,QAAQU,KAAK,KAAK,WACtCV,QAAQU,KAAK,CAACE,KAAK,CAAC,KAAKC,GAAG,CAACC,CAAAA,IAAKA,EAAEC,IAAI,IAAIC,MAAM,CAACF,CAAAA,IAAKA,KACxDG,MAAMC,OAAO,CAAClB,QAAQU,KAAK,IAAIV,QAAQU,KAAK,GAAG,EAAE;QAErD,IAAIC,SAASQ,MAAM,GAAG,GAAG;YACvBd,SAASI,IAAI,CAAC;YACdE,SAASS,OAAO,CAACC,CAAAA,OAAQhB,SAASI,IAAI,CAAC,CAAC,EAAE,EAAEY,MAAM;QACpD;IACF;IAEA,gCAAgC;IAChC,IAAIrB,QAAQsB,YAAY,EAAE;QACxB,MAAMC,OAAON,MAAMC,OAAO,CAAClB,QAAQsB,YAAY,IAAItB,QAAQsB,YAAY,GAAG;YAACtB,QAAQsB,YAAY;SAAC;QAChGjB,SAASI,IAAI,CAAC;QACdc,KAAKH,OAAO,CAAC,CAACI,KAAKC,IAAMpB,SAASI,IAAI,CAAC,GAAGgB,IAAI,EAAE,EAAE,EAAED,KAAK;IAC3D;IAEA,IAAIxB,QAAQ0B,YAAY,EAAE;QACxB,MAAMC,SAASV,MAAMC,OAAO,CAAClB,QAAQ0B,YAAY,IAAI1B,QAAQ0B,YAAY,GAAG;YAAC1B,QAAQ0B,YAAY;SAAC;QAClGrB,SAASI,IAAI,CAAC;QACdkB,OAAOP,OAAO,CAACQ,CAAAA,QAASvB,SAASI,IAAI,CAAC,CAAC,EAAE,EAAEmB,OAAO;IACpD;IAEA,wBAAwB;IACxB,IAAI5B,QAAQ6B,KAAK,EAAE;QACjBxB,SAASI,IAAI,CAAC,CAAC,aAAa,EAAET,QAAQ6B,KAAK,EAAE;IAC/C;IAEA,iFAAiF;IACjF,MAAMC,gBAAgB9B,QAAQ+B,SAAS,IAAI/B,QAAQgC,SAAS,IAAIhC,QAAQiC,SAAS;IACjF,IAAIH,eAAe;QACjBzB,SAASI,IAAI,CAAC,CAAC,yBAAyB,EAAEqB,eAAe;IAC3D;IAEA,0BAA0B;IAC1B,IAAI9B,QAAQkC,kBAAkB,EAAE;QAC9B,MAAMC,WAAWlB,MAAMC,OAAO,CAAClB,QAAQkC,kBAAkB,IACrDlC,QAAQkC,kBAAkB,GAC1B;YAAClC,QAAQkC,kBAAkB;SAAC;QAChC7B,SAASI,IAAI,CAAC;QACd0B,SAASf,OAAO,CAACgB,CAAAA,YAAa/B,SAASI,IAAI,CAAC,CAAC,EAAE,EAAE2B,WAAW;IAC9D;IAEA,uCAAuC;IACvC,IAAIpC,QAAQqC,YAAY,EAAE;QACxBhC,SAASI,IAAI,CAAC;QACd,MAAM6B,SAASrB,MAAMC,OAAO,CAAClB,QAAQqC,YAAY,IAAIrC,QAAQqC,YAAY,GAAG;YAACrC,QAAQqC,YAAY;SAAC;QAClGC,OAAOlB,OAAO,CAAC,CAACmB,OAAOd,IAAMpB,SAASI,IAAI,CAAC,GAAGgB,IAAI,EAAE,EAAE,EAAEc,OAAO;IACjE;IAEA,OAAOlC,SAASmC,IAAI,CAAC;AACvB;AAEA;;CAEC,GACD,SAASC,qBAAqBC,SAAiB,EAAEC,OAAoB;IACnE,IAAIC,OAAO;IAEX,IAAID,QAAQA,OAAO,EAAE;QACnB,2CAA2C;QAC3C,IAAIE,aAAaF,QAAQA,OAAO,CAAC5B,IAAI;QAErC,qDAAqD;QACrD,IAAI8B,WAAWC,QAAQ,CAAC,QAAQ,CAACD,WAAWE,UAAU,CAAC,MAAM;YAC3D,MAAM/C,UAAUF,oBAAoB+C;YACpCD,OAAOxC,kBAAkBJ;YAEzB,8CAA8C;YAC9C,IAAIA,QAAQU,KAAK,IAAIV,QAAQ0B,YAAY,EAAE;gBACzCkB,QAAQ;YACV;QACF,OAEK,IAAI,AAACC,WAAWE,UAAU,CAAC,QAAQF,WAAWG,QAAQ,CAAC,QACvDH,WAAWE,UAAU,CAAC,QAAQF,WAAWG,QAAQ,CAAC,MAAO;YAC5D,IAAI;gBACF,MAAMhD,UAAUiD,KAAKC,KAAK,CAACL;gBAC3BD,OAAOxC,kBAAkBJ;gBAEzB,8CAA8C;gBAC9C,IAAIA,QAAQU,KAAK,IAAIV,QAAQ0B,YAAY,EAAE;oBACzCkB,QAAQ;gBACV;YACF,EAAE,OAAOO,GAAG;gBACV,sCAAsC;gBACtCP,OAAOD,QAAQA,OAAO;YACxB;QACF,OAAO;YACL,qBAAqB;YACrBC,OAAOD,QAAQA,OAAO;QACxB;IACF,OAAO;QACLC,OAAO,CAAC,gBAAgB,EAAEF,UAAU,MAAM,CAAC;IAC7C;IAEA,sBAAsB;IACtB,IAAIC,QAAQ/C,MAAM,EAAE;QAClBgD,QAAQ,CAAC,iBAAiB,EAAED,QAAQ/C,MAAM,EAAE;IAC9C;IAEA,IAAI+C,QAAQS,SAAS,EAAE;QACrBR,QAAQ,CAAC,iBAAiB,EAAED,QAAQS,SAAS,EAAE;IACjD;IAEA,IAAIT,QAAQU,IAAI,EAAE;QAChBT,QAAQ,CAAC,YAAY,EAAED,QAAQU,IAAI,EAAE;IACvC;IAEA,IAAIV,QAAQW,QAAQ,EAAE;QACpBV,QAAQ,CAAC,gBAAgB,EAAED,QAAQW,QAAQ,EAAE;IAC/C;IAEA,IAAIX,QAAQY,YAAY,EAAE;QACxBX,QAAQ,CAAC,mBAAmB,EAAED,QAAQY,YAAY,EAAE;IACtD;IAEA,OAAOX;AACT;AAEA;;CAEC,GACD,SAASY,wBAAwBb,OAAoB;IACnD,MAAMc,MAAgB,EAAE;IAExB,IAAId,QAAQ/C,MAAM,EAAE6D,IAAIhD,IAAI,CAAC,CAAC,QAAQ,EAAEkC,QAAQ/C,MAAM,EAAE;IACxD,IAAI+C,QAAQS,SAAS,EAAEK,IAAIhD,IAAI,CAAC,CAAC,UAAU,EAAEkC,QAAQS,SAAS,EAAE;IAChE,IAAIT,QAAQU,IAAI,EAAEI,IAAIhD,IAAI,CAAC,CAAC,KAAK,EAAEkC,QAAQU,IAAI,EAAE;IACjD,IAAIV,QAAQW,QAAQ,EAAEG,IAAIhD,IAAI,CAAC,CAAC,SAAS,EAAEkC,QAAQW,QAAQ,EAAE;IAC7D,IAAIX,QAAQY,YAAY,EAAEE,IAAIhD,IAAI,CAAC,CAAC,eAAe,EAAEkC,QAAQY,YAAY,EAAE;IAE3E,6BAA6B;IAC7B,MAAMG,cAAcC,QAAQF,GAAG,CAACG,YAAY,KAAK,UAAUD,QAAQF,GAAG,CAACI,cAAc;IACrF,MAAMC,gBAAgBH,QAAQF,GAAG,CAACI,cAAc,IAAI;IAEpD,IAAIH,aAAa;QACfD,IAAIhD,IAAI,CAAC,CAAC,eAAe,EAAEqD,eAAe;IAC5C;IAEA,wEAAwE;IACxE,IAAIJ,eAAeD,IAAItC,MAAM,KAAK,GAAG;QACnCsC,IAAIhD,IAAI,CAAC,CAAC,eAAe,EAAEqD,eAAe;IAC5C;IAEA,IAAIL,IAAItC,MAAM,KAAK,KAAK,CAACuC,aAAa,OAAO;IAE7C,IAAIK,cAAc,CAAC;;;;AAIrB,EAAEN,IAAIjB,IAAI,CAAC,MAAM;;AAEjB,CAAC;IAEC,0CAA0C;IAC1C,IAAIkB,aAAa;QACfK,eAAe,CAAC;;;;;;2BAMO,EAAED,cAAc;4CACC,EAAEA,cAAc;8CACd,EAAEA,cAAc;;yEAEW,EAAEA,cAAc;AACzF,CAAC;IACC;IAEA,OAAOC;AACT;AAEA;;CAEC,GACD,eAAeC,mBACbtB,SAAiB,EACjBC,OAAoB;IAEpB,qBAAqB;IACrB,IAAIgB,QAAQF,GAAG,CAACQ,mBAAmB,KAAK,QAAQ;QAC9C,OAAO,EAAE;IACX;IAEA,IAAI;QACF,MAAMC,SAASP,QAAQF,GAAG,CAACU,kBAAkB,IAAI;QACjD,MAAMC,cAAc,IAAI1E,YAAYwE,QAAQ;YAC1CG,aAAa;YACbC,cAAc;YACdC,UAAU,MAAM,WAAW;QAC7B;QAEA,8CAA8C;QAC9C,MAAMC,WAAW7B,QAAQ6B,QAAQ,IAAI7B,QAAQA,OAAO,EAAE8B,iBAAiB;QAEvE,MAAMC,SAAS,MAAMN,YAAYJ,kBAAkB,CAACtB,WAAW;YAC7D9C,QAAQ+C,QAAQ/C,MAAM;YACtB4E;YACAG,OAAOhC,QAAQgC,KAAK;YACpBtB,MAAMV,QAAQU,IAAI;YAClBD,WAAWT,QAAQS,SAAS;QAC9B;QAEAgB,YAAYQ,KAAK;QACjB,OAAOF;IACT,EAAE,OAAOG,OAAO;QACdC,QAAQC,IAAI,CAAC,CAAC,8CAA8C,EAAEF,OAAO;QACrE,OAAO,EAAE;IACX;AACF;AAEA;;CAEC,GACD,SAASG,sBAAsBN,MAAe;IAC5C,IAAIA,OAAOvD,MAAM,KAAK,GAAG;QACvB,OAAO;IACT;IAEA,MAAMd,WAAqB,EAAE;IAE7BA,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC;IAEd,KAAK,MAAMwE,SAASP,OAAQ;QAC1B,MAAMQ,gBAAgBD,MAAME,aAAa,KAAK,SAAS,MAClCF,MAAME,aAAa,KAAK,aAAa,MAAM;QAChE9E,SAASI,IAAI,CAAC,CAAC,IAAI,EAAEwE,MAAMG,IAAI,CAAC,GAAG,EAAEH,MAAMI,OAAO,CAAC,GAAG,EAAEH,cAAc,CAAC,EAAED,MAAME,aAAa,CAAC,CAAC,CAAC;QAC/F9E,SAASI,IAAI,CAAC;QACd,IAAIwE,MAAMK,OAAO,EAAE;YACjBjF,SAASI,IAAI,CAACwE,MAAMK,OAAO;QAC7B,OAAO;YACLjF,SAASI,IAAI,CAAC,CAAC,6BAA6B,CAAC;QAC/C;QACAJ,SAASI,IAAI,CAAC;IAChB;IAEA,OAAOJ,SAASmC,IAAI,CAAC;AACvB;AAEA;;CAEC,GACD,OAAO,eAAe+C,iBACpBC,UAA2B,EAC3B7C,OAAoB;IAEpB,8EAA8E;IAC9E,MAAM9C,UAAU8C,QAAQ9C,OAAO,IAAI,GAAG2F,WAAWJ,IAAI,CAAC,CAAC,EAAEzC,QAAQS,SAAS,IAAI,GAAG;IACjF,MAAMqC,YAAYC,KAAKC,GAAG;IAE1B,MAAMtF,WAAqB,EAAE;IAE7B,6BAA6B;IAC7BA,SAASI,IAAI,CAAC,CAAC,SAAS,EAAE+E,WAAWJ,IAAI,EAAE;IAC3C/E,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC+E,WAAWI,WAAW;IACpCvF,SAASI,IAAI,CAAC;IAEd,sBAAsB;IACtBJ,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAACgC,qBAAqB+C,WAAWJ,IAAI,EAAEzC;IACpDtC,SAASI,IAAI,CAAC;IAEd,4CAA4C;IAC5C,uDAAuD;IACvD,IAAIkC,QAAQ/C,MAAM,IAAI+C,QAAQS,SAAS,IAAIT,QAAQS,SAAS,GAAG,GAAG;QAChE,IAAI;YACF,MAAMyC,UAAU,MAAMrG,qBAAqBmD,QAAQ/C,MAAM,EAAEC,SAAS8C,QAAQS,SAAS;YACrF,MAAM0C,cAAcrG,uBAAuBoG,SAASlD,QAAQS,SAAS;YACrE/C,SAASI,IAAI,CAACqF;YACdzF,SAASI,IAAI,CAAC;QAChB,EAAE,OAAOsF,KAAK;YACZjB,QAAQC,IAAI,CAAC,CAAC,wDAAwD,CAAC,EAAEgB;QACzE,2BAA2B;QAC7B;IACF;IAEA,mDAAmD;IACnD1F,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC+E,WAAWF,OAAO;IAChCjF,SAASI,IAAI,CAAC;IAEd,oEAAoE;IACpE,IAAI;QACF,MAAMiE,SAAS,MAAMV,mBAAmBwB,WAAWQ,IAAI,IAAIR,WAAWJ,IAAI,EAAEzC;QAE5E,IAAI+B,OAAOvD,MAAM,GAAG,GAAG;YACrB,MAAM8E,aAAajB,sBAAsBN;YACzCrE,SAASI,IAAI,CAACwF;YACd5F,SAASI,IAAI,CAAC;YAEd,0CAA0C;YAC1C,IAAIkD,QAAQF,GAAG,CAACQ,mBAAmB,KAAK,UAAUtB,QAAQ/C,MAAM,EAAE;gBAChE,IAAI;oBACF,MAAMsE,SAASP,QAAQF,GAAG,CAACU,kBAAkB,IAAI;oBACjD,MAAMC,cAAc,IAAI1E,YAAYwE;oBAEpC,MAAME,YAAY8B,aAAa,CAAC;wBAC9BrG,SAASA;wBACT6C,WAAW8C,WAAWQ,IAAI,IAAIR,WAAWJ,IAAI;wBAC7Ce,UAAUzB,OAAO7D,GAAG,CAACuF,CAAAA,IAAKA,EAAEC,EAAE,EAAErF,MAAM,CAACqF,CAAAA,KAAMA,KAAK;wBAClDzG,QAAQ+C,QAAQ/C,MAAM;wBACtB+E,OAAOhC,QAAQgC,KAAK;wBACpB2B,UAAU,IAAIZ;wBACda,iBAAiBb,KAAKC,GAAG,KAAKF;oBAChC;oBAEArB,YAAYQ,KAAK;gBACnB,EAAE,OAAO4B,UAAU;oBACjB1B,QAAQC,IAAI,CAAC,CAAC,kDAAkD,EAAEyB,UAAU;gBAC9E;YACF;QACF;IACF,EAAE,OAAOC,YAAY;QACnB3B,QAAQC,IAAI,CAAC,CAAC,6CAA6C,EAAE0B,YAAY;IACzE,0BAA0B;IAC5B;IAEA,wFAAwF;IACxF,IAAI9D,QAAQ/C,MAAM,IAAIC,SAAS;QAC7BQ,SAASI,IAAI,CAACd,qBAAqBgD,QAAQ/C,MAAM,EAAEC;QACnDQ,SAASI,IAAI,CAAC;IAChB;IAEA,yBAAyB;IACzB,MAAMiG,aAAalD,wBAAwBb;IAC3C,IAAI+D,YAAY;QACdrG,SAASI,IAAI,CAACiG;QACdrG,SAASI,IAAI,CAAC;IAChB;IAEA,4BAA4B;IAC5BJ,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC;IACd,IAAIkC,QAAQS,SAAS,IAAIT,QAAQS,SAAS,GAAG,GAAG;QAC9C/C,SAASI,IAAI,CAAC;QACdJ,SAASI,IAAI,CAAC;QACdJ,SAASI,IAAI,CAAC;IAChB,OAAO;QACLJ,SAASI,IAAI,CAAC;QACdJ,SAASI,IAAI,CAAC;IAChB;IACAJ,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC;IAEd,8CAA8C;IAC9CJ,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC,CAAC,iFAAiF,EAAEZ,QAAQ,EAAE,CAAC;IAC7GQ,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC,CAAC,+EAA+E,EAAEZ,QAAQ,EAAE,CAAC;IAC3GQ,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC,CAAC,kEAAkE,EAAEZ,QAAQ,CAAC,CAAC;IAC7FQ,SAASI,IAAI,CAAC;IACdJ,SAASI,IAAI,CAAC;IAEd,mBAAmB;IACnB,IAAI+E,WAAWmB,KAAK,IAAInB,WAAWmB,KAAK,CAACxF,MAAM,GAAG,GAAG;QACnDd,SAASI,IAAI,CAAC;QACdJ,SAASI,IAAI,CAAC;QACdJ,SAASI,IAAI,CAAC,CAAC,oBAAoB,EAAE+E,WAAWmB,KAAK,CAACnE,IAAI,CAAC,OAAO;QAClEnC,SAASI,IAAI,CAAC;IAChB;IAEA,OAAOJ,SAASmC,IAAI,CAAC;AACvB;AAEA;;;CAGC,GACD,OAAO,SAASoE,WAAWpB,UAA2B,EAAE7C,OAAoB;IAC1E,IAAIA,QAAQ9C,OAAO,EAAE;QACnB,OAAO8C,QAAQ9C,OAAO;IACxB;IACA,OAAO,GAAG2F,WAAWJ,IAAI,CAAC,CAAC,EAAEzC,QAAQS,SAAS,IAAI,GAAG;AACvD;AAEA;;CAEC,GACD,OAAO,SAASyD,kBAAkBrB,UAA2B;IAC3D,OAAO,CAAC,QAAQ,EAAEA,WAAWJ,IAAI,CAAC;;MAE9B,EAAEI,WAAWQ,IAAI,IAAI,aAAa;OACjC,EAAER,WAAWsB,KAAK,CAAC;OACnB,EAAEtB,WAAWmB,KAAK,CAACnE,IAAI,CAAC,MAAM;;mFAE8C,CAAC;AACpF"}
|
|
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 * - Skills (Phase 5 - Skills Database integration)\r\n */\r\n\r\nimport { AgentDefinition, hasCFNLoopProtocol } from './agent-definition-parser.js';\r\nimport { loadIterationHistory, formatIterationHistory } from './iteration-history.js';\r\nimport { SkillLoader, Skill } from './skill-loader.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 agentId?: string;\r\n keywords?: string; // Phase 5: For skill filtering\r\n phase?: string; // Phase 5: CFN Loop phase (loop1, loop2, loop3)\r\n}\r\n\r\n/**\r\n * Build CLI Mode Redis Completion Protocol for CLI Mode\r\n */\r\nfunction buildCLIModeProtocol(taskId: string, agentId: string): string {\r\n return `\r\n## CLI Mode Redis Completion Protocol\r\n\r\nYou are running in CLI Mode with Main Chat coordination. Follow this protocol EXACTLY:\r\n\r\n### Step 1: Complete Your Work\r\nExecute your assigned task (implementation, review, testing, etc.)\r\n\r\n### Step 2: Signal Completion to Main Chat\r\nSend a Redis signal to notify Main Chat that you're finished:\r\n\r\n\\`\\`\\`bash\r\n# Use Node.js for Redis communication\r\nnode -e \"\r\nconst { createClient } = require('redis');\r\nconst signal = {\r\n agentId: '${agentId}',\r\n taskId: '${taskId}',\r\n status: 'completed',\r\n timestamp: new Date().toISOString(),\r\n provider: process.env.PROVIDER || 'unknown',\r\n model: process.env.MODEL || 'unknown',\r\n confidence: 0.90, // Replace with your actual confidence\r\n metadata: {\r\n iteration: process.env.ITERATION || 1,\r\n mode: process.env.MODE || 'standard'\r\n }\r\n};\r\n\r\n(async () => {\r\n const client = createClient({ url: 'redis://localhost:6379' });\r\n await client.connect();\r\n\r\n const signalKey = \\`cfn:cli:\\${process.env.TASK_ID}:completion\\`;\r\n await client.lPush(signalKey, JSON.stringify(signal));\r\n\r\n console.log(\\`✅ Completion signal sent to Main Chat via Redis\\`);\r\n await client.disconnect();\r\n})();\r\n\"\r\n\\`\\`\\`\r\n\r\n### Step 3: Exit Cleanly\r\nAfter sending the signal, exit immediately. Main Chat is waiting for your Redis signal.\r\n\r\n**Why This Protocol:**\r\n- Main Chat uses Redis BLPOP to wait for your completion signal\r\n- Enables simple 2-layer coordination (Main Chat → CLI agents)\r\n- No complex orchestrator needed for CLI mode\r\n- Supports different AI providers via environment variables\r\n\r\n**Environment Variables Available:**\r\n- TASK_ID: ${taskId}\r\n- AGENT_ID: ${agentId}\r\n- PROVIDER: AI provider (zai, kimi, anthropic, etc.)\r\n- MODEL: Specific model being used\r\n- ITERATION: Current iteration number\r\n- MODE: Execution mode (mvp, standard, enterprise)\r\n\r\n**Main Chat Workflow:**\r\n1. Spawns you via CLI with specific provider/model\r\n2. Waits via \\`redis-cli BLPOP cfn:cli:${taskId}:completion\\`\r\n3. Processes your completion signal when received\r\n4. Continues with next task or spawns additional agents\r\n\r\n**CRITICAL:** Send Redis signal before exiting. Main Chat cannot proceed without your completion signal.\r\n`;\r\n}\r\n\r\n/**\r\n * Parse shell variable format into JSON object\r\n * Example: \"WORKSPACE='/tmp/test' MODE='standard'\" -> {WORKSPACE: '/tmp/test', MODE: 'standard'}\r\n */\r\nfunction parseShellVariables(shellContext: string): any {\r\n const jsonObj: any = {};\r\n const regex = /([A-Z_]+)='([^']*)'/g;\r\n let match;\r\n while ((match = regex.exec(shellContext)) !== null) {\r\n jsonObj[match[1]] = match[2];\r\n }\r\n return jsonObj;\r\n}\r\n\r\n/**\r\n * Parse and enrich JSON context into natural language instructions\r\n */\r\nfunction enrichJSONContext(jsonObj: any): string {\r\n const sections: string[] = [];\r\n\r\n // Extract task description (support both 'task' and 'taskDescription' keys)\r\n const taskText = jsonObj.task || jsonObj.taskDescription;\r\n if (taskText) {\r\n sections.push(`**Task:** ${taskText}`);\r\n }\r\n\r\n // Parse files - convert comma-separated string to bullet list\r\n if (jsonObj.files) {\r\n const fileList = typeof jsonObj.files === 'string'\r\n ? jsonObj.files.split(',').map(f => f.trim()).filter(f => f)\r\n : Array.isArray(jsonObj.files) ? jsonObj.files : [];\r\n\r\n if (fileList.length > 0) {\r\n sections.push('\\n**Files to process:**');\r\n fileList.forEach(file => sections.push(`- ${file}`));\r\n }\r\n }\r\n\r\n // Add requirements/deliverables\r\n if (jsonObj.requirements) {\r\n const reqs = Array.isArray(jsonObj.requirements) ? jsonObj.requirements : [jsonObj.requirements];\r\n sections.push('\\n**Requirements:**');\r\n reqs.forEach((req, i) => sections.push(`${i + 1}. ${req}`));\r\n }\r\n\r\n if (jsonObj.deliverables) {\r\n const delivs = Array.isArray(jsonObj.deliverables) ? jsonObj.deliverables : [jsonObj.deliverables];\r\n sections.push('\\n**Deliverables:**');\r\n delivs.forEach(deliv => sections.push(`- ${deliv}`));\r\n }\r\n\r\n // Add batch information\r\n if (jsonObj.batch) {\r\n sections.push(`\\n**Batch:** ${jsonObj.batch}`);\r\n }\r\n\r\n // Add directory context - support 'directory', 'WORKSPACE', and 'workspace' keys\r\n const workspacePath = jsonObj.directory || jsonObj.WORKSPACE || jsonObj.workspace;\r\n if (workspacePath) {\r\n sections.push(`\\n**Working Directory:** ${workspacePath}`);\r\n }\r\n\r\n // Add acceptance criteria\r\n if (jsonObj.acceptanceCriteria) {\r\n const criteria = Array.isArray(jsonObj.acceptanceCriteria)\r\n ? jsonObj.acceptanceCriteria\r\n : [jsonObj.acceptanceCriteria];\r\n sections.push('\\n**Acceptance Criteria:**');\r\n criteria.forEach(criterion => sections.push(`- ${criterion}`));\r\n }\r\n\r\n // Add explicit instructions if present\r\n if (jsonObj.instructions) {\r\n sections.push('\\n**Instructions:**');\r\n const instrs = Array.isArray(jsonObj.instructions) ? jsonObj.instructions : [jsonObj.instructions];\r\n instrs.forEach((instr, i) => sections.push(`${i + 1}. ${instr}`));\r\n }\r\n\r\n return sections.join('\\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 // Try to parse context in multiple formats\r\n let contextStr = context.context.trim();\r\n\r\n // Parse shell variables BEFORE attempting JSON parse\r\n if (contextStr.includes('=') && !contextStr.startsWith('{')) {\r\n const jsonObj = parseShellVariables(contextStr);\r\n desc = enrichJSONContext(jsonObj);\r\n\r\n // Add instruction footer for structured tasks\r\n if (jsonObj.files || jsonObj.deliverables) {\r\n desc += '\\n\\n**Process each item systematically and report confidence when complete.**';\r\n }\r\n }\r\n // Check if context looks like JSON\r\n else if ((contextStr.startsWith('{') && contextStr.endsWith('}')) ||\r\n (contextStr.startsWith('[') && contextStr.endsWith(']'))) {\r\n try {\r\n const jsonObj = JSON.parse(contextStr);\r\n desc = enrichJSONContext(jsonObj);\r\n\r\n // Add instruction footer for structured tasks\r\n if (jsonObj.files || jsonObj.deliverables) {\r\n desc += '\\n\\n**Process each item systematically and report confidence when complete.**';\r\n }\r\n } catch (e) {\r\n // Not valid JSON, treat as plain text\r\n desc = context.context;\r\n }\r\n } else {\r\n // Plain text context\r\n desc = context.context;\r\n }\r\n } else {\r\n desc = `Execute task as ${agentType} agent`;\r\n }\r\n\r\n // Add metadata fields\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 // Docker workspace detection\r\n const isDockerEnv = process.env.DOCKER_AGENT === 'true' || process.env.WORKSPACE_ROOT;\r\n const workspaceRoot = process.env.WORKSPACE_ROOT || '/workspace';\r\n\r\n if (isDockerEnv) {\r\n env.push(`WORKSPACE_ROOT=${workspaceRoot}`);\r\n }\r\n\r\n // Always include Docker context if detected, even if env array is empty\r\n if (isDockerEnv && env.length === 0) {\r\n env.push(`WORKSPACE_ROOT=${workspaceRoot}`);\r\n }\r\n\r\n if (env.length === 0 && !isDockerEnv) return '';\r\n\r\n let contextText = `\r\n## Environment Variables\r\n\r\n\\`\\`\\`bash\r\n${env.join('\\n')}\r\n\\`\\`\\`\r\n`;\r\n\r\n // Add Docker workspace notice if detected\r\n if (isDockerEnv) {\r\n contextText += `\r\n\r\n## Docker Container Environment\r\n\r\n**CRITICAL:** You are running inside a Docker container.\r\n\r\n- **Working Directory:** \\`${workspaceRoot}\\`\r\n- **File Paths:** All file operations use \\`${workspaceRoot}/\\` prefix\r\n- **Example:** To read \\`src/file.ts\\`, use \\`${workspaceRoot}/src/file.ts\\`\r\n\r\n**DO NOT** use paths from your training data or Main Chat context. Use \\`${workspaceRoot}/\\` for all file operations.\r\n`;\r\n }\r\n\r\n return contextText;\r\n}\r\n\r\n/**\r\n * Load skills for agent (Phase 5: Skills Database Integration)\r\n */\r\nasync function loadSkillsForAgent(\r\n agentType: string,\r\n context: TaskContext\r\n): Promise<Skill[]> {\r\n // Feature flag check\r\n if (process.env.CFN_SKILLS_DATABASE !== 'true') {\r\n return [];\r\n }\r\n\r\n try {\r\n const dbPath = process.env.CFN_SKILLS_DB_PATH || './.claude/skills-database/skills.db';\r\n const skillLoader = new SkillLoader(dbPath, {\r\n enableCache: true,\r\n cacheMaxSize: 100,\r\n cacheTTL: 60000 // 1 minute\r\n });\r\n\r\n // Extract keywords from context for filtering\r\n const keywords = context.keywords || context.context?.toLowerCase() || '';\r\n\r\n const skills = await skillLoader.loadSkillsForAgent(agentType, {\r\n taskId: context.taskId,\r\n keywords,\r\n phase: context.phase,\r\n mode: context.mode,\r\n iteration: context.iteration\r\n });\r\n\r\n skillLoader.close();\r\n return skills;\r\n } catch (error) {\r\n console.warn(`[agent-prompt-builder] Failed to load skills: ${error}`);\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * Format skills for prompt injection\r\n */\r\nfunction formatSkillsForPrompt(skills: Skill[]): string {\r\n if (skills.length === 0) {\r\n return '';\r\n }\r\n\r\n const sections: string[] = [];\r\n\r\n sections.push('## Applicable Skills');\r\n sections.push('');\r\n sections.push('The following skills have been loaded based on your agent type and task context:');\r\n sections.push('');\r\n\r\n for (const skill of skills) {\r\n const approvalBadge = skill.approvalLevel === 'auto' ? '✓' :\r\n skill.approvalLevel === 'escalate' ? '⚠' : '✋';\r\n sections.push(`### ${skill.name} (v${skill.version}) [${approvalBadge} ${skill.approvalLevel}]`);\r\n sections.push('');\r\n if (skill.content) {\r\n sections.push(skill.content);\r\n } else {\r\n sections.push(`*Skill content not available*`);\r\n }\r\n sections.push('');\r\n }\r\n\r\n return sections.join('\\n');\r\n}\r\n\r\n/**\r\n * Build complete prompt for agent execution (async for iteration history + skills)\r\n */\r\nexport async function buildAgentPrompt(\r\n definition: AgentDefinition,\r\n context: TaskContext\r\n): Promise<string> {\r\n // Use explicit agent ID if provided, otherwise generate from name + iteration\r\n const agentId = context.agentId || `${definition.name}-${context.iteration || 1}`;\r\n const startTime = Date.now();\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 // 4a. Load and inject skills (Phase 5: Skills Database Integration)\r\n try {\r\n const skills = await loadSkillsForAgent(definition.type || definition.name, context);\r\n\r\n if (skills.length > 0) {\r\n const skillsText = formatSkillsForPrompt(skills);\r\n sections.push(skillsText);\r\n sections.push('');\r\n\r\n // Log skill usage for analytics (Phase 5)\r\n if (process.env.CFN_SKILLS_DATABASE === 'true' && context.taskId) {\r\n try {\r\n const dbPath = process.env.CFN_SKILLS_DB_PATH || './.claude/skills-database/skills.db';\r\n const skillLoader = new SkillLoader(dbPath);\r\n\r\n await skillLoader.logSkillUsage({\r\n agentId: agentId,\r\n agentType: definition.type || definition.name,\r\n skillIds: skills.map(s => s.id).filter(id => id > 0), // Exclude bootstrap skills (negative IDs)\r\n taskId: context.taskId,\r\n phase: context.phase,\r\n loadedAt: new Date(),\r\n executionTimeMs: Date.now() - startTime\r\n });\r\n\r\n skillLoader.close();\r\n } catch (logError) {\r\n console.warn(`[agent-prompt-builder] Failed to log skill usage: ${logError}`);\r\n }\r\n }\r\n }\r\n } catch (skillError) {\r\n console.warn(`[agent-prompt-builder] Skill loading failed: ${skillError}`);\r\n // Continue without skills\r\n }\r\n\r\n // 5. CLI Mode protocol (ALWAYS inject when taskId present - enables Redis coordination)\r\n if (context.taskId && agentId) {\r\n sections.push(buildCLIModeProtocol(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 // 7a. Pre-edit backup requirement (MANDATORY)\r\n sections.push('## Pre-Edit Backup Protocol (MANDATORY)');\r\n sections.push('');\r\n sections.push('**BEFORE ANY Edit/Write/MultiEdit operation, you MUST create a backup:**');\r\n sections.push('');\r\n sections.push('```bash');\r\n sections.push(`BACKUP_PATH=$(./.claude/hooks/cfn-invoke-pre-edit.sh \"$FILE_TO_EDIT\" --agent-id \"${agentId}\")`);\r\n sections.push('```');\r\n sections.push('');\r\n sections.push('**Why:** Enables safe file revert without git operations during parallel sessions.');\r\n sections.push('**Location:** `.backups/[agent-id]/[timestamp]_[hash]/`');\r\n sections.push('**Retention:** 24h TTL (configurable)');\r\n sections.push('');\r\n sections.push('**Complete Edit Workflow:**');\r\n sections.push('```bash');\r\n sections.push('# 1. Pre-Edit: Create backup');\r\n sections.push(`BACKUP_PATH=$(./.claude/hooks/cfn-invoke-pre-edit.sh \"src/file.ts\" --agent-id \"${agentId}\")`);\r\n sections.push('');\r\n sections.push('# 2. Edit: Perform file modification');\r\n sections.push('Edit: file_path=\"src/file.ts\" old_string=\"...\" new_string=\"...\"');\r\n sections.push('');\r\n sections.push('# 3. Post-Edit: Validate changes');\r\n sections.push(`./.claude/hooks/cfn-invoke-post-edit.sh \"src/file.ts\" --agent-id \"${agentId}\"`);\r\n sections.push('```');\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 * If agentId is explicitly provided in context, use it; otherwise generate from name + iteration\r\n */\r\nexport function getAgentId(definition: AgentDefinition, context: TaskContext): string {\r\n if (context.agentId) {\r\n return context.agentId;\r\n }\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":["loadIterationHistory","formatIterationHistory","SkillLoader","buildCLIModeProtocol","taskId","agentId","parseShellVariables","shellContext","jsonObj","regex","match","exec","enrichJSONContext","sections","taskText","task","taskDescription","push","files","fileList","split","map","f","trim","filter","Array","isArray","length","forEach","file","requirements","reqs","req","i","deliverables","delivs","deliv","batch","workspacePath","directory","WORKSPACE","workspace","acceptanceCriteria","criteria","criterion","instructions","instrs","instr","join","buildTaskDescription","agentType","context","desc","contextStr","includes","startsWith","endsWith","JSON","parse","e","iteration","mode","priority","parentTaskId","buildEnvironmentContext","env","isDockerEnv","process","DOCKER_AGENT","WORKSPACE_ROOT","workspaceRoot","contextText","loadSkillsForAgent","CFN_SKILLS_DATABASE","dbPath","CFN_SKILLS_DB_PATH","skillLoader","enableCache","cacheMaxSize","cacheTTL","keywords","toLowerCase","skills","phase","close","error","console","warn","formatSkillsForPrompt","skill","approvalBadge","approvalLevel","name","version","content","buildAgentPrompt","definition","startTime","Date","now","description","history","historyText","err","type","skillsText","logSkillUsage","skillIds","s","id","loadedAt","executionTimeMs","logError","skillError","envContext","tools","getAgentId","buildSystemPrompt","model"],"mappings":"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"}
|
package/dist/cli/agent-spawn.js
CHANGED
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
* Validates all parameters that will be passed to execFileSync()
|
|
16
16
|
*/ /**
|
|
17
17
|
* Validates taskId format to prevent command injection attacks
|
|
18
|
-
* Pattern: alphanumeric, underscore, hyphen
|
|
18
|
+
* Pattern: optional namespace prefix (e.g., "cli:", "task:"), alphanumeric, underscore, hyphen, dot (max 64 chars)
|
|
19
|
+
* Examples: "task-123", "cli:task-456", "orchestrator:batch-789"
|
|
19
20
|
*/ function validateTaskId(taskId) {
|
|
20
21
|
if (typeof taskId !== 'string' || taskId.length === 0) {
|
|
21
22
|
return {
|
|
@@ -23,11 +24,12 @@
|
|
|
23
24
|
error: 'Task ID must be a non-empty string'
|
|
24
25
|
};
|
|
25
26
|
}
|
|
26
|
-
|
|
27
|
+
// Allow optional namespace prefix (lowercase letters + colon), followed by alphanumeric/underscore/hyphen/dot
|
|
28
|
+
const taskIdPattern = /^([a-z]+:)?[a-zA-Z0-9_.-]{1,64}$/;
|
|
27
29
|
if (!taskIdPattern.test(taskId)) {
|
|
28
30
|
return {
|
|
29
31
|
valid: false,
|
|
30
|
-
error: 'Invalid task ID format - must contain
|
|
32
|
+
error: 'Invalid task ID format - must contain optional namespace prefix (e.g., "cli:") and alphanumeric characters, underscores, hyphens, or dots (max 64 chars)'
|
|
31
33
|
};
|
|
32
34
|
}
|
|
33
35
|
return {
|
|
@@ -221,7 +223,8 @@
|
|
|
221
223
|
if (taskId) {
|
|
222
224
|
// SECURITY FIX (CVSS 8.9): Use safe parameter validation and execFileSync()
|
|
223
225
|
// Prevent command injection by validating all parameters BEFORE execution
|
|
224
|
-
|
|
226
|
+
// FIX: Default to 'localhost' for CLI mode (host execution), not 'cfn-redis' (Docker)
|
|
227
|
+
const redisHost = process.env.CFN_REDIS_HOST || 'localhost';
|
|
225
228
|
const redisPort = process.env.CFN_REDIS_PORT || '6379';
|
|
226
229
|
// Validate Redis connection parameters
|
|
227
230
|
const hostValidation = validateRedisHost(redisHost);
|
|
@@ -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, execFileSync } from 'child_process';\r\nimport { resolve } from 'path';\r\n\r\ninterface AgentSpawnOptions {\r\n agentType: string;\r\n agentId?: 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 * SECURITY: Parameter validation to prevent command injection (CVSS 8.9)\r\n * Validates all parameters that will be passed to execFileSync()\r\n */\r\n\r\n/**\r\n * Validates taskId format to prevent command injection attacks\r\n * Pattern: alphanumeric, underscore, hyphen only, 1-64 chars\r\n */\r\nfunction validateTaskId(taskId: string): { valid: boolean; error?: string } {\r\n if (typeof taskId !== 'string' || taskId.length === 0) {\r\n return { valid: false, error: 'Task ID must be a non-empty string' };\r\n }\r\n\r\n const taskIdPattern = /^[a-zA-Z0-9_-]{1,64}$/;\r\n if (!taskIdPattern.test(taskId)) {\r\n return {\r\n valid: false,\r\n error: 'Invalid task ID format - must contain only alphanumeric characters, underscores, and hyphens (max 64 chars)'\r\n };\r\n }\r\n return { valid: true };\r\n}\r\n\r\n/**\r\n * Validates Redis host to prevent command injection\r\n * Allows: hostnames, domain names, localhost, IPv4, IPv6 (::1)\r\n */\r\nfunction validateRedisHost(host: string): { valid: boolean; error?: string } {\r\n if (typeof host !== 'string' || host.length === 0) {\r\n return { valid: false, error: 'Redis host must be a non-empty string' };\r\n }\r\n\r\n // Pattern: alphanumeric, hyphens, dots (for domains), plus special IPv6 loopback\r\n const hostPattern = /^[a-zA-Z0-9.-]+$|^::1$/;\r\n if (!hostPattern.test(host)) {\r\n return { valid: false, error: 'Invalid Redis host format' };\r\n }\r\n return { valid: true };\r\n}\r\n\r\n/**\r\n * Validates Redis port to prevent command injection\r\n * Range: 1-65535\r\n */\r\nfunction validateRedisPort(port: string): { valid: boolean; error?: string } {\r\n if (typeof port !== 'string' || port.length === 0) {\r\n return { valid: false, error: 'Redis port must be a non-empty string' };\r\n }\r\n\r\n const portNum = parseInt(port, 10);\r\n if (isNaN(portNum) || portNum < 1 || portNum > 65535) {\r\n return { valid: false, error: 'Invalid Redis port - must be between 1 and 65535' };\r\n }\r\n return { valid: true };\r\n}\r\n\r\n/**\r\n * Safely retrieves context from Redis using execFileSync()\r\n * Prevents command injection by using array-based arguments instead of template literals\r\n */\r\nfunction getRedisContextSafely(\r\n taskId: string,\r\n redisHost: string,\r\n redisPort: string,\r\n contextKey: string\r\n): string {\r\n try {\r\n // Validate all parameters BEFORE executing\r\n const taskIdValidation = validateTaskId(taskId);\r\n if (!taskIdValidation.valid) {\r\n console.warn(`[cfn-spawn] Invalid task ID: ${taskIdValidation.error}`);\r\n return '';\r\n }\r\n\r\n const hostValidation = validateRedisHost(redisHost);\r\n if (!hostValidation.valid) {\r\n console.warn(`[cfn-spawn] Invalid Redis host: ${hostValidation.error}`);\r\n return '';\r\n }\r\n\r\n const portValidation = validateRedisPort(redisPort);\r\n if (!portValidation.valid) {\r\n console.warn(`[cfn-spawn] Invalid Redis port: ${portValidation.error}`);\r\n return '';\r\n }\r\n\r\n // All parameters validated - now execute safely with execFileSync()\r\n // Using array arguments prevents shell interpolation of metacharacters\r\n const redisKey = `swarm:${taskId}:${contextKey}`;\r\n const result = execFileSync('redis-cli', [\r\n '-h', redisHost,\r\n '-p', redisPort,\r\n 'get',\r\n redisKey\r\n ], { encoding: 'utf8' });\r\n\r\n const trimmed = result.trim();\r\n return trimmed === '(nil)' ? '' : trimmed;\r\n } catch (e) {\r\n // Redis not available or key doesn't exist - fail silently\r\n return '';\r\n }\r\n}\r\n\r\n/**\r\n * Parse command line arguments for agent spawning\r\n */\r\nexport function 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 // Validate agent type exists and is not a flag\r\n if (!agentType || agentType.startsWith('--')) {\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 '--agent-id':\r\n options.agentId = value;\r\n break;\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\nexport async function spawnAgent(options: AgentSpawnOptions): Promise<void> {\r\n const { agentType, agentId, taskId, iteration, context, mode, priority, parentTaskId } = options;\r\n\r\n console.log(`[cfn-spawn] Spawning agent: ${agentType}`);\r\n if (agentId) console.log(`[cfn-spawn] Agent ID: ${agentId}`);\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 (agentId) {\r\n claudeArgs.push('--agent-id', agentId);\r\n }\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 // SECURITY FIX (CVSS 8.9): Use safe parameter validation and execFileSync()\r\n // Prevent command injection by validating all parameters BEFORE execution\r\n const redisHost = process.env.CFN_REDIS_HOST || 'cfn-redis';\r\n const redisPort = process.env.CFN_REDIS_PORT || '6379';\r\n\r\n // Validate Redis connection parameters\r\n const hostValidation = validateRedisHost(redisHost);\r\n const portValidation = validateRedisPort(redisPort);\r\n\r\n if (hostValidation.valid && portValidation.valid) {\r\n // Try to read epic-level context from Redis\r\n epicContext = getRedisContextSafely(taskId, redisHost, redisPort, 'epic-context');\r\n\r\n // Try to read phase-specific context\r\n phaseContext = getRedisContextSafely(taskId, redisHost, redisPort, 'phase-context');\r\n\r\n // Try to read success criteria\r\n successCriteria = getRedisContextSafely(taskId, redisHost, redisPort, 'success-criteria');\r\n\r\n if (epicContext) {\r\n console.log(`[cfn-spawn] Epic context loaded from Redis`);\r\n }\r\n } else {\r\n console.warn(`[cfn-spawn] Invalid Redis configuration - skipping context load`);\r\n if (!hostValidation.valid) console.warn(`[cfn-spawn] ${hostValidation.error}`);\r\n if (!portValidation.valid) console.warn(`[cfn-spawn] ${portValidation.error}`);\r\n }\r\n }\r\n\r\n // Add environment variables for agent context - WHITELIST ONLY APPROACH\r\n // SECURITY FIX: Do not use ...process.env spread which exposes ALL variables including secrets\r\n // Instead, explicitly whitelist safe variables to pass to spawned process\r\n const safeEnvVars = [\r\n 'CFN_REDIS_HOST',\r\n 'CFN_REDIS_PORT',\r\n 'CFN_REDIS_PASSWORD', // CRITICAL: Required for Redis authentication\r\n 'CFN_REDIS_URL',\r\n 'REDIS_PASSWORD', // Fallback for Redis password\r\n 'CFN_MEMORY_BUDGET',\r\n 'CFN_API_HOST',\r\n 'CFN_API_PORT',\r\n 'CFN_LOG_LEVEL',\r\n 'CFN_LOG_FORMAT',\r\n 'CFN_CONTAINER_MODE',\r\n 'CFN_DOCKER_SOCKET',\r\n 'CFN_NETWORK_NAME',\r\n 'CFN_CUSTOM_ROUTING',\r\n 'CFN_DEFAULT_PROVIDER',\r\n 'NODE_ENV',\r\n 'PATH',\r\n 'HOME',\r\n 'PWD' // Required for working directory context\r\n ];\r\n\r\n // Build whitelist-only env object\r\n const env: Record<string, string> = {};\r\n\r\n // Add whitelisted CFN variables\r\n for (const key of safeEnvVars) {\r\n const value = process.env[key];\r\n if (value !== undefined) {\r\n env[key] = value;\r\n }\r\n }\r\n\r\n // Add API key only when explicitly needed (with strict validation)\r\n if (process.env.ANTHROPIC_API_KEY) {\r\n // Validate format: should start with \"sk-\" or \"sk-ant-\"\r\n if (process.env.ANTHROPIC_API_KEY.match(/^sk-[a-zA-Z0-9-]+$/)) {\r\n env.ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY;\r\n } else {\r\n console.warn('[cfn-spawn] Warning: ANTHROPIC_API_KEY format invalid, not passing to agent');\r\n }\r\n }\r\n\r\n // Add task and execution context variables\r\n env.AGENT_TYPE = agentType;\r\n env.TASK_ID = taskId || '';\r\n env.ITERATION = iteration?.toString() || '1';\r\n env.CONTEXT = context || '';\r\n env.MODE = mode || 'cli';\r\n env.PRIORITY = priority?.toString() || '5';\r\n env.PARENT_TASK_ID = parentTaskId || '';\r\n\r\n // Epic-level context from Redis (sanitized)\r\n env.EPIC_CONTEXT = epicContext;\r\n env.PHASE_CONTEXT = phaseContext;\r\n env.SUCCESS_CRITERIA = successCriteria;\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\nexport function 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 !== undefined) 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 --agent-id <id> Explicit agent identifier (overrides auto-generation)\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 cfn-spawn tester --agent-id tester-1-1 --task-id test-phase --iteration 1\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","execFileSync","validateTaskId","taskId","length","valid","error","taskIdPattern","test","validateRedisHost","host","hostPattern","validateRedisPort","port","portNum","parseInt","isNaN","getRedisContextSafely","redisHost","redisPort","contextKey","taskIdValidation","console","warn","hostValidation","portValidation","redisKey","result","encoding","trimmed","trim","e","parseAgentArgs","args","agentType","optionArgs","slice","startsWith","options","i","key","value","agentId","iteration","context","mode","priority","parentTaskId","spawnAgent","log","claudeArgs","push","toString","epicContext","phaseContext","successCriteria","process","env","CFN_REDIS_HOST","CFN_REDIS_PORT","safeEnvVars","undefined","ANTHROPIC_API_KEY","match","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","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, execFileSync } from 'child_process';\r\nimport { resolve } from 'path';\r\n\r\ninterface AgentSpawnOptions {\r\n agentType: string;\r\n agentId?: 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 * SECURITY: Parameter validation to prevent command injection (CVSS 8.9)\r\n * Validates all parameters that will be passed to execFileSync()\r\n */\r\n\r\n/**\r\n * Validates taskId format to prevent command injection attacks\r\n * Pattern: optional namespace prefix (e.g., \"cli:\", \"task:\"), alphanumeric, underscore, hyphen, dot (max 64 chars)\r\n * Examples: \"task-123\", \"cli:task-456\", \"orchestrator:batch-789\"\r\n */\r\nfunction validateTaskId(taskId: string): { valid: boolean; error?: string } {\r\n if (typeof taskId !== 'string' || taskId.length === 0) {\r\n return { valid: false, error: 'Task ID must be a non-empty string' };\r\n }\r\n\r\n // Allow optional namespace prefix (lowercase letters + colon), followed by alphanumeric/underscore/hyphen/dot\r\n const taskIdPattern = /^([a-z]+:)?[a-zA-Z0-9_.-]{1,64}$/;\r\n if (!taskIdPattern.test(taskId)) {\r\n return {\r\n valid: false,\r\n error: 'Invalid task ID format - must contain optional namespace prefix (e.g., \"cli:\") and alphanumeric characters, underscores, hyphens, or dots (max 64 chars)'\r\n };\r\n }\r\n return { valid: true };\r\n}\r\n\r\n/**\r\n * Validates Redis host to prevent command injection\r\n * Allows: hostnames, domain names, localhost, IPv4, IPv6 (::1)\r\n */\r\nfunction validateRedisHost(host: string): { valid: boolean; error?: string } {\r\n if (typeof host !== 'string' || host.length === 0) {\r\n return { valid: false, error: 'Redis host must be a non-empty string' };\r\n }\r\n\r\n // Pattern: alphanumeric, hyphens, dots (for domains), plus special IPv6 loopback\r\n const hostPattern = /^[a-zA-Z0-9.-]+$|^::1$/;\r\n if (!hostPattern.test(host)) {\r\n return { valid: false, error: 'Invalid Redis host format' };\r\n }\r\n return { valid: true };\r\n}\r\n\r\n/**\r\n * Validates Redis port to prevent command injection\r\n * Range: 1-65535\r\n */\r\nfunction validateRedisPort(port: string): { valid: boolean; error?: string } {\r\n if (typeof port !== 'string' || port.length === 0) {\r\n return { valid: false, error: 'Redis port must be a non-empty string' };\r\n }\r\n\r\n const portNum = parseInt(port, 10);\r\n if (isNaN(portNum) || portNum < 1 || portNum > 65535) {\r\n return { valid: false, error: 'Invalid Redis port - must be between 1 and 65535' };\r\n }\r\n return { valid: true };\r\n}\r\n\r\n/**\r\n * Safely retrieves context from Redis using execFileSync()\r\n * Prevents command injection by using array-based arguments instead of template literals\r\n */\r\nfunction getRedisContextSafely(\r\n taskId: string,\r\n redisHost: string,\r\n redisPort: string,\r\n contextKey: string\r\n): string {\r\n try {\r\n // Validate all parameters BEFORE executing\r\n const taskIdValidation = validateTaskId(taskId);\r\n if (!taskIdValidation.valid) {\r\n console.warn(`[cfn-spawn] Invalid task ID: ${taskIdValidation.error}`);\r\n return '';\r\n }\r\n\r\n const hostValidation = validateRedisHost(redisHost);\r\n if (!hostValidation.valid) {\r\n console.warn(`[cfn-spawn] Invalid Redis host: ${hostValidation.error}`);\r\n return '';\r\n }\r\n\r\n const portValidation = validateRedisPort(redisPort);\r\n if (!portValidation.valid) {\r\n console.warn(`[cfn-spawn] Invalid Redis port: ${portValidation.error}`);\r\n return '';\r\n }\r\n\r\n // All parameters validated - now execute safely with execFileSync()\r\n // Using array arguments prevents shell interpolation of metacharacters\r\n const redisKey = `swarm:${taskId}:${contextKey}`;\r\n const result = execFileSync('redis-cli', [\r\n '-h', redisHost,\r\n '-p', redisPort,\r\n 'get',\r\n redisKey\r\n ], { encoding: 'utf8' });\r\n\r\n const trimmed = result.trim();\r\n return trimmed === '(nil)' ? '' : trimmed;\r\n } catch (e) {\r\n // Redis not available or key doesn't exist - fail silently\r\n return '';\r\n }\r\n}\r\n\r\n/**\r\n * Parse command line arguments for agent spawning\r\n */\r\nexport function 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 // Validate agent type exists and is not a flag\r\n if (!agentType || agentType.startsWith('--')) {\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 '--agent-id':\r\n options.agentId = value;\r\n break;\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\nexport async function spawnAgent(options: AgentSpawnOptions): Promise<void> {\r\n const { agentType, agentId, taskId, iteration, context, mode, priority, parentTaskId } = options;\r\n\r\n console.log(`[cfn-spawn] Spawning agent: ${agentType}`);\r\n if (agentId) console.log(`[cfn-spawn] Agent ID: ${agentId}`);\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 (agentId) {\r\n claudeArgs.push('--agent-id', agentId);\r\n }\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 // SECURITY FIX (CVSS 8.9): Use safe parameter validation and execFileSync()\r\n // Prevent command injection by validating all parameters BEFORE execution\r\n // FIX: Default to 'localhost' for CLI mode (host execution), not 'cfn-redis' (Docker)\r\n const redisHost = process.env.CFN_REDIS_HOST || 'localhost';\r\n const redisPort = process.env.CFN_REDIS_PORT || '6379';\r\n\r\n // Validate Redis connection parameters\r\n const hostValidation = validateRedisHost(redisHost);\r\n const portValidation = validateRedisPort(redisPort);\r\n\r\n if (hostValidation.valid && portValidation.valid) {\r\n // Try to read epic-level context from Redis\r\n epicContext = getRedisContextSafely(taskId, redisHost, redisPort, 'epic-context');\r\n\r\n // Try to read phase-specific context\r\n phaseContext = getRedisContextSafely(taskId, redisHost, redisPort, 'phase-context');\r\n\r\n // Try to read success criteria\r\n successCriteria = getRedisContextSafely(taskId, redisHost, redisPort, 'success-criteria');\r\n\r\n if (epicContext) {\r\n console.log(`[cfn-spawn] Epic context loaded from Redis`);\r\n }\r\n } else {\r\n console.warn(`[cfn-spawn] Invalid Redis configuration - skipping context load`);\r\n if (!hostValidation.valid) console.warn(`[cfn-spawn] ${hostValidation.error}`);\r\n if (!portValidation.valid) console.warn(`[cfn-spawn] ${portValidation.error}`);\r\n }\r\n }\r\n\r\n // Add environment variables for agent context - WHITELIST ONLY APPROACH\r\n // SECURITY FIX: Do not use ...process.env spread which exposes ALL variables including secrets\r\n // Instead, explicitly whitelist safe variables to pass to spawned process\r\n const safeEnvVars = [\r\n 'CFN_REDIS_HOST',\r\n 'CFN_REDIS_PORT',\r\n 'CFN_REDIS_PASSWORD', // CRITICAL: Required for Redis authentication\r\n 'CFN_REDIS_URL',\r\n 'REDIS_PASSWORD', // Fallback for Redis password\r\n 'CFN_MEMORY_BUDGET',\r\n 'CFN_API_HOST',\r\n 'CFN_API_PORT',\r\n 'CFN_LOG_LEVEL',\r\n 'CFN_LOG_FORMAT',\r\n 'CFN_CONTAINER_MODE',\r\n 'CFN_DOCKER_SOCKET',\r\n 'CFN_NETWORK_NAME',\r\n 'CFN_CUSTOM_ROUTING',\r\n 'CFN_DEFAULT_PROVIDER',\r\n 'NODE_ENV',\r\n 'PATH',\r\n 'HOME',\r\n 'PWD' // Required for working directory context\r\n ];\r\n\r\n // Build whitelist-only env object\r\n const env: Record<string, string> = {};\r\n\r\n // Add whitelisted CFN variables\r\n for (const key of safeEnvVars) {\r\n const value = process.env[key];\r\n if (value !== undefined) {\r\n env[key] = value;\r\n }\r\n }\r\n\r\n // Add API key only when explicitly needed (with strict validation)\r\n if (process.env.ANTHROPIC_API_KEY) {\r\n // Validate format: should start with \"sk-\" or \"sk-ant-\"\r\n if (process.env.ANTHROPIC_API_KEY.match(/^sk-[a-zA-Z0-9-]+$/)) {\r\n env.ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY;\r\n } else {\r\n console.warn('[cfn-spawn] Warning: ANTHROPIC_API_KEY format invalid, not passing to agent');\r\n }\r\n }\r\n\r\n // Add task and execution context variables\r\n env.AGENT_TYPE = agentType;\r\n env.TASK_ID = taskId || '';\r\n env.ITERATION = iteration?.toString() || '1';\r\n env.CONTEXT = context || '';\r\n env.MODE = mode || 'cli';\r\n env.PRIORITY = priority?.toString() || '5';\r\n env.PARENT_TASK_ID = parentTaskId || '';\r\n\r\n // Epic-level context from Redis (sanitized)\r\n env.EPIC_CONTEXT = epicContext;\r\n env.PHASE_CONTEXT = phaseContext;\r\n env.SUCCESS_CRITERIA = successCriteria;\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\nexport function 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 !== undefined) 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 --agent-id <id> Explicit agent identifier (overrides auto-generation)\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 cfn-spawn tester --agent-id tester-1-1 --task-id test-phase --iteration 1\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","execFileSync","validateTaskId","taskId","length","valid","error","taskIdPattern","test","validateRedisHost","host","hostPattern","validateRedisPort","port","portNum","parseInt","isNaN","getRedisContextSafely","redisHost","redisPort","contextKey","taskIdValidation","console","warn","hostValidation","portValidation","redisKey","result","encoding","trimmed","trim","e","parseAgentArgs","args","agentType","optionArgs","slice","startsWith","options","i","key","value","agentId","iteration","context","mode","priority","parentTaskId","spawnAgent","log","claudeArgs","push","toString","epicContext","phaseContext","successCriteria","process","env","CFN_REDIS_HOST","CFN_REDIS_PORT","safeEnvVars","undefined","ANTHROPIC_API_KEY","match","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","err","message","kill","buildTaskDescription","desc","main","argv","includes","isMainModule","url","endsWith","replace","catch"],"mappings":"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"}
|