UNPKG

trace.ai-cli

Version:

A powerful AI-powered CLI tool

164 lines (138 loc) 5.89 kB
const fs = require('fs').promises; const path = require('path'); const { getFileType } = require('../utils/fileUtils'); const { processWithAI } = require('./aiService'); function buildSimpleFileTree(folderPath, items, statsCache, depth = 0) { let tree = ''; const indent = ' '.repeat(depth); for (const item of items) { const itemPath = path.join(folderPath, item); const stats = statsCache.get(itemPath); tree += `${indent}${item}${stats.isDirectory() ? '/' : ''}\n`; if (stats.isDirectory()) { try { const subItems = fs.readdirSync(itemPath); const subStatsCache = new Map(); for (const subItem of subItems) { const subItemPath = path.join(itemPath, subItem); subStatsCache.set(subItemPath, fs.statSync(subItemPath)); } tree += buildSimpleFileTree(itemPath, subItems, subStatsCache, depth + 1); } catch (error) { tree += `${indent} (error accessing directory)\n`; } } } return tree; } async function analyzeFolder(folderPath, maxDepth = 2, currentDepth = 0) { try { const stats = await fs.stat(folderPath); if (!stats.isDirectory()) { throw new Error('Path is not a directory'); } const analysis = { path: folderPath, files: [], folders: [], fileTree: '', // Store simple file tree summary: { totalFiles: 0, totalFolders: 0, fileTypes: {}, languages: {}, size: 0 } }; const items = await fs.readdir(folderPath); const statsCache = new Map(); // Cache stats for all items for (const item of items) { const itemPath = path.join(folderPath, item); statsCache.set(itemPath, await fs.stat(itemPath)); } // Build simple file tree analysis.fileTree = buildSimpleFileTree(folderPath, items, statsCache); for (const item of items) { const itemPath = path.join(folderPath, item); const itemStats = statsCache.get(itemPath); if (itemStats.isDirectory()) { analysis.folders.push(item); analysis.summary.totalFolders++; if (currentDepth < maxDepth) { try { const subAnalysis = await analyzeFolder(itemPath, maxDepth, currentDepth + 1); analysis.summary.totalFiles += subAnalysis.summary.totalFiles; analysis.summary.totalFolders += subAnalysis.summary.totalFolders; analysis.summary.size += subAnalysis.summary.size; Object.keys(subAnalysis.summary.fileTypes).forEach(type => { analysis.summary.fileTypes[type] = (analysis.summary.fileTypes[type] || 0) + subAnalysis.summary.fileTypes[type]; }); Object.keys(subAnalysis.summary.languages).forEach(lang => { analysis.summary.languages[lang] = (analysis.summary.languages[lang] || 0) + subAnalysis.summary.languages[lang]; }); } catch (error) { console.warn(`Warning: Cannot access folder ${itemPath}`); } } } else { const fileType = getFileType(itemPath); analysis.files.push({ name: item, type: fileType, size: itemStats.size, modified: itemStats.mtime }); analysis.summary.totalFiles++; analysis.summary.size += itemStats.size; analysis.summary.fileTypes[fileType] = (analysis.summary.fileTypes[fileType] || 0) + 1; if (fileType !== 'image' && fileType !== 'Unknown') { analysis.summary.languages[fileType] = (analysis.summary.languages[fileType] || 0) + 1; } } } return analysis; } catch (error) { if (error.code === 'ENOENT') { throw new Error(`Folder not found: ${folderPath}`); } if (error.code === 'EACCES') { throw new Error(`Access denied: ${folderPath}`); } throw error; } } async function analyzeFolderStructure(folderPath, query = '') { try { const analysis = await analyzeFolder(folderPath); const structureText = ` Folder: ${analysis.path} Files: ${analysis.summary.totalFiles} Folders: ${analysis.summary.totalFolders} Total Size: ${(analysis.summary.size / 1024).toFixed(2)} KB Files and Directories: ${analysis.fileTree} File Types: ${Object.entries(analysis.summary.fileTypes).map(([type, count]) => `- ${type}: ${count}`).join('\n')} Languages/Technologies: ${Object.entries(analysis.summary.languages).map(([lang, count]) => `- ${lang}: ${count} files`).join('\n')} `; let prompt; if (query) { prompt = `Project Structure: ${structureText} User Question: ${query}`; } else { prompt = `Analyze this project structure: ${structureText} Provide a brief overview of the project based on its file structure.`; } const result = await processWithAI(prompt); return { text: result || 'No response generated' }; // Ensure text property is always defined } catch (error) { throw error; } } module.exports = { analyzeFolderStructure };