Claude Code 源码笔记 -- State状态流转

张开发
2026/4/11 8:14:34 15 分钟阅读

分享文章

Claude Code 源码笔记 -- State状态流转
State 是 queryLoop 唯一的跨轮可变量所有记忆都在这里typeState{// 完整消息历史messages:Message[]// 工具上下文包含 AbortController、工具列表、agentId 等迭代内可能被更新toolUseContext:ToolUseContext// 自动压缩跟踪autoCompactTracking:AutoCompactTrackingState|undefined// max_output_tokens 恢复重试次数上限3maxOutputTokensRecoveryCount:number// 是否已尝试防止 reactive compact 陷入无限循环的守卫位hasAttemptedReactiveCompact:boolean// 临时 token 上限覆盖设置后下一轮将以 64k token 上限重试maxOutputTokensOverride:number|undefined// 异步预生成的工具摘要上一轮工具调用摘要的异步 Promise下一轮 yield 给前端pendingToolUseSummary:PromiseToolUseSummaryMessage|null|undefined// stop hook 是否活跃防止 hook 错误触发死循环stopHookActive:boolean|undefined// 当前轮次用于 maxTurns 限制检查turnCount:number// 上一轮 continue 的原因transition:Continue|undefined}迭代内临时变量这些变量每轮重新声明相当于当前轮的草稿纸// 流式收集本轮模型产生的所有 assistant 消息包括思考、文本、tool_useconstassistantMessages:AssistantMessage[][]// 工具执行完毕后的结果消息将作为下一轮模型的输入consttoolResults:(UserMessage|AttachmentMessage)[][]// 从流中提取的所有 tool_use 块决定本轮需要调用哪些工具consttoolUseBlocks:ToolUseBlock[][]// 只要流中出现了 tool_use 块就置为 true是有工具要执行的信号letneedsFollowUpfalse迭代末尾这些草稿被合并进持久状态:state.messages[...messagesForQuery,...assistantMessages,...toolResults]状态枚举继续循环以下场景触发state next; continue即不退出开始下一轮next_turn—— 正常推进触发条件模型输出了 tool_use工具执行完毕一切正常。 这是最常见的 continue 原因代表 agent 正在正常工作中。工具结果被追加到 messages 后进入下一轮让模型基于结果继续推理。collapse_drain_retry—— 上下文折叠恢复触发条件收到 HTTP 413prompt too long且 context collapse 功能开启且本轮并非已经从 collapse 中恢复过。 做法是将部分上下文折叠压缩释放空间然后用更短的 messages 重新请求模型不增加 turnCount。reactive_compact_retry—— 响应式压缩恢复触发条件收到 413 或媒体大小错误尝试对整个对话做一次 compact生成摘要替换历史。hasAttemptedReactiveCompact被设为 true确保此路径只走一次防止无限压缩。max_output_tokens_escalate—— 提升 token 上限触发条件模型输出被max_output_tokens截断且本轮还没有尝试过提升上限。 下一轮将以 64k tokens 的上限重试同样的请求。此路径只触发一次由maxOutputTokensOverride undefined守卫。max_output_tokens_recovery—— 注入恢复提示触发条件max_output_tokens 截断且 escalate 也没有解决或不适用。 向对话注入一条 meta 消息告知模型输出被截断直接继续不要道歉最多重试 3 次由maxOutputTokensRecoveryCount 3守卫。stop_hook_blocking—— Stop Hook 阻塞重试触发条件模型给出了正常响应非 API 错误stop hook 执行后发现有阻塞性错误需要反馈给模型。 将 hook 产生的错误消息追加到 messages让模型看到并修正。stopHookActive 被设为 true 以标记 hook 正在活跃。token_budget_continuation—— Token Budget 未耗尽触发条件TOKEN_BUDGET 功能开启模型给出了响应但 budget 检查认为还有配额应该继续。 向对话注入一条nudge消息引导模型继续输出直到 budget 耗尽或任务完成。状态枚举 退出循环以下场景触发return { reason: ... }循环终止blocking_limittoken 数量已经达到硬性上限且用户关闭了 autocompact。此时不允许继续输出错误消息后退出。这是一个安全阀为用户保留手动运行 /compact 的空间。model_error/image_error模型调用抛出了无法恢复的异常或图片大小超限且无法压缩恢复。aborted_streaming用户在模型流式输出过程中按下了中断CtrlC。aborted_tools用户在工具执行过程中中断。hook_stopped某个工具的 hook 明确返回了阻止继续的指令shouldPreventContinuation true。prompt_too_long收到 413且所有恢复手段collapse drain reactive compact都已用尽只能放弃。stop_hook_preventedstop hook 明确返回了preventContinuation: true通常表示某个外部策略要求停止。completed正常完成。分两种情况模型返回了 API 错误非 tool_use→ 上报 failure hook 后退出模型给出正常文本响应stop hook 无异议token budget 也耗尽或不需要继续 → 正常完成max_turnsturnCount超过了调用方传入的 maxTurns 上限。queryLoop 进入 │ ▼ 初始化 state第268行 turnCount1, transitionundefined │ ╔═════════════════════════════════════════════╗ ║ while(true) 循环体 ║ ║ ║ ║ Step 1: 消息预处理 ║ ║ snip截断过长历史 ║ ║ → microcompact轻量压缩 ║ ║ → contextCollapse上下文折叠 ║ ║ → autoCompacttoken超阈值时自动压缩 ║ ║ │ ║ ║ Step 2: blocking_limit 检查 ║ ║ token超限且autocompact关闭 ║ ║ 是 ──────────────────────────────► return ║ ║ │ 否 blocking_ ║ ║ Step 3: callModel() 流式调用 limit ║ ║ │ ║ ║ ┌─────▼──────────────────────┐ ║ ║ │ 内层 while(attemptWithFallback)│ ║ ║ │ 收集 assistantMessages │ ║ ║ │ 收集 toolUseBlocks │ ║ ║ │ 设置 needsFollowUptrue │ ║ ║ │ FallbackTriggeredError? │ ║ ║ │ → 切换模型continue(内层) │ ║ ║ └─────────────────────────────┘ ║ ║ │ ║ ║ 其他异常 ──────────────────────► return ║ ║ │ model_error ║ ║ 用户中断 ──────────────────────► return ║ ║ │ aborted_streaming ║ ║ │ ║ ║ ┌──────▼──────────────────────────────┐ ║ ║ │ needsFollowUp false? │ ║ ║ │ 模型没有产生 tool_use │ ║ ║ └──────┬──────────────────────────┬───┘ ║ ║ true │无工具 false │有工具║ ║ │ │ ║ ║ ┌───────▼──────────┐ ┌────────────▼──────┐ ║ ║ │ 停止条件分支 │ │ 工具执行分支 │ ║ ║ │ │ │ │ ║ ║ │ ①413恢复路径: │ │ runTools()执行 │ ║ ║ │ collapse_drain │ │ 所有 toolUseBlocks│ ║ ║ │ → continue │ │ │ ║ ║ │ reactive_compact│ │ 用户中断? │ ║ ║ │ → continue │ │ → return │ ║ ║ │ 都失败 → return │ │ aborted_tools │ ║ ║ │ │ │ │ ║ ║ │ ②max_output截断: │ │ hook阻止? │ ║ ║ │ escalate │ │ → return │ ║ ║ │ → continue │ │ hook_stopped │ ║ ║ │ recovery(×3) │ │ │ ║ ║ │ → continue │ │ maxTurns超限? │ ║ ║ │ 耗尽 → yield err │ │ → return │ ║ ║ │ │ │ max_turns │ ║ ║ │ ③API error? │ │ │ ║ ║ │ → return │ │ 一切正常: │ ║ ║ │ completed │ │ messages合并 │ ║ ║ │ │ │ turnCount │ ║ ║ │ ④stop hook检查: │ │ transition │ ║ ║ │ prevented │ │ next_turn │ ║ ║ │ → return │ │ statenext │ ║ ║ │ blocking │ │ → continue ────┐ │ ║ ║ │ → continue │ └────────────────│──┘ ║ ║ │ │ │ ║ ║ │ ⑤token budget: │ │ ║ ║ │ continue budget │ │ ║ ║ │ → continue │ │ ║ ║ │ done │ │ ║ ║ │ → return │ │ ║ ║ │ completed │ │ ║ ║ └──────────────────┘ │ ║ ║ │ return │ ║ ╚═════════╪═══════════════════════════════╪════╝ │ │ ▼ ┌──────────┘ 循环终止 │ 回到循环顶部 ▼ 解构新的 state 开始下一轮函数触发的状态流转callModel()驱动主循环通过流产生assistantMessages和toolUseBlocksrunTools()执行工具填充toolResults可触发aborted_tools/hook_stoppedhandleStopHooks()返回preventContinuation/blockingErrors触发stop_hook_*系列转换contextCollapse.recoverFromOverflow()触发collapse_drain_retryreactiveCompact.tryReactiveCompact()触发reactive_compact_retrycheckTokenBudget()触发token_budget_continuation或completedcalculateTokenWarningState()触发blocking_limitisMaxOutputTokensTruncated()触发max_output_tokens_escalate/recovery

更多文章