模块一 · 第五节:PromptSuggestion 智能提示与推测执行
核心问题
Claude Code 如何预测用户意图?Speculative Execution(推测执行)是什么?提示建议和推测执行如何协同工作?背后的实现机制是什么?
◇ 本节位置
Claude Code 全局架构
┌─────────────────────────────────────────────────────────────────────┐
│ 服务层(services/) │
│ │
│ PromptSuggestion ← 本节 │
│ ├── 提示建议 │
│ ├── 推测执行(Speculation) │
│ └── Forked Agent │
└─────────────────────────────────────────────────────────────────────┘
一、概述
1.1 两大核心功能
源码位置 :src/services/PromptSuggestion/
PromptSuggestion 包含两个相关但不同的功能:
┌─────────────────────────────────────────────────────────────────────┐
│ PromptSuggestion 系统 │
│ │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ Prompt Suggestion │ │ Speculative Exec │ │
│ │ (提示建议) │ │ (推测执行) │ │
│ │ │ │ │ │
│ │ 预测用户输入内容 │ │ Fork Agent 预执行 │ │
│ │ Tab 键采纳 │ │ 用户确认后应用 │ │
│ └─────────────────────┘ └─────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
1.2 提示建议(Prompt Suggestion)
- 作用:预测用户可能输入的提示词
- 触发:用户开始输入时显示建议
- 采纳:按 Tab 键采纳建议
1.3 推测执行(Speculative Execution)
- 作用:Fork 一个子代理预先执行可能的操作
- 触发:基于用户上下文自动开始
- 应用:用户确认后将其修改合并到主会话
二、推测执行核心机制
2.1 核心常量
源码位置 :src/services/PromptSuggestion/speculation.ts
typescript
// 推测执行限制
const MAX_SPECULATION_TURNS = 20 // 最多执行 20 轮
const MAX_SPECULATION_MESSAGES = 100 // 最多 100 条消息
2.2 工具白名单
typescript
// 允许的写操作工具
const WRITE_TOOLS = new Set(['Edit', 'Write', 'NotebookEdit'])
// 安全的只读工具
const SAFE_READ_ONLY_TOOLS = new Set([
'Read',
'Glob',
'Grep',
'ToolSearch',
'LSP',
'TaskGet',
'TaskList',
])
推测执行只允许:
- 读操作:Read, Glob, Grep 等(不修改文件)
- 写操作:Edit, Write, NotebookEdit(会修改文件)
2.3 隔离机制 - Overlay 文件系统
源码位置 :speculation.ts
typescript
// 推测执行使用 Overlay 文件系统隔离
function getOverlayPath(id: string): string {
return join(getClaudeTempDir(), 'speculation', String(process.pid), id)
}
工作原理:
┌─────────────────────────────────────────────────────────────────────┐
│ Overlay 文件系统隔离 │
│ │
│ 用户真实目录 (cwd) 推测 Overlay 目录 │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ 真实文件 │ │ 隔离副本 │ │
│ │ (不修改) │◄──────►│ (可修改) │ │
│ └─────────────────┘ copy └─────────────────┘ │
│ │ │
│ ▼ │
│ 如果推测被采纳 │
│ │ │
│ ▼ │
│ 复制到真实目录 │
└─────────────────────────────────────────────────────────────────────┘
2.4 执行流程
typescript
// 推测执行完整流程
async function speculate(context: REPLHookContext) {
// 1. 创建隔离的 Overlay
const overlayPath = getOverlayPath(speculationId)
await mkdir(overlayPath, { recursive: true })
// 2. Fork 子代理执行
const forkedAgent = await runForkedAgent({
prompt: suggestionPrompt,
cwd: overlayPath, // 在 Overlay 中执行
isolation: 'overlay'
})
// 3. 收集推测结果
const result = await forkedAgent.waitForCompletion()
// 4. 如果用户采纳
if (userAccepts()) {
// 将 Overlay 中的修改复制回主目录
await copyOverlayToMain(overlayPath, result.writtenPaths)
} else {
// 清理 Overlay
await safeRemoveOverlay(overlayPath)
}
}
三、采纳与回滚
3.1 采纳机制
源码位置 :speculation.ts
typescript
async function copyOverlayToMain(
overlayPath: string,
writtenPaths: Set<string>,
cwd: string,
): Promise<boolean> {
let allCopied = true
for (const rel of writtenPaths) {
const src = join(overlayPath, rel)
const dest = join(cwd, rel)
try {
// 确保目标目录存在
await mkdir(dirname(dest), { recursive: true })
// 复制文件
await copyFile(src, dest)
} catch {
allCopied = false
}
}
return allCopied
}
3.2 自动清理
typescript
// 安全删除 Overlay
function safeRemoveOverlay(overlayPath: string): void {
rm(
overlayPath,
{
recursive: true,
force: true,
maxRetries: 3, // 最多重试 3 次
retryDelay: 100, // 重试间隔 100ms
},
() => {} // 忽略错误
)
}
四、提示建议实现
4.1 生成策略
源码位置 :promptSuggestion.ts
typescript
// 提示建议通过多种策略生成
async function generateSuggestion(context: {
messages: Message[]
systemPrompt: string
}): Promise<string | null> {
// 策略 1: 分析最近对话模式
const recentPattern = analyzeRecentConversations(context.messages)
// 策略 2: 读取项目文件推断意图
const projectContext = await inferFromProjectFiles(context)
// 策略 3: 用户设置偏好
const userPreference = getUserPreference()
// 综合生成建议
return combineSuggestions([recentPattern, projectContext, userPreference])
}
4.2 抑制条件
typescript
// 某些情况下不显示建议
function shouldSuppressSuggestion(): 'swarm_teammate' | 'non_interactive' | null {
// 1. Swarm 团队成员不显示
if (isAgentSwarmsEnabled() && isTeammate()) {
return 'swarm_teammate'
}
// 2. 非交互模式不显示
if (getIsNonInteractiveSession()) {
return 'non_interactive'
}
return null
}
五、Forked Agent
5.1 Forked Agent 与 Overlay
源码位置 :src/utils/forkedAgent.ts
typescript
// Forked Agent 是推测执行的核心
interface ForkedAgentParams {
prompt: string
cwd: string // Overlay 目录
isolation: 'overlay'
maxTurns?: number // 默认 20
}
async function runForkedAgent(
params: ForkedAgentParams
): Promise<ForkedAgent> {
// 1. 创建隔离的子进程
const child = spawn('node', ['--fork', 'agent.js'], {
cwd: params.cwd,
env: { ...process.env, CLAUDE_ISOLATED: '1' }
})
// 2. 传递上下文
child.send({ type: 'init', ...params })
// 3. 返回 Agent 接口
return {
waitForCompletion: () => waitForResult(child),
abort: () => child.kill()
}
}
5.2 文件状态缓存隔离
typescript
// Magic Docs 和推测执行都使用文件状态缓存隔离
function cloneFileStateCache(
original: FileStateCache
): FileStateCache {
// 克隆缓存,避免共享状态
return new Map(original)
}
六、实战应用
6.1 典型场景
场景:用户想要添加一个新功能
1. Claude Code 分析用户最近的对话和项目上下文
2. 启动推测执行,Fork Agent:
- 读取相关文件
- 编写代码
- 所有修改在 Overlay 中进行
3. 用户在终端看到推测的代码执行结果
4. 用户输入确认,推测被采纳
5. Overlay 中的修改合并到主目录
6.2 性能优化
typescript
// 推测执行优化
// 1. 智能阈值
// - 只有置信度 > 阈值时才执行推测
// - 避免不必要的资源消耗
// 2. 后台执行
// - 不阻塞用户输入
// - 用户可以继续工作
// 3. 早期终止
// - 如果用户已经输入不同内容
// - 终止推测执行
七、思考题
思考题 1:推测执行和预执行有什么区别?
答案:
typescript
// 预执行(Pre-execution):
// - 在用户确认前执行
// - 结果可见但不生效
// - 例如:SQL 执行计划
// 推测执行(Speculative Execution):
// - Fork 独立 Agent 执行
// - 使用 Overlay 隔离
// - 用户确认后才合并
// - 特点:完全隔离,可回滚
思考题 2:Overlay 文件系统有什么优势?
答案:
typescript
// 优势:
// 1. 完全隔离
// - 不影响主工作目录
// - 用户看不到未确认的修改
// 2. 原子性
// - 用户不采纳时完全不修改
// - 采纳时一次性合并
// 3. 可回滚
// - 不需要版本控制系统
// - 直接删除 Overlay 即可
思考题 3:推测执行有什么限制?
答案:
typescript
// 限制:
// 1. 轮数限制
// - 最多 20 轮(MAX_SPECULATION_TURNS)
// - 防止推测时间过长
// 2. 消息限制
// - 最多 100 条消息
// - 控制 Token 消耗
// 3. 工具限制
// - 只能用白名单工具
// - 禁止可能有副作用的操作
// 4. 环境依赖
// - 推测时环境可能变化
// - 某些操作不适合推测
八、延伸阅读
| 资源 | 说明 |
|---|---|
src/services/PromptSuggestion/promptSuggestion.ts |
提示建议实现 |
src/services/PromptSuggestion/speculation.ts |
推测执行核心 |
src/utils/forkedAgent.ts |
Forked Agent |
src/utils/fileStateCache.ts |
文件状态缓存 |