abyss-ai
Version:
Autonomous AI coding agent - enhanced OpenCode with autonomous capabilities
302 lines (253 loc) • 9.67 kB
text/typescript
import { Log } from "../../util/log"
import { AgentTask, AgentType, ReasoningMode } from "../types/agent"
import { Config } from "../../config/config"
export interface GeneratedQuestion {
id: string
question: string
perspective: string
targetAgentName: string // Changed to use OpenCode's agent names
reasoningMode: ReasoningMode
priority: number
expectedCapabilities: string[]
}
export interface QuestionGenerationResult {
questions: GeneratedQuestion[]
context: {
originalQuery: string
analysisScope: string
complexity: number
estimatedProcessingTime: number
}
}
export class QuestionGenerator {
private log = Log.create({ service: "question-generator" })
constructor() {
this.log.info("QuestionGenerator initialized")
}
/**
* Generate specialized research questions from a user query or task
* Similar to make-it-heavy's approach but tailored for code analysis
*/
async generateQuestions(task: AgentTask): Promise<QuestionGenerationResult> {
this.log.info("Generating specialized questions for task", {
taskId: task.id,
taskType: task.type
})
const questions = await this.createQuestionSet(task)
const context = this.analyzeTaskContext(task)
const result: QuestionGenerationResult = {
questions,
context: {
originalQuery: task.type,
analysisScope: this.determineAnalysisScope(task),
complexity: this.assessComplexity(task),
estimatedProcessingTime: this.estimateProcessingTime(questions)
}
}
this.log.debug("Questions generated", {
questionCount: questions.length,
perspectives: questions.map(q => q.perspective),
complexity: result.context.complexity
})
return result
}
/**
* Create a diverse set of research questions for comprehensive analysis
*/
private async createQuestionSet(task: AgentTask): Promise<GeneratedQuestion[]> {
const questions: GeneratedQuestion[] = []
// Generate questions based on task type and content
const baseQuestions = this.generateBaseQuestions(task)
const perspectiveQuestions = this.generatePerspectiveQuestions(task)
const validationQuestions = this.generateValidationQuestions(task)
const innovationQuestions = this.generateInnovationQuestions(task)
questions.push(...baseQuestions, ...perspectiveQuestions, ...validationQuestions, ...innovationQuestions)
// Sort by priority and limit to avoid overwhelming
return questions
.sort((a, b) => b.priority - a.priority)
.slice(0, 6) // Limit to 6 questions max
}
/**
* Generate foundational analysis questions
*/
private generateBaseQuestions(task: AgentTask): GeneratedQuestion[] {
const questions: GeneratedQuestion[] = []
// Code structure and quality analysis
if (this.isCodeAnalysisTask(task)) {
questions.push({
id: `base-structure-${task.id}`,
question: "Analyze the code structure, architecture patterns, and overall design quality",
perspective: "Structural Analysis",
targetAgentName: "code-analyzer",
reasoningMode: ReasoningMode.ULTRAREASONING,
priority: 0.9,
expectedCapabilities: ["analysis", "architecture", "design-patterns"]
})
}
// Error detection and potential issues
if (this.needsErrorDetection(task)) {
questions.push({
id: `base-errors-${task.id}`,
question: "Identify potential errors, bugs, and code quality issues with their severity levels",
perspective: "Error Detection",
targetAgentName: "error-detector",
reasoningMode: ReasoningMode.ULTRATHINKING,
priority: 0.85,
expectedCapabilities: ["error-detection", "debugging", "validation"]
})
}
return questions
}
/**
* Generate multi-perspective analysis questions
*/
private generatePerspectiveQuestions(task: AgentTask): GeneratedQuestion[] {
const questions: GeneratedQuestion[] = []
// Security perspective
questions.push({
id: `perspective-security-${task.id}`,
question: "Evaluate security vulnerabilities, potential attack vectors, and compliance with security best practices",
perspective: "Security Analysis",
targetAgentName: "security-analyzer",
reasoningMode: ReasoningMode.HYBRID_REASONING,
priority: 0.8,
expectedCapabilities: ["security", "vulnerability-detection", "compliance"]
})
// Performance perspective
questions.push({
id: `perspective-performance-${task.id}`,
question: "Assess performance characteristics, bottlenecks, and optimization opportunities",
perspective: "Performance Analysis",
targetAgentName: "performance-analyzer",
reasoningMode: ReasoningMode.HYBRID_REASONING,
priority: 0.75,
expectedCapabilities: ["performance", "optimization", "profiling"]
})
return questions
}
/**
* Generate validation and verification questions
*/
private generateValidationQuestions(task: AgentTask): GeneratedQuestion[] {
const questions: GeneratedQuestion[] = []
// Cross-validation question
questions.push({
id: `validation-cross-${task.id}`,
question: "Cross-validate findings from other analyses and identify potential conflicts or complementary insights",
perspective: "Cross-Validation",
targetAgentName: "code-analyzer",
reasoningMode: ReasoningMode.HYBRID_THINKING,
priority: 0.6,
expectedCapabilities: ["validation", "synthesis", "conflict-resolution"]
})
return questions
}
/**
* Generate innovative and creative analysis questions
*/
private generateInnovationQuestions(task: AgentTask): GeneratedQuestion[] {
const questions: GeneratedQuestion[] = []
// For now, skip innovation questions to keep it simple
// Can be added later when we have more specialized agents
return questions
}
/**
* Analyze the context and scope of the task
*/
private analyzeTaskContext(task: AgentTask): any {
return {
hasCodeContent: this.hasCodeContent(task),
projectSize: this.estimateProjectSize(task),
languageContext: this.extractLanguageContext(task),
frameworkContext: this.extractFrameworkContext(task)
}
}
/**
* Determine the scope of analysis needed
*/
private determineAnalysisScope(task: AgentTask): string {
if (this.isFileProcessingTask(task)) {
return "file-level"
}
if (this.isProjectAnalysisTask(task)) {
return "project-level"
}
if (this.isCodeSnippetTask(task)) {
return "snippet-level"
}
return "general"
}
/**
* Assess the complexity of the task
*/
private assessComplexity(task: AgentTask): number {
let complexity = 0.5 // Base complexity
// Factor in data size
if (task.data && typeof task.data === 'string') {
const lines = task.data.split('\n').length
if (lines > 1000) complexity += 0.3
else if (lines > 100) complexity += 0.2
else if (lines > 10) complexity += 0.1
}
// Factor in reasoning modes
if (task.reasoningModes.length > 2) {
complexity += 0.2
}
// Factor in task type
if (task.type.includes('refactor') || task.type.includes('security')) {
complexity += 0.2
}
return Math.min(1, complexity)
}
/**
* Estimate processing time based on questions and complexity
*/
private estimateProcessingTime(questions: GeneratedQuestion[]): number {
const baseTimePerQuestion = 30000 // 30 seconds
const complexityMultiplier = questions.length > 4 ? 1.5 : 1.2
return questions.length * baseTimePerQuestion * complexityMultiplier
}
// Helper methods for task classification
private isCodeAnalysisTask(task: AgentTask): boolean {
return task.type.includes('analysis') || task.type.includes('code')
}
private needsErrorDetection(task: AgentTask): boolean {
return !task.type.includes('documentation') && this.hasCodeContent(task)
}
private needsDocumentationAnalysis(task: AgentTask): boolean {
return task.type.includes('documentation') || task.type.includes('analysis')
}
private needsRefactoringAnalysis(task: AgentTask): boolean {
return task.type.includes('refactor') || task.type.includes('improvement')
}
private isFileProcessingTask(task: AgentTask): boolean {
return task.type.includes('file') || task.type.includes('process')
}
private isProjectAnalysisTask(task: AgentTask): boolean {
return task.type.includes('project') || (task.context.projectPath && task.context.projectPath.length > 0)
}
private isCodeSnippetTask(task: AgentTask): boolean {
return task.data && typeof task.data === 'string' && task.data.length < 1000
}
private hasCodeContent(task: AgentTask): boolean {
if (!task.data) return false
if (typeof task.data !== 'string') return false
// Simple heuristic to detect code content
const codeIndicators = ['{', '}', '(', ')', ';', 'function', 'class', 'import', 'export']
return codeIndicators.some(indicator => task.data.includes(indicator))
}
private estimateProjectSize(task: AgentTask): 'small' | 'medium' | 'large' {
if (task.data && typeof task.data === 'string') {
const length = task.data.length
if (length > 50000) return 'large'
if (length > 5000) return 'medium'
}
return 'small'
}
private extractLanguageContext(task: AgentTask): string | undefined {
return task.context.language
}
private extractFrameworkContext(task: AgentTask): string[] {
return task.context.frameworks || []
}
}