abyss-ai
Version:
Autonomous AI coding agent - enhanced OpenCode with autonomous capabilities
790 lines (649 loc) • 22.4 kB
text/typescript
import { ReasoningMode, type ProcessingContext, type ProcessingResult } from "../types/agent"
import { BaseReasoningProcessor } from "./reasoning-processor"
// Ultrareasoning - Structural/Logical Validation
export class UltrareasoningProcessor extends BaseReasoningProcessor {
readonly mode = ReasoningMode.ULTRAREASONING
async process(code: string, context: ProcessingContext): Promise<ProcessingResult> {
this.log.info("Starting ultrareasoning analysis", {
codeLength: code.length,
language: context.language
})
const { result: analysisResult, duration } = await this.measureExecutionTime(async () => {
// Deep structural and logical validation
const structureValidation = await this.validateStructure(code)
const logicalValidation = await this.validateLogic(code, context)
const consistencyCheck = await this.checkConsistency(code, context)
return {
structure: structureValidation,
logic: logicalValidation,
consistency: consistencyCheck
}
})
const confidence = this.calculateConfidence(analysisResult)
const validationReport = this.generateValidationReport(
analysisResult.structure,
analysisResult.logic
)
return {
type: 'ultrareasoning',
result: analysisResult,
confidence,
processingTime: duration,
validationReport
}
}
calculateConfidence(result: any): number {
if (!result) return 0.1
const { structure, logic, consistency } = result
// Weight the confidence based on validation success
const structureScore = (structure.score || 0) * 0.4
const logicScore = (logic.score || 0) * 0.4
const consistencyScore = (consistency.score || 0) * 0.2
return Math.min(1, structureScore + logicScore + consistencyScore)
}
private async validateStructure(code: string) {
this.log.debug("Validating code structure")
const structure = this.analyzeCodeStructure(code)
const issues = []
let score = 1.0
// Syntax validation
const syntaxIssues = this.checkSyntax(code)
if (syntaxIssues.length > 0) {
issues.push(...syntaxIssues)
score -= syntaxIssues.length * 0.1
}
// Structural patterns
const structuralIssues = this.checkStructuralPatterns(code, structure)
if (structuralIssues.length > 0) {
issues.push(...structuralIssues)
score -= structuralIssues.length * 0.05
}
// Architectural validation
const architecturalIssues = this.validateArchitecture(structure)
if (architecturalIssues.length > 0) {
issues.push(...architecturalIssues)
score -= architecturalIssues.length * 0.1
}
return {
score: Math.max(0, score),
issues,
structure,
metrics: this.calculateStructuralMetrics(structure),
valid: issues.length === 0
}
}
private checkSyntax(code: string) {
const issues = []
// Basic syntax checks
const braceBalance = this.checkBraceBalance(code)
if (!braceBalance.balanced) {
issues.push({
type: 'syntax',
severity: 'high',
message: `Unbalanced braces: ${braceBalance.issue}`,
line: braceBalance.line
})
}
const parenBalance = this.checkParenthesesBalance(code)
if (!parenBalance.balanced) {
issues.push({
type: 'syntax',
severity: 'high',
message: `Unbalanced parentheses: ${parenBalance.issue}`,
line: parenBalance.line
})
}
// Common syntax errors
const commonErrors = this.checkCommonSyntaxErrors(code)
issues.push(...commonErrors)
return issues
}
private checkBraceBalance(code: string) {
let balance = 0
let line = 1
let lastImbalanceLine = 0
for (let i = 0; i < code.length; i++) {
if (code[i] === '\n') line++
if (code[i] === '{') {
balance++
} else if (code[i] === '}') {
balance--
if (balance < 0) {
lastImbalanceLine = line
}
}
}
return {
balanced: balance === 0,
issue: balance > 0 ? 'Missing closing braces' : 'Extra closing braces',
line: lastImbalanceLine || line
}
}
private checkParenthesesBalance(code: string) {
let balance = 0
let line = 1
let lastImbalanceLine = 0
for (let i = 0; i < code.length; i++) {
if (code[i] === '\n') line++
if (code[i] === '(') {
balance++
} else if (code[i] === ')') {
balance--
if (balance < 0) {
lastImbalanceLine = line
}
}
}
return {
balanced: balance === 0,
issue: balance > 0 ? 'Missing closing parentheses' : 'Extra closing parentheses',
line: lastImbalanceLine || line
}
}
private checkCommonSyntaxErrors(code: string) {
const issues: any[] = []
const lines = code.split('\n')
lines.forEach((line, index) => {
const lineNum = index + 1
// Missing semicolons (for languages that use them)
if (line.match(/^[^\/]*[a-zA-Z0-9_\]]$/) && !line.trim().endsWith(';') && !line.includes('{')) {
issues.push({
type: 'syntax',
severity: 'low',
message: 'Possible missing semicolon',
line: lineNum
})
}
// Unclosed strings
const quotes = line.match(/["'`]/g)
if (quotes && quotes.length % 2 !== 0) {
issues.push({
type: 'syntax',
severity: 'medium',
message: 'Possible unclosed string',
line: lineNum
})
}
})
return issues
}
private checkStructuralPatterns(code: string, structure: any) {
const issues: any[] = []
// Function complexity
if (structure.functions) {
structure.functions.forEach((funcName: string) => {
const funcComplexity = this.getFunctionComplexity(code, funcName)
if (funcComplexity > 10) {
issues.push({
type: 'structural',
severity: 'medium',
message: `Function '${funcName}' has high cyclomatic complexity (${funcComplexity})`,
suggestion: 'Consider breaking down into smaller functions'
})
}
})
}
// Deep nesting
const maxNesting = this.getMaxNestingDepth(code)
if (maxNesting > 4) {
issues.push({
type: 'structural',
severity: 'medium',
message: `Deep nesting detected (${maxNesting} levels)`,
suggestion: 'Consider reducing nesting depth'
})
}
// Long parameter lists
const longParams = this.findLongParameterLists(code)
longParams.forEach(func => {
issues.push({
type: 'structural',
severity: 'low',
message: `Function has many parameters (${func.paramCount})`,
suggestion: 'Consider using an options object'
})
})
return issues
}
private getFunctionComplexity(code: string, funcName: string): number {
const funcRegex = new RegExp(`function\\s+${funcName}[^{]*{([^}]*)}`, 's')
const match = code.match(funcRegex)
if (match) {
return this.calculateUltraCyclomaticComplexity(match[1])
}
return 0
}
private calculateUltraCyclomaticComplexity(code: string): number {
const patterns = [
/\bif\s*\(/g,
/\belse\s+if\b/g,
/\bwhile\s*\(/g,
/\bfor\s*\(/g,
/\bcase\s+/g,
/\bcatch\s*\(/g,
/\?\s*.*\s*:/g,
/&&/g,
/\|\|/g
]
return patterns.reduce((complexity, pattern) => {
const matches = code.match(pattern)
return complexity + (matches ? matches.length : 0)
}, 1)
}
private getMaxNestingDepth(code: string): number {
let maxDepth = 0
let currentDepth = 0
for (const char of code) {
if (char === '{') {
currentDepth++
maxDepth = Math.max(maxDepth, currentDepth)
} else if (char === '}') {
currentDepth--
}
}
return maxDepth
}
private findLongParameterLists(code: string) {
const funcRegex = /function\s+(\w+)\s*\(([^)]*)\)/g
const longParams = []
let match
while ((match = funcRegex.exec(code)) !== null) {
const params = match[2].split(',').filter(p => p.trim())
if (params.length > 5) {
longParams.push({
name: match[1],
paramCount: params.length
})
}
}
return longParams
}
private validateArchitecture(structure: any) {
const issues: any[] = []
// Check for circular dependencies
if (structure.imports && structure.imports.length > 0) {
const circularDeps = this.detectCircularDependencies(structure.imports)
if (circularDeps.length > 0) {
issues.push({
type: 'architectural',
severity: 'high',
message: 'Potential circular dependencies detected',
dependencies: circularDeps
})
}
}
// Check separation of concerns
const concernsIssues = this.checkSeparationOfConcerns(structure)
issues.push(...concernsIssues)
return issues
}
private detectCircularDependencies(imports: string[]): string[] {
// Simplified circular dependency detection
const relativePaths = imports.filter(imp => imp.startsWith('.'))
const duplicates = relativePaths.filter((item, index) => relativePaths.indexOf(item) !== index)
return duplicates
}
private checkSeparationOfConcerns(structure: any) {
const issues: any[] = []
// Check if a single file has too many responsibilities
const responsibilities = []
if (structure.functions && structure.functions.length > 10) {
responsibilities.push('many functions')
}
if (structure.classes && structure.classes.length > 3) {
responsibilities.push('multiple classes')
}
if (structure.imports && structure.imports.length > 15) {
responsibilities.push('many dependencies')
}
if (responsibilities.length > 2) {
issues.push({
type: 'architectural',
severity: 'medium',
message: 'File may have too many responsibilities',
responsibilities,
suggestion: 'Consider splitting into multiple files'
})
}
return issues
}
private calculateStructuralMetrics(structure: any) {
return {
linesOfCode: structure.lineCount,
cyclomaticComplexity: structure.complexity,
functionCount: structure.functions?.length || 0,
classCount: structure.classes?.length || 0,
importCount: structure.imports?.length || 0,
cohesion: this.calculateCohesion(structure),
coupling: this.calculateCoupling(structure)
}
}
private calculateCohesion(structure: any): number {
// Simplified cohesion calculation
const totalElements = (structure.functions?.length || 0) + (structure.classes?.length || 0)
const imports = structure.imports?.length || 0
if (totalElements === 0) return 1
// Higher cohesion when fewer external dependencies relative to internal elements
return Math.max(0, 1 - (imports / (totalElements * 2)))
}
private calculateCoupling(structure: any): number {
// Simplified coupling calculation based on imports
const imports = structure.imports?.length || 0
// Normalize coupling score (lower is better)
return Math.min(1, imports / 10)
}
private async validateLogic(code: string, _context: ProcessingContext) {
this.log.debug("Validating code logic")
const issues = []
let score = 1.0
// Data flow analysis
const dataFlowIssues = this.analyzeDataFlow(code)
if (dataFlowIssues.length > 0) {
issues.push(...dataFlowIssues)
score -= dataFlowIssues.length * 0.1
}
// Logical consistency checks
const consistencyIssues = this.checkLogicalConsistency(code)
if (consistencyIssues.length > 0) {
issues.push(...consistencyIssues)
score -= consistencyIssues.length * 0.15
}
// Type consistency (if applicable)
const typeIssues = this.checkTypeConsistency(code)
if (typeIssues.length > 0) {
issues.push(...typeIssues)
score -= typeIssues.length * 0.1
}
return {
score: Math.max(0, score),
issues,
dataFlow: this.mapDataFlow(code),
valid: issues.filter(i => i.severity === 'high').length === 0
}
}
private analyzeDataFlow(code: string) {
const issues: any[] = []
// Check for undefined variables
const undefinedVars = this.findUndefinedVariables(code)
undefinedVars.forEach(varName => {
issues.push({
type: 'logic',
severity: 'high',
message: `Variable '${varName}' may be used before definition`,
variable: varName
})
})
// Check for unused variables
const unusedVars = this.findUnusedVariables(code)
unusedVars.forEach(varName => {
issues.push({
type: 'logic',
severity: 'low',
message: `Variable '${varName}' is declared but never used`,
variable: varName
})
})
return issues
}
private findUndefinedVariables(code: string): string[] {
// Simplified undefined variable detection
const declared = new Set<string>()
const used = new Set<string>()
// Find declarations
const declMatches = code.matchAll(/(?:let|const|var)\s+(\w+)/g)
for (const match of declMatches) {
declared.add(match[1])
}
// Find usage
const useMatches = code.matchAll(/\b(\w+)\s*[=\(\[\.]/g)
for (const match of useMatches) {
used.add(match[1])
}
// Return variables used but not declared
return Array.from(used).filter(v => !declared.has(v) && !this.isBuiltIn(v))
}
private findUnusedVariables(code: string): string[] {
const declared = new Set<string>()
const used = new Set<string>()
// Find declarations
const declMatches = code.matchAll(/(?:let|const|var)\s+(\w+)/g)
for (const match of declMatches) {
declared.add(match[1])
}
// Find usage (excluding declarations)
const useMatches = code.matchAll(/(?<!(?:let|const|var)\s+)\b(\w+)\b/g)
for (const match of useMatches) {
used.add(match[1])
}
// Return declared but unused variables
return Array.from(declared).filter(v => !used.has(v))
}
private isBuiltIn(varName: string): boolean {
const builtIns = [
'console', 'window', 'document', 'process', 'global',
'require', 'module', 'exports', 'Buffer', 'setTimeout',
'setInterval', 'clearTimeout', 'clearInterval', 'Promise'
]
return builtIns.includes(varName)
}
private checkLogicalConsistency(code: string) {
const issues: any[] = []
// Check for logical contradictions
const contradictions = this.findLogicalContradictions(code)
issues.push(...contradictions)
// Check for unreachable code
const unreachable = this.findUnreachableCode(code)
issues.push(...unreachable)
return issues
}
private findLogicalContradictions(code: string) {
const issues: any[] = []
const lines = code.split('\n')
lines.forEach((line, index) => {
// Check for always true/false conditions
if (line.includes('if (true)') || line.includes('if(true)')) {
issues.push({
type: 'logic',
severity: 'medium',
message: 'Condition is always true',
line: index + 1
})
}
if (line.includes('if (false)') || line.includes('if(false)')) {
issues.push({
type: 'logic',
severity: 'medium',
message: 'Condition is always false',
line: index + 1
})
}
})
return issues
}
private findUnreachableCode(code: string) {
const issues: any[] = []
const lines = code.split('\n')
for (let i = 0; i < lines.length - 1; i++) {
const line = lines[i].trim()
const nextLine = lines[i + 1].trim()
// Code after return statement
if (line.includes('return') && nextLine && !nextLine.startsWith('}') && !nextLine.startsWith('//')) {
issues.push({
type: 'logic',
severity: 'medium',
message: 'Unreachable code after return statement',
line: i + 2
})
}
}
return issues
}
private checkTypeConsistency(code: string) {
const issues = []
// Basic type consistency checks
const typeIssues = this.findTypeInconsistencies(code)
issues.push(...typeIssues)
return issues
}
private findTypeInconsistencies(code: string) {
const issues = []
// Check for number/string comparisons
const numStringComparisons = code.match(/\d+\s*[=!]==\s*["'`]|["'`]\s*[=!]==\s*\d+/g)
if (numStringComparisons) {
issues.push({
type: 'type',
severity: 'medium',
message: 'Comparing number with string',
suggestion: 'Consider using strict equality (===) and type conversion'
})
}
return issues
}
private mapDataFlow(code: string) {
// Simplified data flow mapping
const variables = []
const functions = []
// Extract variable assignments
const assignments = code.matchAll(/(\w+)\s*=\s*([^;]+)/g)
for (const match of assignments) {
variables.push({
name: match[1],
assignment: match[2].trim()
})
}
// Extract function calls
const calls = code.matchAll(/(\w+)\s*\(/g)
for (const match of calls) {
functions.push(match[1])
}
return { variables, functions }
}
private async checkConsistency(code: string, _context: ProcessingContext) {
this.log.debug("Checking code consistency")
const issues = []
let score = 1.0
// Naming consistency
const namingIssues = this.checkNamingConsistency(code)
if (namingIssues.length > 0) {
issues.push(...namingIssues)
score -= namingIssues.length * 0.05
}
// Style consistency
const styleIssues = this.checkStyleConsistency(code)
if (styleIssues.length > 0) {
issues.push(...styleIssues)
score -= styleIssues.length * 0.02
}
// Pattern consistency
const patternIssues = this.checkPatternConsistency(code)
if (patternIssues.length > 0) {
issues.push(...patternIssues)
score -= patternIssues.length * 0.1
}
return {
score: Math.max(0, score),
issues,
valid: issues.filter(i => i.severity === 'high').length === 0
}
}
private checkNamingConsistency(code: string) {
const issues = []
// Check variable naming conventions
const variables = code.match(/(?:let|const|var)\s+(\w+)/g) || []
const namingStyles = new Set()
variables.forEach(varDecl => {
const varName = varDecl.split(/\s+/)[1]
if (varName.includes('_')) {
namingStyles.add('snake_case')
} else if (varName.match(/[a-z][A-Z]/)) {
namingStyles.add('camelCase')
} else if (varName.match(/^[A-Z]/)) {
namingStyles.add('PascalCase')
}
})
if (namingStyles.size > 1) {
issues.push({
type: 'consistency',
severity: 'low',
message: 'Inconsistent variable naming conventions',
styles: Array.from(namingStyles)
})
}
return issues
}
private checkStyleConsistency(code: string) {
const issues = []
// Check indentation consistency
const lines = code.split('\n').filter(line => line.trim())
const indentations = new Set()
lines.forEach(line => {
const indent = line.match(/^(\s*)/)?.[1] || ''
if (indent.length > 0) {
indentations.add(indent.includes('\t') ? 'tabs' : `${indent.length}spaces`)
}
})
if (indentations.size > 2) { // Allow some variation
issues.push({
type: 'consistency',
severity: 'low',
message: 'Inconsistent indentation style',
styles: Array.from(indentations)
})
}
return issues
}
private checkPatternConsistency(code: string) {
const issues = []
// Check error handling patterns
const hasAsyncAwait = code.includes('async') && code.includes('await')
const hasPromises = code.includes('Promise') || code.includes('.then(')
const hasTryCatch = code.includes('try') && code.includes('catch')
if (hasAsyncAwait && hasPromises && !hasTryCatch) {
issues.push({
type: 'consistency',
severity: 'medium',
message: 'Mixed async patterns without proper error handling',
suggestion: 'Consider consistent error handling with try-catch blocks'
})
}
return issues
}
private generateValidationReport(structureValidation: any, logicalValidation: any) {
const totalIssues = [
...(structureValidation.issues || []),
...(logicalValidation.issues || [])
]
const severityCounts = {
high: totalIssues.filter(i => i.severity === 'high').length,
medium: totalIssues.filter(i => i.severity === 'medium').length,
low: totalIssues.filter(i => i.severity === 'low').length
}
return {
summary: {
totalIssues: totalIssues.length,
severityCounts,
structureScore: structureValidation.score,
logicScore: logicalValidation.score,
overallScore: (structureValidation.score + logicalValidation.score) / 2
},
recommendations: this.generateRecommendations(totalIssues),
metrics: structureValidation.metrics
}
}
private generateRecommendations(issues: any[]) {
const recommendations = []
const highIssues = issues.filter(i => i.severity === 'high')
if (highIssues.length > 0) {
recommendations.push('Address high-severity issues immediately')
}
const structuralIssues = issues.filter(i => i.type === 'structural')
if (structuralIssues.length > 3) {
recommendations.push('Consider refactoring for better code structure')
}
const logicIssues = issues.filter(i => i.type === 'logic')
if (logicIssues.length > 0) {
recommendations.push('Review logic flow and data handling')
}
return recommendations
}
}