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
409 lines (391 loc) • 15 kB
JavaScript
"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.AIIntelligenceService = void 0;
const claude_code_1 = require("@anthropic-ai/claude-code");
const fs = __importStar(require("fs-extra"));
const path = __importStar(require("path"));
class AIIntelligenceService {
constructor() {
this.apiKeySource = this.detectAPIKeySource();
this.aiEnabled = this.shouldEnableAI();
}
detectAPIKeySource() {
if (process.env.ANTHROPIC_API_KEY)
return 'anthropic';
if (process.env.CLAUDE_CODE_USE_BEDROCK)
return 'bedrock';
if (process.env.CLAUDE_CODE_USE_VERTEX)
return 'vertex';
return 'none';
}
shouldEnableAI() {
// User can explicitly disable AI with environment variable
if (process.env.CONTEXT_FORGE_DISABLE_AI === 'true') {
return false;
}
// Only enable if we have valid API credentials
return this.apiKeySource !== 'none';
}
async generateSmartDefaults(projectPath, basicAnalysis, options = { projectPath }) {
if (!this.aiEnabled) {
return this.getFallbackSuggestions(basicAnalysis);
}
try {
const projectContext = await this.buildProjectContext(projectPath, options);
const prompt = this.buildSmartDefaultsPrompt(projectContext, basicAnalysis);
const messages = [];
for await (const message of (0, claude_code_1.query)({
prompt,
options: {
maxTurns: options.maxTurns || 3,
},
})) {
messages.push(message);
}
const lastMessage = messages[messages.length - 1];
if (lastMessage.type === 'result' && lastMessage.subtype === 'success') {
return this.parseAIResponse(lastMessage.result);
}
throw new Error('Failed to get AI response');
}
catch (error) {
console.warn('AI analysis failed, using fallback:', error);
return this.getFallbackSuggestions(basicAnalysis);
}
}
async suggestEnhancements(projectPath, currentConfig, options = { projectPath }) {
if (!this.aiEnabled) {
return this.getFallbackEnhancementSuggestions(currentConfig);
}
try {
const projectContext = await this.buildProjectContext(projectPath, options);
const prompt = this.buildEnhancementPrompt(projectContext, currentConfig);
const messages = [];
for await (const message of (0, claude_code_1.query)({
prompt,
options: {
maxTurns: options.maxTurns || 2,
},
})) {
messages.push(message);
}
const lastMessage = messages[messages.length - 1];
if (lastMessage.type === 'result' && lastMessage.subtype === 'success') {
const response = this.parseAIResponse(lastMessage.result);
return response.suggestions || [];
}
throw new Error('Failed to get enhancement suggestions');
}
catch (error) {
console.warn('Enhancement suggestion failed, using fallback:', error);
return this.getFallbackEnhancementSuggestions(currentConfig);
}
}
async generateErrorRecoverySuggestions(error, context, _projectPath) {
if (!this.aiEnabled) {
return this.getFallbackErrorSuggestions(error);
}
try {
const prompt = this.buildErrorRecoveryPrompt(error, context);
const messages = [];
for await (const message of (0, claude_code_1.query)({
prompt,
options: {
maxTurns: 2,
},
})) {
messages.push(message);
}
const lastMessage = messages[messages.length - 1];
if (lastMessage.type === 'result' && lastMessage.subtype === 'success') {
const response = this.parseAIResponse(lastMessage.result);
return response.suggestions || [];
}
return this.getFallbackErrorSuggestions(error);
}
catch (aiError) {
console.warn('Error recovery AI failed:', aiError);
return this.getFallbackErrorSuggestions(error);
}
}
async buildProjectContext(projectPath, options) {
const context = [`Project Analysis for: ${projectPath}`];
// Add package.json if it exists
const packageJsonPath = path.join(projectPath, 'package.json');
if (await fs.pathExists(packageJsonPath)) {
try {
const packageJson = await fs.readJson(packageJsonPath);
context.push(`Package.json: ${JSON.stringify(packageJson, null, 2)}`);
}
catch {
context.push('Package.json: [Unable to read]');
}
}
// Add basic file structure
try {
const files = await fs.readdir(projectPath);
context.push(`Root files: ${files.join(', ')}`);
}
catch {
context.push('Root files: [Unable to read]');
}
// Add additional context if provided
if (options.context) {
context.push(`Additional context: ${options.context}`);
}
return context.join('\n\n');
}
buildSmartDefaultsPrompt(projectContext, basicAnalysis) {
return `
You are an expert software development consultant analyzing a project to provide intelligent configuration suggestions.
Project Context:
${projectContext}
Basic Analysis:
${JSON.stringify(basicAnalysis, null, 2)}
Please analyze this project and provide smart configuration suggestions. Return a JSON response with this structure:
{
"suggestions": [
{
"type": "config|feature|migration|optimization",
"title": "Brief title",
"description": "Detailed description",
"priority": "high|medium|low",
"effort": "trivial|small|medium|large",
"reasoning": "Why this suggestion makes sense",
"suggestedConfig": {} // Optional partial configuration
}
],
"confidence": 0-100,
"reasoning": "Overall analysis reasoning",
"optimizations": [
{
"category": "performance|security|maintainability|developer-experience",
"title": "Optimization title",
"description": "What this optimization does",
"impact": "high|medium|low",
"implementation": ["step1", "step2"]
}
]
}
Focus on:
1. Identifying the most suitable IDE configurations
2. Recommending appropriate features for the project type
3. Suggesting performance and security improvements
4. Providing actionable next steps
Be specific and practical in your suggestions.`;
}
buildEnhancementPrompt(projectContext, currentConfig) {
return `
You are an expert software development consultant reviewing an existing project configuration to suggest enhancements.
Project Context:
${projectContext}
Current Configuration:
${JSON.stringify(currentConfig, null, 2)}
Please suggest intelligent enhancements for this project. Return a JSON array of suggestions:
[
{
"type": "feature|optimization|migration|config",
"title": "Enhancement title",
"description": "Detailed description of the enhancement",
"priority": "high|medium|low",
"effort": "trivial|small|medium|large",
"reasoning": "Why this enhancement would be valuable"
}
]
Focus on:
1. Missing features that would benefit this project type
2. Performance optimizations
3. Developer experience improvements
4. Security enhancements
5. Maintainability improvements
Be practical and consider the current tech stack and project complexity.`;
}
buildErrorRecoveryPrompt(error, context) {
return `
You are an expert software troubleshooter helping a developer resolve an error.
Error Details:
- Message: ${error.message}
- Stack: ${error.stack || 'No stack trace available'}
Context:
${context}
Please provide recovery suggestions as a JSON array:
[
{
"type": "config",
"title": "Solution title",
"description": "Step-by-step solution",
"priority": "high|medium|low",
"effort": "trivial|small|medium|large",
"reasoning": "Why this solution should work"
}
]
Focus on:
1. Most likely causes and solutions
2. Configuration issues
3. Missing dependencies
4. Permission problems
5. Environment setup issues
Provide actionable, specific solutions.`;
}
parseAIResponse(response) {
try {
const parsed = JSON.parse(response);
return {
suggestions: parsed.suggestions || parsed || [],
confidence: parsed.confidence || 75,
reasoning: parsed.reasoning || 'AI analysis completed',
optimizations: parsed.optimizations || [],
};
}
catch (error) {
console.warn('Failed to parse AI response:', error);
return {
suggestions: [],
confidence: 0,
reasoning: 'Failed to parse AI response',
optimizations: [],
};
}
}
getFallbackSuggestions(basicAnalysis) {
const suggestions = [];
// Analyze tech stack for basic suggestions
if (Array.isArray(basicAnalysis.techStack) && basicAnalysis.techStack.includes('React')) {
suggestions.push({
type: 'config',
title: 'React Development Setup',
description: 'Configure optimized settings for React development',
priority: 'high',
effort: 'trivial',
reasoning: 'React project detected - optimized configuration recommended',
suggestedConfig: {
extras: {
testing: true,
linting: true,
examples: true,
},
},
});
}
if (Array.isArray(basicAnalysis.techStack) && basicAnalysis.techStack.includes('TypeScript')) {
suggestions.push({
type: 'optimization',
title: 'TypeScript Optimization',
description: 'Enable strict TypeScript checking and advanced type features',
priority: 'medium',
effort: 'small',
reasoning: 'TypeScript detected - strict mode will improve code quality',
});
}
return {
suggestions,
confidence: 60,
reasoning: 'Using fallback analysis based on detected tech stack',
optimizations: [],
};
}
getFallbackEnhancementSuggestions(config) {
const suggestions = [];
if (!config.extras.testing) {
suggestions.push({
type: 'feature',
title: 'Add Testing Framework',
description: 'Set up comprehensive testing with jest and testing utilities',
priority: 'high',
effort: 'medium',
reasoning: 'Testing not enabled - critical for project quality',
});
}
if (!config.extras.cicd) {
suggestions.push({
type: 'feature',
title: 'CI/CD Pipeline',
description: 'Add continuous integration and deployment pipeline',
priority: 'medium',
effort: 'large',
reasoning: 'CI/CD improves deployment reliability and team productivity',
});
}
return suggestions;
}
getFallbackErrorSuggestions(error) {
const suggestions = [];
if (error.message.includes('permission')) {
suggestions.push({
type: 'config',
title: 'Fix Permission Error',
description: 'Check file permissions and user access rights',
priority: 'high',
effort: 'trivial',
reasoning: 'Permission error detected in error message',
});
}
if (error.message.includes('ENOENT') || error.message.includes('not found')) {
suggestions.push({
type: 'config',
title: 'Missing File or Directory',
description: 'Verify file paths and ensure required files exist',
priority: 'high',
effort: 'small',
reasoning: 'File not found error detected',
});
}
return suggestions;
}
isAIEnabled() {
return this.aiEnabled;
}
getAIStatus() {
if (!this.aiEnabled) {
if (process.env.CONTEXT_FORGE_DISABLE_AI === 'true') {
return 'AI features manually disabled (CONTEXT_FORGE_DISABLE_AI=true)';
}
return 'AI features disabled - no API key found';
}
switch (this.apiKeySource) {
case 'anthropic':
return 'AI enhanced - Connected to Anthropic API';
case 'bedrock':
return 'AI enhanced - Connected via Amazon Bedrock';
case 'vertex':
return 'AI enhanced - Connected via Google Vertex AI';
default:
return 'AI features disabled - no API key found';
}
}
}
exports.AIIntelligenceService = AIIntelligenceService;
//# sourceMappingURL=aiIntelligenceService.js.map