UNPKG

cortexweaver

Version:

CortexWeaver is a command-line interface (CLI) tool that orchestrates a swarm of specialized AI agents, powered by Claude Code and Gemini CLI, to assist in software development. It transforms a high-level project plan (plan.md) into a series of coordinate

443 lines (421 loc) โ€ข 18.3 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.CLICommands = void 0; const fs = __importStar(require("fs")); const path = __importStar(require("path")); const config_1 = require("../config"); const orchestrator_1 = require("../orchestrator"); const session_1 = require("../session"); const workspace_1 = require("../workspace"); const cli_templates_1 = require("../cli-templates"); const cli_contracts_1 = require("../cli-contracts"); const auth_manager_1 = require("../auth-manager"); const cli_utils_1 = require("../cli-utils"); /** * CLI Commands implementation * Contains all command logic extracted from the main CLI class */ class CLICommands { constructor() { this.authManager = new auth_manager_1.AuthManager(); } async authStatus(projectRoot = process.cwd()) { console.log('๐Ÿ” Checking authentication status...'); try { const authManager = new auth_manager_1.AuthManager(projectRoot); await authManager.discoverAuthentication(); return await authManager.getAuthReport(); } catch (error) { throw new Error(`Failed to check authentication status: ${error.message}`); } } async authConfigure(method, projectRoot = process.cwd()) { console.log('๐Ÿ” Configuring authentication...'); try { const authManager = new auth_manager_1.AuthManager(projectRoot); await authManager.discoverAuthentication(); const status = await authManager.getAuthStatus(); let configReport = ` ๐Ÿ” Authentication Configuration Guide ${'='.repeat(50)} ๐Ÿค– Claude Authentication: Current: ${status.claudeAuth.method} Status: ${status.claudeAuth.isAuthenticated ? 'โœ… Authenticated' : 'โŒ Not Authenticated'} ๐Ÿง  Gemini Authentication: Current: ${status.geminiAuth.method} Status: ${status.geminiAuth.isAuthenticated ? 'โœ… Authenticated' : 'โŒ Not Authenticated'} ๐Ÿ’ก Setup Instructions: 1. For Claude Code CLI (Recommended): โ€ข Install Claude Code CLI: https://claude.ai/docs/cli โ€ข Login: \`claude auth login\` โ€ข Verify: \`claude auth status\` 2. For Gemini CLI: โ€ข Install Google Cloud CLI: https://cloud.google.com/sdk/docs/install โ€ข Login: \`gcloud auth login\` โ€ข Setup AI Platform: \`gcloud auth application-default login\` 3. For Direct API Keys: โ€ข Set ANTHROPIC_API_KEY in your .env file โ€ข Set GOOGLE_API_KEY in your .env file ๐Ÿ“Š Current Recommendations: ${status.recommendations.map(rec => ` โ€ข ${rec}`).join('\n')} `; return configReport.trim(); } catch (error) { throw new Error(`Failed to show authentication configuration: ${error.message}`); } } async authSwitch(method, projectRoot = process.cwd()) { console.log(`๐Ÿ”„ Switching authentication method to: ${method}`); try { const authManager = new auth_manager_1.AuthManager(projectRoot); await authManager.discoverAuthentication(); // Validate the method const validMethods = ['claude-code', 'gemini-cli', 'direct-api']; if (!validMethods.includes(method)) { throw new Error(`Invalid authentication method: ${method}. Valid methods: ${validMethods.join(', ')}`); } const status = await authManager.getAuthStatus(); // Check if the requested method is available if (method === 'claude-code' && !status.claudeAuth.isAuthenticated) { throw new Error('Claude Code CLI not configured. Run "claude auth login" first.'); } if (method === 'gemini-cli' && !status.geminiAuth.isAuthenticated) { throw new Error('Gemini CLI not configured. Run "gcloud auth login" first.'); } console.log(`โœ… Authentication method switched to: ${method}`); console.log('๐Ÿ’ก Note: This switch affects the current session only.'); console.log(' Update your project configuration to make this change permanent.'); } catch (error) { throw new Error(`Failed to switch authentication method: ${error.message}`); } } async logs(taskId, projectRoot = process.cwd()) { if (!cli_utils_1.CLIUtils.validateProject(projectRoot)) { throw new Error('Not a CortexWeaver project. Run "cortex-weaver init" first.'); } console.log(`๐Ÿ“‹ Retrieving logs for task: ${taskId}`); try { const sessionManager = new session_1.SessionManager(); // Get session output for the task const sessionId = `cortex-${taskId}`; const sessionOutput = await sessionManager.getSessionOutput(sessionId); if (!sessionOutput) { return `โŒ No logs found for task: ${taskId}`; } const logReport = ` ๐Ÿ” Task Logs: ${taskId} ${'='.repeat(50)} ๐Ÿ“ Session Output: ${sessionOutput} ๐Ÿ“Š Log retrieval completed at: ${new Date().toISOString()} `; return logReport.trim(); } catch (error) { throw new Error(`Failed to retrieve logs for task ${taskId}: ${error.message}`); } } async retry(taskId, projectRoot = process.cwd()) { if (!cli_utils_1.CLIUtils.validateProject(projectRoot)) { throw new Error('Not a CortexWeaver project. Run "cortex-weaver init" first.'); } console.log(`๐Ÿ”„ Retrying failed task: ${taskId}`); try { // Load configuration const configService = new config_1.ConfigService(projectRoot); const projectConfig = configService.loadProjectConfig(); const envVars = configService.loadEnvironmentVariables(); Object.assign(process.env, envVars); // Initialize Cognitive Canvas connection const neo4jUri = process.env.NEO4J_URI || 'bolt://localhost:7687'; const neo4jUsername = process.env.NEO4J_USERNAME || 'neo4j'; const neo4jPassword = configService.getRequiredEnvVar('NEO4J_PASSWORD'); const orchestratorConfig = { neo4j: { uri: neo4jUri, username: neo4jUsername, password: neo4jPassword }, claude: { apiKey: configService.getRequiredEnvVar('CLAUDE_API_KEY'), defaultModel: projectConfig.models.claude, budgetLimit: projectConfig.budget.maxCost } }; const orchestrator = new orchestrator_1.Orchestrator(orchestratorConfig); await orchestrator.initialize(projectRoot); // Check if task exists and is in FAILED state const canvas = orchestrator.canvas; const task = await canvas.getTaskById(taskId); if (!task) { throw new Error(`Task ${taskId} not found`); } if (task.status !== 'failed') { throw new Error(`Task ${taskId} is not in FAILED state. Current status: ${task.status}`); } // Reset task status to pending for retry await canvas.updateTaskStatus(taskId, 'pending'); // Clean up any existing sessions/worktrees for this task const workspaceManager = new workspace_1.WorkspaceManager(); const sessionManager = new session_1.SessionManager(); try { // Remove existing worktree if it exists await workspaceManager.removeWorktree(taskId); } catch (error) { // Worktree might not exist, that's okay } try { // Kill existing sessions for this task const sessions = sessionManager.listSessions(); const taskSessions = sessions.filter(s => s.taskId === taskId); for (const session of taskSessions) { await sessionManager.killSession(session.sessionId); } } catch (error) { // Sessions might not exist, that's okay } console.log(`โœ… Task ${taskId} has been re-queued for retry`); await orchestrator.shutdown(); } catch (error) { throw new Error(`Failed to retry task ${taskId}: ${error.message}`); } } async listAgents(projectRoot = process.cwd()) { console.log('๐Ÿค– Discovering available agent personas...'); try { const promptsDir = path.join(projectRoot, 'prompts'); // Check if prompts directory exists if (!fs.existsSync(promptsDir)) { // Create prompts directory with default agent personas await this.createDefaultAgentPersonas(promptsDir); } // Scan prompts directory for agent files const agentFiles = fs.readdirSync(promptsDir) .filter(file => file.endsWith('.md') || file.endsWith('.txt')) .sort(); if (agentFiles.length === 0) { return `โŒ No agent personas found in ${promptsDir}`; } let agentList = ` ๐Ÿค– Available Agent Personas ${'='.repeat(40)} ๐Ÿ“ Prompts Directory: ${promptsDir} ๐Ÿ“Š Total Agents Found: ${agentFiles.length} ๐ŸŽญ Agent Personas: `; for (const file of agentFiles) { const filePath = path.join(promptsDir, file); const content = fs.readFileSync(filePath, 'utf-8'); // Extract agent info from file content const agentInfo = cli_utils_1.CLIUtils.parseAgentPersona(content, file); agentList += ` ๐Ÿ“‹ ${agentInfo.name} Role: ${agentInfo.role} File: ${file} Description: ${agentInfo.description} `; } agentList += ` ๐Ÿ’ก Usage: Use these personas in your plan.md to specify which agents handle specific features. ๐Ÿ“– Each agent has specialized capabilities and knowledge domains. `; return agentList.trim(); } catch (error) { throw new Error(`Failed to list agents: ${error.message}`); } } async init(projectRoot = process.cwd()) { const configService = new config_1.ConfigService(projectRoot); // Create .cortexweaver directory const cortexDir = configService.getCortexWeaverDir(); if (!fs.existsSync(cortexDir)) { fs.mkdirSync(cortexDir, { recursive: true }); } // Create contracts directory structure await cli_contracts_1.CLIContracts.createContractsStructure(projectRoot); // Create plan.md template await cli_templates_1.CLITemplates.createPlanTemplate(projectRoot); // Create default config.json await this.createDefaultConfig(configService); // Create docker-compose.yml for MCP servers await cli_templates_1.CLITemplates.createDockerCompose(projectRoot); // Create .env.example template await cli_templates_1.CLITemplates.createEnvTemplate(projectRoot); // Create prompts directory with agent personas await cli_templates_1.CLITemplates.createPromptsDirectory(projectRoot); // Create prototypes directory await cli_templates_1.CLITemplates.createPrototypesDirectory(projectRoot); // Discover available authentication methods console.log('\n๐Ÿ” Discovering authentication methods...'); try { const authManager = new auth_manager_1.AuthManager(projectRoot); await authManager.discoverAuthentication(); const status = await authManager.getAuthStatus(); if (status.claudeAuth.isAuthenticated || status.geminiAuth.isAuthenticated) { console.log('โœ… Authentication configured:'); if (status.claudeAuth.isAuthenticated) { console.log(` - Claude: ${status.claudeAuth.method}`); } if (status.geminiAuth.isAuthenticated) { console.log(` - Gemini: ${status.geminiAuth.method}`); } } else { console.log('โš ๏ธ No authentication methods configured'); console.log(' Run "cortex-weaver auth configure" to set up authentication'); } } catch (error) { console.log(`โš ๏ธ Authentication discovery failed: ${error.message}`); } console.log('โœ… CortexWeaver project initialized successfully!'); console.log(` Next steps: 1. ๐Ÿ” Verify authentication: 'cortex-weaver auth status' 2. ๐Ÿ“ Copy .env.example to .env and fill in your API keys (if using direct-api) 3. ๐Ÿณ Run 'docker-compose up -d' to start MCP servers 4. ๐Ÿ“‹ Edit plan.md to define your project features 5. ๐Ÿ“‘ Define formal contracts in the /contracts directory 6. ๐Ÿค– Customize agent personas in the /prompts directory 7. ๐Ÿงช Create prototypes and experiments in the /prototypes directory 8. ๐Ÿš€ Run 'cortex-weaver start' to begin orchestration ๐Ÿ“‹ Specification-Driven Development: - Use /contracts/api/ for OpenAPI specifications - Use /contracts/schemas/ for JSON Schema definitions - Use /contracts/properties/ for property-based test invariants - Use /contracts/examples/ for sample data and usage patterns ๐Ÿงช Prototyping & Experimentation: - Use /prototypes/ for rapid prototyping and experimental features - /prototypes/features/ - Feature prototypes and early implementations - /prototypes/experiments/ - Experimental code and research implementations - /prototypes/proofs-of-concept/ - POCs for core system functionality - /prototypes/spike-solutions/ - Time-boxed investigation solutions - /prototypes/algorithms/ - Algorithm implementations and testing - Prototype validation before formal contract creation - Explore technical feasibility and design alternatives ๐Ÿค– Agent Personas (CortexWeaver 3.0): - Agent persona files are now available in /prompts directory - Each agent has a comprehensive persona defining role, responsibilities, and instructions - Personas can be versioned and improved over time as first-class citizens - The new Reflector agent provides retrospective analysis and continuous improvement `); } async createDefaultConfig(configService) { const defaultConfig = { models: { claude: 'claude-3-opus-20240229', gemini: 'gemini-pro' }, costs: { claudeTokenCost: 0.015, geminiTokenCost: 0.0005 }, budget: { maxTokens: 50000, maxCost: 500 }, parallelism: { maxConcurrentTasks: 5, maxConcurrentAgents: 3 }, monitoring: { enableMetrics: true, logLevel: 'info' } }; configService.saveProjectConfig(defaultConfig); } async createDefaultAgentPersonas(promptsDir) { fs.mkdirSync(promptsDir, { recursive: true }); const defaultPersonas = [ { filename: 'spec-writer.md', content: `# Spec Writer Agent ## Role Requirements Analysis and Specification Creation ## Description Creates comprehensive BDD specifications and feature files based on project requirements. ## Capabilities - User story creation - Acceptance criteria definition - Gherkin scenario writing - Requirements documentation - Behavior-driven development specifications ## Knowledge Domains - Business analysis - Requirements engineering - BDD/TDD methodologies - User experience design ` }, { filename: 'formalizer.md', content: `# Formalizer Agent ## Role Contract and Mathematical Specification ## Description Transforms BDD specifications into formal contracts and mathematical representations. ## Capabilities - Contract specification creation - Mathematical modeling - Invariant definition - Precondition/postcondition specification - Formal verification support ## Knowledge Domains - Formal methods - Mathematical modeling - Contract-based design - Verification and validation ` } // Note: Shortened for space - full implementation would include all personas ]; for (const persona of defaultPersonas) { const filePath = path.join(promptsDir, persona.filename); fs.writeFileSync(filePath, persona.content); } console.log(`โœ… Created ${defaultPersonas.length} default agent personas in ${promptsDir}`); } } exports.CLICommands = CLICommands; //# sourceMappingURL=commands.js.map