结论:能接着上一轮说。但会话 id 不能自己起,第一轮得用 --json 从首行事件里捞;它还认目录,换了目录就续不上。
前两期分别写过它怎么装、怎么把结果接走。这期只回答一个问题:无头模式每次跑完就退出,第二次调用还记不记得第一次说过什么。
本次实测
环境:WSL2(Ubuntu)、Node 22.23.2、dsh 0.2.0-rc.2。沙箱 /tmp/dsh_20261016/,每条命令都套 timeout 280。
| # | 测试项 | 命令要点 | 结果 | 耗时 |
|---|---|---|---|---|
| 1 | 自己给会话起名字 | --session-id myjob |
exit 1,报 session "myjob" does not exist |
2.2 s |
| 2 | 跑一轮并取出 id | --json,新会话 |
exit 0,stdout 首行 {"type":"session","sessionId":"session-3337…"} |
9.5 s |
| 3 | 埋一个暗号 | --json,不碰任何文件 |
exit 0,末行 final = 「记住了」 |
3.8 s |
| 4 | 同 id 再调一次 | --session-id session-6e45… |
exit 0,事件里 "turn":2,答出「青竹七号」,全程没读文件 |
3.9 s |
| 5 | 同上,去掉 --json |
普通输出 | exit 0,stdout 13 字节,就是暗号 | 5.8 s |
| 6 | 换目录续跑 | cd /tmp 后同 id |
exit 1,报 was recorded in "/tmp/dsh_20261016", not "/tmp" |
2.6 s |
第 3、4 步是这期的关键。第 3 步只让它记住一个自己编的暗号,不写任何文件;第 4 步用同一个 id 再调一次,问暗号是什么。它答对了。答案不在磁盘上,只可能在上一轮的会话里。
会话记录落在 ~/.dsh/sessions/ 下面。一级目录是工作目录转义出来的名字(/tmp/dsh_20261016 → --tmp-dsh_20261016--),再往下一层,每个会话一个文件夹,里面是 session.v4.jsonl.zstd 加一把 session.lock。上面那个会话跑了两轮,文件 26 KB。第 4 步的事件里还带着用量:219 个新输入 token、5376 个缓存读取 token。
会话也不自己清理。~/.dsh/sessions 下还留着 10 月 9 日那次测试的沙箱目录,整个目录现在 376 KB,session.lock 是 0 字节。
第 2 步那次会话比第 3 步慢了一倍多(9.5 秒对 3.8 秒),差在动作上:事件流里它先发了一次 bash 去确认目标文件不存在,第二次才走 write 落盘;第 3 步只回一句话,没有工具调用。
一条坑:id 得捞,目录得对
现象:想给会话起个固定名字方便脚本引用,--session-id myjob 直接退 1,提示这个 id 不存在。它只认已经存在的会话。
复现:
sh
dsh --profile headless --session-id myjob "随便说一句"
解法:第一轮照常跑,加上 --json,从 stdout 第一行把 id 抠出来存着。我拿第 3 步的输出验过这一行能正确取到 session-6e45…:
sh
sid=$(timeout 280 dsh --profile headless --json "$TASK" | head -1 | sed 's/.*"sessionId":"\([^"]*\)".*/\1/')
timeout 280 dsh --profile headless --session-id "$sid" "继续"
不带 --json 时 stdout 只有答案(13 字节),stderr 里只有推理文本,两边都不给 id,所以这个 id 只能从事件流里拿。
第二件事同样会绊人:id 对了、目录错了也不行(第 6 步)。会话按工作目录归档,脚本中途 cd 过,就得 cd 回来再续。
一句话总评
4.3 / 5,只评「跨进程记住上下文」这一项。 续跑确实省掉复述:第二次调用用 219 个新输入 token 就接上了上一轮的暗号,比把上下文重贴一遍划算。扣分全在 id 上,--help 只写了 "an unknown id is an error",没说 id 从哪来,也没提会话绑目录,这两件事都得撞一次才知道。
测试环境:WSL2(Ubuntu)、Node 22.23.2、dsh 0.2.0-rc.2。命令、输出片段、耗时、退出码均为本机实测。
文 / 程实
广告


