(root: string, maxFiles: number)
| 43 | } |
| 44 | |
| 45 | export async function walkSource(root: string, maxFiles: number): Promise<{ abs: string; rel: string; content: string }[]> { |
| 46 | const out: { abs: string; rel: string; content: string }[] = []; |
| 47 | const stack = [root]; |
| 48 | while (stack.length > 0 && out.length < maxFiles) { |
| 49 | const dir = stack.pop()!; |
| 50 | let entries; |
| 51 | try { entries = await fs.readdir(dir, { withFileTypes: true }); } catch { continue; } |
| 52 | for (const e of entries) { |
| 53 | if (out.length >= maxFiles) break; |
| 54 | if (e.isDirectory()) { |
| 55 | if (SKIP_DIRS.has(e.name) || e.name.startsWith('.')) continue; |
| 56 | stack.push(path.join(dir, e.name)); |
| 57 | } else if (e.isFile()) { |
| 58 | const ext = path.extname(e.name).toLowerCase(); |
| 59 | if (!SOURCE_EXTS.has(ext)) continue; |
| 60 | const abs = path.join(dir, e.name); |
| 61 | try { |
| 62 | const stat = await fs.stat(abs); |
| 63 | if (stat.size > 500_000) continue; |
| 64 | const content = await fs.readFile(abs, 'utf-8'); |
| 65 | out.push({ abs, rel: path.relative(root, abs), content }); |
| 66 | } catch { /* skip */ } |
| 67 | } |
| 68 | } |
| 69 | } |
| 70 | return out; |
| 71 | } |
| 72 | |
| 73 | export function chunkFile(rel: string, content: string, chunkLines: number, overlap: number): Chunk[] { |
| 74 | const lines = content.split('\n'); |
no test coverage detected