(root: string, recursive: boolean, maxEntries: number = MAX_ENTRIES)
| 19 | const MAX_ENTRIES = 800 |
| 20 | |
| 21 | export function walkFiles(root: string, recursive: boolean, maxEntries: number = MAX_ENTRIES): string[] { |
| 22 | const entries: string[] = [] |
| 23 | const queue: string[] = [root] |
| 24 | |
| 25 | while (queue.length > 0 && entries.length < maxEntries) { |
| 26 | const dir = queue.shift()! |
| 27 | let dirents: fs.Dirent[] |
| 28 | try { |
| 29 | dirents = fs.readdirSync(dir, { withFileTypes: true }) |
| 30 | } catch { |
| 31 | continue |
| 32 | } |
| 33 | dirents.sort((a, b) => a.name.localeCompare(b.name)) |
| 34 | for (const dirent of dirents) { |
| 35 | if (entries.length >= maxEntries) break |
| 36 | const full = path.join(dir, dirent.name) |
| 37 | // Always report forward-slash paths: the UI (@-mention filtering) and |
| 38 | // the model both treat "/" as the separator, even on Windows. |
| 39 | const rel = path.relative(root, full).split(path.sep).join("/") |
| 40 | if (dirent.isDirectory()) { |
| 41 | entries.push(rel + "/") |
| 42 | if (recursive && !IGNORED_DIRS.has(dirent.name) && !dirent.name.startsWith(".")) { |
| 43 | queue.push(full) |
| 44 | } |
| 45 | } else { |
| 46 | entries.push(rel) |
| 47 | } |
| 48 | } |
| 49 | } |
| 50 | return entries |
| 51 | } |
| 52 | |
| 53 | export async function listFiles(args: Record<string, unknown>, context: ToolContext): Promise<ToolResult> { |
| 54 | const dirPath = resolveWorkspacePath(context.cwd, String(args.path ?? ".")) |
no outgoing calls
no test coverage detected