Files
deepseek-harness/packages/bash/bash/README.zh.md
Tianyi Cui 5717726835 subprocess: one explicit env channel on the spawn spec
Drop SubprocessSpawnSpec.dshEnv and splitEnvChannels(); childEnv() is now
scrubbed-base + explicit entries with no namespace validation. The invariant
dropped is the reserved-namespace check on explicit entries (DSH_* rejected
from env, non-DSH_* rejected from dshEnv). Explicit-entry trust already
covers it: an explicit credential-shaped entry has always merged after the
scrub as a deliberate caller opt-in, and an explicit DSH_* entry is the same
deliberate act — the staleness invariant lives entirely in scrubbedParentEnv
dropping AMBIENT credential-shaped and DSH_* names, which stays. The
validation's only observed effect was rejecting legitimate explicit entries:
both recent CI breakages (DSH_GATE_CONCURRENCY exported into every job
crashing lsp specs, DSH_PERMISSION_MODE in acp config.env crashing the
child spawn) were this check firing on values a caller meant to pass, each
fixed by routing around the bureaucracy the seam itself imposed.

The bash seam keeps its own request/spec dshEnv field: that is bash-owned
trusted-plugin vocabulary (the ctx.bashEnv collected overlay) whose merge-last
position guarantees a caller env entry cannot displace a managed fact;
bash-local now flattens ENV_OVERRIDES -> spec.env -> spec.dshEnv into the
seam's one env map. subagent-acp and lsp-local pass their single config env
map straight through. DshEnvironment/DshEnvironmentKey/DSH_ENV_PREFIX stay on
the subprocess seam as the namespace vocabulary (bash re-exports them;
scrubbedParentEnv filters on the prefix).

Tests: the two channel-rejection specs and the splitEnvChannels partition
spec are deleted; one spawn spec now proves an explicit DSH_* env entry
reaches the child while an ambient one is scrubbed; the acp/lsp forwarding
specs keep their MOCK_ECHO_ENV / LSP_FAKE_ECHO_ENV assertions with the split
comments rewritten to merge-after-scrub. Docs (en+zh, re-recorded) and the
owning Agent Notes updated; cordis api/services catalogs regenerated.
2026-07-27 04:14:51 +08:00

5.5 KiB
Raw Blame History

@deepseek-ai/dsh-bash

English | 中文

bash 执行器 seam:抽象 BashExecutor 服务(ctx.bash)定义 bash 后端做什么即运行前台命令与启动后台进程但不规定如何实现。task id、所有权、收集、取消与通知属于通用 ctx.tasks 运行时。

本包是 bash 能力中负责接口的四分之一,各项职责因此可以独立演进(和替换):

职责
@deepseek-ai/dsh-bash(本包) 接口:抽象服务 + 词汇类型
@deepseek-ai/dsh-bash-local 实现:本地子进程
@deepseek-ai/dsh-bash-sandbox 实现:沿用 dsh-bash-local 的机制,但通过 ctx.sandbox 限制每次 spawn并将拒绝报告为结果事实
@deepseek-ai/dsh-tool-bash 基于 ctx.bash、面向模型的工具 schema

该拆分与 LLM seamLlmServiceLlmAdapter)及 agent 工具调研结果一致pi 将执行隐藏在 BashOperations 接口之后(本地 shellSSHVM 后端Codex 则隐藏在 exec-server 协议之后。dsh-bash-sandbox 正是这种替换的实际应用:沙箱执行器位于同一接口之后;消费方检测其 sandboxMode 能力并添加升权字段,无需导入实现。容器化或远程执行器也可以同样接入。

服务 APIctx.bash

成员 语义
run(spec) 前台执行。命令完成时 resolve。只会因基础设施失败而 reject工作目录不可用、shell 缺失、信号已在调用前中止);非零退出、超时终止和中止终止都会 resolve 为描述性 BashRunResult
start(spec) 后台执行。立即返回不含任务语义的 BashProcess 句柄;不应用超时。调用方可以将其适配到 ctx.tasks
sandboxMode 工具层的能力事实:沙箱执行器用于限制执行的默认模式(基类中为 undefined,即「此执行器不使用沙箱」)。dsh-tool-bash 会在注册时读取它,仅当组合确实支持升权字段时才公布这些字段。
BashProcess.readOutput() 增量 读取输出:连续读取绝不会重复交付。因缓冲区边界丢失数据的读取会标记 lossy,并指向完整流 spill 文件。
BashProcess.kill() 终止进程组。如果进程已结束,返回 false

实现会继承 BashExecutor 并实现抽象方法。dispose 必须终止每个运行中的进程并等待其退出,详见 HMR 安全测试。

词汇

BashExecRequestcommand、workdir?、timeoutMs?、stdoutMaxBytes?、signal?、stdin?、env?、dshEnv?、sandboxPolicy?)在执行前解析为 BashExecSpeccommand、workdir、timeoutMs、stdoutMaxBytes、signal?、stdin?、env?、dshEnv?、sandboxPolicystdoutMaxBytes 是受信任前台运行的捕获预算,用于必须解析完整有界 stdout 的消费方;面向模型的 bash 工具不公开该字段。sandboxPolicy 在请求上可选,在已解析 spec 上必填但可为 null它携带完整的每次调用模式与工作区根目录。沙箱工具路径通过 ctx.sandboxPolicy 从调用会话解析它;沙箱执行器的直接调用方回退到部署策略,非沙箱执行器则携带该字段但不作限制。

每会话沙箱模式覆盖词汇('sandbox/mode' 事件、effectiveSandboxMode(events) fold 以及 setSandboxMode(session, mode) 写入路径)不位于此处。它是所有强制执行家族共享的策略状态,属于 @deepseek-ai/dsh-sandbox-policyrun() 返回 BashRunResultstart() 返回 BashProcess,其增量读取与终止方法由 dsh-tool-bash 适配为通用任务注册。沙箱执行器会在前台结果与已结算进程句柄上标记 BashSandboxInfo。详见 src/types.tscore-data-structures/bash.md

stdin 与普通 env 由同进程插件hooks 桥接、原生插件)设置,用于向 hook 命令提供其 JSON payload 和 CLAUDE_PROJECT_DIRCLAUDE_PLUGIN_ROOT 值。dshEnv 是受类型限制、仅允许受管 key 的独立受信任 overlay导出的 DSH_ENV_PREFIX 是该 namespace、其 DshEnvironmentKey 模板类型、执行器清理、注册表验证、派生内置名称与模型指引的单一真源。模型 bash 使用 ctx.bashEnv 收集的当前快照。实现会移除继承的受管 key再在普通 env 之后合并 dshEnv,因此省略的当前事实不会回退到陈旧环境状态,env 条目也无法顶掉受管值。面向模型的工具不公开任何一个字段。这三者在已解析 spec 上仍然可选缺失表示没有输入overlay。详见 bash-stdin-env Agent Note会话环境 Agent Note

模型体验

通过 dsh-tool-bash 间接影响;该工具会将执行器输出与沙箱事实转为指引和保留的工具结果 token。

KV Cache 影响

不会直接失效;请求前缀变更由具名消费方负责。

已知限制与暂缓事项

  • 没有交互式输入词汇stdin 只会在 spawn 时写入一次并关闭seam 不提供向运行中任务继续输入的通道,也没有 PTY 会话概念。
  • 前台超时始终由执行器拥有seam 上的调用方拥有 deadline 模式已由 工具调用超时策略 Agent Note 明确暂缓。