Daemon 事件封套与状态投影
区分 wire envelope、ACP metadata、会话状态和前向兼容。
SSE data 行装载完整 daemon envelope,含 v、type、data,以及可选 id、originatorClientId、_meta。当前事件 schema 为 v:1;具体已知类型以对应 SDK 的 DAEMON_KNOWN_EVENT_TYPE_VALUES 为准。
两层 metadata
envelope._meta.serverTimestamp 表示服务器事件时间;ACP payload 的 data._meta 另可包含工具来源、serverId 或 display 信息。二者不能互相覆盖。
EventBus 为正常发布事件补充时间并保留 metadata;当前源码保留已有有效数值 serverTimestamp,缺失或无效时使用当前时间。绕过 bus 的 synthetic frame 可由 SSE formatter 补充时间。
工具 provenance 按 subagent、MCP 命名、builtin 等规则形成,MCP 可带 serverId。渲染器优先使用这些结构化值,见UI 渲染。排序仍使用 eventId,不用时间戳代替顺序号。
并非每帧都有 ID
正常保留事件有 session 内递增 id;state_resync_required、replay_complete、client_evicted、slow_client_warning、stream_error、session_snapshot 等 synthetic 帧不消耗序列 ID。
history_truncated 是 load replay 中的状态标记,也不带 id。客户端只能在有 id 的帧上推进重连游标,不能为私有警告自行补造序号。
SDK 解析与 reducer
asKnownDaemonEvent 将可识别事件转为 typed union,不认识的类型返回 undefined。添加可选字段通常保持兼容;改变既有 payload 形状需更新 schema 和相应 capability。
会话 reducer 维护当前模型、显示名、审批、终态、慢客户端和 MCP 警告等;workspace auth device flow 应交给独立 auth reducer,不当作当前 session 的聊天状态。
settings_changed/settings_reloaded 可被识别,却不一定有独立会话状态字段。Skill toggle 的 mutation metadata 允许增量刷新;其他宿主可将其作为重读信号,不能假定所有事件都自动改变可见 transcript。
记录降级与快照
session_recording_degraded 表示异步 transcript writer 写入失败后永久停止,reason 为 write_failed。会话状态记录为 sticky;显式 session_snapshot.recordingDegraded 值具有权威性。
session_snapshot 还可携带 currentModelId、currentApprovalMode。恢复时读到有效快照与看到普通增量是不同信息,不能只取最后一条 text chunk 重建全部状态。
需要额外处理的兼容情形
mcp_server_restart_refused 的 reason 使用已知集合;新 reason 可能被旧 SDK 丢弃,发布新行为时需同时考虑 SDK 更新。user_shell_command/result 在该版文档中没有完整 typed data interface,由 UI normalizer 专门解析,不能仅依赖 asKnownDaemonEvent 覆盖所有 UI 输入。
extensions_changed 的 enabled/disabled 可来自旧 daemon;有 extension_activation_explicit_refresh 时,activation 提交不立即广播这两个状态,后续 refresh 走无 status 的广播。
session_branched 是旧兼容事件,当前 branch endpoint 直接返回结果,不发该事件。客户端不能为了等待它而永久挂起。
不可序列化事件
当前 EventBus 在分配最终序号和保留到 ring 前验证 JSON 序列化。BigInt、循环结构等无法编码的事件返回 undefined,不保留、不扇出、不消耗 id;summary 模式过滤掉的事件也不消耗 id。
旧 EventBus 说明中“序列化失败按零字节继续”的描述已不符合该源码。publish 的不抛出契约不等于每个输入都能成功投递,调用方应理解返回值与诊断。