implemented(除 4 篇超长文档随后补)、proposed、rejected 全树配对; 同一流水线 + 二遍校验(paraphrase-back + 仓库上下文一致性)产出。 docs/rfc/implemented/AGENTS.md 与其 CLAUDE.md 符号链接列入排除 (agent 指令文件,与根 AGENTS.md 同策略)。
4.5 KiB
RFC:停止将 token 流镜像为 agent 事件
Status: implemented
English | 中文
问题
agent loop(智能体循环)将模型的每个 token 增量同时记录为持久的 assistant/chunk 会话事件,并发射一个携带相同数据的并行实时 agent/stream-chunk Cordis 事件。在 packages/core/agent-loop/src/loop.ts 中,两者仅相隔一行:
const chunkEvent = session.append('assistant/chunk', { turn, step, chunk })
chunkSeqs.push(chunkEvent.seq)
ctx.emit('agent/stream-chunk', agent, turn, step, chunk) // ← the mirror
- 持久事件:
assistant/chunk: { turn, step, chunk }。 - 实时发射:
agent/stream-chunk(agent, turn, step, chunk)——相同的StreamChunk,相同的turn/step。
实时发射相比会话事件唯一多出的东西是实时的 Agent 句柄,而唯一的消费方丢弃了它(其处理函数签名为 (_agent, _turn, _step, chunk))。
这与边界镜像移除为轮次/步骤边界消除的重复如出一辙:消费方对同一个持久事实有两个真源,每次修改都必须同时触及两处。那份 RFC 将分片流推迟处理(「assistant/chunk 的持久化仍然是承重的,因此分片流后续可以作为镜像来评估,但那是一个独立的决策」),而非一并打包。本 RFC 就是那个独立的决策。
推迟所依赖的前提已经尘埃落定:分片持久化是权威的,且将保留。停止持久化分片、仅保留瞬态实时流事件的提案已被否决——高保真回放、部分失败的流以及快照回放都依赖持久化的 assistant/chunk 流。因此 session/event 上的 assistant/chunk 是持久的、承重的 token 流,而 agent/stream-chunk 是它的纯冗余镜像。
决策
从 agent 事件分类体系中移除 agent/stream-chunk。token 流通过 session/event 以 assistant/chunk 的形式读取——持久化和回放已经使用的正是同一条流。session/event 是唯一的实时 transcript(文本记录)流(assistant 分片、轮次/步骤边界、工具活动、todo)。
消费方。 唯一重要的生产消费方——ACP 桥接层(dsh-acp,真正面向编辑器的流式输出接口)——已经从 session/event 渲染 assistant/chunk,从未使用 agent/stream-chunk,因此不受影响。stdio UI(dsh-ui-stdio,一个一次性的测试 REPL)是唯一的实时消费方;它在边界迁移时已经有了 session/event 监听器,因此其分片渲染被折叠进该监听器的 assistant/chunk 分支。合并为一个监听器还消除了一个潜在隐患:inReasoning dim-SGR 标志此前在两个独立的监听器(agent/stream-chunk 和 session/event)之间共享,分片与边界在该标志上竞争时没有确定的顺序;单一监听器按追加顺序处理,使交错变为确定性的。
范围
移除:agent/stream-chunk。
未触及:
assistant/chunk(持久会话事件)——权威的 token 流,原样保留。本 RFC 移除的是实时镜像,而非持久化(持久化移除提案已被单独否决,见上文)。agent/steering——本决策未触及(它是控制信号,不是 token 流)。其持久孪生事件是steering/message,镜像发射由其自己的后续 RFC 移除:移除agent/steering镜像发射。agent/status、agent/error、agent/created/agent/disposed、agent/queued、agent/session-start——生命周期/控制事件,不是 transcript 数据,也没有持久副本。
曾考虑的替代方案
移除持久化、仅保留瞬态实时流——反向裁剪,已被单独否决:高保真回放、部分失败的流以及快照回放都依赖持久化的 assistant/chunk 流。这一点既已确定,实时发射就是配对中冗余的那一半。
后果
插件不再能从以 Agent 为首参的事件观察 token 增量。它应订阅 session/event 并过滤 assistant/chunk(如需 Agent 句柄,可从 agent/created/agent/disposed 构建的 session-id→agent 映射中恢复,与边界消费方的做法完全一致)。没有任何生产消费方在分片时需要实时的 Agent;这与边界镜像移除所做的权衡完全相同,是可接受的。