refactor: apply repository naming contract

Apply the accepted pre-release package, service, type, directory, and role renames as one repository-wide change.
This commit is contained in:
Tianyi Cui
2026-08-13 00:36:22 +08:00
parent 101df7cf58
commit a2d0f7f411
3281 changed files with 21730 additions and 21592 deletions

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write packages/fs/tool-fs-search/README.md
README.md: 7803ce52c1b9d2d858dadb718edd163585360aef
README.zh.md: b4f04017ee178217a5b98427ae2a5335e697c598
README.md: 83290df98260e977a8cd3ea808f491ea63e75857
README.zh.md: b33fe002fc4ccc2bfe5fefec342f2044e3511078

View File

@@ -6,13 +6,13 @@ The **model-facing filesystem discovery tools**—`glob`, `grep`—are backed by
```ts ignore-check
// A deployment chooses how over-cap glob pages are selected.
await ctx.plugin(LocalSubprocessService) // @deepseek-ai/dsh-subprocess-local
await ctx.plugin(LocalSubprocessRuntime) // @deepseek-ai/dsh-subprocess-local
await ctx.plugin(ToolFsSearch, { sampleOverCapGlobResults: false })
// Optional: a spill backend makes capped results fully recoverable.
await ctx.plugin(LocalSpillStore) // @deepseek-ai/dsh-spill-local
```
Why spawn-backed: local workspace discovery is naturally a process-backed `rg` workflow, and putting search on `ctx.fs` would force every filesystem backend to grow a search API. The subprocess seam owns spawn execution, process-tree termination, environment scrubbing, and bounded output capture; this package owns schemas, argument validation, argv construction, parsing, retention, formatted-result spill, and timeout declaration. The tools never expose a background task — the call returns only after `rg` exits, is terminated by the cooperative timeout, is aborted, or fails.
Why spawn-backed: local workspace discovery is naturally a process-backed `rg` workflow, and putting search on `ctx.fs` would force every filesystem backend to grow a search API. The subprocess seam owns spawn execution, process-tree termination, environment scrubbing, and bounded output capture; this package owns schemas, argument validation, argv construction, parsing, retention, formatted-result spill, and timeout declaration. The tools never expose a background job — the call returns only after `rg` exits, is terminated by the cooperative timeout, is aborted, or fails.
## Deployment requirement: no host rg, co-located workdir/filesystem
@@ -29,7 +29,7 @@ The binary ships with the package on every supported platform (macOS/Linux/Windo
| `grepMaxMatches` | `250` | Max flat matches one `grep` call retains inline (matches Claude Code's `GrepTool` `head_limit`); later matches go to the formatted spill artifact. |
| `grepMaxLineBytes` | `2000` | Byte cap per matched-line preview; the cut preserves UTF-8 boundaries and is marked `(line truncated)`. |
| `rawOutputMaxBytes` | `20000000` | Max complete raw `rg` stdout a search will parse (matches Claude Code's ripgrep raw buffer); larger raw output fails with `SEARCH_RAW_OUTPUT_OVERFLOW`. |
| `timeoutMs` | `30000` | Cooperative tool-call budget attached to both tool definitions, enforced by `@deepseek-ai/dsh-timeout-policy` through `exec.signal`; the subprocess seam's terminate escalation is the hard kill. |
| `timeoutMs` | `30000` | Cooperative tool-call budget attached to both tool definitions, enforced by `@deepseek-ai/dsh-tool-call-timeout-policy` through `exec.signal`; the subprocess seam's terminate escalation is the hard kill. |
| `graceMs` | `3000` | Positive terminate-escalation grace the subprocess seam grants past `timeoutMs` before the search fails as `SEARCH_ABORTED`; it cannot exceed [`MAX_TIMER_DELAY_MS`](../../util/timeout/README.md). |
| `stderrMaxBytes` | `65536` | Diagnostic-tail budget for `rg` stderr, captured through the subprocess seam's collect disposition; a lossy read keeps only the tail (marked `[stderr truncated]`). |

View File

@@ -6,7 +6,7 @@
```ts ignore-check
// A deployment chooses how over-cap glob pages are selected.
await ctx.plugin(LocalSubprocessService) // @deepseek-ai/dsh-subprocess-local
await ctx.plugin(LocalSubprocessRuntime) // @deepseek-ai/dsh-subprocess-local
await ctx.plugin(ToolFsSearch, { sampleOverCapGlobResults: false })
// Optional: a spill backend makes capped results fully recoverable.
await ctx.plugin(LocalSpillStore) // @deepseek-ai/dsh-spill-local
@@ -29,7 +29,7 @@ await ctx.plugin(LocalSpillStore) // @deepseek-ai/dsh-
| `grepMaxMatches` | `250` | 一次 `grep` 调用内联保留的最大平铺匹配数(与 Claude Code 的 `GrepTool` `head_limit` 相同);后续匹配写入格式化 spill 产物。 |
| `grepMaxLineBytes` | `2000` | 每条匹配行预览的字节上限;截断会保留 UTF-8 边界,并标记为 `(line truncated)`。 |
| `rawOutputMaxBytes` | `20000000` | 搜索将解析的完整原始 `rg` stdout 上限(与 Claude Code 的 ripgrep 原始 buffer 相同);更大的原始输出以 `SEARCH_RAW_OUTPUT_OVERFLOW` 失败。 |
| `timeoutMs` | `30000` | 附加到两个工具定义上的协作式工具调用预算,由 `@deepseek-ai/dsh-timeout-policy` 通过 `exec.signal` 强制执行;subprocess seam 的终止升级提供硬终止。 |
| `timeoutMs` | `30000` | 附加到两个工具定义上的协作式工具调用预算,由 `@deepseek-ai/dsh-tool-call-timeout-policy` 通过 `exec.signal` 强制执行;subprocess seam 的终止升级提供硬终止。 |
| `graceMs` | `3000` | subprocess seam 在 `timeoutMs` 之外授予的终止升级宽限期须为正值;超过后搜索以 `SEARCH_ABORTED` 失败;该宽限期不得大于 [`MAX_TIMER_DELAY_MS`](../../util/timeout/README.md)。 |
| `stderrMaxBytes` | `65536` | `rg` stderr 的诊断尾部预算,经 subprocess seam 的 collect 形态捕获;lossy 读取只保留尾部(标记 `[stderr truncated]`)。 |

View File

@@ -38,7 +38,7 @@
"peerDependencies": {
"@deepseek-ai/dsh-invariants": "workspace:^",
"@deepseek-ai/dsh-llm": "workspace:^",
"@deepseek-ai/dsh-retention": "workspace:^",
"@deepseek-ai/dsh-output-retention": "workspace:^",
"@deepseek-ai/dsh-session": "workspace:^",
"@deepseek-ai/dsh-spill": "workspace:^",
"@deepseek-ai/dsh-subprocess": "workspace:^",
@@ -53,7 +53,7 @@
"@deepseek-ai/dsh-subprocess-local": "workspace:^",
"@deepseek-ai/dsh-invariants": "workspace:^",
"@deepseek-ai/dsh-llm": "workspace:^",
"@deepseek-ai/dsh-retention": "workspace:^",
"@deepseek-ai/dsh-output-retention": "workspace:^",
"@deepseek-ai/dsh-session": "workspace:^",
"@deepseek-ai/dsh-spill": "workspace:^",
"@deepseek-ai/dsh-system-prompt": "workspace:^",

View File

@@ -14,7 +14,7 @@
import type { Context } from '@deepseek-ai/cordis'
import { defineTool } from '@deepseek-ai/dsh-tools'
import type { GenericCallView, SearchResultView, ToolResult } from '@deepseek-ai/dsh-tools'
import type { RetainedItems } from '@deepseek-ai/dsh-retention'
import type { RetainedItems } from '@deepseek-ai/dsh-output-retention'
import type { SpillRef } from '@deepseek-ai/dsh-spill'
import type {} from '@deepseek-ai/dsh-system-prompt'
import type { GrepMatch } from './search-core.ts'

View File

@@ -8,7 +8,7 @@
*
* Local workspace discovery is a process-backed `rg` workflow, so these tools
* execute through `ctx.subprocess.spawn()` with fixed ripgrep argv templates —
* never `ctx.bash`, never `ctx.bash.start()`, never a model-visible background
* never `ctx.shell`, never `ctx.shell.start()`, never a model-visible background
* task. The tool layer owns schemas, argument validation, argv construction
* ({@link module:@deepseek-ai/dsh-tool-fs-search/glob} /
* {@link module:@deepseek-ai/dsh-tool-fs-search/grep}), result parsing,
@@ -87,7 +87,10 @@ export interface Config {
graceMs?: number
/** Max bytes retained for one search's stderr tail; the excerpt is embedded in `SEARCH_*` error messages, never shown on success. */
stderrMaxBytes?: number
/** Cooperative tool-call timeout budget (ms) on both tools, enforced by `@deepseek-ai/dsh-timeout-policy` through `exec.signal`. */
/**
* Cooperative tool-call timeout budget (ms) on both tools, enforced by
* `@deepseek-ai/dsh-tool-call-timeout-policy` through `exec.signal`.
*/
timeoutMs?: number
}

View File

@@ -31,7 +31,7 @@ import type {
SearchLineMatch,
SearchResultView,
} from '@deepseek-ai/dsh-tools'
import type { RetainedItems } from '@deepseek-ai/dsh-retention'
import type { RetainedItems } from '@deepseek-ai/dsh-output-retention'
import type { GrepMatch } from './search-core.ts'
/**

View File

@@ -6,7 +6,7 @@
* and workdir-relative path display.
*
* Both tools execute as ordinary foreground spawns through `ctx.subprocess` —
* never `ctx.bash`, never `ctx.bash.start()`, never a model-visible background
* never `ctx.shell`, never `ctx.shell.start()`, never a model-visible background
* task. The ripgrep binary ships inside the npm package, so no system `rg`
* install is required, and no shell layer exists between the argv vector and
* ripgrep, so no shell quoting is involved. Raw `rg` stdout is an internal
@@ -22,8 +22,8 @@
import { isAbsolute, relative, sep } from 'node:path'
import type { Context } from '@deepseek-ai/cordis'
import { HarnessError } from '@deepseek-ai/dsh-llm'
import { ItemRetainer, TextRetainer } from '@deepseek-ai/dsh-retention'
import type { RetainedItems } from '@deepseek-ai/dsh-retention'
import { ItemRetainer, TextRetainer } from '@deepseek-ai/dsh-output-retention'
import type { RetainedItems } from '@deepseek-ai/dsh-output-retention'
import type { SubprocessHandle, SubprocessOutcome, SubprocessOutputRead, SubprocessSpawnSpec } from '@deepseek-ai/dsh-subprocess'
import type { SaveTextSpill, SpillRef } from '@deepseek-ai/dsh-spill'
import type { ToolExecution } from '@deepseek-ai/dsh-tools'
@@ -37,7 +37,7 @@ export const RAW_OUTPUT_MAX_BYTES = 20_000_000
/**
* Default cooperative tool-call timeout budget in milliseconds (the `timeoutMs`
* config), attached to both tool definitions for
* `@deepseek-ai/dsh-timeout-policy` to enforce through `exec.signal`.
* `@deepseek-ai/dsh-tool-call-timeout-policy` to enforce through `exec.signal`.
*/
export const SEARCH_TIMEOUT_MS = 30_000
@@ -178,7 +178,7 @@ export function resolveRgPath(): Promise<string> {
* complete raw stdout. The working directory is the calling agent's session
* cwd (`exec.agent.session.header.cwd`) when available, else
* `process.cwd()`. `exec.signal` is forwarded so the cooperative tool timeout
* (`@deepseek-ai/dsh-timeout-policy`) and caller cancellation terminate the
* (`@deepseek-ai/dsh-tool-call-timeout-policy`) and caller cancellation terminate the
* process tree.
*
* The spawn is unconfined (a plain `ctx.subprocess` call), so `--no-config`

View File

@@ -17,8 +17,8 @@ import { join } from 'node:path'
import { Context } from '@deepseek-ai/cordis'
import { CallId } from '@deepseek-ai/dsh-llm'
import SystemPrompt from '@deepseek-ai/dsh-system-prompt'
import ToolRegistry, { TOOL_ABORTED_BEFORE_DISPATCH } from '@deepseek-ai/dsh-tools'
import LocalSubprocessService from '@deepseek-ai/dsh-subprocess-local'
import ToolRuntime, { TOOL_ABORTED_BEFORE_DISPATCH } from '@deepseek-ai/dsh-tools'
import LocalSubprocessRuntime from '@deepseek-ai/dsh-subprocess-local'
import * as ToolFsSearch from '@deepseek-ai/dsh-tool-fs-search'
const testToolSignal = new AbortController().signal
@@ -62,8 +62,8 @@ describe('search tools over the real subprocess service + the packaged rg', () =
ctx = new Context()
await ctx.plugin(SystemPrompt)
await ctx.plugin(ToolRegistry)
await ctx.plugin(LocalSubprocessService)
await ctx.plugin(ToolRuntime)
await ctx.plugin(LocalSubprocessRuntime)
await ctx.plugin(ToolFsSearch, { sampleOverCapGlobResults: true })
})

View File

@@ -18,8 +18,8 @@ import { describe, expect, it } from 'vitest'
import { Context } from '@deepseek-ai/cordis'
import Loader from '@deepseek-ai/cordis-plugin-loader'
import SystemPrompt from '@deepseek-ai/dsh-system-prompt'
import ToolRegistry from '@deepseek-ai/dsh-tools'
import LocalSubprocessService from '@deepseek-ai/dsh-subprocess-local'
import ToolRuntime from '@deepseek-ai/dsh-tools'
import LocalSubprocessRuntime from '@deepseek-ai/dsh-subprocess-local'
import * as toolFsSearch from '@deepseek-ai/dsh-tool-fs-search'
describe('dsh-tool-fs-search real-load-path guard', () => {
@@ -38,8 +38,8 @@ describe('dsh-tool-fs-search real-load-path guard', () => {
it('boots over ctx.subprocess through the unwrapped module without an inject error', async () => {
const ctx = new Context()
await ctx.plugin(SystemPrompt)
await ctx.plugin(ToolRegistry)
await ctx.plugin(LocalSubprocessService)
await ctx.plugin(ToolRuntime)
await ctx.plugin(LocalSubprocessRuntime)
const loader = Object.create(Loader.prototype) as Loader
const unwrapped = loader.unwrapExports(toolFsSearch) as Parameters<Context['plugin']>[0]

View File

@@ -6,7 +6,7 @@
* abort/timeout kills, signal kills, ripgrep exit codes — so these tests
* verify schemas, argument validation, argv construction, workdir derivation,
* signal forwarding, `SEARCH_*` error classification, retention,
* formatted-result spill handoff, and the no-background-task invariant.
* formatted-result spill handoff, and the no-background-job invariant.
* Real-`rg` behavior is pinned separately in integration.spec.ts.
*/
@@ -15,8 +15,8 @@ import { Context } from '@deepseek-ai/cordis'
import { join, sep } from 'node:path'
import { createUserMessage, CallId } from '@deepseek-ai/dsh-llm'
import SystemPrompt, { renderPrompt } from '@deepseek-ai/dsh-system-prompt'
import ToolRegistry, { TOOL_ABORTED_BEFORE_DISPATCH, type ToolExecution, type ToolExecutionToken } from '@deepseek-ai/dsh-tools'
import { SubprocessService } from '@deepseek-ai/dsh-subprocess'
import ToolRuntime, { TOOL_ABORTED_BEFORE_DISPATCH, type ToolExecution, type ToolExecutionToken } from '@deepseek-ai/dsh-tools'
import { SubprocessRuntime } from '@deepseek-ai/dsh-subprocess'
import type { SubprocessCollectedOutputs, SubprocessHandle, SubprocessOutcome, SubprocessOutputRead, SubprocessOutputReader, SubprocessSpawnSpec } from '@deepseek-ai/dsh-subprocess'
import { MAX_TIMER_DELAY_MS } from '@deepseek-ai/dsh-timeout'
import { rgPath } from '@vscode/ripgrep'
@@ -146,7 +146,7 @@ class FakeHandle implements SubprocessHandle {
* never spawn outside a single awaited foreground call, so every test can
* assert on the exact spawn specs and settled handles.
*/
class FakeSubprocess extends SubprocessService {
class FakeSubprocess extends SubprocessRuntime {
spawns: SubprocessSpawnSpec[] = []
override async resolveExecutable(command: string): Promise<string> { return command }
override spawnTerminal(): Promise<never> { throw new Error('search tools spawn pipes, never terminals') }
@@ -192,7 +192,7 @@ async function setup(options: SetupOptions = {}) {
const warnings: string[] = []
ctx.logger.warn = ((message: unknown) => { warnings.push(String(message)) }) as typeof ctx.logger.warn
await ctx.plugin(SystemPrompt)
await ctx.plugin(ToolRegistry)
await ctx.plugin(ToolRuntime)
await ctx.plugin(FakeSubprocess)
const subprocess = ctx.subprocess as FakeSubprocess
if (options.spill === true) await ctx.plugin(FakeSpill)
@@ -250,7 +250,7 @@ describe('registration', () => {
it('stays pending until ctx.subprocess exists (inject)', async () => {
const ctx = new Context()
await ctx.plugin(SystemPrompt)
await ctx.plugin(ToolRegistry)
await ctx.plugin(ToolRuntime)
await ctx.plugin(ToolFsSearch, DEFAULT_CONFIG) // no subprocess service
expect(ctx.tools.schemas()).toHaveLength(0)
})
@@ -308,7 +308,7 @@ describe('config validation', () => {
] as const)('rejects a non-positive or fractional %s at load', async (name, config) => {
const ctx = new Context()
await ctx.plugin(SystemPrompt)
await ctx.plugin(ToolRegistry)
await ctx.plugin(ToolRuntime)
await ctx.plugin(FakeSubprocess)
await expect(ctx.plugin(ToolFsSearch, { ...DEFAULT_CONFIG, ...config })).rejects.toThrow(new RegExp(`tool-fs-search: ${name} must be a positive integer`))
})
@@ -316,7 +316,7 @@ describe('config validation', () => {
it('rejects a grace beyond the Node timer range at load', async () => {
const ctx = new Context()
await ctx.plugin(SystemPrompt)
await ctx.plugin(ToolRegistry)
await ctx.plugin(ToolRuntime)
await ctx.plugin(FakeSubprocess)
await expect(ctx.plugin(ToolFsSearch, {
...DEFAULT_CONFIG,
@@ -1090,7 +1090,7 @@ describe('rg --json transport failures (SEARCH_FAILED)', () => {
})
})
describe('the no-background-task invariant', () => {
describe('the no-background-job invariant', () => {
it('settles every spawned search handle across successful and failed searches', async () => {
const { ctx, subprocess } = await setup()
subprocess.handler = () => runResult('a.ts\n')

View File

@@ -16,7 +16,7 @@
"path": "../../../vendor/schemastery"
},
{
"path": "../../util/retention"
"path": "../../util/output-retention"
},
{
"path": "../../llm/llm"
@@ -31,7 +31,7 @@
"path": "../../core/system-prompt"
},
{
"path": "../../bash/bash"
"path": "../../shell/shell"
},
{
"path": "../../spill/spill"
@@ -40,7 +40,7 @@
"path": "../../util/timeout"
},
{
"path": "../../support/invariants"
"path": "../../runtime-diagnostics/invariants"
}
]
}