|
|
пре 1 месец | |
|---|---|---|
| .. | ||
| src | пре 1 месец | |
| tests | пре 1 месец | |
| README.md | пре 1 месец | |
| package.json | пре 1 месец | |
| tsconfig.json | пре 2 месеци | |
Local-subprocess implementation of the @deepseek-ai/dsh-bash executor seam: LocalBashExecutor spawns bash -c <command> per call in its own process group, collects bounded output with size-limited full-stream spill files, and escalates kills SIGTERM→SIGKILL across the whole group.
The package root exports the default and named LocalBashExecutor plugin plus its Config; subprocess plumbing stays internal to the implementation package.
- id: bash
name: '@deepseek-ai/dsh-bash-local'
config:
cwd: /path/to/workspace # default: process.cwd()
timeoutMs: 120000 # default foreground timeout
maxTimeoutMs: 600000 # cap for per-call overrides
maxOutputBytes: 64000 # per-stream in-memory cap; overflow spills to disk
maxSpillBytes: 67108864 # per-stream full-output spill cap
graceMs: 3000 # kill escalation and post-exit pipe-drain grace
Design surveyed against the bash tools of Claude Code, OpenCode, Codex, and pi; the notable choices:
bash -c (deterministic; no rc files). All four surveyed tools spawn per call. XXX(stateful-shell) in src/run.ts records the two proven stateful designs (Claude Code's cwd-only persistence; Codex's PTY exec sessions) for when real workflows demand them.detached (own process group); kills send SIGTERM to the group, then SIGKILL after the graceMs grace (default 3s — OpenCode's escalation; pipelines and subshells die with the parent). After the main shell exits, inherited stdout/stderr pipes receive the same bounded drain grace so a surviving descendant cannot hold the command open indefinitely. ESRCH is tolerated; daemons that re-parent away from the group can still survive — same caveat as the surveyed tools.maxOutputBytes keeps the in-memory TAIL (errors/results cluster at the end — pi/OpenCode rationale) while the FULL stream is appended to a temp file whose path is reported when available. A foreground BashExecRequest.stdoutMaxBytes can raise stdout's capture budget for one trusted caller; stderr and background tasks still use maxOutputBytes. A stream larger than maxSpillBytes discards its now-incomplete spill and returns only the marked truncated tail. If the final spill close reports a delayed writeback failure, the executor likewise withholds the path rather than advertising an incomplete file.process.env minus credential-shaped vars (*KEY*/*SECRET*/*TOKEN*) and all ambient DSH_* names, then NO_COLOR=1 TERM=dumb PAGER=cat GIT_PAGER=cat (Codex's hardcoded set) so pagers and ANSI color don't garble results. A spec's ordinary env is merged after the scrub but rejects DSH_*; managed dshEnv rejects ordinary names and merges last, preventing stale nested-harness identity. Supplied stdin is written and closed; otherwise fd 0 is /dev/null. See the stdin/env Agent Note and managed environment Agent Note.start() returns a live BashProcess handle immediately, no timeout applies (Claude Code detaches timeouts when backgrounding), the handle's readOutput() is incremental with whole-stream byte offsets, and disposal kills every running process and awaits its exit. Everything task-shaped (ids, ownership, polling, notices) lives in the generic ctx.tasks runtime, which the tool layer registers the handle with — this executor never sees a session or a registry.Indirectly, through dsh-tool-bash, which renders this executor's bounded stdout/stderr tails, background-process deltas, spill-file paths, and infrastructure failures.
No direct invalidation; the named consumer owns any request-prefix changes.
dsh-bash-sandbox, while per-call allow/deny/ask policy belongs on tools/pre-execute.bash -c; cwd-only persistence and interactive terminal sessions remain deferred until a real workflow requires them.bash binary, detached process groups, group kills, and SIGTERM→SIGKILL escalation are hardcoded; Windows is unsupported.*KEY*/*SECRET*/*TOKEN* only; differently-named secrets (e.g. *PASSWORD*) pass through, and a whitelist for over-scrubbed vars is noted future work.The raw process handling lives in src/run.ts; src/index.ts is the service wiring.