DSH Session 使用与恢复指南:事件日志、Fork 与 Compaction

基于 DeepSeek Harness 0.1.1-rc.2 官方源码,解释 Session 事件日志、持久化、崩溃恢复、Fork、回放与上下文压缩。

社区整理已复核原始来源
DSH
0.1.1-rc.2
风险
medium

先看结论

DSH Session 不是一份简单聊天记录,而是一条由类型化事件组成的仅追加日志。用户消息、模型输出、工具调用、工具结果、轮次边界和运行时请求状态都从这条日志形成可回放历史;LLM 消息不是另外保存的一份副本。

恢复、Fork 和 Compaction 解决三个不同问题:恢复让持久化会话重新变成可运行 Agent;Fork 从已完成轮次的稳定前缀创建子会话;Compaction 用摘要替换模型当前可见的旧上下文,但不删除底层事件,也不会撤销外部副作用。本文依据官方 dsh-v0.1.1-rc.2 源码复核。

一次任务怎样写进 Session

DSH 把一次用户任务称为一个 turn,一个 turn 可以包含多个 step。每个 step 包含一次模型请求,以及该请求触发的工具执行。常见事件顺序可简化为:

turn/start
→ user/message
→ step/start
→ request/header
→ assistant/message 或 tool/call
→ tool/result
→ step/end
→ 需要时进入下一 step
→ turn/end

事件带有连续的 seq 和时间戳。tool/calltool/result 通过 callId 配对;模型流式分片也会保留,以支持逐步回放。插件可以增加自己的事件类型,因此 Session 同时也是审批、压缩、Hook 等子系统的审计载体。

“唯一真源”对用户意味着什么

模型下一次请求看到的历史是由 Session 的可见 surface 派生出来的。请求配置、模型、系统提示和工具 schema 则以完整的 request/header 快照记录。这样恢复或回放时不需要猜测当时模型看到了什么。

但“日志完整”不等于“世界状态可逆”。命令已经改过的文件、发出的网络请求、数据库更新和外部消息不会因为回放旧事件而自动回滚。对这些副作用仍应使用 Git、备份、事务、测试环境和审批策略。

持久化和恢复如何工作

内存 Session 与持久化是两个子系统。持久化后端订阅事件并批量写入;显式 flush 会取消等待并排空待写数据,dispose 时也会执行最终排空。

如果进程在一个 turn 中途崩溃,冷加载不会截断已经落盘的事件。后端会追加一个合成的 turn/end,原因标记为 interrupted,把遗留轮次配平后再供恢复使用。活跃会话不会被另一个加载流程擅自修复;若当前 turn 仍开放,加载会拒绝操作。

恢复持久化会话与简单读取日志不同。官方接口通过 ctx.agents.resume({ resumeSessionId }) 恢复可运行 Agent;恢复时还要使用 Session header 中的工作目录、血统、Agent preset 和格式版本等元数据。

Resume、Replay 和 Fork 的区别

操作输入结果适用目的
Resume已持久化 Session重新得到可运行 Agent继续未完成或跨进程任务
Replay同一组事件重建历史或展示审计、调试、读取 transcript
Fork源 Session 的稳定事件前缀带父会话血统的新 Session从某个节点尝试不同方案

普通 Fork 默认复制到源 Session 当前最后一条事件,也可以显式指定包含边界。被选择的前缀必须结束在没有开放 turn 的位置;如果边界落在进行中的轮次里,API 会拒绝,而不是悄悄截断。子会话会继承 cwd,并记录 parentSessionseedLength

因此,想比较两个实现方案时,先让当前 turn 完整结束,再从对应 turn/end 位置 Fork。不要把复制工作目录、复制 Session 历史和回滚文件状态混为一谈:Fork 继承事件上下文,不会替你创建独立 Git 分支或文件快照。

Compaction 是否会删除历史

不会。Compaction 的目标是缩小模型可见上下文:它选出一段平衡的 surface,把摘要作为新的可见节点替换那段内容,同时在仅追加日志中记录开始、摘要和结束事件。原始事件仍保留在底层日志里。

选择范围时必须保持工具调用与结果成对,避免摘要后只剩一半工具语义。自动压缩可由上下文压力或模型确认的上下文溢出触发;手动压缩也可能因为 Session 忙碌、范围变化、摘要失败、持久化失败或取消而停止。

压缩有三个重要限制:

  1. 摘要是有损表示,后续模型看到的是摘要而非全部旧 surface;
  2. 压缩不会删除审计日志,也不是隐私擦除功能;
  3. 压缩不会撤销工具已经产生的文件或外部系统副作用。

升级时为什么要关注 Session 格式

Session header 包含磁盘格式版本。0.1.1-rc.2 的持久化实现会拒绝无法可靠理解的更旧或更新格式,而不是猜测迁移。SQLite 后端也有独立 schema 版本,并明确拒绝旧 schema,而非自动迁移。

升级 DSH 前应:

  1. 停止新任务并等待当前 turn 结束;
  2. 正常关闭进程,让持久化队列完成 flush;
  3. 备份 $DSH_HOME、项目工作区和重要 Session 数据;
  4. 阅读目标 Release Notes 中的 Session、persistence、SQLite 与 compaction 变化;
  5. 先用副本验证能否列出、读取和恢复旧会话;
  6. 保留原版本和回滚路径,不直接覆盖唯一数据副本。

如何验证一次 Session 是否可复核

完成一个最小任务后,检查以下证据:

  • 用户输入、模型结果和工具调用是否按顺序显示;
  • 每个工具调用是否有对应结果或明确中断;
  • turn 是否正常结束,崩溃恢复时是否标记 interrupted
  • 恢复后使用的工作目录和 Agent preset 是否仍正确;
  • Fork 的子会话是否记录父会话血统,并从预期边界开始;
  • Compaction 前后的当前上下文是否保持工具调用/结果配对;
  • Session 日志中是否含有不应长期保留的敏感内容。

Session 可能保存用户输入、工具参数、输出片段和工作目录等信息。不要把含凭据或客户数据的原始 transcript 直接公开;用于排障时应先脱敏,并说明 DSH 版本、持久化后端和验证日期。

想理解 Session 在整体插件树中的位置,阅读DeepSeek Harness 架构解析;想控制工具执行范围,阅读DSH 权限与沙箱指南;第一次运行则从DeepSeek Harness 中文入门开始。

常见问题

恢复 Session 会重新执行以前的工具吗

事件回放本身用于重建历史,不应被理解为重放外部副作用。后续 Agent 是否再次调用工具,取决于新的请求与执行流程。

Fork 会复制工作目录里的文件吗

不会。Fork 继承 Session 的 cwd 元数据和事件前缀,不等于复制目录或创建 Git 分支。

Compaction 能否用来删除敏感信息

不能。它替换模型可见 surface,但底层事件日志仍是仅追加记录。敏感信息处理需要凭据轮换、数据清理和存储层处置流程。

来源与维护信息

本文根据以下原始资料整理。版本变化后,请以官方资料和页面标注的验证日期为准。