Merge origin/master into codex/truncated-design

This commit is contained in:
Dudu-0223
2026-07-17 18:21:54 +08:00
1057 changed files with 42961 additions and 18526 deletions
+44
View File
@@ -44,3 +44,47 @@ Raw `rg` stdout is an internal transport detail. Each search requests `stdoutMax
## Errors
Search failures carry the package-owned `SearchError` (a `HarnessError` subclass), surfaced as `{ name, code }` on `isError` results: `SEARCH_INVALID_PATTERN` (ripgrep rejected the regex/glob), `SEARCH_FAILED` (missing `rg`, inaccessible target, signal kill, malformed `--json` output), `SEARCH_RAW_OUTPUT_OVERFLOW` (raw output over `rawOutputMaxBytes`, or still truncated after the requested stdout capture budget), and `SEARCH_ABORTED` (tool timeout, caller cancellation, or the bash executor's own timeout). ripgrep exit semantics are tool-owned: exit 0 is success with results, exit 1 is a successful empty search (`No files found` / `No matches found`), and only other exits are failures. Model argument mistakes (blank pattern, a list-valued `include`) stay ordinary tool argument errors.
## Model Experience
### System prompt
**What the model sees**: Every request in this plugin's registration scope contains the independently registered glob and grep guidance below. Agent-scoped tool restrictions can hide either schema without removing its prompt section.
**Token effect**: Fixed guidance cost per request while the plugin is active.
#### Glob guidance
```markdown
Use the glob tool — not shell find or ls — to discover files by path pattern. Results are sorted by modification time and include hidden and ignored files.
```
#### Grep guidance
```markdown
Use the grep tool — not shell grep or rg — to search file contents. Use read on a matched file when you need surrounding context.
```
### Tool schemas
**What the model sees**: The generated [`glob` and `grep` schemas](../../../docs/tool-catalog.md#deepseek-aidsh-tool-fs-search) while this surface is visible.
**Token effect**: Fixed schema cost on every request where the tools are visible.
### Results and spill notices
**What the model sees**: `glob` returns one path per line; `grep` groups `Line <line>: <preview>` matches beneath each path. Empty searches return `No files found` or `No matches found`. A capped result ends with its omission count plus the spill locator and backend retrieval hint, or says the complete result could not be saved.
**Token effect**: Inline paths and matches are bounded by `globMaxResults`, `grepMaxMatches`, and `grepMaxLineBytes`; the call and retained result remain in history until compaction.
### Tool errors
**What the model sees**: Failures are normalized as `Error: <message>` with structured `SEARCH_INVALID_PATTERN`, `SEARCH_FAILED`, `SEARCH_RAW_OUTPUT_OVERFLOW`, or `SEARCH_ABORTED` metadata for callers.
**Token effect**: Only a failing call adds these retained tokens.
## Known Limitations and Deferred Work
- **Search and file access have no shared-workspace proof** — returned paths are follow-up-readable only when the bash workdir and filesystem root denote the same workspace; the package performs no runtime cross-service validation.
- **Ripgrep is a deployment dependency** — a missing or incompatible `rg` executable fails calls with `SEARCH_FAILED`; remote or virtual filesystems need a co-located executor or another search consumer.
- **The schemas expose one bounded page** — offset pagination, case-mode switches, alternate output modes, and provider-backed discovery remain outside this package; capped complete output requires a spill backend.
+2 -18
View File
@@ -16,7 +16,7 @@ import { CallId } from '@deepseek-ai/dsh-llm'
import SystemPrompt, { renderPrompt } from '@deepseek-ai/dsh-system-prompt'
import ToolRegistry from '@deepseek-ai/dsh-tools'
import { BashExecutor } from '@deepseek-ai/dsh-bash'
import type { BashExecRequest, BashExecSpec, BashRunResult, BashTask, BashTaskId, BashTaskRead, OwnerToken } from '@deepseek-ai/dsh-bash'
import type { BashExecRequest, BashExecSpec, BashProcess, BashRunResult } from '@deepseek-ai/dsh-bash'
import { SpillLocator, SpillStore } from '@deepseek-ai/dsh-spill'
import type { SaveTextSpill, SpillRef } from '@deepseek-ai/dsh-spill'
import * as ToolFsSearch from '@deepseek-ai/dsh-tool-fs-search'
@@ -65,7 +65,6 @@ class FakeBash extends BashExecutor {
timeoutMs: request.timeoutMs ?? 60_000,
stdoutMaxBytes: request.stdoutMaxBytes ?? 64_000,
signal: request.signal,
owner: request.owner,
sandboxMode: request.sandboxMode,
}
}
@@ -73,25 +72,10 @@ class FakeBash extends BashExecutor {
this.specs.push(spec)
return Promise.resolve(this.handler(spec))
}
override start(): BashTask {
override start(): BashProcess {
this.startCalls++
throw new Error('search tools must never start a background task')
}
override get(): BashTask | undefined {
return undefined
}
override ownerOf(): OwnerToken | undefined {
return undefined
}
override list(): BashTask[] {
return []
}
override readOutput(id: BashTaskId): BashTaskRead {
throw new Error(`unknown bash task ${id}`)
}
override kill(id: BashTaskId): boolean {
throw new Error(`unknown bash task ${id}`)
}
}
/** A recording spill backend; arm `failWith` to script a storage failure. */