Claude Code 架构解析:QueryEngine

发布于 — 2026 年 03 月 31 日

基于 Claude Code 源码的深度分析,深入解析其核心引擎 QueryEngine 的设计哲学与实现细节。

一、整体架构概览

Claude Code 是一个基于终端的 AI 编程助手,采用管道模型

flowchart LR
    A["用户输入"] --> B["CLI 解析器"]
    B --> C["QueryEngine"]
    C --> D["LLM API"]
    D --> E{"需要工具?"}
    E -->|是| F["工具执行循环"]
    E -->|否| G["终端 UI"]
    F --> D
    G --> H["输出"]
    F -->|结果注入| C

整个项目规模庞大:

  • ~1,900 个文件
  • 512,000+ 行 TypeScript 代码
  • 使用 Bun 作为运行时
  • UI 层基于 React + Ink(React 的终端版本)

关键目录结构

src/
├── QueryEngine.ts       # 核心引擎 (~46K 行)
├── query.ts             # 查询循环实现 (~67K 行)
├── Tool.ts              # 工具基类 (~28K 行)
├── main.tsx             # CLI 入口 (~800K)
├── tools/               # 所有工具实现 (~40+ 工具)
├── commands/            # 斜杠命令系统
├── bridge/              # IDE 桥接层 (VS Code/JetBrains)
├── services/            # 服务层
│   ├── api/            # Anthropic API 客户端
│   ├── mcp/             # MCP 协议客户端
│   ├── compact/         # 对话压缩
│   └── ...
├── entrypoints/         # 入口点 (CLI/SDK/MCP)
└── server/              # Web 服务器

二、QueryEngine 详解

2.1 核心定位

QueryEngine 是 Claude Code 的心脏,它管理整个对话生命周期——从接收用户输入到流式返回响应,再到工具调用循环。

文件位置: src/QueryEngine.ts (~1,300 行核心代码,不含 query.ts)

2.2 类结构

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
export class QueryEngine {
  private config: QueryEngineConfig        // 配置
  private mutableMessages: Message[]        // 可变消息历史
  private abortController: AbortController   // 中断控制器
  private permissionDenials: SDKPermissionDenial[]  // 权限拒绝记录
  private totalUsage: NonNullableUsage       // 总使用量统计
  private readFileState: FileStateCache     // 文件读取缓存
  private discoveredSkillNames: Set<string> // 发现的技能
  private loadedNestedMemoryPaths: Set<string>  // 加载的嵌套内存路径

  async *submitMessage(prompt, options): AsyncGenerator<SDKMessage>
  interrupt(): void
  getMessages(): readonly Message[]
  getReadFileState(): FileStateCache
  getSessionId(): string
  setModel(model: string): void
}

2.3 submitMessage 执行流程

flowchart TD
    A["submitMessage()"] --> B["processUserInput"]
    B --> C["处理斜杠命令 /review /commit 等"]
    B --> D["附件处理"]
    B --> E["权限规则更新"]

    E --> F["fetchSystemPromptParts"]
    F --> G["构建系统提示"]
    F --> H["加载技能 & 插件"]

    H --> I["buildSystemInitMessage"]
    I --> J["进入 query() 循环"]

    J --> K{"API 速率限制?"}
    K -->|是| L["指数退避重试"]
    L --> M["调用 LLM API"]
    K -->|否| M

    M --> N{"需要工具?"}
    N -->|是| O["runTools() 执行工具"]
    O --> P["工具结果注入消息"]
    P --> J
    N -->|否| Q["返回 SDKResultMessage"]

    Q --> R["成功/错误状态"]
    R --> S["Token 使用量"]
    S --> T["权限拒绝记录"]

2.4 查询循环 (query.ts)

src/query.ts (~1,731 行) 是 QueryEngine 的核心,包含真正的 LLM 调用循环

