模块定位
packages/core/session 是 Harness 的事实账本。它不是“聊天消息数组”,而是 append-only event-sourced session log。模型历史、UI transcript、持久化、fork、resume、telemetry 都从这份 log 派生。
源码入口:
packages/core/session/src/index.tspackages/core/session/src/types.tspackages/core/session/src/surface.tspackages/core/session/src/request-header.tspackages/core/session/src/chunk-rows.tsdocs/persistence-catalog.mddocs/subsystems/session.md
为什么不是 messages 数组
一个真实 Agent 会产生的不只是 user/assistant message。它还有:
- turn/step 边界。
- assistant streaming chunks。
- tool call 与 tool result。
- request header。
- usage 信息。
- compaction replacement。
- hook、retry、workflow、subagent 等子系统事件。
- crash repair 事件。
如果只存最终 messages,会丢掉大量运行事实。DeepSeek Harness 的做法是:raw log 保存事实,surface projection 决定哪些事实形成模型历史。
1 | flowchart TD |
SessionStore 与 Session
ctx.sessions 是 SessionStore service。它负责创建、发布、flush、fork、查询 live session。
关键 API:
ctx.sessions.create(id?, { seed?, meta? })ctx.sessions.flush(session)ctx.sessions.fork(source, boundary?, childSessionId?)ctx.sessions.get(id)ctx.sessions.list()
Session 本身是普通 class,不是 Cordis service。它负责 append、deriveMessages、deriveEventMessage、surface projection、header、seq、events snapshot。
append 做了什么
session.append(type, data, opts?) 不是普通 push。它会:
- snapshot durable JSON。
- freeze event data。
- 校验 marker、sourceEventSeqs、surfaceOp。
- 校验 replacement 覆盖关系。
- 同步提交 seq。
- 通知
session/eventobserver。
这保证 log 里的 durable data 不会被 append 后的外部引用继续修改。
Surface Projection
Surface 是 raw log 之上的有序投影,用来高效生成模型消息。它处理:
- append-origin entries。
- replacement entries。
- compaction summary。
- tool result content-only rewrite。
模型历史读的是 surface,而不是 raw log。人类 transcript 则不一定应该只看 surface,因为 surface replacement 会 shadow 旧内容,而人类可能需要看到原始发生过的历史。
Request Header
request/header 记录非历史 request envelope:provider、model、system prompt、tool schemas、adapter defaults 等。它不重复塞进模型 messages,但可以让系统重建当时发给 provider 的请求边界。
这对调试很关键:如果后来默认模型、tool order、prompt section 都变了,历史请求仍然可以按当时 header 复原。
Unknown events 与版本
Session event map 是 merge-extensible 的。插件可以声明自己的事件类型。未知事件默认拒绝读取,除非 event envelope 标记 ignorable: true。这是 pre-release 阶段保持安全读取的方式:不知道怎么解释的必需事件,不应该被悄悄跳过。
Crash repair
恢复时可能遇到 assistant 请求了工具,但工具结果没有完整落盘。系统会生成带风险提示的 synthetic result,例如:
TOOL_NOT_STARTEDTOOL_OUTCOME_UNKNOWN
这比盲目重试安全,因为某些工具可能有副作用。
常见坑
第一,新增模型可见内容必须考虑 session event。只改 prompt assembly 不够。
第二,工具 canonical value 不一定持久保存;持久的是模型可见 content 和 presentation metadata。
第三,fork 只能切在稳定边界,不能从 open turn 中间随便切。
第四,session format 仍处于 pre-release,旧格式兼容不应默认承诺。
继续读源码
packages/core/session/README.mdpackages/core/session/src/types.tsdocs/persistence-catalog.mdpackages/session/README.md