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
JavaScript
;
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