import * as fs from 'fs'; import { HandlerContext } from './types'; import { validatePath } from '../../security'; import { EXCLUDED_DIRS } from '../../config'; export async function applyListFilesActions(ctx: HandlerContext): Promise { const { aiMessage, rootPath, report } = ctx; let match: RegExpExecArray | null; // Action 6: List Files const listRegex = /(?:<\/list_files>)?/gi; while ((match = listRegex.exec(aiMessage)) !== null) { const relPath = match[1].trim() || '.'; try { const absPath = validatePath(rootPath, relPath); if (fs.existsSync(absPath) && fs.statSync(absPath).isDirectory()) { const entries = fs.readdirSync(absPath, { withFileTypes: true }); let listing = entries .filter(e => !e.name.startsWith('.') && !EXCLUDED_DIRS.has(e.name)) .map(e => e.isDirectory() ? `${e.name}/` : e.name) .join('\n'); if (listing.length > 5000) { listing = listing.slice(0, 5000) + "\n... (truncated for context)"; } report.push(`📂 Listed: ${relPath}`); ctx.chatHistory.push({ role: 'system', content: `[Result of list_files ${relPath}]\n${listing}`, internal: true }); } } catch (err: any) { report.push(`❌ Listing failed: ${err.message}`); } } }