为 DeepSeek Harness 提供 Codex 风格 shell 工具集,支持 exec_command 启动进程、write_stdin 持续喂入,专门解决需要 stdin 交互的 CLI 场景。
$ dsh plugin --profile web add github:Ephemeral-AI-Lab/dsh-plugins/codex-shellRun the command above in your terminal to install this plugin via the dsh CLI. You can switch Profile in the top-right corner. New to dsh? Read the beginner tutorial
落地页对应的仓库子路径是
codex-shell,但仓库中实际承载该插件代码的目录是codex-terminal,npm 包名dsh-codex-terminal。该插件是Ephemeral-AI-Lab/dsh-plugins这个 monorepo 下的子包之一。本百科聚焦codex-shell路径对应的能力。
为 DeepSeek Harness 增加 Codex 风格的双工具 shell:用 exec_command 启动进程并自动接管超时,再用 write_stdin 给同一会话持续喂输入,专门处理普通 shell 工具搞不定的交互式 CLI、REPL、OAuth 流程等场景。
defaultYieldTimeMs(默认 10 秒)时自动转为 codex-terminal-N job,返回的 job_id 同时被 write_stdin、job_list、job_kill 共享。write_stdin(job_id, chars) 发送一行 stdin,等于空字符串就是只轮询未读输出,结果会和 exit_code 一起返回。ctx.jobs,让原生 dsh-tools 任务工具统一管理长期运行 session。ctx.steer 通知 owner 在下一步拉一次输出,避免 owner 被 followup 误唤醒。/bin/zsh,Linux 默认 bash/sh;可用 windowsShell / posixShell 自定义。max_output_tokens 限制(默认 10000 tokens),单会话保留不超过 1 MiB;收集完毕后进程句柄、输出缓存、监听器都释放。tsc 编译到 lib/,package.json:5 声明 "type": "module")node-pty(原生,PTY 后端的可选 transport,pipe fallback 默认不走)@deepseek-ai/cordis(>=4.0.0):声明 inject: ['tools', 'systemPrompt', 'jobs'],插件通过 Cordis 注册到宿主@deepseek-ai/dsh-tools:用 defineTool 注册 exec_command / write_stdin@deepseek-ai/schemastery(>=3.18.0):工具入参 schema 校验cordis.patch.yml 给宿主注入一行 codex-terminal;apply(ctx, config) 内部用 PTY-first + 可配置 pipe fallback 工厂,三类后端(node-pty / pipe / pty-first 工厂)都在 src/backend/ 下;shell 适配器按 process.platform 自动切换。codex-terminal/src/index.ts(同时 export name = 'codex-terminal'、inject = ['tools','systemPrompt','jobs'],src/index.ts:10-11)当 DSH agent 跑的任务必须跟一个需要持续 stdin 喂入的 CLI 进程对话时(设备码登录、OAuth 回调、Python/Node REPL、SSH 会话、数据库客户端 prompt、需要回答"N Y/n" 的安装脚本等),普通 bash 工具只能启动+一次性取输出,没法继续喂输入;codex-terminal 通过 job_id 留出"再说话"的通道,让 agent 能完整跑完一轮交互。
| 依赖 | 最低版本 | 说明 |
|---|---|---|
@deepseek-ai/dsh-tools | >=0.1.0-rc.5 | peerDependencies,没有它注册不了工具 |
@deepseek-ai/cordis | >=4.0.0 | peerDependencies,宿主插件框架 |
@deepseek-ai/schemastery | >=3.18.0 | peerDependencies,工具参数校验 |
@deepseek-ai/dsh-jobs-local + @deepseek-ai/dsh-tool-jobs | 任意可用版本 | 未在 package.json 声明,但 README 和 src/index.ts:32-35 写明必须配合加载,否则插件启动即抛错 |
node-pty | ^1.1.0 | 原生模块,启用 PTY 传输时需要;pipe fallback(默认)编译失败也能跑 |
| 平台 | 跨平台 | Windows / macOS / Linux 全部支持,分别走 PowerShell、zsh、bash/sh |
| Node.js | 未声明 | package.json 没声明 engines,devDependency 是 @types/node ^22.20.0 |
dsh plugin --profile web add github:Ephemeral-AI-Lab/dsh-plugins/codex-shell
| 配置 | 类型 | 说明 | 默认值 |
|---|---|---|---|
executionMode | 'trusted' | 'host-policy' | 部署级执行策略;'host-policy' 当前会主动抛错(src/policy/execution-policy.ts:10-13),只能留 'trusted' | trusted |
ptyFallback | 'pipe' | 'error' | PTY 后端分配失败时回退到 pipe 还是直接报错 | pipe |
maxSessions | 整数 | 同时存在的会话上限,超过即拒绝新 job | 64 |
defaultYieldTimeMs | 正整数(毫秒) | exec_command 默认等待时长;超时则转为后台 job 返回 job_id | 10000 |
pollYieldTimeMs | 正整数(毫秒) | write_stdin 空轮询时的默认等输出时长 | 250 |
maxOutputBytes | 正整数 | 单个会话保留的输出字节上限(内存) | 1048576(1 MiB) |
defaultMaxOutputTokens | 正整数 | 单次工具响应里允许返回的最大 token 数;超过会分页 | 10000 |
rows | 正整数 | 伪终端行数(仅 PTY 模式生效) | 24 |
cols | 正整数 | 伪终端列数(仅 PTY 模式生效) | 80 |
windowsPtyStartupGraceMs | 非负整数(毫秒) | Windows 上 ConPTY 启动后保护首次 stdin 不被吞掉的等待时间 | 2000 |
windowsShell | 字符串 | 自定义 Windows shell 路径 | 不配置则用 PowerShell |
posixShell | 字符串 | 自定义 macOS/Linux shell 路径,留空时按 $SHELL → /bin/zsh → /bin/bash → /bin/sh 顺序探测 | 自动探测 |
Q: 装完之后怎么启用?
A: 不是装完就能用,必须到 DSH Web UI 进入 Settings → Agent presets,用 Creator mode 新建一个名为 "Codex Whale"、id 为 codex-whale 的 preset(duplicate Standard preset,加入一行 id: codex-terminal 并禁用 tool-bash/tool-pwsh),设置成默认 preset、重启 DSH、新建会话后才生效。
Q: 原生 node-pty 编译失败怎么办?
A: 默认 ptyFallback: 'pipe' 已经让 pipe 后端接管 exec_command + write_stdin 整条链路(README.md:101-103),所以本地编译失败不影响主要功能;想用真 PTY 的话,去目标 profile 的 pnpm-workspace.yaml 加 allowBuilds: { node-pty: true } 后重新装。
Q: 现有会话还在用旧的 shell 工具?
A: 故意为之。README.md:165-166 明确说"existing sessions keep their old tools",所以装完插件必须新建会话才能体验新工具。
Q: 报错 "background jobs unavailable"?
A: 意味着当前 DSH profile 没把 @deepseek-ai/dsh-jobs-local 和 @deepseek-ai/dsh-tool-jobs 加载进来——src/index.ts:32-35 在拿不到 ctx.jobs 时直接抛错,这俩插件不打开 exec_command 没意义。
Q: 长输出会被截断吗?输到一半内容丢了怎么办?
A: 单次响应按 defaultMaxOutputTokens 分页,已缓冲的输出不会丢(changelog/0.1.2.md 修复了"截断就释放 session"的回归 bug);继续用 write_stdin(job_id) 空轮询就能拉下一页,直到响应里不再带 job_id 为止。
Q: 进程自然结束了,怎么知道?
A: 通过 owner-level steer 发一次内部通知(README.md:120-123),agent 下一步会收到"用空 chars 调一次 write_stdin 拉收尾"的提示;如果 exec_command/write_stdin 在自己的 yield 内就探到了 exit code,背景 notify 会抑制,避免重复打扰。
Q: 能和原生的 bash/pwsh 工具同时开吗?
A: Codex Whale preset 专门把 tool-bash 和 tool-pwsh 禁了(README.md:54),所以正常使用下不会撞车;如果硬要同时启用,两套工具会同时出现在 agent tool 列表里,可能造成同一会话被两条路径操作导致状态错乱。
进阶 — 玩家必须先理解 DSH Agent preset / profile 加载机制,再手工建 Codex Whale preset、配套打开 jobs 插件、决定要不要编译 node-pty;按 README 走一遍需要六七步,但每步有具体命令和验证方式,不算难。
executionMode: 'host-policy' 已声明但未实现,选这个值会在启动时主动抛 unsupported until an explicit DHS policy adapter is supplied(src/policy/execution-policy.ts:10-13),只能保持 trusted。@deepseek-ai/dsh-jobs-local 和 @deepseek-ai/dsh-tool-jobs,否则 src/index.ts:33-35 直接 throw;插件不会自己加载兄弟插件。README.md:165-166)。job_output 必须从 agent 视角隐藏——codex-terminal 的完成通知走专门的 steer 通道,不通过 job_output,混用会丢输出。node-pty 在某些受限环境(容器、CI)会被 pnpm 构建守护拦下,需要在 profile 的 pnpm-workspace.yaml 加 allowBuilds 白名单(README.md:201-208)。maxOutputBytes 截断。