Agent 循环与查询引擎深度分析
本文基于
src/query.ts、src/QueryEngine.ts、src/query/*、src/services/tools/*等核心模块, 详细阐述 Codev (Claude Code) 的 Agent 循环架构、模型调用管道、工具调度机制、恢复策略与继续决策逻辑。 文中列出具体文件路径、函数名称与行号,供开发者快速定位代码。
目录
1. 主循环架构 (queryLoop)
1.1 概述
queryLoop() 是整个 Agent 的核心,它是一个 AsyncGenerator,运行在 query() 函数内部的 while (true) 无限循环中。每次迭代代表一个 turn(回合),包括:输入处理、模型调用、工具执行、后处理钩子、继续决策。
┌─────────────────────────────────────────────────────────────────┐
│ queryLoop (AsyncGenerator) │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Pre-model │──>│ Model │──>│ Tool │──>│ Stop │──> │
│ │ Context │ │Invocation│ │Dispatch │ │ Hooks │ │
│ │ Shaping │ │(Stream) │ │& Exec │ │(Post-turn)│ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ │ │ │ │ │
│ │ │ │ │ │
│ └──────────────┴──────────────┴──────────────┘ │
│ │ │
│ ┌─────▼──────┐ │
│ │ Continuation│ │
│ │ Decision │──> continue (loop again) │
│ └─────┬──────┘ │
│ │ stop │
│ ▼ │
│ return Terminal │
└─────────────────────────────────────────────────────────────────┘
文件: src/query.ts
query()函数: 第 219-239 行 — 公共入口,封装 queryLoop 并处理 consumedCommandUuidsqueryLoop()函数: 第 241-1729 行 — 主循环体QueryParams类型: 第 181-199 行 — 循环的输入参数State类型: 第 204-217 行 — 跨迭代的可变状态
1.2 五种核心阶段
每一个 turn 循环包含以下阶段:
阶段 A: Pre-model Context Shaping (第 365-548 行)
在调用模型之前,对消息列表进行一系列上下文压缩和优化:
- Tool Result Budget (第 376-394 行):
applyToolResultBudget()限制每个消息中 tool_result 的总大小,防止工具输出膨胀。 - Snip Compact (第 400-410 行):
snipCompactIfNeeded()— 被HISTORY_SNIP特性门控,裁剪历史消息中的冗余内容。 - Microcompact (第 413-426 行):
deps.microcompact()— 对连续工具结果进行微压缩,减小上下文体积。 - Context Collapse (第 440-447 行):
applyCollapsesIfNeeded()— 被CONTEXT_COLLAPSE门控,对历史消息进行投影式折叠。 - Auto-compact (第 454-543 行):
deps.autocompact()— 全自动上下文压缩,当 Token 数超过阈值时触发。 - Blocking Limit Check (第 628-648 行): 计算是否已达到硬性阻塞限制,阻止 API 调用并返回
blocking_limit。
阶段 B: Model Invocation (第 652-863 行)
见第 2 节详细分析。
阶段 C: Tool Dispatch & Execution (第 1360-1409 行)
- 如果启用
StreamingToolExecutor,使用getRemainingResults()处理流式工具结果 - 否则使用
runTools()执行工具(通过toolOrchestration.ts) - 工具结果被收集到
toolResults数组中
阶段 D: Stop Hooks (第 1267-1306 行)
handleStopHooks() 处理后处理管道(见第 4 节)。
阶段 E: Continuation Decision (第 1308-1357 行)
根据 token 预算、stop hooks 结果等决定是否继续循环。
1.3 状态管理
queryLoop 使用 State 类型(第 204-217 行)管理跨迭代的可变状态:
type State = {
messages: Message[]
toolUseContext: ToolUseContext
autoCompactTracking: AutoCompactTrackingState | undefined
maxOutputTokensRecoveryCount: number
hasAttemptedReactiveCompact: boolean
maxOutputTokensOverride: number | undefined
pendingToolUseSummary: Promise<ToolUseSummaryMessage | null> | undefined
stopHookActive: boolean | undefined
turnCount: number
transition: Continue | undefined
}
每次迭代开始时解构 state(第 311-321 行),在所有继续点(continue sites)通过 state = { ... }(第 1099-1116 行、第 1207-1221 行等)整体替换。
transition 字段记录上次迭代的继续原因,用于测试断言恢复路径是否正确触发。
2. 模型调用管道
2.1 callModel 实现
模型调用通过 deps.callModel()(第 659 行)进行,其类型为 typeof queryModelWithStreaming(src/query/deps.ts 第 23 行)。
queryDeps.ts (第 21-30 行) 定义了四种依赖:
callModel:typeof queryModelWithStreaming— 流式 API 调用microcompact:typeof microcompactMessages— 微压缩autocompact:typeof autoCompactIfNeeded— 自动压缩uuid:() => string— UUID 生成
productionDeps() (第 33-39 行) 提供生产环境实现。
2.2 流式事件处理
模型输出的流式事件在 for await (const message of deps.callModel({...})) 循环中处理(第 659-863 行):
| 事件类型 | 处理位置 | 说明 |
|---|---|---|
text_delta |
由 claude.ts 封装 | 文本增量 |
tool_use |
第 829-845 行 | 提取 tool_use 块,推入 toolUseBlocks |
content_block |
第 748-787 行 | 处理 content block,backfill tool_use input |
message_stop |
第 866-892 行 | 处理缓存的微压缩边界消息 |
关键逻辑:
- Backfill tool_use input (第 748-787 行): 当工具定义包含
backfillObservableInput时,对 tool_use 块进行输入回填(如展开文件路径)。 - Withhold 机制 (第 799-825 行): 可恢复的错误(prompt-too-long、max-output-tokens、media-size-error)在流中被扣留(withhold),不 yield 给调用方,直到恢复机制确认无法恢复后才暴露。
- Streaming Fallback (第 712-741 行): 当发生流式模型回退时,清空 previous assistant messages 和 tool results,创建新的 StreamingToolExecutor。
2.3 max_output_tokens 恢复机制
代码位置: 第 164 行、第 1188-1256 行
恢复步骤:
1. 第1次: 设置 maxOutputTokensOverride = ESCALATED_MAX_TOKENS (64K) 重试
(第 1194-1221 行, 仅当 capEnabled 且第一次)
2. 第2-4次: 注入恢复消息 "Output token limit hit. Resume directly..."
(第 1223-1252 行, 最多 3 次 = MAX_OUTPUT_TOKENS_RECOVERY_LIMIT)
3. 超出限制: 暴露扣留的错误消息并返回 (第 1254-1256 行)
如果用户设置了 CLAUDE_CODE_MAX_OUTPUT_TOKENS 环境变量,8K→64K 的自动升级会被跳过(第 1202 行)。
2.4 缓存控制
skipCacheWrite参数(第 192 行)— 传递给 API 调用选项(第 697 行),控制是否跳过缓存写入。pendingCacheEdits(第 423-425 行)—CACHED_MICROCOMPACT特性门控,在 API 响应后使用实际 API 报告的cache_deleted_input_tokens生成边界消息(第 870-892 行)。
3. 工具调度与流式执行
3.1 StreamingToolExecutor 架构
文件: src/services/tools/StreamingToolExecutor.ts
StreamingToolExecutor 是一个类(第 40-519 行),实现工具的流式执行调度。它在模型仍输出内容时就开始执行已到达的工具。
模型流式输出工具调用
│
▼
StreamingToolExecutor.addTool()
│
├── 并发安全工具(concurrency-safe)→ 并行执行
└── 非并发安全工具 → 独占执行
│
▼
收集结果 → getCompletedResults() / getRemainingResults()
核心数据结构
type TrackedTool = {
id: string
block: ToolUseBlock
assistantMessage: AssistantMessage
status: ToolStatus // 'queued' | 'executing' | 'completed' | 'yielded'
isConcurrencySafe: boolean
promise?: Promise<void>
results?: Message[]
pendingProgress: Message[]
contextModifiers?: Array<(context: ToolUseContext) => ToolUseContext>
}
并发控制
addTool()(第 76-124 行): 将工具加入队列,立即触发processQueue()。canExecuteTool()(第 129-135 行): 决定是否可以执行:- 如果没有正在执行的工具 → 总是可以
- 如果工具是并发安全的且所有正在执行的工具也是并发安全的 → 可以
- 否则 → 阻塞
processQueue()(第 140-150 行): 遍历队列,对每个 queued 工具检查执行条件。getCompletedResults()(第 412-440 行): 非阻塞收集已完成的结果,保持顺序(非并发工具会阻断后续工具的 yield)。getRemainingResults()(第 453-490 行): 等待所有工具完成,带进度唤醒。
Bash 错误级联
当 Bash 工具失败时(第 359-363 行),hasErrored 被置为 true,兄弟工具通过 siblingAbortController 被取消。这防止了在 mkdir 失败后继续执行依赖的命令。
进度通知
- BashProgress: Bash 工具执行的 stdout/stderr 增量更新
- AgentProgress: 子 agent 执行进度
- MCPProgress: MCP 工具执行的进度
进度消息通过 pendingProgress 队列立即 yield(第 368-374 行),并通过 progressAvailableResolve 信号唤醒 getRemainingResults()。
3.2 非流式工具执行 (runTools)
文件: src/services/tools/toolOrchestration.ts
当 StreamingToolExecutor 未启用时,使用 runTools() 函数(第 19-82 行)。
工具批处理分区
partitionToolCalls()(第 91-116 行)将工具调用分区为批次:
- 并发安全批次: 多个工具并行执行(通过
runToolsConcurrently()) - 非并发安全批次: 单个工具串行执行(通过
runToolsSerially())
最大并发数由 CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY 环境变量控制,默认为 10(第 8-12 行)。
4. Stop Hooks (后处理管道)
文件: src/query/stopHooks.ts
4.1 概要
handleStopHooks() 函数(第 65-473 行)在每一 turn 的模型响应结束后运行。它是一个 AsyncGenerator,yield 进度/附件消息,最终返回 StopHookResult。
type StopHookResult = {
blockingErrors: Message[] // 阻断性错误(钩子注入的消息)
preventContinuation: boolean // 是否阻止继续循环
}
4.2 执行流程
1. 保存 cacheSafeParams (第 96-98 行)
2. 模板作业分类 (第 108-132 行)
3. Prompt 建议 (第 139 行) [fire-and-forget]
4. Memory 提取 (第 141-153 行) [fire-and-forget]
5. Auto-dream (第 154-156 行) [fire-and-forget]
6. MCP 清理 (第 164-173 行)
7. executeStopHooks() (第 180 行) — 主钩子执行
8. Teammate hooks (第 335-453 行)
4.3 Stop Hooks 执行
executeStopHooks()(第 180 行)返回一个 generator,产生进度消息和阻断错误。
钩子结果处理(第 192-295 行):
- 进度消息 (第 201-215 行): 收集每个钩子的
command和promptText - 阻断错误 (第 257-267 行): 创建
createUserMessage({ isMeta: true })作为阻断消息 - 继续阻止 (第 269-280 行): 生成
hook_stopped_continuation附件 - 中止检测 (第 283-294 行): 如果被中止,返回
{ preventContinuation: true }
4.4 后台任务
| 任务 | 位置 | 说明 |
|---|---|---|
executePromptSuggestion() |
第 139 行 | 生成提示建议(仅非 bare 模式) |
executeExtractMemories() |
第 141-153 行 | 提取记忆(EXTRACT_MEMORIES 门控) |
executeAutoDream() |
第 154-156 行 | 自动记忆整理 |
cleanupComputerUseAfterTurn() |
第 164-173 行 | MCP 计算机使用清理(CHICAGO_MCP 门控) |
4.5 模板作业分类
当设置了 CLAUDE_JOB_DIR 环境变量时(第 110 行),jobClassifierModule!.classifyAndWriteState()(第 121 行)在每次 turn 后分类作业状态。加 60 秒超时(第 127-131 行)。
4.6 Teammate Hooks
在 teammate 模式下(第 335 行):
- TaskCompleted hooks (第 345-400 行): 对每个
in_progress且属于当前 teammate 的任务执行executeTaskCompletedHooks()。 - TeammateIdle hooks (第 402-441 行): 执行
executeTeammateIdleHooks()。
这两个钩子都支持 preventContinuation 和 blockingErrors。
4.7 阻断错误与继续抑制
blockingErrors: 由钩子注入的系统消息,作为当前 turn 的继续输入(第 1282-1306 行)preventContinuation: 立即结束循环返回stop_hook_prevented(第 1278 行)- 错误免入死亡螺旋 (第 1260-1264 行): 当 lastMessage 是 API 错误时,跳过 stop hooks
5. 继续决策
文件: src/query/tokenBudget.ts
5.1 checkTokenBudget
function checkTokenBudget(
tracker: BudgetTracker,
agentId: string | undefined,
budget: number | null, // getCurrentTurnTokenBudget()
globalTurnTokens: number, // getTurnOutputTokens()
): TokenBudgetDecision
第 45-93 行。
5.2 决策逻辑
1. 跳过条件: agentId 存在 OR budget 为 null/0 → stop (第 51-53 行)
2. 计算使用率 pct = turnTokens / budget * 100 (第 56 行)
3. 收益递减检测: 连续 3+ 次继续且每次增量 < 500 tokens (第 59-62 行)
4. 如果 pct < 90% 且非收益递减 → continue (第 66-75 行)
5. 否则 → stop (第 78-92 行)
5.3 90% 阈值
COMPLETION_THRESHOLD = 0.9(第 3 行): 当 token 消耗达到预算的 90% 时触发继续。
5.4 收益递减检测
DIMINISHING_THRESHOLD = 500(第 4 行): 当连续 3+ 次继续且每次增量 < 500 tokens,认为模型收益递减,提前停止。
5.5 集成到 queryLoop
在 queryLoop 中(src/query.ts 第 1308-1355 行):
if (feature('TOKEN_BUDGET')) {
const decision = checkTokenBudget(budgetTracker!, ...)
if (decision.action === 'continue') {
// 注入 nudgemessage
// incrementBudgetContinuationCount()
// 设置 state.transition = { reason: 'token_budget_continuation' }
// continue (继续循环)
}
// 否则记录 completionEvent
}
// return { reason: 'completed' }
5.6 任务预算 (taskBudget)
taskBudget(src/query.ts 第 197-198 行)是 API 端的 task_budget(output_config.task_budget, beta task-budgets-2026-03-13)。与 tokenBudget +500k 自动继续的不同。
- 在每次压缩后计算
taskBudgetRemaining(第 508-515 行、第 1138-1146 行) - 传递给 API 调用(第 699-706 行)
6. 恢复机制
6.1 max_output_tokens 恢复
文件: src/query.ts
| 恢复阶段 | 触发条件 | 行为 | 行号 |
|---|---|---|---|
| 8K→64K 升级 | 首次命中上限,capEnabled 且无用户自定义 | 设置 maxOutputTokensOverride=64K,重试 | 第 1194-1221 行 |
| 恢复消息注入 | 已升级或 cap 关闭 | 注入 "Output token limit hit" 消息 | 第 1223-1252 行 |
| 限制耗尽 | 超过 3 次 | 暴露扣留的错误 | 第 1254-1256 行 |
MAX_OUTPUT_TOKENS_RECOVERY_LIMIT = 3(第 164 行)。
6.2 Context Collapse 压缩
文件: src/query.ts
当 API 返回 prompt-too-long 错误时(第 1085-1118 行):
- 首先尝试
contextCollapse.recoverFromOverflow()(第 1094 行) — 从已分阶段(staged)的折叠队列中释放 - 如果已经尝试过
collapse_drain_retry(第 1092 行),则跳过直接走 reactive compact
6.3 Reactive Compact
文件: src/query.ts
当 prompt-too-long 错误和 reactive compact 都启用时(第 1119-1175 行):
- 调用
reactiveCompact.tryReactiveCompact()(第 1120 行) - 成功→构建压缩消息,设置
hasAttemptedReactiveCompact = true - 失败→暴露错误消息
6.4 错误恢复策略总结
API 413 (prompt too long)
├── Context Collapse drain (第 1094 行)
│ └── 失败→ fall through
├── Reactive Compact (第 1120 行)
│ └── 失败→ 返回 prompt_too_long
└── (如果两者都不可用) → 返回 blocking_limit
max_output_tokens
├── 8K→64K escalate (第 1194 行)
├── 恢复消息注入 x3 (第 1223 行)
└── 暴露错误 (第 1254 行)
model fallback (第 893-953 行)
└── 切换到备用模型,清理并重试
一般错误 (第 955-997 行)
└── yield 错误消息,返回 model_error
7. QueryEngine.ts 的角色
文件: src/QueryEngine.ts
7.1 概述
QueryEngine 类(第 184-1177 行)封装了查询生命周期和会话状态,是 ask() 函数的核心引擎。它提取了在 headless/SDK 和 REPL 间共享的逻辑。
7.2 与 query.ts 的关系
ask() 函数 QueryEngine.submitMessage() 方法
│ │
│ 创建 QueryEngine 实例 │
│ (第 1249-1285 行) │
│ │
└─── query() ────────────────────────────┘
│
│ AsyncGenerator
▼
yield 消息流 (assistant/user/attachment/stream_event/...)
ask()(第 1186-1295 行)是一个便利包装器,创建QueryEngine实例并调用submitMessage()QueryEngine.submitMessage()(第 209-1156 行)处理完整的查询生命周期:- 构建
ProcessUserInputContext(第 335-395 行) - 处理用户输入(第 410-428 行)
- 记录 transcript(第 450-463 行)
- 调用
query()(第 675-686 行) - 处理 query 产出的所有消息类型(第 757-969 行)
- 生成最终 result(第 1082-1155 行)
- 构建
7.3 关键职责
- 消息持久化:
recordTranscript()(第 717-732 行) - 权限跟踪:
wrappedCanUseTool()包装(第 244-271 行)记录权限拒绝 - SDK 消息规范化:
normalizeMessage()(第 769、783、787 行) - 预算检查: USD 预算(第 972-1002 行)和结构化输出重试限制(第 1005-1048 行)
- Snip 回放:
snipReplay回调(第 905-914 行)在 SDK 模式下处理 snip 边界
7.4 submitMessage 的消息处理
submitMessage() 的 for await 循环处理 10+ 种消息类型:
| 消息类型 | 处理 | 行号 |
|---|---|---|
assistant |
push 到 mutableMessages,yield 规范化 | 第 761-769 行 |
user |
push,yield 规范化,turnCount++ | 第 753-787 行 |
progress |
push,记录 transcript | 第 771-783 行 |
stream_event |
累积 usage,跟踪 stop_reason | 第 788-827 行 |
attachment |
处理结构化输出、max_turns、queued_command | 第 829-893 行 |
system |
处理 compact_boundary、api_error、snip | 第 897-958 行 |
tool_use_summary |
yield 工具使用摘要 | 第 959-969 行 |
8. 工具执行引擎
文件: src/services/tools/toolExecution.ts
8.1 工具执行九步生命周期
runToolUse() 函数(第 337-490 行)实现工具的完整执行生命周期:
1. Tool Lookup & Validation
│ findToolByName() (第 345 行)
│ 别名回退 (第 350-355 行)
▼
2. Abort Check
│ abortController.signal.aborted (第 415 行)
▼
3. Input Validation (Zod)
│ tool.inputSchema.safeParse() (第 615 行)
▼
4. Custom Validation
│ tool.validateInput() (第 683 行)
▼
5. Pre-Tool Hooks
│ runPreToolUseHooks() (第 800 行)
▼
6. Permission Check & User Confirmation
│ resolveHookPermissionDecision() (第 921 行)
│ canUseTool() (第 927 行)
▼
7. Tool Execution
│ tool.call() (第 1207 行)
▼
8. Result Processing
│ tool.mapToolResultToToolResultBlockParam() (第 1292 行)
│ processToolResultBlock() (第 1415 行)
▼
9. Post-Tool Hooks
│ runPostToolUseHooks() (第 1483 行)
│ runPostToolUseFailureHooks() (第 1700 行)
8.2 详细步骤解析
步骤 1-2: 工具查找与中止检查
runToolUse()(第 337-490 行):
// 1. 查找工具 (第 345-355 行)
let tool = findToolByName(toolUseContext.options.tools, toolName)
if (!tool) {
// 通过别名回退 (第 350-355 行)
}
// 2. 中止检查 (第 415-453 行)
if (toolUseContext.abortController.signal.aborted) {
// yield "cancelled" 消息
}
步骤 3-4: 输入验证
checkPermissionsAndCallTool()(第 599-1745 行):
Zod Schema 验证(第 615-679 行):
tool.inputSchema.safeParse(input)使用 Zod 验证模型输入- 失败时生成格式化的 Zod 错误并附加 schema-not-sent 提示(第 578-597 行)
buildSchemaNotSentHint(): 检测到延迟工具(deferred tool)的 schema 没有被发送到 API 时,提示模型使用 ToolSearch 重新加载
自定义验证(第 683-733 行):
- 每个工具可以定义自己的
validateInput()方法 - 验证失败返回
isValidCall.result === false
步骤 5: Pre-Tool Hooks
文件: src/services/tools/toolHooks.ts
runPreToolUseHooks()(第 435-650 行):
返回多类型结果:
| 结果类型 | 说明 |
|---|---|
message |
进度消息或附件消息 |
hookPermissionResult |
钩子做出的权限决定 (allow/deny/ask) |
hookUpdatedInput |
钩子修改后的输入 (passthrough) |
preventContinuation |
阻止继续 |
stopReason |
停止原因 |
additionalContext |
额外的上下文消息 |
stop |
立即停止 |
步骤 6: 权限检查
文件: src/services/tools/toolHooks.ts
resolveHookPermissionDecision()(第 332-433 行):
- Hook allow: 仍然检查 settings.json 的 deny/ask 规则(第 373-385 行)
- Hook deny: 直接拒绝(第 408-411 行)
- 无钩子决定: 走正常权限流程,可能包含 forceDecision(第 413-432 行)
- 需用户交互: 钩子批准后如果
requiresUserInteraction()或requireCanUseTool,仍调用canUseTool()(第 356-370 行)
canUseTool 在 src/hooks/useCanUseTool.tsx 中实现(React hook),处理 interactive/coordinator/swarm 三种权限模式。
步骤 7: 工具执行
tool.call()(第 1207 行):
- 使用处理后的输入调用工具
- 通过
onToolProgress回调报告进度 - 使用
toolAbortController(第 301 行)实现 per-tool 取消
Bash 错误级联(第 359-363 行):
if (tool.block.name === BASH_TOOL_NAME) {
this.hasErrored = true
this.siblingAbortController.abort('sibling_error')
}
步骤 8: 结果处理
tool.mapToolResultToToolResultBlockParam()(第 1292 行)映射工具结果processPreMappedToolResultBlock()/processToolResultBlock()(第 1409-1415 行)进行后处理applyToolResultBudget()(第 379 行)限制工具结果大小
步骤 9: Post-Tool Hooks
文件: src/services/tools/toolHooks.ts
runPostToolUseHooks()(第 39-191 行):
- 对 MCP 工具,支持
updatedMCPToolOutput - 支持
blockingError、preventContinuation、additionalContext
runPostToolUseFailureHooks()(第 193-319 行):
- 工具失败时执行
- 同样支持
blockingError、preventContinuation、additionalContext
8.3 错误分类与处理
classifyToolError()(第 150-171 行)将错误分类为安全的 telemetry 字符串:
TelemetrySafeError: 使用预审的 telemetryMessage- Node.js
errno错误: 记录ENOENT等代码 - 已知错误类型: 使用构造函数名称
- 未知错误: 降级为
"Error"
8.4 工具遥测
工具执行的每个阶段都会发出遥测事件:
| 事件 | 触发时机 | 代码位置 |
|---|---|---|
tengu_tool_use_error |
工具不存在 | 第 372 行 |
tengu_tool_use_cancelled |
工具被取消 | 第 416 行 |
tengu_tool_use_progress |
进度更新 | 第 523 行 |
tengu_tool_use_can_use_tool_rejected |
权限拒绝 | 第 1001 行 |
tengu_tool_use_can_use_tool_allowed |
权限批准 | 第 1105 行 |
tengu_tool_use_success |
工具执行成功 | 第 1331 行 |
tool_decision (OTel) |
权限决策 | 第 962 行 |
tool_result (OTel) |
工具结果 | 第 1381 行 |
9. 参考文件索引
| 文件 | 路径 | 核心内容 |
|---|---|---|
| 主查询循环 | src/query.ts |
query(), queryLoop(), 完整 Agent 循环 |
| 查询配置 | src/query/config.ts |
buildQueryConfig(), QueryConfig 类型 |
| 查询依赖 | src/query/deps.ts |
QueryDeps, productionDeps() |
| 停止钩子 | src/query/stopHooks.ts |
handleStopHooks(), StopHookResult |
| Token 预算 | src/query/tokenBudget.ts |
checkTokenBudget(), BudgetTracker |
| 转换类型 | src/query/transitions.ts |
Terminal, Continue 类型 |
| 查询引擎 | src/QueryEngine.ts |
QueryEngine 类, ask() 函数 |
| 工具流式执行器 | src/services/tools/StreamingToolExecutor.ts |
StreamingToolExecutor 类 |
| 工具执行 | src/services/tools/toolExecution.ts |
runToolUse(), checkPermissionsAndCallTool() |
| 工具编排 | src/services/tools/toolOrchestration.ts |
runTools(), partitionToolCalls() |
| 工具钩子 | src/services/tools/toolHooks.ts |
runPreToolUseHooks(), runPostToolUseHooks(), resolveHookPermissionDecision() |
| 权限检查 | src/hooks/useCanUseTool.tsx |
useCanUseTool() React hook, 权限模式 |