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.
63 lines
2.9 KiB
Markdown
63 lines
2.9 KiB
Markdown
# @deepseek-ai/dsh-tool-bash
|
|
|
|
The model-facing bash tools — `bash`, `bash_output`, `bash_kill` — registered
|
|
over the `ctx.bash` executor seam (`@deepseek-ai/dsh-bash`). Pure schema +
|
|
text shaping; every process concern lives behind the seam, so sandboxed or
|
|
remote executor implementations swap in without changing what the model sees.
|
|
|
|
Requires a loaded executor implementation (e.g.
|
|
`@deepseek-ai/dsh-bash-local`); the plugin stays pending until `ctx.bash`
|
|
exists (`inject: ['tools', 'bash']`).
|
|
|
|
## Tools
|
|
|
|
### `bash`
|
|
|
|
| Arg | Type | Notes |
|
|
|---|---|---|
|
|
| `command` | string (required) | Run via `bash -c`. No state persists between calls — use `workdir`, not `cd`. |
|
|
| `description` | string (required) | One-line, active-voice summary of the command (5-10 words), for UI/log display only — no effect on execution. |
|
|
| `timeoutMs` | number | Default/max from executor config (120s/600s for bash-local). |
|
|
| `workdir` | string | Working directory for this call. |
|
|
| `run_in_background` | boolean | Return a task id immediately; no timeout applies. |
|
|
|
|
`command`, `workdir`, and `timeoutMs` are resolved against the executor's
|
|
config defaults via `ctx.bash.resolve()` before execution, so the executor
|
|
seam (`BashExecSpec`) receives explicit `workdir`/`timeoutMs` values.
|
|
|
|
Result text: stdout, then a `[stderr]` section, then status markers —
|
|
`[timed out after Nms]` whenever the executor's timer fired (reported
|
|
independently of how the process ended, so a command that traps SIGTERM and
|
|
exits 0 still shows it), `[killed by signal: …]` for a signal death,
|
|
`[exit code: N]` for a non-zero exit (reported, **not** `isError`: the model
|
|
decides how to react), and `[output truncated; full output: <path>]` when the
|
|
tail was kept. Only infrastructure failures (spawn errors, aborts) surface as
|
|
`isError` results.
|
|
|
|
### `bash_output`
|
|
|
|
`task_id` → output produced **since the previous `bash_output` call** plus a
|
|
status line (`running` / `completed, exit code: N` / `killed`). Reads that
|
|
lost data to buffer bounds say so and point at the full-output spill file.
|
|
|
|
### `bash_kill`
|
|
|
|
`task_id` → SIGTERM→SIGKILL on the task's process group. Killing an
|
|
already-finished task is a reported no-op; unknown ids are errors.
|
|
|
|
## Background completion notices
|
|
|
|
When a background task finishes, a short notice is injected into the owning
|
|
agent's session (`agent.inject()`, source `{kind: 'plugin', plugin:
|
|
'tool-bash'}`). Injection is **durable context for the next model request,
|
|
not a wake-up** — an idle agent stays idle until something sends a message.
|
|
That's why the tool descriptions tell the model to poll with `bash_output`.
|
|
|
|
## Permissions
|
|
|
|
`TODO(permissions)`: commands run with the executor's full authority. The
|
|
permission/sandbox seam is the `tools/execute` waterfall (veto or ask) plus
|
|
sandboxing `BashExecutor` implementations — see docs/architecture.md.
|
|
`@cordisjs/plugin-capability` (a named-permission service with a session
|
|
`test()`) is a candidate building block for that work.
|