Three packages following the new capability-seam pattern (interface / implementation / consumer, now documented in docs/architecture.md): - dsh-bash: abstract BashExecutor service (ctx.bash) + vocabulary types. - dsh-bash-local: local subprocesses — bash -c per call in a detached process group, SIGTERM→SIGKILL group kills, tail-keep truncation with full-stream spill files, model-friendly env, background task registry. - dsh-tool-bash: the bash / bash_output / bash_kill tool schemas with runtime arg validation and background completion notices via agent.inject(). Non-zero exits are reported, not errored. Design surveyed against the bash tools of Claude Code, OpenCode, Codex, and pi (notes in the package READMEs). Permissions/sandbox stay TODO on the tools/execute waterfall seam; stateful-shell alternatives recorded in run.ts.
43 lines
2.3 KiB
Markdown
43 lines
2.3 KiB
Markdown
# @deepseek-ai/dsh-bash
|
|
|
|
The **bash executor seam**: an abstract `BashExecutor` service (`ctx.bash`)
|
|
defining WHAT a bash backend does — run commands, manage background tasks —
|
|
without saying HOW.
|
|
|
|
This package is one third of the bash capability, split so each concern can
|
|
evolve (and be swapped) independently:
|
|
|
|
| Package | Role |
|
|
|---|---|
|
|
| `@deepseek-ai/dsh-bash` (this) | the interface: abstract service + vocabulary types |
|
|
| `@deepseek-ai/dsh-bash-local` | an implementation: local subprocesses |
|
|
| `@deepseek-ai/dsh-tool-bash` | the model-facing tool schemas over `ctx.bash` |
|
|
|
|
The split mirrors the LLM seam (`LlmService`/`LlmAdapter`) and the agent-tool
|
|
survey: pi hides execution behind a `BashOperations` interface (local shell /
|
|
SSH / VM backends), Codex behind an exec-server protocol. A future sandboxed,
|
|
containerized, or remote executor implements this interface and the tool
|
|
schemas don't change.
|
|
|
|
## Service API (`ctx.bash`)
|
|
|
|
| Member | Semantics |
|
|
|---|---|
|
|
| `run(spec)` | Foreground execution. Resolves when the command finishes. **Rejects only for infrastructure failures** (unusable workdir, missing shell, pre-aborted signal); nonzero exits, timeout kills, and abort kills resolve with a descriptive `BashRunResult`. |
|
|
| `start(spec)` | Background execution. Returns a `BashTask` handle immediately; **no timeout applies** (stop tasks via `kill`). |
|
|
| `get(id)` / `list()` | Task lookup. |
|
|
| `readOutput(id)` | **Incremental** output read — consecutive reads never re-deliver. Reads that lost data to buffer bounds flag `lossy` and point at full-stream spill files. Throws for unknown ids. |
|
|
| `kill(id)` | Kill a running task. Returns `false` when it already finished; throws for unknown ids. |
|
|
| `onTaskDone(listener)` | Completion listener (effect-based, disposer returned). Fires exactly once per task; never after the service is disposed. |
|
|
|
|
Implementations subclass `BashExecutor`, implement the abstract methods, and
|
|
call `notifyTaskDone(task)` on background completion. Disposal must kill every
|
|
running task (no orphan processes) — see the HMR-safety tests.
|
|
|
|
## Vocabulary
|
|
|
|
`BashExecSpec` (command, workdir?, timeoutMs?, signal?) →
|
|
`BashRunResult` (exitCode, signal, timedOut, aborted, timeoutMs, stdout/stderr
|
|
as `CollectedOutput`) and `BashTask`/`BashTaskRead` for the background side.
|
|
See `src/types.ts` for the full contracts.
|