跳到主要内容
路径文档

子进程与终端

一句话版ctx.subprocess 是 DSH 的进程底子:负责任何 child-process 的可执行查找、受管进程树、原始或收集 stdio,以及一个深度终端原语(PTY、前台组、会话清理)。命令默认语义、shell、超时、framing 归消费者。

会话里的 bash 工具、LSP、PTY、ACP 都建立在它之上。这一篇讲清"DSH 怎么跑进程"。

一、是什么

ctx.subprocess进程半边的执行世界:抽象 SubprocessRuntime 暴露可执行查找、普通受管 spawn,和一个终端进程原语。它的词汇覆盖原始/收集 stdio、进程与终端句柄、退出事实、树/会话清理、受管的 DSH_* 环境命名空间。

ctx key角色
subprocessctx.subprocess服务定义(可执行查找、受管 spawn、终端原语、句柄生命周期)
subprocess-local本地 provider(分离进程树、有界收集/spill、node-pty、树信号、terminate-and-join)

消费它的是 shell executor、LSP host、terminal 后端、ACP backend。ctx.subprocess 不替代 ctx.shell:bash 是更上层、面向模型的封装。

二、普通受管 spawn

spawn(spec) 立即返回活句柄;done 在进程关闭时 resolve 退出事实(SubprocessOutcome 无输出、无原因分类,只报 spawn 级失败)。

  • spec 完全显式:argv、cwd、每流 stdio、grace:部署相关默认归调用方 config,不藏在 subprocess 默认里
  • argv 永不被 shell 解释;要 shell 就自己传 ['bash','-c',command]
  • stdio Node 形状:'pipe' 给你原始流自己 framing(如 LSP JSON-RPC、ACP ndjson);'inherit' 透传父描述子;collect 模式({maxBytes, spill?})缓冲有界尾部 + 可选全流 spill 文件

三、收集输出(collect)

  • collect readers 取整流字节偏移,从不消费:独立 reader 不会偷走彼此的 delta
  • 读时偏移滑出内存尾部 → lossy,有 spill 则指向 spill 文件
  • 收集输出在 settle 后仍可读

四、终止与清理(树级)

  • 所有平台树作用域终止(POSIX detached group + direct-child fallback;Windows taskkill /T)
  • terminate() 是唯一终止动词:升级 SIGTERM → grace → SIGKILL(幂等;也由 spec 的 abort 信号驱动;树没了就是 no-op)
  • waitForExit(signal?) 观察整树存活,让调用方 teardown 阶梯每层等真实 quiescence
  • manager 只反应,不分类原因:deadline、teardown 阶梯、原因分类归调用方

五、终端原语(spawnTerminal)

spawnTerminal(spec)唯一非 pipe 原语,句柄拥有真实 PTY:

  • UTF-8 文本 I/O、前台进程组检查/信号、一次 awaited terminate()
  • terminate 对 provider 仍能观察到的每个会话成员达到 quiescence,并 settle 在途句柄调用
  • spec signal 只取消分配;已发布句柄自持生命周期
  • 顶部进程退出后输出流在排空队列后结束;live transport 失败 reject done

普通 pipe 无法分配控制终端/清理终端会话成员,所以这是单独一个 substrate 原语。

六、环境净化

scrubbedParentEnv() / SENSITIVE_ENV_PATTERN:丢弃凭据形状和 DSH_* 名字的环境,显式 env 在净化后 merge。本地普通与终端 spawn 都应用它;SDK 管理的传输可以直接 import。

七、终端会话专节(ctx.terminals 与 terminal-bash)

spawnTerminal 是"分配一个 PTY"的底层原语;真正给模型一个持久交互式 shell的是 ctx.terminals 服务缝 + 其 terminal-bash 后端:

ctx key角色
terminalctx.terminalsowner 作用域的持久终端服务缝:铸不透明 session id、经命名后端路由创建、每个操作栅栏到确切的 live Agent、dispose 时等后端 quiescence
terminal-bash—(后端 type: shell)ctx.subprocess.spawnTerminal 上的持久 shell 后端
  • ctx.terminals 本身不含 node-pty/沙箱/工具 schema/提示词/任务/终端渲染策略:实现管终端机制,消费者管模型呈现
  • terminal-bash 在共享 ctx.sandboxPolicy 下启动交互 shell:danger-full-access 直接起;受限模式要求一个 same-world ctx.sandbox,把 shell argv 包进 confine,没挂就 spawn 前失败
  • readiness 是组合证据:前台验证的 bash 私有提示符 marker + provider 报的前台 stdin-wait 事实 + 静默回退 + 绝对超时;echo 的输入或更早提示符不能误判为本次 send 已就绪
  • send 取消把排队输入标记为取消,再向当前前台进程组发真实 SIGINT;收尾靠 terminal_close
  • 会话进程本地,harness 重启不恢复;同一后端组合本地或远程 execution-world provider

挂载:terminal / terminal-bash 在 base 里不默认挂载;minimal preset 以 entry-local realm 把它们连同 tool-bash-persistent 一起挂(持久 shell 是这个精简组合刻意保留的两个工具之一)。

八、验证

# 看 subprocess 是否装载
dsh web --dump-config | grep -iE "subprocess"
# 会话里看 bash/lsp 子进程(透传的)
zstdcat ~/.dsh/sessions/*/*/session.jsonl.zstd | grep -E '"bash|"tool/' | head

下一步