/** * Native (pure-JS) fallbacks for the `find` and `grep` tools. * * The tools normally shell out to `fd` / `rg`, which are downloaded on demand * (see tools-manager.ts). In restricted environments those binaries may be * neither on PATH nor downloadable, and `HOOCODE_NATIVE_SEARCH=1` can also force * this path. Rather than failing the tool and asking the model to fall back to * `bash`, these functions reproduce the essential behaviour in JS so search * degrades automatically: * * - hierarchical `.gitignore` handling (each `.gitignore` is scoped to its own * subtree, matching fd's `--no-require-git` behaviour and issue #3303), * - hidden files included (like `fd --hidden` / `rg --hidden`), * - `.git` always skipped; `node_modules` skipped for `find` (mirrors the * tool's built-in excludes) but left to `.gitignore` for `grep` (like rg). * * These are best-effort approximations, not byte-for-byte fd/rg parity: globs * are matched with `minimatch` and patterns with JS `RegExp`, and only * `.gitignore` files are honoured (not `.ignore` or global excludes). */ type EntryType = "f" | "d" | "l"; export interface CollectedEntry { /** Absolute path. */ abs: string; /** POSIX path relative to the walk root. */ rel: string; type: EntryType; } export interface WalkOptions { /** Max entry depth relative to root; direct children are depth 1. */ maxDepth?: number; signal?: AbortSignal; /** Directory names to never descend into. Defaults to `.git`. */ alwaysSkipDirs?: Set; } /** * Walk `root` depth-first, returning every entry not excluded by `.gitignore` * or an always-skip directory. Symlinks are reported but never followed (avoids * cycles). Enumeration stops at {@link MAX_ENTRIES}. */ export declare function collectEntries(root: string, opts?: WalkOptions): CollectedEntry[]; interface NativeGrepMatch { filePath: string; lineNumber: number; lineText: string; } export interface NativeGrepOptions { pattern: string; /** True when `root` is a directory; false when it is a single file. */ isDirectory: boolean; ignoreCase?: boolean; literal?: boolean; /** Optional glob filter applied to file paths (like rg --glob). */ glob?: string; /** Stop after this many matches. */ limit: number; signal?: AbortSignal; readFile: (absolutePath: string) => Promise | string; } export interface NativeGrepResult { matches: NativeGrepMatch[]; matchLimitReached: boolean; } /** * Native replacement for the rg-backed content search. Collects up to `limit` * matches as `{ filePath, lineNumber, lineText }`, the same shape the tool's * formatter already consumes from rg's JSON output. * * Throws an Error tagged `invalidRegex` when a non-literal pattern is not a * valid JS regex, so the caller can surface the same "pass literal: true" hint. */ export declare function nativeGrep(root: string, opts: NativeGrepOptions): Promise; /** Whether the native search path is forced regardless of fd/rg availability. */ export declare function isNativeSearchForced(): boolean; export {}; //# sourceMappingURL=native-search.d.ts.map