QueryEngine 编排器
概述
QueryEngine 是 query() 函数之上的高层编排器,负责管理会话级别的状态:消息历史、系统提示词组装、文件快照、权限跟踪等。
Source:
src/QueryEngine.ts(1320 行)
类定义
typescript
// Source: src/QueryEngine.ts:186-209
export class QueryEngine {
private config: QueryEngineConfig
private mutableMessages: Message[]
private abortController: AbortController
private permissionDenials: SDKPermissionDenial[]
private totalUsage: NonNullableUsage
private hasHandledOrphanedPermission = false
private readFileState: FileStateCache
private discoveredSkillNames = new Set<string>()
private loadedNestedMemoryPaths = new Set<string>()
}QueryEngineConfig
typescript
// Source: src/QueryEngine.ts:132-175
type QueryEngineConfig = {
cwd: string
tools: Tools
commands: Command[]
mcpClients: MCPServerConnection[]
agents: AgentDefinition[]
canUseTool: CanUseToolFn
getAppState: () => AppState
setAppState: (f: (prev: AppState) => AppState) => void
initialMessages?: Message[]
readFileCache: FileStateCache
customSystemPrompt?: string
appendSystemPrompt?: string
userSpecifiedModel?: string
fallbackModel?: string
thinkingConfig?: ThinkingConfig
maxTurns?: number
maxBudgetUsd?: number
taskBudget?: { total: number }
verbose?: boolean
// ... 更多选项
}submitMessage() — 主入口
Source:
src/QueryEngine.ts:211+
typescript
async *submitMessage(
prompt: string | ContentBlockParam[],
options?: { uuid?: string; isMeta?: boolean },
): AsyncGenerator<SDKMessage, void, unknown>这是 SDK 和 REPL 提交用户消息的入口。它是一个 Generator,会逐步 yield 出消息事件。
执行流程
阶段 1:初始化 (行 215-286)
typescript
// 清理每轮技能发现
this.discoveredSkillNames.clear();
// 包装权限检查以跟踪拒绝
const wrappedCanUseTool = (tool, input, context) => {
const result = await this.config.canUseTool(tool, input, context);
if (result.behavior === 'deny') {
this.permissionDenials.push({ tool, input, reason: result.message });
}
return result;
};
// 确定模型和思考配置
const model = this.config.userSpecifiedModel ?? getDefaultMainLoopModel();
const thinkingConfig = resolveThinkingConfig(model, this.config.thinkingConfig);阶段 2:系统提示词组装 (行 287-328)
typescript
// 获取系统提示词的各部分
const parts = await fetchSystemPromptParts();
// 获取用户上下文
const userContext = await getUserContext();
// 组合最终系统提示词
const systemPrompt = composeSystemPrompt(
this.config.customSystemPrompt ?? parts.defaultPrompt,
memoryMechanicsPrompt,
this.config.appendSystemPrompt
);阶段 3:用户输入处理 (行 413-431)
processUserInput() 解析斜杠命令、附件等:
typescript
const { messages, shouldQuery, allowedTools, modelOverrides } =
await processUserInput(prompt, context);如果 shouldQuery 为 false(例如 /help 命令),不会发起 API 查询。
阶段 4:查询循环
将处理后的消息传入 query() 函数执行核心循环。QueryEngine 逐步 yield 出来自 query() 的所有事件。
与 query() 的关系
| 职责 | QueryEngine | query() |
|---|---|---|
| 消息历史持久化 | ✅ | |
| 系统提示词组装 | ✅ | |
| 用户输入解析 | ✅ | |
| 权限拒绝跟踪 | ✅ | |
| 用量统计 | ✅ | |
| 对话轮次循环 | ✅ | |
| 消息压缩 | ✅ | |
| 工具执行 | ✅ | |
| 错误恢复 | ✅ | |
| 流式事件分发 | ✅ |