flowchart LR
    subgraph 循环体
        A["turnCount++"] --> B{"检查上下文长度"}
        B -->|超限| C["AutoCompact 压缩"]
        B -->|正常| D["callModel() 流式调用 LLM"]
        C --> D
        D --> E{"解析响应类型"}
        E -->|text/thinking| F["yield 流式消息"]
        E -->|tool_use| G["needsFollowUp = true"]
        F --> H{"继续?"}
        G --> H
        H -->|是| A
        H -->|否| I["返回 completed"]
    end
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
export async function* query(
  params: QueryParams,
): AsyncGenerator<StreamEvent | Message | Terminal> {
  // 循环状态
  let state: State = {
    messages: params.messages,
    toolUseContext: params.toolUseContext,
    autoCompactTracking: undefined,
    maxOutputTokensRecoveryCount: 0,
    turnCount: 1,
    // ...
  }

  while (true) {
    // 1. 上下文压缩检查
    const { compactionResult } = await deps.autocompact(...)

    // 2. 调用 LLM API (流式)
    for await (const message of deps.callModel({...})) {
      // 处理 text, thinking, tool_use 块
      yield message
    }

    // 3. 工具执行循环
    if (needsFollowUp) {
      for await (const update of runTools(...)) {
        yield update.message
      }
    }

    // 4. 检查终止条件
    if (!needsFollowUp) {
      return { reason: 'completed' }
    }

    // 5. 循环继续
    state = { ...state, turnCount: state.turnCount + 1 }
  }
}

2.5 关键设计模式

1. AsyncGenerator 模式

QueryEngine 使用 AsyncGenerator 实现流式响应

1
2
3
4
5
6
7
async *submitMessage(prompt): AsyncGenerator<SDKMessage> {
  // 每次 LLM 输出一个 content block 就 yield
  for await (const message of query({...})) {
    yield normalizeMessage(message)  // 实时流式返回
  }
  yield { type: 'result', ... }  // 最终结果
}

2. 工具调用循环

当 LLM 返回 tool_use 块时,进入工具执行阶段:

sequenceDiagram
    participant LLM
    participant QueryEngine
    participant ToolOrchestration
    participant Tool

    LLM->>QueryEngine: tool_use block
    QueryEngine->>ToolOrchestration: runTools(toolUseBlocks)
    ToolOrchestration->>Tool: execute(input, context)
    Tool-->>ToolOrchestration: ToolResult
    ToolOrchestration-->>QueryEngine: ToolUpdate stream
    QueryEngine->>LLM: 工具结果注入下一轮对话
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// 从流中提取 tool_use 块
const toolUseBlocks = message.message.content.filter(
  c => c.type === 'tool_use'
) as ToolUseBlock[]

// 执行工具
const toolUpdates = runTools(toolUseBlocks, ...)

// 将结果注入下一轮对话
messagesForQuery = [...messagesForQuery, ...assistantMessages, ...toolResults]

3. 错误恢复机制

QueryEngine 实现了多层错误恢复

错误类型恢复策略
API 速率限制指数退避重试
模型降级自动切换到 fallback 模型
Prompt 太长触发上下文压缩 (AutoCompact)
Max Output Tokens自动扩展到 64k
工具权限拒绝记录并跳过

4. 上下文压缩 (AutoCompact)

当对话过长时,自动压缩历史消息:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
const { compactionResult } = await deps.autocompact(
  messagesForQuery,
  toolUseContext,
  { systemPrompt, userContext, ... },
  querySource,
  tracking,
  snipTokensFreed,
)

// 压缩后继续对话
messagesForQuery = postCompactMessages

2.6 配置选项

QueryEngine 接受丰富的配置:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
export type QueryEngineConfig = {
  cwd: string
  tools: Tools
  commands: Command[]
  mcpClients: MCPServerConnection[]
  agents: AgentDefinition[]
  canUseTool: CanUseToolFn
  initialMessages?: Message[]
  readFileCache: FileStateCache
  customSystemPrompt?: string
  appendSystemPrompt?: string
  userSpecifiedModel?: string
  fallbackModel?: string
  thinkingConfig?: ThinkingConfig
  maxTurns?: number
  maxBudgetUsd?: number
  taskBudget?: { total: number }
  jsonSchema?: Record<string, unknown>
  verbose?: boolean
  replayUserMessages?: boolean
  includePartialMessages?: boolean
  setSDKStatus?: (status: SDKStatus) => void
  abortController?: AbortController
  orphanedPermission?: OrphanedPermission
  snipReplay?: SnipReplayFn  // 历史裁剪回调
}

三、三层架构:Agent / Session / Query

Claude Code 的会话模型分为三层:

flowchart BT
    subgraph Agent层
        A1["claudeCodeGuideAgent"]
        A2["exploreAgent"]
        A3["planAgent"]
        A4["verificationAgent"]
    end

    subgraph Session层
        S["SessionManager"]
        S -->|"管理状态"| A
        S -->|"管理历史"| M["Message History"]
    end

    subgraph Query层
        Q["QueryEngine.query()"]
        Q -->|"每次调用"| T["Tool Execution Loop"]
        Q -->|"Token 预算"| B["Budget Tracking"]
    end

    S --> Q
    Q --> A

