拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Claude Code核心引擎QueryEngine内幕:4.6万行代码如何实现LLM流式工具调用循环

Claude Code核心引擎QueryEngine内幕4.6万行代码如何实现LLM流式工具调用循环【免费下载链接】claude-codeClaude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.项目地址: https://gitcode.com/gh_mirrors/claudecode5/claude-codeClaude Code 是一个运行在终端里的 AI 智能体编程工具agentic coding tool它通过自然语言命令理解你的代码库、执行例行任务并处理 git 工作流。而让这一切运转起来的心脏就是核心引擎QueryEngine及其背后的流式工具调用循环。本文带你拆解这套引擎的设计它如何发起一次对话、如何流式接收 LLM 响应、如何在模型还在说话时就开始执行工具、又如何管理上下文与失败恢复——看完你会明白AI 在终端里自己干活到底是怎么实现的。引擎总览两层结构各司其职Claude Code 的查询引擎采用清晰的两层设计这是理解整个系统的关键层级文件职责生命周期会话层src/QueryEngine.ts一个会话conversation对应一个 QueryEngine 实例持有消息历史、Token 用量、文件缓存、权限拒绝记录等跨轮次状态贯穿整个会话轮次层src/query.ts处理单条用户消息的完整 agentic 循环调模型 → 跑工具 → 再调模型……直到模型不再请求工具单个 turn用一句话概括QueryEngine 管理一场对话query() 管理一次往返。会话层的 submitMessage() 是一个异步生成器AsyncGenerator负责组装系统提示词、处理斜杠命令、持久化会话记录然后把真正的重活委托给轮次层的 query()。主循环解剖一个 while(true) 状态机整个流式工具调用循环的骨架在 queryLoop()核心是一个while (true)循环L307。它不是简单的调一次 API 等结果而是一个状态机每轮迭代结束时根据模型输出决定是继续还是终止。循环携带的可变状态定义在 State 中包括当前消息列表、自动压缩追踪、输出 Token 恢复计数、轮次计数等。每轮迭代顶部分解状态L311-L321所有继续点统一写成state {...}的整体替换而不是零散赋值——这让循环中 7 个不同的 continue 分支都保持可追踪。每轮迭代按固定流水线推进上下文瘦身按顺序应用工具结果预算 → snip 裁剪 → 微压缩microcompact→ 上下文折叠 → 自动压缩autocompact详见下文上下文管理硬性上限检查Token 超出阻断线时直接返回blocking_limitL628-L648流式调用模型进入for await (deps.callModel(...))L659-L708执行工具消费工具结果流L1380-L1408附加物注入记忆预取结果、技能发现、排队命令、文件变更通知等作为 attachment 追加到本轮L1580-L1628决定去留needsFollowUp为真则拼接[...历史, ...助手消息, ...工具结果]进入下一轮L1715-L1727循环怎么知道该停了代码里有个很诚实的注释L553-L556stop_reason tool_use并不可靠不能作为唯一的退出信号。真正的信号是流式过程中是否出现了 tool_use 块——needsFollowUp标志位在流中实时设置流结束后若为 false则进入终止路径stop hooks 检查、Token 预算检查、return { reason: completed }。所有退出路径都通过Terminal原因显式化定义在 src/query/transitions.ts包括completed、aborted_streaming、aborted_tools、prompt_too_long、max_turns、stop_hook_prevented、blocking_limit等——每个原因都可被 SDK 消费者精确判断。流式 API 调用边收边干模型调用层在 src/services/api/claude.ts约 3400 行它把 Anthropic Messages API 的流式事件转译为引擎内部消息。循环内有三类值得注意的流式处理用量累计message_start/message_delta/message_stop事件分别触发用量重置、增量累计与总量归并QueryEngine.ts L788-L816最终汇入会话级totalUsage备用模型热切换若主模型高负载触发FallbackTriggeredError引擎会丢弃已流出的部分消息用 tombstone 消息从 UI 和转录中抹掉孤儿消息避免签名失效的 thinking 块污染历史然后用备用模型重放整个请求L893-L951可恢复错误的扣留prompt-too-long、媒体超限、max_output_tokens 这几类错误在流中先被 withhold暂不下发给 SDK 消费者等恢复机制压缩、重试判定失败后才真正抛出——防止桌面端等消费者看到中间错误就杀掉会话工具调用编排只读并发写入串行 ⚡模型一轮可能吐出多个 tool_use 块。它们不是傻乎乎地排队执行src/services/tools/toolOrchestration.ts 中的runTools()先用 partitionToolCalls() 分批只读工具如 Grep、Glob、文件读取由isConcurrencySafe()判定聚成一批并发执行默认并发上限 10可用CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY调整L8-L12写类工具编辑文件、跑 Bash 命令每个单独成批串行执行保证上下文变更按序生效更激进的是流式工具执行开启实验门控后StreamingToolExecutor 会在模型还在流式输出时就开始执行已完整的工具调用L837-L844——模型说 30 秒工具前 5 秒就跑完了。用户按下 CtrlC 中断时执行器还会为排队中的工具生成合成的 tool_result 块保证 API 协议上每个 tool_use 必有对应 tool_result的契约不被破坏L1015-L1029。上下文管理四层压缩流水线长会话必然撞上上下文窗口query.ts 内置了一整条渐进式瘦身流水线全部在每轮迭代开头按序执行顺序机制作用代码位置1工具结果预算按单条消息限制工具结果总大小过大内容替换为摘要L379-L3942Snip 裁剪按边界裁剪历史释放 TokenL401-L4103Microcompact对过期工具结果做微压缩L414-L4194Context Collapse折叠旧上下文为可读投影L440-L4475Auto-Compact全量摘要压缩插入 compact_boundary 消息L454-L535如果主动压缩都来不及、API 直接回了 413prompt too long还有被动恢复先排空已暂存的 context collapse再触发 reactive compact 全量摘要重试L1085-L1183。压缩成功后QueryEngine 会在边界处物理删除压缩前的消息以释放内存QueryEngine.ts L918-L942防止长时间 headless 会话内存泄漏。失败恢复与护栏不止是重试 ️循环对每一种失败都有明确的恢复策略这是这套引擎健壮性的来源输出截断max_output_tokens先用更高上限重放同一请求失败则注入一条直接续写不要道歉的元消息继续多轮恢复最多 3 次L1188-L1256MAX_OUTPUT_TOKENS_RECOVERY_LIMITStop Hooks模型结束回复后handleStopHooks() 可以拦截并注入阻塞错误让模型继续干活——但代码特别小心地避开了死循环API 错误消息不触发 hooks否则会出现错误 → 钩子拦截 → 重试 → 又错误的死亡螺旋L1258-L1306Token 预算checkTokenBudget() 允许按预算比例继续追加并带收益递减早停轮次上限maxTurns到达时发出max_turns_reached附件并终止L1704-L1712QueryEngine 层将其转译为error_max_turns结果USD 预算会话层在每条消息后检查累计费用超限立即返回error_max_budget_usdQueryEngine.ts L971-L1001SDK 与 REPL 共享同一引擎QueryEngine 是会话逻辑从ask()中抽离出来的独立类L175-L183同时服务 headless/SDK 路径与交互式 REPL。对外它只 yield 标准化的SDKMessage流系统初始化消息、助手/用户消息、压缩边界、重试通知、以及最终的result消息含耗时、轮数、总费用、用量明细、权限拒绝列表等。一次性调用的便捷包装 ask() 则负责构造引擎、委托submitMessage()并在结束时回收文件读取缓存。权限也是环环相扣的QueryEngine 在 canUseTool 外包了一层每次拒绝都被记录进permissionDenials随result消息上报给 SDK 消费者。核心文件导航 想继续深挖从这张地图出发文件行数说明src/QueryEngine.ts1297会话层状态持有、消息编排、预算与结果src/query.ts1730轮次层while(true) 主循环、恢复与终止src/services/api/claude.ts3420流式 API 调用层、事件转译、模型回退src/services/tools/toolOrchestration.ts189工具分批只读并发 / 写入串行src/services/tools/StreamingToolExecutor.ts531流式期间提前执行工具src/query/stopHooks.ts474结束钩子拦截并驱动模型继续src/query/tokenBudget.ts94轮次 Token 预算判定src/query/config.ts / src/query/deps.ts47 / 41运行配置快照与依赖注入可测试性关键src/Tool.ts794工具接口定义与查找得益于 src/query/deps.ts 的依赖注入设计callModel、microcompact、autocompact等重活都是可替换的依赖测试时可以轻松打桩——这也是这个上万行级核心循环能保持可维护性的重要原因。小结Claude Code 的 QueryEngine 展示了 agentic 循环工程的完整面貌生成器函数贯穿始终UI、SDK、持久化都能无阻塞地消费消息流、状态机显式化每个继续/终止分支、流式输出与工具执行重叠换取低延迟、多层渐进式上下文压缩对抗 Token 膨胀、扣留-恢复-兜底三段式处理可恢复错误。理解了这个while (true)循环你就握住了终端 AI 编程助手的心脏。【免费下载链接】claude-codeClaude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.项目地址: https://gitcode.com/gh_mirrors/claudecode5/claude-code创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门