description: "The local host provider for the subprocess service: run managed process trees and real terminal sessions on the host machine."
English | 中文
Mount dsh-subprocess-local in any composition that runs child processes on the host: it resolves local executables, spawns detached process trees with explicit stdio, and provides real terminal sessions through node-pty. It has no configuration, so every disposition, limit, terminal size, and grace arrives on the spawn request from the calling capability seam. Output collection keeps a bounded in-memory tail with optional spill files for full-stream recovery, children start from a scrubbed environment, and disposal terminates and joins every running tree.
Mount the provider beside its consumers and start processes exactly as the subprocess service specifies; this package decides only how those processes run on the host.
Load the provider in the same composition as its consumers. It has no config fields: every choice arrives on the spawn request, so deployment-varying decisions stay with the caller's configuration.
- name: '@deepseek-ai/dsh-subprocess-local'
- name: '@deepseek-ai/dsh-bash-local'
Absolute executable paths are verified; bare names resolve against the scrubbed PATH with platform-aware executable extensions (.COM/.EXE/.BAT/.CMD on Windows). Relative paths containing separators are rejected — provide an absolute path or a bare PATH name — and relative PATH entries resolve from the host process cwd.
Collect mode keeps the last maxBytes of a stream in memory — errors and final results cluster at the end — and, when a spill cap is configured, appends the complete stream to a private file under a per-process directory in the OS temp dir (a 0700 directory, 0600 random-named files). A stream larger than the spill cap discards its incomplete spill and returns only the marked truncated tail. Reads are offset-based and non-consuming, so background and batch readers coexist before and after exit.
spawnTerminal allocates a real PTY and bridges UTF-8 text; you can inspect and signal the current foreground process group and await a terminate() that settles every session member the provider can still observe. On Linux, an exact input wait requires a foreground thread whose fd 0 identifies the shell's controlling terminal and whose current syscall waits on that fd. If the kernel denies the syscall probe, the provider reports no exact wait and leaves the higher PTY backend to its idle inference; process sleep state is not evidence. On Windows, SIGINT is delivered as a Ctrl-C input write, SIGTSTP and SIGHUP are unsupported, and teardown verifies the shell's termination through the process table because an externally killed shell may never fire the PTY exit notification.
Normal disposal terminates every running tree and terminal and awaits their exit. During a JavaScript-observable host exit — direct process.exit(), default uncaught exceptions, default unhandled rejections — a synchronous finalization force-terminates everything still owned (SIGKILL to the group, taskkill /T /F on Windows) without creating promises or timers. Unhandled SIGTERM/SIGINT/SIGHUP, SIGKILL, fatal OOM, native crashes, and power loss need an external supervisor.
An executable that cannot be resolved fails loud with a stable error; a spawn that never starts rejects done. A read past the retained tail is lossy and points at the spill file when one exists. A daemonized descendant that leaves the tree or terminal session can outlive cleanup — see the limitations below.
Read these pages when the provider-level contract is not enough. They move from the exhaustive type reference to the abstract contract and the decisions behind the host mechanics.
DSH_* environment in full.Indirectly, through consumer seams such as the bash executor family, which own all model-facing rendering of spawned process output and lifecycle.
No direct invalidation; the named consumers own any request-prefix changes.
These limits define when the provider is a poor fit or needs special operational care. They are current package constraints, not a general platform comparison or a task backlog.
taskkill /PID <pid> /T /F with all outcomes contained (absent tree, races, missing binary), and liveness falls back to the direct-child boundary.\x03 Ctrl-C input write that conhost turns into a console-wide CTRL_C event; SIGTSTP and SIGHUP are rejected as unavailable; a taskkill without /F does not terminate console processes, so the teardown TERM tier is a grace wait before the /F escalation.setsid child leaves both the tree and the owned terminal session; the provider adds no continuous process-table monitor.process.exit(), default uncaught exceptions, and default unhandled rejections emit Node's synchronous exit event; an unhandled SIGTERM, SIGINT, or SIGHUP, SIGKILL, fatal OOM, process.abort(), native crashes, and power loss require an external supervisor, container init, or equivalent OS owner.*KEY*/*PASSWORD*/*SECRET*/*TOKEN* only; differently named secrets (for example *PASSPHRASE*) pass through, and a whitelist for over-scrubbed variables is noted future work.