3.1 Agent 层 (src/tools/AgentTool/)

Agent 是可复用的子任务执行单元

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// 内置 Agent 类型
export type BuiltInAgentDefinition = {
  source: 'built-in'
  getSystemPrompt: (params) => string
  callback?: () => void
}

// 自定义 Agent (从 .md 文件加载)
export type CustomAgentDefinition = {
  source: 'user' | 'project' | 'policySettings'
  getSystemPrompt: () => string
  filename?: string
  baseDir?: string
}

内置 Agent

  • claudeCodeGuideAgent - Claude Code 使用指南
  • exploreAgent - 代码探索
  • planAgent - 任务规划
  • verificationAgent - 代码验证

3.2 Session 层

Session 管理会话状态和历史

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// SessionStore - Web 服务器端会话管理
export class SessionManager {
  private store: SessionStore
  private maxSessions: number
  private rateLimiter: UserHourlyRateLimiter

  create(ws, cols, rows, user?): string | null
  resume(token, ws, cols, rows): boolean
  destroySession(token): void
}

3.3 Query 层

Query 是单次 LLM 调用的完整生命周期

  • 从用户输入到最终响应
  • 包含工具调用循环
  • 管理 Token 使用和预算
  • 处理错误和恢复

四、工具系统

4.1 工具定义

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// src/Tool.ts
export type Tool = {
  name: string
  description: string
  inputSchema: ZodSchema
  permissionModel: PermissionModel
  execute: (input, context) => Promise<ToolResult>
  render?: (input, result) => React.ReactNode
  isConcurrencySafe?: () => boolean
}

4.2 工具执行

1
2
3
4
5
6
7
// src/services/tools/toolOrchestration.ts
export async function* runTools(
  toolUseBlocks: ToolUseBlock[],
  assistantMessages: AssistantMessage[],
  canUseTool: CanUseToolFn,
  toolUseContext: ToolUseContext,
): AsyncGenerator<ToolUpdate>

五、MCP (Model Context Protocol)

Claude Code 同时是 MCP ClientMCP Server

flowchart LR
    subgraph Claude Code
        Client["McpClient"] -->|"调用工具"| Server["McpServer"]
    end

    subgraph 外部 MCP Server
        E1["文件系统 MCP"]
        E2["Git MCP"]
        E3["数据库 MCP"]
    end

    Client --> E1
    Client --> E2
    Client --> E3

    External["外部 IDE"] --> Server
    Server -->|"暴露工具"| External
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// Client: 消费外部 MCP 工具
export class McpClient {
  async connect(config: McpServerConfig): Promise<void>
  async listTools(): Promise<McpTool[]>
  async callTool(name: string, args: object): Promise<ToolResult>
}

// Server: 暴露 Claude Code 工具给外部
// src/entrypoints/mcp.ts
export async function startMcpServer() {
  // 实现 MCP 协议
}

六、权限系统

Claude Code 实现了集中式权限管理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// 权限模式
export type PermissionMode =
  | 'default'      // 每个操作都询问
  | 'plan'         // 一次询问整个执行计划
  | 'bypassPermissions'  // 自动批准 (危险)
  | 'auto'         // ML 分类器自动决策

// 权限规则示例
Bash(git *)           // 允许所有 git 命令
FileEdit(/src/*)      // 允许编辑 src 目录

七、状态管理

使用 React Context + 自定义 Store 模式:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// 全局状态
export type AppState = {
  toolPermissionContext: ToolPermissionContext
  fileHistory: FileHistoryState
  attribution: AttributionState
  mcp: McpState
  // ...
}

// Context Providers
export const NotificationContext = createContext<NotificationContext>(null)
export const OverlayContext = createContext<OverlayContext>(null)

八、构建系统

8.1 特性开关 (Dead Code Elimination)

1
2
3
4
5
import { feature } from 'bun:bundle'

if (feature('VOICE_MODE')) {
  const voiceCommand = require('./commands/voice/index.js').default
}

8.2 懒加载

1
2
3
4
// 重量级模块延迟加载
const reactiveCompact = feature('REACTIVE_COMPACT')
  ? require('./services/compact/reactiveCompact.js')
  : null

总结

Claude Code 的架构设计体现了几个核心原则:

  1. 流式优先 - AsyncGenerator 模式让响应实时可见
  2. 容错设计 - 多层错误恢复保证对话不中断
  3. 可扩展性 - 工具、Agent、命令都支持插件化
  4. 资源管理 - Token 预算和上下文压缩控制成本
  5. 模块化 - 清晰的层次划分 (Agent → Session → Query)