Query Engine 是 Claude Code 的系统心脏。真正把“用户输入”变成“多轮 agent 执行”的,是 QueryEngine 和 query.ts 这条主干。
src/QueryEngine.ts会话级控制器src/query.ts回合执行循环src/query/config.tsquery 配置src/query/tokenBudget.tstoken budget 管理src/query/stopHooks.ts回合结束后的 stop hookssrc/services/compact/*compact 相关逻辑
flowchart TB
Submit[submitMessage]
Engine[QueryEngine]
Q[query.ts]
API[Claude API]
Tools[toolOrchestration]
Compact[compact/reactive compact]
Stop[stop hooks]
Persist[session storage]
Submit --> Engine
Engine --> Q
Q --> API
API --> Tools
Tools --> Q
Q --> Compact
Q --> Stop
Engine --> Persist
更偏会话级编排:
- 持有
mutableMessages - 持有
readFileState - 累积
totalUsage - 管理 abort controller
- 负责与 session storage、SDK 兼容层对接
更偏单次 turn 的执行状态机:
- 请求前上下文处理
- 流式响应消费
- tool_use 检测
- tool_result 回填
- compact/recovery
- stop hook 执行
sequenceDiagram
participant U as User
participant E as QueryEngine
participant Q as query.ts
participant API as Claude API
participant T as Tools
U->>E: submitMessage(...)
E->>Q: query(params)
Q->>API: send request
API-->>Q: stream assistant blocks
Q->>Q: detect tool_use
Q->>T: runTools(...)
T-->>Q: tool_result
Q->>API: continue next iteration
Q-->>E: final messages / usage / events
src/query.ts 中维护了显式状态:
- messages
- toolUseContext
- autoCompactTracking
- recovery count
- transition reason
- turn count
这意味着 Claude Code 每回合都可能进入不同分支:
- 正常结束
- 工具调用继续
- prompt too long 恢复
- max_output_tokens 恢复
- auto compact
- reactive compact
- stop hooks
因此它绝不是一次 request-response 的轻量 wrapper。
compact 不是离线工具,而是 query loop 的内建能力。
相关能力包括:
- auto compact
- reactive compact
- micro compact
- snip compact
它们的目的都是在不破坏会话连续性的前提下,把上下文压到可继续运行的范围内。
query.ts 一旦收到 tool_use,不会直接结束,而是:
- 调用
runTools() - 把结果封成
tool_result - 追加回消息链
- 再次向模型发请求
这就是 Claude Code 变成 agent runtime 的核心闭环。
当一轮真正结束时,query/stopHooks.ts 会被触发,处理如:
- 自动记忆提取
- auto dream
- 其它回合结束后动作
所以 stop hooks 是 query loop 的“尾插阶段”。
重点看:
QueryEngineConfigsubmitMessage()- 内部会话状态字段
重点看:
query()queryLoop()- tool loop
- compact / recovery 分支
- 会话级状态与回合级状态分离
- 工具调用天然是多轮循环的一部分
- compact、budget、hooks 都内建在主循环
- 既能服务 REPL,也能服务 headless/SDK
建议打开源码时同时对照:
QueryEngine.tsquery.tsservices/tools/toolOrchestration.tsservices/compact/*query/stopHooks.ts