Implements docs/rfc/implemented/feature/2026-07-09-bash-backed-grep-glob- discovery.md: model-facing glob/grep in a new @deepseek-ai/dsh-tool-fs-search package, executing fixed ripgrep templates through ctx.bash.resolve/run — not ctx.fs provider methods — so filesystem backends stay free of a search contract and sandboxed/remote executors substitute cleanly. The tools never call ctx.bash.start(); the tool layer owns quoting (one singleQuote safety boundary), rg --json parsing, ItemRetainer/TextRetainer retention, and the first tool-owned ctx.spillFiles.saveText() handoff (item-level retention the generic post-execute spill policy cannot recover). RFC amendments on the way to implemented/: a shared src/search-core.ts (the SEARCH_* vocabulary + bash-run/raw-spill/spill plumbing was byte-identical across both tools — the missed-extraction smell), and a snapshot-gap note: wiring the acp-agent tree changes the assembled prompt, so goldens need a keyed re-record; the spill notice text is pinned by unit tests instead and only the coding-agent example ships the tools for now.
28 lines
1.3 KiB
TypeScript
28 lines
1.3 KiB
TypeScript
/**
|
|
* The one shell-quoting helper both search tools MUST route every
|
|
* model-controlled value through before it enters an `rg` command string. The
|
|
* bash seam (`ctx.bash`) accepts a command STRING, not an argv vector, so this
|
|
* is the safety boundary that stops a `pattern`, `path`, or `include` from
|
|
* breaking out of its argument and injecting shell syntax.
|
|
*
|
|
* Command builders in `glob.ts` / `grep.ts` must never hand-roll quoting or
|
|
* concatenate an unquoted model value — they call {@link singleQuote}.
|
|
*
|
|
* @module @deepseek-ai/dsh-tool-fs-search/shell-quote
|
|
*/
|
|
|
|
/**
|
|
* POSIX single-quote a string for safe use as ONE shell word. Wraps the value
|
|
* in single quotes and rewrites every embedded single quote as `'\''` (close
|
|
* quote, an escaped literal quote, reopen quote). Inside single quotes the shell
|
|
* treats every other byte literally — spaces, newlines, `$`, backticks, `;`,
|
|
* `|`, `&`, glob metacharacters, and a leading `-` are all inert — so the result
|
|
* is a single, injection-safe argument regardless of the input.
|
|
*
|
|
* @param value - the raw, possibly model-controlled string to quote.
|
|
* @returns the value wrapped as one safe single-quoted shell word.
|
|
*/
|
|
export function singleQuote(value: string): string {
|
|
return `'${value.replaceAll("'", "'\\''")}'`
|
|
}
|