AtomCode v5.2.3 新子系统深度分析 — 会话事件化 + 回复断流自动续接 + Anthropic 原生缓存
基于
strings结构体元数据 + 提示注入串 + 模块路径的还原分析 2026-10-14 前置报告:06-version-diff-v5.0.9-to-v5.2.3.md姊妹报告:DEEP_ANALYSIS_53(架构重写)、DEEP_ANALYSIS_55(后台会话与团队)、DEEP_ANALYSIS_44(v5.0.9 会话持久化)
1. 会话事件化(Event-Sourced Sessions)
1.1 设计动机
v5.0.9 的会话是可变快照:每次操作改写同一份状态。v5.2.2 起改为事件溯源: 撤销、回退、压缩都作为新记录追加,不改写历史。中断或崩溃后可完整恢复。
1.2 新模块
crates/atomcode-capabilities/src/session/events.rs ← SessionEvent 事件流
crates/atomcode-coding/src/session_store.rs ← 会话存储
crates/atomcode-capabilities/src/session/session_list.rs ← 会话列表
crates/atomcode-capabilities/src/session/status_reminder.rs1.3 SessionEvent 枚举(26 个变体,完整结构体元数据)
struct variant SessionEvent::TurnStart with 1 elements
struct variant SessionEvent::UserMessage with 3 elements
struct variant SessionEvent::StepStart with 2 elements
struct variant SessionEvent::RequestHeader with 4 elements
struct variant SessionEvent::AssistantChunk with 4 elements
struct variant SessionEvent::AssistantMessage with 7 elements
struct variant SessionEvent::ToolStarted with 3 elements
struct variant SessionEvent::ToolResultLogged with 6 elements
struct variant SessionEvent::ToolResultsStubbed with 2 elements
struct variant SessionEvent::StepEnd with 3 elements
struct variant SessionEvent::TurnEnd with 3 elements
struct variant SessionEvent::Usage with 3 elements
struct variant SessionEvent::Compacted with 4 elements
struct variant SessionEvent::Rewound with 3 elements
struct variant SessionEvent::MessagesRewritten with 2 elements
struct variant SessionEvent::Answered with 3 elements
struct variant SessionEvent::Asked with 2 elements
struct variant SessionEvent::Injected with 3 elements
struct variant SessionEvent::Interrupted with 2 elements
struct variant SessionEvent::PartialReply with 4 elements
struct variant SessionEvent::PolicyIntervention with 2 elements
struct variant SessionEvent::RateLimitPaused with 2 elements
struct variant SessionEvent::Notice with 4 elements
struct variant SessionEvent::Titled with 3 elements
struct variant SessionEvent::Checkpointed with 2 elements
struct variant SessionEvent::Stopped with 1 element1.4 事件流时序
TurnStart
└─ UserMessage / Injected / Asked / Answered
└─ StepStart
└─ RequestHeader → AssistantChunk* → AssistantMessage
└─ ToolStarted → ToolResultLogged / ToolResultsStubbed
└─ StepEnd
└─ TurnEnd
Usage / Notice / Titled / Checkpointed / Compacted / Rewound /
MessagesRewritten / PolicyIntervention / RateLimitPaused / PartialReply /
Interrupted / Stopped1.5 事件即快照(关键语义)
resume = true continues that session by replaying the events `session-persistence`
stored for it before the first turn. There is no separate snapshot format for this:
the stored events are the snapshot.→ 无独立快照格式:存储的事件本身即快照。恢复 = 重放事件流。
1.6 存储布局(架构文档原文)
SESSION IDENTITY. The tree's own agent takes its session from the `session` row: `id`
names it (minted when absent), and `resume = true` continues that session by replaying
the events `session-persistence` stored for it before the first turn. There is no
separate snapshot format for this: the stored events are the snapshot.
every fact of the conversation, appended as it happens; a resume replays that file and
nothing else; `<id>.index` holds its name, working directory and per-turn statistics.
append every committed event to <root>/<session-id>.jsonl→ 持久化为 <root>/<session-id>.jsonl + <id>.index(名称 / 工作目录 / 每轮统计)。 插件名:session-persistence-jsonl / session-event-log / session-event-log/this-session。
1.7 快照状态位(上次会话结束原因)
SessionSnapshot / turn_counter / request_counter(单调计数器,冲突检测)
overflow_compacted / provider_retry / output_left_cut_off / compaction_degraded /
config_skipped / member_not_restored
appendMemberHeader / internal_nudge / compaction_summary / team_note→ 快照携带两个单调计数器(turn 级、请求级)+ 6 个状态位枚举,记录上次结束退化原因。 appendMemberHeader 与团队功能联动;team_note 为团队注记事件。
1.8 相关结构体
struct SessionSnapshot ← 快照(5 元素)
struct SessionHeader ← 会话头
struct SessionMeta ← 会话元数据
struct TurnRecord ← 回合记录
struct HistoryEntry ← 历史条目
struct ForkInfo ← fork 信息(5 元素:root_id/forked_at_ms/base_message_count/base_turn_count)
struct ImportInfo ← 导入信息(4 元素:legacy_schema/source_sha256/metadata_only/format_version)
struct UsageRecord ← 用量记录
struct InflightSnapshot ← 飞行中快照(3 元素)
struct MemberHeader ← 团队成员头
struct RewrittenText ← 重写文本1.9 相关内部事件标记
turn_start / user_message / step_start / request_header / assistant_chunk /
assistant_message / tool_started / tool_result_logged / tool_results_stubbed /
step_end / turn_end / usage / compacted / rewound / messages_rewritten /
answered / asked / injected / interrupted / partial_reply / policy_intervention /
rate_limit_paused / notice / titled / checkpointed / stopped / appendMemberHeader1.10 会话迁移与修复状态机
import intent must not claim completed import provenance / begin legacy import
commit point requires owner=native / replace import metadata without expected-state CAS
replace native sidecars without expected-state CAS / import staging residue is not a regular file
inflight snapshot / rewind transaction / session transcript lines / repair missing presentation
load native session / serialized supplied snapshot / validated session id
begin legacy import with expected-state CAS / legacy import intent must use owner=legacy
native session health probe panicked / ended: session persistence became uncertain
ended: active agent did not stop safely / requested_generation / current_generation
agent_available(代际计数,冲突检测)→ 旧版会话(legacy)可迁移到 native 事件格式(begin legacy import), 带 expected-state CAS 并发控制(replace ... without expected-state CAS 为错误条件)。
2. 回复断流自动续接(Stream Recovery)
2.1 触发条件(二进制证据)
stream_transport_interrupted ← 传输中断
stream_idle_timeout ← 流式空闲超时
stream timeout after automatic reconnects
stream timeout after partial response2.2 安全续接流程
stream timed out again after one safe continuation; current progress was preserved;
send 'continue' to resume
stream timeout after partial response; to avoid duplicate output or tool execution,
the request was not replayed; partial response preserved续接条件(从 release notes + 字符串还原):
- 当前请求已有正文,或上一批工具已全部执行成功
- 断流处没有新的工具调用或参数片段
- 仅自动续接一次
2.3 不重复执行工具(关键设计)
[The previous assistant stream was interrupted. The preserved assistant messages and
paired tool results above are authoritative. Continue from that saved progress.
Do not repeat completed tool calls or restart the task.]→ 续接中相同工具、相同参数、相同工作目录的已完成有副作用调用复用已确认结果。 注入给模型的恢复指令明确要求"不要重复已完成的工具调用"。
2.4 恢复提示注入
stream_transport_interrupted / stream_idle_timeout / recovery
llm-stream-recovery 插件行:keep what a broken stream produced and continue from it
crates/atomcode-harness/src/plugins/recovery.rs
crates/atomcode-capabilities/src/provider/latency.rs(流式延迟事件)2.5 静默超时连接恢复(连接池刷新 + 重试总预算)
reconnecting (
stdout while reading headers / Missing Content-Length header / Invalid Content-Length
stdio reconnect failed: / MCP stdio reconnect failed
refresh connection pool(最多刷新一次,避免复用失效连接)
retry budget:建立请求的重试与退避共用总等待预算,默认最多 180 秒
覆盖 OpenAI 兼容、Responses 和 Anthropic 请求
provider 客户端可替换:Anthropic 与 OpenAI 兼容 provider 的 HTTP 客户端
支持在超时恢复时重建连接池2.6 策略表配置(二进制内嵌 [[insert]] 行)
# Recovery, outermost first: a bound that each retry resets is not a bound,
# and waiting out a limit has to happen outside everything that would burn it.
[[insert]] name = "llm-request-timeout" config = { request_secs = 600 }
[[insert]] name = "llm-rate-limit" config = { max_waits = 5, max_wait_secs = 120, fallback_secs = 5 }
[[insert]] name = "compaction-overflow" config = { max_attempts = 3 }
[[insert]] name = "truncation-recovery" config = { max_continuations = 4 }
[[insert]] name = "llm-stream-recovery" config = { max_recoveries = 1 }
[[insert]] name = "llm-retry" config = { attempts = 3, backoff_ms = 3000, cap_ms = 30000 }→ llm-stream-recovery / max_recoveries = 1:每轮仅 1 次安全续接。 恢复层由外到内:llm-request-timeout(600s)→ llm-rate-limit(max_waits=5)→ compaction-overflow(3 次)→ truncation-recovery(4 次续接)→ llm-stream-recovery(1 次)。
2.7 防重复执行标记与断流错误码
=[Recovery: confirmed result reused; tool not executed again]
os error 10054 ← Windows 连接重置(WSAECONNRESET)
"stream idle timeout: no event for ← 无事件超时诊断
pool_refreshed(openai_compat.rs:1131) ← 静默超时刷新连接池
provider open retry budget exhausted ← 重试预算耗尽(budget_ms)
MCP tool execution result is unknown; request was not replayed to avoid duplicate side
effects, and stdio recovery continues in the background3. Anthropic 原生 Prompt Caching
3.1 证据
cache_control / ephemeral / cache_read_input_tokens / cache_creation_input_tokens
redacted_thinking / thinking_delta / text_delta / signature_delta
message_start / content_block_start / content_block_delta / content_block_stop /
message_delta / message_stop
crates/atomcode-capabilities/src/provider/anthropic.rs(事件行 1038 / 438 / 473 / 449)cache_control 在 v5.0.9 中命中 0 次,是 v5.2.3 全新加入的事件枚举字段(位于 provider/anthropic.rs 的流事件枚举中)。v5.2.3 把 cache_read_input_tokens / cache_creation_input_tokens 提前到 thinking 事件之前 —— 流用量累计在事件分发层优先处理。 ephemeral 在二进制中仅作为 CLI 参数/WebUI 字段出现,非 Anthropic cache_control JSON 字面量 —— 断点类型常量以内联枚举/构造方式生成。
3.2 机制还原
| 特性 | 二进制证据 | 机制 |
|---|---|---|
| 4 个缓存断点 | add up to four cache breakpoints across tools, system and conversation history | 工具 / system / 对话历史各设断点 |
| 跳过 thinking | redacted_thinking / thinking_delta | 缓存跳过 thinking 块 |
| 保留签名 | signature_delta | 保序签名保留 |
| 命中统计 | cache_read_input_tokens | 缓存命中读取 tokens |
| 创建统计 | cache_creation_input_tokens | 缓存创建写入 tokens |
| 防重复计数 | Update cumulative streaming input and cache usage without double counting, retaining prior values when fields are absent | 缺失字段保留已有数值 |
| 前缀稳定 | the session's system prompt stays fixed, Plan mode notes and compaction summaries move out of it, and earlier file reads stay unchanged, so the prefix cache no longer collapses periodically | 固定 system prompt,Plan 笔记/压缩摘要移出 |
3.3 与 TUI 状态栏集成
✻ Done · 0ms · 1 轮 · 2 工具 · 880 tokens · 本轮缓存 33%
replay │ AtomCodeReverseEngineering │ 1.2K tok │ 缓存 33%
stats.cacheHit / cachedOnOff→ 回合结束条与状态栏实时显示缓存命中率。
4. 稳定缓存优化(Steadier Caching)
- **Steadier caching**: the session's system prompt stays fixed, Plan mode notes
and compaction summaries move out of it, and earlier file reads stay unchanged,
so the prefix cache no longer collapses periodically.→ 关键优化:system prompt 固定 + Plan 模式笔记 / 压缩摘要移出 system prompt + 早期文件读保持不变 → 前缀缓存不再周期性失效。
5. 与其他子系统的关系
- 会话事件化 支撑
/resume预览、Ctrl+D删除、/rewind代码回退 - 断流恢复 依赖 provider 客户端可替换(连接池重建)
- 缓存 与 TUI 状态栏、
stats.cacheHit集成
6. 相关配置项
network.upstream_retry_max_attempts ← 上游重试上限
ATOMCODE_STREAM_TIMEOUT_SECS ← 流式超时
ATOMCODE_FIRST_TOKEN_TIMEOUT_SECS ← 首 token 超时
coding.repeat_stop_rounds ← 重复调用熔断阈值(不再把等长任务误判死循环)7. 运行时验证记录
- daemon health 端点返回
capabilities: ["goal", "session_scoped_live"] --tui --demo显示本轮缓存 33%、缓存 33%状态栏