UNPKG

context-forge

Version:

AI orchestration platform with autonomous teams, enhancement planning, migration tools, 25+ slash commands, checkpoints & hooks. Multi-IDE: Claude, Cursor, Windsurf, Cline, Copilot

347 lines 15.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; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.initCommand = void 0; const commander_1 = require("commander"); const chalk_1 = __importDefault(require("chalk")); const ora_1 = __importDefault(require("ora")); const path_1 = __importDefault(require("path")); const fs_extra_1 = __importDefault(require("fs-extra")); const prompts_1 = require("../prompts"); const generators_1 = require("../../generators"); const validator_1 = require("../../utils/validator"); const adapters_1 = require("../../adapters"); const aiIntelligenceService_1 = require("../../services/aiIntelligenceService"); const projectAnalyzer_1 = require("../../services/projectAnalyzer"); const errorRecoveryService_1 = require("../../services/errorRecoveryService"); const progressTracker_1 = require("../../services/progressTracker"); exports.initCommand = new commander_1.Command('init') .description('Initialize AI IDE configurations and documentation for your project') .option('-o, --output <path>', 'output directory for generated files', '.') .option('-p, --preset <preset>', 'use a preset configuration') .option('-c, --config <path>', 'path to configuration file') .option('--no-ai', 'disable AI-powered smart suggestions') .option('--quick', 'use quick setup with smart defaults') .option('-i, --ide <ide>', 'target IDE (claude, cursor, windsurf, cline, roo, gemini, copilot)', (value) => { const validIDEs = (0, adapters_1.getSupportedIDEs)(); const ides = value.split(',').map((ide) => ide.trim()); for (const ide of ides) { if (!validIDEs.includes(ide)) { throw new Error(`Invalid IDE: ${ide}. Valid options: ${validIDEs.join(', ')}`); } } return ides; }) .action(async (options) => { console.log(chalk_1.default.blue.bold('\n🚀 Welcome to Context Forge!\n')); console.log(chalk_1.default.gray("Let's set up AI-optimized documentation for your project.\n")); const spinner = (0, ora_1.default)(); const aiService = new aiIntelligenceService_1.AIIntelligenceService(); const errorRecovery = new errorRecoveryService_1.ErrorRecoveryService(); const progressTracker = new progressTracker_1.ProgressTracker(); const outputPath = path_1.default.resolve(options.output); let config; let operationId = ''; // Show AI status const aiStatus = aiService.getAIStatus(); console.log(chalk_1.default.gray(`${aiStatus}\n`)); try { // Start progress tracking operationId = await progressTracker.startOperation('init', 'Project initialization', { aiEnabled: aiService.isAIEnabled(), targetIDEs: options.ide || ['claude'], }); // Validate output path await (0, validator_1.validateOutputPath)(outputPath); let aiSuggestions = null; if (options.config) { // Load configuration from file const stepId = await progressTracker.addStep(operationId, 'Load configuration file'); spinner.start('Loading configuration file...'); const configPath = path_1.default.resolve(options.config); config = await fs_extra_1.default.readJson(configPath); spinner.succeed('Configuration loaded'); await progressTracker.completeStep(operationId, stepId); } else if (options.preset) { // Load preset configuration const stepId = await progressTracker.addStep(operationId, 'Load preset configuration'); spinner.start('Loading preset configuration...'); config = await loadPreset(options.preset); spinner.succeed('Preset loaded'); await progressTracker.completeStep(operationId, stepId); } else if (options.quick) { // Quick setup with AI-powered smart defaults const stepId = await progressTracker.addStep(operationId, 'Quick setup with smart defaults'); spinner.start('Analyzing project for smart defaults...'); const analyzer = new projectAnalyzer_1.ProjectAnalyzer(outputPath); const basicAnalysis = await analyzer.analyzeBasic(); if (aiService.isAIEnabled() && !options.ai === false) { aiSuggestions = await aiService.generateSmartDefaults(outputPath, basicAnalysis); spinner.succeed('AI analysis complete'); // Show AI suggestions if (aiSuggestions.suggestions.length > 0) { console.log(chalk_1.default.yellow('\n🤖 AI Suggestions:')); aiSuggestions.suggestions.slice(0, 3).forEach((suggestion, index) => { console.log(chalk_1.default.gray(` ${index + 1}. ${suggestion.title} (${suggestion.priority})`)); console.log(chalk_1.default.gray(` ${suggestion.description}`)); }); console.log(''); } } else { spinner.succeed('Project analysis complete'); } // Generate smart default config config = await generateSmartDefaultConfig(basicAnalysis, aiSuggestions || null); await progressTracker.completeStep(operationId, stepId); } else { // Run interactive prompts with AI enhancement const stepId = await progressTracker.addStep(operationId, 'Interactive setup wizard'); if (aiService.isAIEnabled() && !options.ai === false) { spinner.start('Analyzing project for intelligent suggestions...'); const analyzer = new projectAnalyzer_1.ProjectAnalyzer(outputPath); const basicAnalysis = await analyzer.analyzeBasic(); aiSuggestions = await aiService.generateSmartDefaults(outputPath, basicAnalysis); spinner.succeed('Project analyzed'); } config = await (0, prompts_1.runPrompts)(aiSuggestions); await progressTracker.completeStep(operationId, stepId); } // Override targetIDEs if --ide flag was used if (options.ide && config) { config.targetIDEs = options.ide; } if (!config) { throw new Error('Configuration not created'); } // Generate documentation const docStepId = await progressTracker.addStep(operationId, 'Generate documentation'); console.log(chalk_1.default.blue.bold('\n📝 Generating documentation...\n')); await (0, generators_1.generateDocumentation)(config, outputPath); await progressTracker.completeStep(operationId, docStepId); // Success message console.log(chalk_1.default.green.bold('\n✨ Context Forge setup complete!\n')); console.log(chalk_1.default.white('Generated files in:'), chalk_1.default.cyan(outputPath)); // Show IDE-specific instructions const targetIDEs = config.targetIDEs || ['claude']; console.log(chalk_1.default.white('\nGenerated configurations for:')); targetIDEs.forEach((ide) => { console.log(chalk_1.default.gray(` • ${ide.charAt(0).toUpperCase() + ide.slice(1)}`)); }); // Show AI enhancement summary if (aiSuggestions && aiSuggestions.suggestions.length > 0) { console.log(chalk_1.default.yellow(`\n🤖 Applied ${aiSuggestions.suggestions.length} AI suggestions`)); console.log(chalk_1.default.gray(` Confidence: ${aiSuggestions.confidence}%`)); } console.log(chalk_1.default.blue.bold('\n🎯 Next steps:\n')); console.log(chalk_1.default.white('1. Review the generated documentation')); console.log(chalk_1.default.white(`2. Open your project in your AI IDE`)); console.log(chalk_1.default.white('3. Start implementing using the staged approach')); console.log(chalk_1.default.white('4. Update documentation as your project evolves\n')); // Complete progress tracking await progressTracker.completeOperation(operationId, 'completed', { filesGenerated: config.targetIDEs.length + (config.features?.length || 0), targetIDEs: config.targetIDEs, }); } catch (error) { spinner.fail('Setup failed'); // Use error recovery service to provide intelligent suggestions await errorRecovery.handleError(error, { command: 'init', operation: 'initialization', projectPath: outputPath, config, }); // Mark operation as failed if (operationId) { await progressTracker.completeOperation(operationId, 'failed', { errors: [error.message], }); } throw error; } }); async function loadPreset(presetName) { // Preset configurations will be implemented in data/presets.ts const presets = { 'nextjs-fastapi': { projectType: 'fullstack', techStack: { frontend: 'nextjs', backend: 'fastapi', database: 'postgresql', auth: 'jwt', }, }, 'react-express': { projectType: 'fullstack', techStack: { frontend: 'react', backend: 'express', database: 'mongodb', auth: 'jwt', }, }, }; if (!presets[presetName]) { throw new Error(`Unknown preset: ${presetName}. Available presets: ${Object.keys(presets).join(', ')}`); } // For presets, we still need some basic info const { projectInfo } = await Promise.resolve().then(() => __importStar(require('../prompts/projectInfo'))); const basicInfo = await projectInfo(); return { ...basicInfo, ...presets[presetName], features: [], timeline: 'mvp', teamSize: 'solo', deployment: 'vercel', extras: { docker: true, testing: true, linting: true, }, }; } async function generateSmartDefaultConfig(basicAnalysis, aiSuggestions) { const { projectInfo } = await Promise.resolve().then(() => __importStar(require('../prompts/projectInfo'))); const basicInfo = await projectInfo(); // Smart defaults based on analysis const detectedTechStack = Array.isArray(basicAnalysis.techStack) ? basicAnalysis.techStack : []; const smartDefaults = { projectType: detectProjectType(detectedTechStack), techStack: { frontend: detectFrontend(detectedTechStack), backend: detectBackend(detectedTechStack), database: detectDatabase(detectedTechStack), auth: 'jwt', }, timeline: 'standard', teamSize: 'small', deployment: detectDeployment(detectedTechStack), extras: { docker: detectedTechStack.includes('docker'), testing: true, // Always recommend testing linting: true, // Always recommend linting examples: true, prp: true, claudeCommands: true, hooks: true, checkpoints: true, }, }; // Apply AI suggestions if available if (aiSuggestions && aiSuggestions.suggestions) { aiSuggestions.suggestions.forEach((suggestion) => { if (suggestion.suggestedConfig) { Object.assign(smartDefaults, suggestion.suggestedConfig); } }); } return { ...basicInfo, ...smartDefaults, features: [], }; } function detectProjectType(techStack) { if (techStack.some((tech) => ['react-native', 'flutter', 'ionic'].includes(tech.toLowerCase()))) { return 'mobile'; } if (techStack.some((tech) => ['electron', 'tauri'].includes(tech.toLowerCase()))) { return 'desktop'; } if (techStack.some((tech) => ['express', 'fastapi', 'django', 'rails', 'spring'].includes(tech.toLowerCase()))) { if (techStack.some((tech) => ['react', 'vue', 'angular', 'svelte'].includes(tech.toLowerCase()))) { return 'fullstack'; } return 'api'; } return 'web'; } function detectFrontend(techStack) { if (techStack.includes('React')) return 'react'; if (techStack.includes('Next.js')) return 'nextjs'; if (techStack.includes('Vue')) return 'vue'; if (techStack.includes('Angular')) return 'angular'; if (techStack.includes('Svelte')) return 'svelte'; return 'react'; // Default } function detectBackend(techStack) { if (techStack.includes('Express')) return 'express'; if (techStack.includes('FastAPI')) return 'fastapi'; if (techStack.includes('Django')) return 'django'; if (techStack.includes('Rails')) return 'rails'; if (techStack.includes('Spring')) return 'spring'; return 'express'; // Default } function detectDatabase(techStack) { if (techStack.some((tech) => tech.toLowerCase().includes('postgres'))) return 'postgresql'; if (techStack.some((tech) => tech.toLowerCase().includes('mongo'))) return 'mongodb'; if (techStack.some((tech) => tech.toLowerCase().includes('mysql'))) return 'mysql'; if (techStack.some((tech) => tech.toLowerCase().includes('sqlite'))) return 'sqlite'; return 'postgresql'; // Default } function detectDeployment(techStack) { if (techStack.includes('Next.js')) return 'vercel'; if (techStack.includes('FastAPI') || techStack.includes('Django')) return 'railway'; if (techStack.includes('Docker')) return 'docker'; return 'vercel'; // Default } //# sourceMappingURL=init.js.map