@sethdouglasford/claude-flow
Version:
Claude Code Flow - Advanced AI-powered development workflows with SPARC methodology
309 lines • 13.2 kB
JavaScript
/**
* Code Agent - Implements hierarchical model strategy for intelligent code generation
* Uses different models based on task complexity and context requirements
*/
import { BaseAgent } from "./base-agent.js";
import { logger } from "../../core/logger.js";
import { getModelHierarchy } from "../../config/model-config.js";
export class CodeAgent extends BaseAgent {
modelHierarchy;
fileContextCache = new Map();
editComplexityThreshold = 50; // lines of code
constructor(id, config) {
super(id, "developer");
// Use centralized model configuration
const defaultHierarchy = getModelHierarchy(config?.useCase || "development");
this.modelHierarchy = {
primary: config?.models?.primary || defaultHierarchy.primary,
apply: config?.models?.apply || defaultHierarchy.apply,
review: config?.models?.review || defaultHierarchy.review,
};
this.capabilities = {
codeGeneration: true,
codeReview: true,
testing: true,
documentation: true,
research: false,
analysis: true,
webSearch: false,
apiIntegration: false,
fileSystem: true,
terminalAccess: true,
languages: ["typescript", "javascript", "python", "java", "cpp"],
frameworks: ["node", "react", "express", "nestjs"],
domains: ["web-development", "backend-development", "api-development"],
tools: [
"hierarchical-code-generation",
"context-aware-editing",
"smart-chunking",
"progressive-error-recovery",
"test-driven-development",
"apply-model-edits",
"primary-model-planning",
"review-model-validation",
"context-analysis",
"dependency-tracking",
],
maxConcurrentTasks: 3,
maxMemoryUsage: 2048,
maxExecutionTime: 600,
reliability: 0.95,
speed: 0.85,
quality: 0.9,
};
}
async executeTask(task) {
logger.info(`CodeAgent ${this.id} executing task: ${task.name}`);
try {
// Analyze task complexity and select appropriate model
const complexity = await this.analyzeTaskComplexity(task);
const selectedModel = this.selectModel(complexity);
logger.info(`Task complexity: ${complexity}, selected model: ${selectedModel}`);
// Get relevant file context
const context = await this.gatherFileContext(task);
// Execute based on task type and complexity
switch (complexity) {
case "simple":
return await this.executeSimpleEdit(task, context);
case "medium":
return await this.executeMediumEdit(task, context);
case "complex":
return await this.executeComplexEdit(task, context);
default:
throw new Error(`Unknown complexity level: ${complexity}`);
}
}
catch (error) {
logger.error(`CodeAgent ${this.id} task execution failed:`, error);
return await this.handleError(error, task);
}
}
async analyzeTaskComplexity(task) {
// Analyze task description for complexity indicators
const description = task.description.toLowerCase();
const instructions = task.instructions?.toLowerCase() || "";
const complexityIndicators = {
simple: [
"fix typo", "rename variable", "add import", "update comment",
"change value", "fix formatting", "add parameter",
],
medium: [
"implement function", "add method", "update logic", "refactor",
"add validation", "handle error", "optimize performance",
],
complex: [
"design architecture", "implement system", "security audit",
"major refactor", "performance optimization", "integration",
"database schema", "api design",
],
};
// Check for complex indicators first
if (complexityIndicators.complex.some(indicator => description.includes(indicator) || instructions.includes(indicator))) {
return "complex";
}
// Check for medium indicators
if (complexityIndicators.medium.some(indicator => description.includes(indicator) || instructions.includes(indicator))) {
return "medium";
}
// Default to simple for basic tasks
return "simple";
}
selectModel(complexity) {
switch (complexity) {
case "simple":
return this.modelHierarchy.apply;
case "medium":
return this.modelHierarchy.primary;
case "complex":
return this.modelHierarchy.primary;
default:
return this.modelHierarchy.primary;
}
}
async gatherFileContext(task) {
// Implementation would gather relevant file context
// This is a simplified version
const contexts = [];
// Extract file paths from task description/instructions
const filePaths = this.extractFilePaths(`${task.description} ${task.instructions || ""}`);
for (const path of filePaths) {
if (this.fileContextCache.has(path)) {
contexts.push(this.fileContextCache.get(path));
}
else {
const context = await this.analyzeFile(path);
this.fileContextCache.set(path, context);
contexts.push(context);
}
}
return contexts;
}
extractFilePaths(text) {
// Simple regex to extract file paths
const pathRegex = /[\w\-\.\/]+\.(ts|js|tsx|jsx|py|java|cpp|h|css|html|md|json|yaml|yml)/g;
return text.match(pathRegex) || [];
}
async analyzeFile(path) {
// Simplified file analysis - in real implementation would use AST parsing
return {
path,
language: this.detectLanguage(path),
dependencies: [],
exports: [],
complexity: "medium",
lastModified: new Date(),
relatedFiles: [],
};
}
detectLanguage(path) {
const extension = path.split(".").pop()?.toLowerCase();
const languageMap = {
"ts": "typescript",
"tsx": "typescript",
"js": "javascript",
"jsx": "javascript",
"py": "python",
"java": "java",
"cpp": "cpp",
"c": "c",
"h": "c",
"css": "css",
"html": "html",
"md": "markdown",
"json": "json",
"yaml": "yaml",
"yml": "yaml",
};
return languageMap[extension || ""] || "text";
}
async executeSimpleEdit(task, context) {
logger.info(`Executing simple edit with apply model: ${this.modelHierarchy.apply}`);
// Use apply model for fast, precise edits
return {
status: "completed",
model: this.modelHierarchy.apply,
approach: "apply-model-edit",
context: context.map(c => c.path),
result: "Simple edit completed successfully",
};
}
async executeMediumEdit(task, context) {
logger.info(`Executing medium edit with primary model: ${this.modelHierarchy.primary}`);
// Use primary model for complex logic
return {
status: "completed",
model: this.modelHierarchy.primary,
approach: "primary-model-implementation",
context: context.map(c => c.path),
result: "Medium complexity edit completed successfully",
};
}
async executeComplexEdit(task, context) {
logger.info("Executing complex edit with primary + review models");
// Use primary model for implementation, then review model for validation
const implementation = await this.implementWithPrimaryModel(task, context);
const review = await this.reviewWithReviewModel(implementation, context);
return {
status: "completed",
model: `${this.modelHierarchy.primary} + ${this.modelHierarchy.review}`,
approach: "hierarchical-implementation-review",
context: context.map(c => c.path),
implementation,
review,
result: "Complex edit completed with review validation",
};
}
async implementWithPrimaryModel(task, context) {
// Primary model implementation logic
return {
approach: "primary-model",
files: context.map(c => c.path),
changes: "Implementation completed",
};
}
async reviewWithReviewModel(implementation, context) {
// Review model validation logic
return {
approach: "review-model",
quality: "high",
suggestions: [],
approved: true,
};
}
async handleError(error, task) {
logger.error(`Error handling for task ${task.id.id}:`, error);
// Progressive error recovery
return {
status: "error",
error: error.message,
recovery: "attempted",
suggestions: [
"Retry with different model",
"Break down into smaller tasks",
"Request additional context",
],
};
}
getCapabilities() {
return this.capabilities;
}
canHandleTask(task) {
const requiredCapabilities = task.requirements?.capabilities || [];
// Map task capability names to agent capability properties
const capabilityMap = {
// Core capabilities
"analysis": this.capabilities.analysis,
"planning": this.capabilities.analysis, // Planning is part of analysis
"coding": this.capabilities.codeGeneration,
"implementation": this.capabilities.codeGeneration,
"review": this.capabilities.codeReview,
"testing": this.capabilities.testing,
"documentation": this.capabilities.documentation,
"research": this.capabilities.research || true, // CodeAgent can do basic research
"web-search": this.capabilities.webSearch,
"api-integration": this.capabilities.apiIntegration,
"file-system": this.capabilities.fileSystem,
"terminal": this.capabilities.terminalAccess,
// Development strategy specific capabilities
"architecture": this.capabilities.analysis, // Architecture design is analysis
"design": this.capabilities.analysis, // Design is analysis
"frontend": this.capabilities.codeGeneration, // Frontend is code generation
"backend": this.capabilities.codeGeneration, // Backend is code generation
"api_development": this.capabilities.codeGeneration, // API dev is code generation
"coordination": true, // CodeAgent can coordinate through Memory
"quality_assurance": this.capabilities.codeReview, // QA is code review
"integration": this.capabilities.codeGeneration, // Integration is coding
"deployment": this.capabilities.terminalAccess, // Deployment uses terminal
"monitoring": this.capabilities.analysis, // Monitoring is analysis
// Tool capabilities - CodeAgent supports all these through its tools
"memory": true,
"web_search": this.capabilities.webSearch || true, // Can do basic web search
"file_operations": this.capabilities.fileSystem,
"batch_operations": true,
"mcp_orchestration": true,
"pattern_synthesis": this.capabilities.analysis,
"meta_learning": this.capabilities.analysis,
"feature_discovery": this.capabilities.analysis,
"code_review_game": this.capabilities.codeReview,
"virgil_protocol": this.capabilities.analysis,
"ulysses_protocol": this.capabilities.analysis,
"wisdom_distillation": this.capabilities.analysis,
};
// Check if agent can handle all required capabilities
return requiredCapabilities.every(capability => {
const canHandle = capabilityMap[capability];
if (canHandle === undefined) {
// If capability is not mapped, log it and assume agent can handle it
logger.info(`Unknown capability '${capability}' for task ${task.id.id}, assuming agent can handle it`);
return true;
}
return canHandle;
});
}
async cleanup() {
// Clear caches and cleanup resources
this.fileContextCache.clear();
await super.cleanup();
}
}
//# sourceMappingURL=code-agent.js.map