fold 投影(fold / Projection)

fold 投影(fold / Projection)

一句话

定义"如何从一条事件日志算出一个视图"的纯函数就是 fold;算出来的那个视图就是投影(Projection)。

拆开讲

  • fold(折叠/规约):把一条条事件累积成一个结果。输入 = 全部事件,输出 = 一个派生状态,纯函数、无副作用。
  • 投影(Projection):fold 得到的视图,如"当前对话消息列表"“Goal 状态"“会话标题”,每种都是一份投影。

核心哲学

事件日志(唯一真相 Source of Truth)
   ├─ fold → 投影A(消息列表)
   ├─ fold → 投影B(Goal 状态)
   └─ fold → 投影C(会话标题)

在 Dsh-Go 中

1proj := session.FoldAll(sl.Events())
2for _, m := range proj.Messages {
3    fmt.Printf("[%s] %s\n", m.Role, m.Content)
4}
  • FoldAll 把整个日志折叠成 SessionProjection(内含 Messages / Goal / Todo / PlanMode 子投影)
  • 增量 fold(H04):不是每次读都重算,而是 O(N) 增量维护
  • 标题归一化:会话标题来自不可信文本,sessiontitle.CleanTitle 先剥离 ANSI 转义、控制与方向字符并归一空白,TruncateUTF8 再按 UTF-8 字节预算截断而不拆字符,保证标题单行、安全且长度有界。
  • 耗时统计:telemetry.StatsCollector 从 step/tool 边界增量统计回合数、步数与模型耗时、首 token 延迟、工具耗时(turn 去重),用于展示性能画像而无需回溯整段日志。

性能数据

⚡
增量 fold 相对暴力重算:16.9s → 4.9ms,≈ 3437×(10k 事件,每步读)

对照源码

  • pkg/session/fold.go —— 投影函数族
  • pkg/sessiontitle/normalize.go —— 标题清洗与 UTF-8 字节截断
  • pkg/telemetry/stats.go —— 会话耗时增量统计
  • pkg/session/incremental.go —— 增量投影(H04)
  • 可运行示例:examples/tutorial 第 2 步

下一步

→ 学习 Goal 状态机:Agent 如何规划并驱动执行