存储核心(packages/core/session)

Session = append-only 的 typed SessionEvent 日志,单一事实来源;LLM 消息历史是派生的(deriveMessages()),从不单独存储。replay/fork/resume 都是同一套事件的再派生。

  • 每条事件:{ type, seq, time, data },seq 单调连续(seq = log.length),事件深冻结。
  • surface 类型事件另带 sourceEventSeqs 与 surfaceOp;可选 ignorable 标记——不认识的必需事件必须拒绝重建而非静默丢弃。
  • 十二个核心 SessionEventMap 变体:turn/start|end、step/start|end、user/message、assistant/chunk、assistant/message、tool/call、tool/result、todo/write、request/header、request/context,加种子边界 session/end-seed。Map 经 declaration merging 扩展(compaction、hook-protocol、goal、schedule 各自加事件)。
  • user/message 三种来源同一类型:人类 prompt、agent.inject() 合成上下文、goal continuation round——靠 source 区分。
  • assistant/message 携带 usage(token 记账与输出同行)与 sourceEventSeqs(构成它的 chunk 列表)。
  • persistence-catalog 口径:24 个事件命名空间、44 个持久事件名:agent、agent-preset、approval、assistant、command、compaction、feedback、goal、hook、llm、permission、plan、request、sandbox、schedule、session、step、subagent、todo、tool、tool-workflow、turn、user、web(生成文件列全部 payload;注意与 event-producer-consumer 的声明事件矩阵口径不同)。

Surface 与派生规则

  • SurfaceEventType 仅三种:user/message | assistant/message | tool/result(产生 LLM message、可进 ordered surface)。其余全部 log-only(durable、可 replay、不进模型历史)。
  • SurfaceOp = 'append' | { op:'replace', start, end }——compaction 用 replace 遮蔽旧节点(见 context-management)。
  • 派生:user/message → user 消息;assistant/message → assistant 消息(空内容跳过);tool/result → 带 tool-result block 的 user 消息;assistant/chunk 与 turn/*/step/* 不进派生历史。deriveMessages() 带缓存(每 surface node 只投影一次)。
  • request/header:下一次请求的完整 EpochHeader(config + adapterDefaults + 渲染后 system prompt + 工具 schemas)快照入 log——保证”每次会话请求是 log 的纯函数”。request/context 单独记录路由的 contextWindow 容量。
  • TurnEndReasonMap:completed | aborted | blocked | error | max-tokens | interrupted(interrupted 只由崩溃恢复合成,loop 从不发)。
  • session/end-seed:seeded session(resume/fork/replay)的第一次活写入,标记种子边界,让独立开闭括号能区分”上一生命周期遗留”与”当前活跃”。
  • Store(ctx.sessions):create/prepare/enter/announce/flush/get/list/fork。persistence 故意不在此实现——persistence 插件订阅 session/event,在 session/flush(parallel checkpoint)与 dispose 时落盘。后端:JSONL 与 SQLite 两个 provider。fork 要求前缀结束在 open turn 之外。

Projection(派生整值服务)

capability seam:把 log 派生的 per-session 当前整值给客户端。框架驱动、领域计算:registry 只订阅一次 session/event,把每个 committed event fold 过每个 unit;领域不持订阅。

  • Unit(ProjectionDefinition):key + Zod schema + init() + 纯同步 apply(state, event)(不关心必须返回同一引用——Object.is 相等则零下游工作)+ view(state) + stateVersion。
  • snapshot(session) 全同步一致切面(asOfSeq 水印);持久缓存 ctx.sessionProjectionCache throttled write-behind + 两个强制点(turn/end、disposal);冷读阶梯:cached row → persistence tail → registry restore → 回写,全程 fail-soft。
  • 例:subagent 列表的 mode/label 就是一个注册的 subagent projection unit。

Query(会话语料查询)

ctx.sessionQuery(抽象 seam,SQLite provider 提供 FTS 索引),live-preferred(活会话 + persistence 物化):

  • 记录类型:SessionRecord、SessionEventRecord(surface 分类 current | shadowed | log-only)、SessionLogSnapshot(resume preflight 全量重放校验)、SessionSurfaceSnapshot、SessionTitleObservation。
  • 能力:listSessions、readSession、filterSessions/filterEvents(provider 无关谓词;text 是字面量、大小写不敏感、空白宽松的语义扫描)、searchSessions/searchEvents(FTS + opaque cursor 分页)、readSurface、traceSession(祖先/后代 lineage)、traceEvent(替换链 + 源事件引用)、readTitle*。
  • 稳定错误码族 SESSION_QUERY_*(17 种)。模型面工具:session_event_read/search/trace、session_search/trace(opt-in,见 tool-system)。

Title(durable latest-wins)

  • log-only session/title 事件携带 title、所依据的人类 message seqs、source(fallback | provider | user);foldSessionTitle() 取最新。
  • rename() 以 user 来源写入并 pin(自动生成停止调度);provider 可注册 automatic: 'first-prompt' | 'all-prompts' 节奏。LLM 标题调用前先记辅助请求事件(system/messages/route/maxTokens/messageSeqs),保证可复现。

格式立场

所有 payload JSON-serializable(Session.append 强制);格式钉在 SESSION_FORMAT_VERSION = 0,pre-release 无兼容承诺;SQLite 用单调 SCHEMA_VERSION。持久事件 envelope 的完整清单由 scripts/gen-persistence-catalog.ts 生成(verify-persistence-catalog 校验,禁手改)。

相关页面