contaigents
Version:
Modular AI Content Ecosystem with Audio Generation
218 lines (214 loc) • 9 kB
JavaScript
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;
}
}