让 Agent 在流水线里修复代码,并不意味着让它决定流水线是否通过。一个更容易审计的分工是:Agent 提出修改,测试工具独立检查,CI 根据测试工具的真实结果决定状态。
本文使用 CLI 0.2.0-rc.2。先完成安装篇,在安装了 CLI 的练习项目目录执行命令,并使用同一个 DSH_HOME。参数依据同版本headless 声明。下面的 CI 脚本是接入模板,需在自己的项目中执行真实模型任务和测试后验收。
先选择输出契约
普通模式适合只需要最终文字的脚本:
npx --no-install dsh --profile headless \
"Read tutorial-input.txt and report its port field." \
> agent.stdout 2> agent.stderr
agent.stdout 保存最终回答,诊断信息另存到 agent.stderr。发生失败时保留诊断,不在示例中用 2>/dev/null 抹掉排错依据。
0.2.0-rc.2 还支持结构化输出:
npx --no-install dsh --profile headless --json \
"Read tutorial-input.txt and report its port field." \
> agent-events.jsonl 2> agent.stderr
这里的 stdout 是逐行 JSON 事件,不是一个完整 JSON 文档,也不再只是最终回答。解析时按行读取,保留事件顺序,并依据同版本的事件投影实现识别记录,别直接对整个文件调用一次 JSON.parse。
“headless 没有 --json”这个旧结论对应的是 0.1.5-rc.1 的参数面,不能套用到本版本。是否支持某个选项,以你安装的版本运行 --help 为准。
让测试程序决定是否通过
下面的 Bash 模板用于已有 npm test 脚本、已在本地依赖中固定安装 dsh 的 Node 项目。凭据由 CI 的 secret 环境注入 DEEPSEEK_API_KEY,不回显到日志。
#!/usr/bin/env bash
set -euo pipefail
: "${DEEPSEEK_API_KEY:?CI secret DEEPSEEK_API_KEY is required}"
export DSH_HOME="$(mktemp -d)"
# Agent 步骤也有独立的执行时限;GNU timeout 超时会返回非零。
timeout 300s npx --no-install dsh --profile headless \
"Run the project tests and make the smallest change needed to fix failures." \
> agent.stdout 2> agent.stderr
# 重新运行真实测试,直接使用测试进程退出码作为门禁。
npm test > test.log 2>&1
它有两道独立检查:Agent 进程没正常完成时,脚本直接失败;Agent 进程正常结束后,测试程序仍要再跑一次。npm test 失败时,set -e 会让脚本返回非零。非 Node 项目把这一行换成仓库自己的测试命令。
不要用模型回答的 OK 替代第二道检查。 模型可能判断错误、跳过测试,或者只完成部分任务。--json 也只是更容易观察过程,不会自动把一个错误判断变成可靠的验收。
另外,测试通过只说明测试覆盖的条件通过。对真实仓库还要核对差异是否符合任务范围,测试和 CI 配置本身是否被修改,需不需要构建、lint 或人工验收。把这些检查作为流水线的明确步骤,不交给一段“全部完成”的自然语言回答。
会话可以继续,但要保存正确的状态
本版本提供:
npx --no-install dsh --profile headless --session-id "$SESSION_ID" \
"Continue the previous investigation without modifying files."
SESSION_ID 应来自已有会话,并使用原来的 DSH_HOME 和工作区。它不是一个随便指定的任务标签;未知会话 ID 会报错。跨 runner 继续任务时,只有 ID 而没有会话数据,并不能恢复对话。
可复现的 CI 任务通常从干净工作副本和独立 DSH_HOME 开始。确实需要续接时,再明确哪些会话和工作区状态要带到下一步。
权限和执行时限分开处理
headless 只是没有交互界面的运行入口,不等于已经为任意输入建立完整的安全隔离。实际权限来自 profile、Agent 配置、操作系统和 runner 环境。
旧版在 Linux workspace-write 策略下的验证中,工作区外写入受到限制,但 /tmp 和系统临时目录仍可能可写。可写根目录声明给出了判断依据。不要只凭一个模式名称推断进程能接触的全部资源。
同样,模型请求超时和整个 CI 步骤超时是两个范围。上面的 timeout 约束整条命令;runner 是否彻底回收子进程,应结合自己的执行环境检查。别让“等待模型”占满一个长期运行的 worker。
会话和日志需要明确的保留策略
Agent 运行会产生会话数据,其中可能包含 prompt、代码片段、工具参数和回复。agent.stdout、agent.stderr、事件流和 DSH_HOME 也有不同用途。
本例用 mktemp 创建独立 home,但没有在脚本里自动删除它,方便失败时取证。为 CI 配置退出后的清理步骤:先按需要保存受控的测试报告与诊断,再删除该次运行的数据目录。诊断需要上传 artifact 时,检查访问范围并脱敏,不把模型凭据或完整会话无条件公开。
到这里,CI 的职责就明确了:启动 Agent、限制执行范围与时间、保留证据,然后独立验证产物。需要在程序里持续接收事件、管理多轮会话时,接着读TypeScript SDK;需要调整 profile 行为时,读配置覆盖层。