import type { ExecutionEnv } from "../../internal/harness.js"; /** Directories never worth crawling (design/64 §10.3) — dependency/build/cache trees. */ export declare const DEFAULT_IGNORE_DIRS: ReadonlySet; export interface GrepParams { pattern: string; /** Treat `pattern` as a regex; default false = literal substring (CC's `-F`). */ regex?: boolean; /** Restrict the search to this sub-path (relative to root, or absolute within root). */ path?: string; /** Only search files matching this glob (e.g. `*.ts`, `*.{ts,tsx}`). 批④ #6 (CC parity): a * comma/whitespace-separated list (`"*.ts,*.tsx"`) is split into multiple globs (brace globs kept whole). */ glob?: string; /** 批④ #5 (CC 2.1.201 `-o`): print only the matched (non-empty) parts of each matching line, one match * per output line (rg -o / --only-matching). content mode only; ignored otherwise (CC parity). * 1.253: with `multiline` the JS fallback emits the matched SEGMENT's lines (rg -U -o shape). */ only_matching?: boolean; /** content (default): `path:line:text`. files_with_matches: `path`. count: `path:count`. */ output_mode?: "content" | "files_with_matches" | "count"; /** Lines of context around a match (content mode only) — CC's `-C`. */ context?: number; /** Lines of context BEFORE each match (content mode) — CC's `-B`. Wins over `context` for the before-window. */ context_before?: number; /** Lines of context AFTER each match (content mode) — CC's `-A`. Wins over `context` for the after-window. */ context_after?: number; /** File type filter — CC's `type` (rg `--type`): "js", "py", "rust", "go", "ts", … The rg path uses rg's * built-in type table; the JS fallback maps common types to globs (unknown types are ignored with a note). */ type?: string; /** Case-insensitive match — CC's `-i`. */ ignore_case?: boolean; /** Match across line boundaries — CC's multiline `-U`. JS fallback approximates per-file. */ multiline?: boolean; /** Cap the number of output items (default 250) — CC's `head_limit`. */ head_limit?: number; /** Skip the first N output lines — CC's `offset` (pagination partner of head_limit). */ offset?: number; } /** 批④ #6 (CC 2.1.198 Grep call, bundle :333383-333390): split the `glob` param into individual glob * tokens — whitespace-separated first; a token WITHOUT braces is further split on commas * (`"*.ts,*.tsx"` → two globs), while a brace token (`*.{ts,tsx}`) is kept whole (its commas are * alternation syntax, not separators). CC-verbatim splitting rules. */ export declare function splitGlobParam(glob: string): string[]; /** 批④ #8 (CC 2.1.198 RWp, bundle :332987): decompose an ABSOLUTE glob pattern into a base directory + * relative pattern — cut at the last separator before the first glob metachar (`* ? [ {`); a pattern * with no metachar splits dirname/basename. Returns undefined for a relative pattern (caller keeps it * as-is) or when no usable base can be derived. */ export declare function splitAbsoluteGlobPattern(pattern: string): { baseDir: string; relativePattern: string; } | undefined; /** * POSIX-safe single-quote so an arbitrary model-supplied string can't break out of the shell command that * runs ripgrep. Wraps in single quotes (inside which the shell expands nothing — no `$()`, backtick, `;`, or * glob) and escapes any embedded single quote via the `'\''` idiom (close, escaped-quote, reopen). Exported * for direct injection testing (council [R145]). Renamed from `shq` for legibility. */ export declare function shellQuote(s: string): string; /** Lightweight `.gitignore` matcher (handles comments, negation, dir-only `/`, anchoring, `*`/`?`). */ export declare function gitignoreMatcher(content: string): (rel: string, isDir: boolean) => boolean; /** Build the combined ignore predicate (ignore-set ∪ .gitignore) for a JS-fallback walk. * Exported so repo-map (design/72 §1) walks with the SAME ignore semantics as grep/glob. */ export declare function buildIgnore(env: ExecutionEnv, root: string, signal?: AbortSignal): Promise<(rel: string, isDir: boolean) => boolean>; /** What a bounded walk actually saw — so consumers can be HONEST about incompleteness (A-4 class sweep: * silently bounded results must never read as exhaustive). */ export interface WalkResult { /** Greppable text files (binary-extension and oversize files excluded). */ files: string[]; /** Name-only entries: binary-extension + over-{@link FILE_MAX_BYTES} files. Content search skips them * (grep semantics / memory bound), but globbing matches NAMES — these must still be visible to it * (previously `glob *.png` could never match anything). */ nameOnly: string[]; /** True when the walk hit its file-count or depth ceiling — results MAY be missing files. */ incomplete: boolean; /** Non-binary files skipped by content search for being over {@link FILE_MAX_BYTES} (also in * `nameOnly`). Surfaced by grep so "No matches." can't silently mean "didn't look". */ skippedLarge: number; } /** Bounded, ignore-aware recursive walk. Returns absolute file paths under `start`. Exported for * repo-map (design/72 §1) — same bounded/ignore-aware traversal as grep/glob, one source of truth. */ export declare function walk(env: ExecutionEnv, root: string, start: string, ignore: (rel: string, isDir: boolean) => boolean, signal?: AbortSignal): Promise; /** JS-fallback grep: ignore-aware walk + per-line scan, honoring output_mode / context / head_limit. */ export declare function jsGrep(env: ExecutionEnv, root: string, p: GrepParams, signal?: AbortSignal): Promise; /** Detect ripgrep once per env (cached). */ export declare function detectRipgrep(env: ExecutionEnv): Promise; /** ripgrep grep: build flags from params, run, normalize to the same output as {@link jsGrep}. */ export declare function rgGrep(env: ExecutionEnv, root: string, p: GrepParams, signal?: AbortSignal): Promise; /** grep dispatch: ripgrep when the env has it, else the hardened JS fallback (design/64 §10.3). */ export declare function runGrep(env: ExecutionEnv, root: string, p: GrepParams, signal?: AbortSignal): Promise; /** glob: find files by name pattern, with optional sub-path scoping; returns RELATIVE paths (design/64 §10.4). */ export declare function runGlob(env: ExecutionEnv, root: string, pattern: string, opts?: { path?: string; max?: number; }, signal?: AbortSignal): Promise; /** Structured sibling of {@link runGlob} (design/116 W3): same walk/match, plus the CC-shaped facts a * shell renders (`filenames`/`numFiles`/`truncated`/`durationMs`/`totalMatches`/`countIsComplete`) * without re-parsing the text. * * CC207 backlog P2-2 (CC 2.1.206:397761-398004 = 2.1.207:342454-342633, node-sliced verbatim): * · `totalMatches` — "Total number of matching files before truncation. A lower bound when * countIsComplete is false." (CC: `totalMatches: g.length`) * · `countIsComplete` — "Whether totalMatches is the exact total (true) or a floor because the * underlying search truncated its own output (false)." (CC: `countIsComplete: !m`, m = the rg * enumeration cut its own output; sema equivalent = the bounded walk hit its file/depth ceiling) * · `numFiles` — "Number of file paths returned (after any truncation)" (CC: `numFiles: u.length` * post-slice; was matchedAll.length here — pre-truncation total — fixed to the CC contract) * · `truncated` — CC: `y = m || g.length > n + r` (underlying-incomplete OR over the result cap). */ export declare function runGlobDetailed(env: ExecutionEnv, root: string, pattern: string, opts?: { path?: string; max?: number; }, signal?: AbortSignal): Promise<{ text: string; filenames: string[]; numFiles: number; truncated: boolean; durationMs: number; totalMatches: number; countIsComplete: boolean; }>; //# sourceMappingURL=search.d.ts.map