UNPKG

hataraku

Version:

An autonomous coding agent for building AI-powered development tools. The name "Hataraku" (働く) means "to work" in Japanese.

156 lines 6.43 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.listFiles = listFiles; const fast_glob_1 = __importDefault(require("fast-glob")); const os_1 = __importDefault(require("os")); const path = __importStar(require("path")); const path_1 = require("../../utils/path"); /** * Lists files in a directory with safety checks for root and home directories. * * @param dirPath - The directory path to list files from * @param recursive - Whether to list files recursively in subdirectories * @param limit - Maximum number of files to return * @returns A tuple containing [array of file paths, boolean indicating if limit was reached] * @throws Will throw an error if the globbing process times out (via internal globbyLevelByLevel function) * * @example * ```typescript * // List up to 100 files in the current directory (non-recursive) * const [files, limitReached] = await listFiles('.', false, 100); * * // List up to 1000 files recursively * const [allFiles, hitLimit] = await listFiles('./src', true, 1000); * ``` */ async function listFiles(dirPath, recursive, limit) { const absolutePath = path.resolve(dirPath); // Do not allow listing files in root or home directory, which cline tends to want to do when the user's prompt is vague. const root = process.platform === "win32" ? path.parse(absolutePath).root : "/"; const isRoot = (0, path_1.arePathsEqual)(absolutePath, root); if (isRoot) { return [[root], false]; } const homeDir = os_1.default.homedir(); const isHomeDir = (0, path_1.arePathsEqual)(absolutePath, homeDir); if (isHomeDir) { return [[homeDir], false]; } const dirsToIgnore = [ "node_modules", "__pycache__", "env", "venv", "target/dependency", "build/dependencies", "dist", "out", "bundle", "vendor", "tmp", "temp", "deps", "pkg", "Pods", ".*", // '!**/.*' excludes hidden directories, while '!**/.*/**' excludes only their contents. This way we are at least aware of the existence of hidden directories. ].map((dir) => `**/${dir}/**`); const options = { cwd: dirPath, dot: true, // do not ignore hidden files/directories absolute: true, markDirectories: true, // Append a / on any directories matched (/ is used on windows as well, so dont use path.sep) gitignore: recursive, // fast-glob also supports gitignore ignore: recursive ? dirsToIgnore : undefined, // just in case there is no gitignore, we ignore sensible defaults onlyFiles: false, // true by default, false means it will list directories on their own too }; // * globs all files in one dir, ** globs files in nested directories const files = recursive ? await globbyLevelByLevel(limit, options) : (await (0, fast_glob_1.default)("*", options)).slice(0, limit); return [files, files.length >= limit]; } /** * Performs breadth-first traversal of directory structure level by level up to a limit. * * Features: * - Queue-based approach ensures proper breadth-first traversal * - Processes directory patterns level by level * - Captures a representative sample of the directory structure up to the limit * - Minimizes risk of missing deeply nested files * * @param limit - Maximum number of files to return * @param options - Options to pass to fast-glob * @returns Array of file paths up to the specified limit * @throws Will throw an error if the globbing process times out (after 10 seconds) * * Notes: * - Relies on fast-glob to mark directories with / * - Potential for loops if symbolic links reference back to parent * - Timeout mechanism prevents infinite loops */ async function globbyLevelByLevel(limit, options) { let results = new Set(); let queue = ["*"]; const globbingProcess = async () => { while (queue.length > 0 && results.size < limit) { const pattern = queue.shift(); const filesAtLevel = await (0, fast_glob_1.default)(pattern, options); for (const file of filesAtLevel) { if (results.size >= limit) { break; } results.add(file); if (file.endsWith("/")) { queue.push(`${file}*`); } } } return Array.from(results).slice(0, limit); }; // Timeout after 10 seconds and return partial results const timeoutPromise = new Promise((_, reject) => { setTimeout(() => reject(new Error("Globbing timeout")), 10_000); }); try { return await Promise.race([globbingProcess(), timeoutPromise]); } catch (error) { console.warn("Globbing timed out, returning partial results"); return Array.from(results); } } //# sourceMappingURL=list-files.js.map