UNPKG

contaigents

Version:

Modular AI Content Ecosystem with Audio Generation

218 lines (214 loc) 9 kB
import { BaseTool } from '../base/BaseTool.js'; import { IntelligentFileService } from '../../services/IntelligentFileService.js'; export class AnalyzeFileTool extends BaseTool { constructor(context) { super('analyze_file', 'Analyze a file to extract metadata, classify content, and provide intelligent insights', context); this.intelligentFileService = new IntelligentFileService(context.workingDirectory); } async execute(params) { try { const { filePath, includeContent = false, analysisDepth = 'detailed' } = params; if (!filePath) { return this.createErrorResult('File path is required'); } // Check if file exists const exists = await this.intelligentFileService.fileExists(filePath); if (!exists) { return this.createErrorResult(`File not found: ${filePath}`); } let result = {}; switch (analysisDepth) { case 'basic': result = await this.performBasicAnalysis(filePath, includeContent); break; case 'detailed': result = await this.performDetailedAnalysis(filePath, includeContent); break; case 'comprehensive': result = await this.performComprehensiveAnalysis(filePath, includeContent); break; } return this.createSuccessResult(result, { analysisDepth, timestamp: Date.now(), filePath }); } catch (error) { return this.createErrorResult(`Analysis failed: ${error instanceof Error ? error.message : 'Unknown error'}`); } } async performBasicAnalysis(filePath, includeContent) { const content = await this.intelligentFileService.readFile(filePath); const classification = await this.intelligentFileService.classifyFile(filePath); const result = { filePath, classification, size: Buffer.byteLength(content, 'utf8'), lineCount: content.split('\n').length, wordCount: content.split(/\s+/).length, characterCount: content.length }; if (includeContent) { result.content = content; } return result; } async performDetailedAnalysis(filePath, includeContent) { const analysisResult = await this.intelligentFileService.analyzeFile(filePath); const classification = await this.intelligentFileService.classifyFile(filePath); const summary = await this.intelligentFileService.summarizeFile(filePath, 300); const result = { filePath, classification, metadata: analysisResult.metadata, analysis: analysisResult.analysis, summary, statistics: { size: analysisResult.metadata.size, lineCount: analysisResult.content.split('\n').length, wordCount: analysisResult.content.split(/\s+/).length, characterCount: analysisResult.content.length } }; if (includeContent) { result.content = analysisResult.content; } return result; } async performComprehensiveAnalysis(filePath, includeContent) { const detailedResult = await this.performDetailedAnalysis(filePath, includeContent); // Add additional comprehensive analysis const content = await this.intelligentFileService.readFile(filePath); const additionalInsights = await this.generateAdditionalInsights(content, filePath); return { ...detailedResult, comprehensiveInsights: additionalInsights, relationships: await this.analyzeFileRelationships(filePath), qualityMetrics: this.calculateQualityMetrics(content, detailedResult.metadata.contentType) }; } async generateAdditionalInsights(content, filePath) { if (!this.context.llm) { return { insights: ['LLM not available for comprehensive insights'], recommendations: [], potentialIssues: [] }; } const prompt = `Provide comprehensive insights for this file: File: ${filePath} Content: ${content.substring(0, 2000)}${content.length > 2000 ? '...' : ''} Please provide: 1. INSIGHTS: Key insights about the file's content and structure 2. RECOMMENDATIONS: Specific recommendations for improvement 3. ISSUES: Potential issues or concerns Format each section with the label followed by bullet points.`; try { const response = await this.context.llm.executePrompt(prompt); return this.parseComprehensiveInsights(response.content); } catch (error) { return { insights: ['Failed to generate insights'], recommendations: [], potentialIssues: [`Analysis error: ${error}`] }; } } parseComprehensiveInsights(response) { const sections = { insights: [], recommendations: [], potentialIssues: [] }; const lines = response.split('\n'); let currentSection = ''; for (const line of lines) { const trimmed = line.trim(); if (trimmed.startsWith('INSIGHTS:')) { currentSection = 'insights'; } else if (trimmed.startsWith('RECOMMENDATIONS:')) { currentSection = 'recommendations'; } else if (trimmed.startsWith('ISSUES:')) { currentSection = 'potentialIssues'; } else if (trimmed.startsWith('- ') || trimmed.startsWith('• ')) { const item = trimmed.substring(2); if (currentSection && sections[currentSection]) { sections[currentSection].push(item); } } } return sections; } async analyzeFileRelationships(filePath) { try { const content = await this.intelligentFileService.readFile(filePath); const relationships = { imports: [], exports: [], references: [], dependencies: [] }; // Basic pattern matching for common file relationships const importPatterns = [ /import\s+.*\s+from\s+['"]([^'"]+)['"]/g, /require\(['"]([^'"]+)['"]\)/g, /#include\s*<([^>]+)>/g, /#include\s*"([^"]+)"/g ]; for (const pattern of importPatterns) { let match; while ((match = pattern.exec(content)) !== null) { relationships.imports.push(match[1]); } } // Look for markdown links to other files const linkPattern = /\[.*?\]\(([^)]+\.md[^)]*)\)/g; let linkMatch; while ((linkMatch = linkPattern.exec(content)) !== null) { relationships.references.push(linkMatch[1]); } return relationships; } catch (error) { return { imports: [], exports: [], references: [], dependencies: [], error: `Failed to analyze relationships: ${error}` }; } } calculateQualityMetrics(content, contentType) { const metrics = { readabilityScore: 0, complexityScore: 0, maintainabilityScore: 0, documentationScore: 0 }; const lines = content.split('\n'); const words = content.split(/\s+/); // Basic readability (simplified) const avgWordsPerLine = words.length / lines.length; metrics.readabilityScore = Math.max(0, Math.min(100, 100 - (avgWordsPerLine - 10) * 2)); // Complexity based on nesting and special characters const nestingChars = (content.match(/[{}()[\]]/g) || []).length; metrics.complexityScore = Math.min(100, (nestingChars / content.length) * 1000); // Documentation score for markdown files if (contentType === 'markdown') { const headings = (content.match(/^#+\s/gm) || []).length; const codeBlocks = (content.match(/```/g) || []).length / 2; const links = (content.match(/\[.*?\]\(.*?\)/g) || []).length; metrics.documentationScore = Math.min(100, (headings * 10) + (codeBlocks * 5) + (links * 2)); } // Maintainability (inverse of complexity, plus documentation) metrics.maintainabilityScore = Math.max(0, 100 - metrics.complexityScore + (metrics.documentationScore * 0.2)); return metrics; } }