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:
@@ -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
|
||||
|
||||
@@ -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]`). |
|
||||
|
||||
|
||||
@@ -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]`)。 |
|
||||
|
||||
|
||||
@@ -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:^",
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
/**
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -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 })
|
||||
})
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user