Files
claude-code-mirror/claude-code-中文Wiki/03-工具系统.md
2026-04-03 13:01:19 +08:00

950 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 工具系统详解
本文件说明:详细介绍 Claude Code 的工具系统,包括所有内置工具的功能、输入 schema、权限模型和核心逻辑。
## 1. 工具系统架构
### 1.1 工具注册表
所有内置工具在 `tools.ts` 中注册:
```typescript
export function getAllBaseTools(): Tools {
return [
AgentTool,
TaskOutputTool,
BashTool,
GlobTool,
GrepTool,
ExitPlanModeV2Tool,
FileReadTool,
FileEditTool,
FileWriteTool,
NotebookEditTool,
WebFetchTool,
TodoWriteTool,
WebSearchTool,
TaskStopTool,
AskUserQuestionTool,
SkillTool,
EnterPlanModeTool,
// ... 更多工具
]
}
```
### 1.2 工具调用流程
```
用户输入/模型决策
checkPermissions() ────► 权限检查
validateInput() ────► 输入验证
call() ───────────► 工具执行
renderToolResultMessage() ────► 结果渲染
```
### 1.3 工具基类接口
所有工具都实现以下核心方法:
| 方法 | 描述 |
|------|------|
| `call(args, context, canUseTool, parentMessage)` | 工具执行入口 |
| `description(input, options)` | 获取工具描述 |
| `inputSchema` | 输入参数 Zod Schema |
| `checkPermissions(input, context)` | 权限检查 |
| `validateInput(input, context)` | 输入验证 |
| `renderToolUseMessage(input, options)` | 渲染工具调用消息 |
| `renderToolResultMessage(content, options)` | 渲染工具结果 |
## 2. BashTool - Shell 命令执行
### 2.1 功能描述
BashTool 是 Claude Code 最核心的工具之一,负责在用户授权下执行 Shell 命令。
### 2.2 输入 Schema
```typescript
const inputSchema = z.object({
command: z.string().describe('要执行的命令'),
cwd: z.string().optional().describe('工作目录'),
timeout: z.number().optional().describe('超时时间(毫秒)'),
})
```
### 2.3 权限模型
**权限检查规则**
1. 检查命令是否匹配 `alwaysAllowRules`
2. 检查命令是否匹配 `alwaysDenyRules`
3. 检查命令是否属于危险命令(如 `rm -rf`
4. 用户确认后执行
**危险命令警告**
- `rm -rf` 类删除命令
- 格式化命令(如 `mkfs`
- 覆盖系统文件
### 2.4 核心逻辑
```typescript
async call({ command, cwd, timeout }, context) {
// 1. 展开路径
const fullCommand = expandPath(command)
// 2. 权限检查
const decision = await checkBashPermission(fullCommand, context)
// 3. 决定是否使用沙箱
const shouldSandbox = await shouldUseSandbox(fullCommand)
// 4. 执行命令
if (shouldSandbox) {
return executeInSandbox(fullCommand, cwd, timeout)
} else {
return executeDirect(fullCommand, cwd, timeout)
}
// 5. 追踪文件变更
if (result.modifiedFiles) {
for (const file of result.modifiedFiles) {
updateFileHistory(file, 'modified')
}
}
}
```
### 2.5 沙箱执行
Claude Code 支持使用沙箱执行危险命令:
```typescript
async function shouldUseSandbox(command: string): Promise<boolean> {
// 检测命令是否危险
const isDangerous = detectDangerousCommand(command)
// 检查用户是否设置了沙箱偏好
const sandboxPreference = getSandboxPreference()
return isDangerous || sandboxPreference === 'always'
}
```
## 3. FileReadTool - 文件读取
### 3.1 功能描述
FileReadTool 用于读取文件内容,支持多种文件类型:
- 纯文本文件
- 图片文件PNG, JPG, GIF, WebP
- PDF 文档
- Jupyter Notebooks
### 3.2 输入 Schema
```typescript
const inputSchema = z.object({
file_path: z.string().describe('要读取的文件绝对路径'),
offset: z.number().int().nonnegative().optional().describe('起始行号'),
limit: z.number().int().positive().optional().describe('读取行数'),
pages: z.string().optional().describe('PDF 页码范围(如 "1-5"'),
})
```
### 3.3 权限模型
- 检查文件路径是否在允许目录下
- 检查是否匹配 deny rules
- 检查是否为会话相关文件(特殊处理)
### 3.4 核心逻辑
```typescript
async call({ file_path, offset = 1, limit, pages }, context) {
const ext = path.extname(file_path).toLowerCase()
// 根据文件类型处理
if (ext === '.ipynb') {
return readNotebook(file_path)
} else if (IMAGE_EXTENSIONS.has(ext)) {
return readImage(file_path)
} else if (ext === '.pdf') {
return readPDF(file_path, pages)
} else {
return readTextFile(file_path, offset, limit)
}
}
```
### 3.5 特殊处理
**Deduplication去重**
- 如果文件未修改且读取范围相同,返回 `file_unchanged` stub
- 避免重复发送相同内容浪费 Token
**内存新鲜度提示**
```typescript
function memoryFileFreshnessNote(mtimeMs: number): string {
const age = Date.now() - mtimeMs
if (age < 60000) return '(updated seconds ago)'
if (age < 3600000) return `(updated ${Math.floor(age/60000)}m ago)`
// ...
}
```
## 4. FileWriteTool - 文件写入
### 4.1 功能描述
FileWriteTool 用于创建或覆盖文件内容。
### 4.2 输入 Schema
```typescript
const inputSchema = z.object({
file_path: z.string().describe('文件路径'),
content: z.string().describe('文件内容'),
})
```
### 4.3 权限模型
- 写入权限检查
- 目录创建权限
- 危险路径保护(如 `/etc``/System`
### 4.4 核心逻辑
```typescript
async call({ file_path, content }, context) {
// 1. 验证路径
const fullPath = expandPath(file_path)
// 2. 安全检查
if (isDangerousPath(fullPath)) {
throw new Error('Cannot write to protected path')
}
// 3. 确保目录存在
const dir = path.dirname(fullPath)
await ensureDirExists(dir)
// 4. 写入文件
await writeFile(fullPath, content)
// 5. 更新文件状态缓存
context.readFileState.set(fullPath, {
content,
timestamp: Date.now(),
})
return { success: true, path: fullPath }
}
```
## 5. FileEditTool - 文件编辑
### 5.1 功能描述
FileEditTool 支持两种编辑模式:
1. **Search/Replace 模式**:通过 old_string 和 new_string 进行替换
2. **Edit 模式**:直接编辑文件内容
### 5.2 输入 Schema
```typescript
const inputSchema = z.object({
file_path: z.string().describe('文件路径'),
old_string: z.string().optional().describe('要替换的文本(精确匹配)'),
new_string: z.string().optional().describe('替换后的文本'),
// 或者使用 partial_diff
partial_diff: z.object({
replacements: z.array(z.object({
old_string: z.string(),
new_string: z.string(),
}))
}).optional()
})
```
### 5.3 权限模型
- 需要有效的 old_string防止意外覆盖
- 不能用于删除整个文件
- 禁止编辑二进制文件
### 5.4 核心逻辑
```typescript
async call({ file_path, old_string, new_string, partial_diff }, context) {
// 1. 读取当前文件内容
const content = await readFile(file_path)
// 2. 执行替换
let newContent: string
if (partial_diff) {
// 批量替换
newContent = content
for (const { old_string, new_string } of partial_diff.replacements) {
newContent = applyReplacement(newContent, old_string, new_string)
}
} else {
// 单次替换
newContent = applyReplacement(content, old_string, new_string)
}
// 3. 验证 old_string 存在且唯一
const occurrences = countOccurrences(content, old_string)
if (occurrences === 0) {
throw new Error('old_string not found in file')
}
if (occurrences > 1) {
throw new Error('old_string appears multiple times, be more specific')
}
// 4. 写入文件
await writeFile(file_path, newContent)
// 5. 更新缓存
context.readFileState.set(file_path, {
content: newContent,
timestamp: Date.now(),
})
}
```
## 6. GlobTool - 文件模式匹配
### 6.1 功能描述
使用 glob 模式查找文件。
### 6.2 输入 Schema
```typescript
const inputSchema = z.object({
pattern: z.string().describe('Glob 模式(如 "**/*.ts"'),
cwd: z.string().optional().describe('搜索根目录'),
})
```
### 6.3 核心逻辑
```typescript
async call({ pattern, cwd }, context) {
// 使用 ripgrep 的 glob 功能实现高性能搜索
const results = await execFile('rg', [
'--files-with-matches',
'--glob', pattern,
cwd || process.cwd()
])
return {
files: results.split('\n').filter(Boolean)
}
}
```
## 7. GrepTool - 代码搜索
### 7.1 功能描述
在代码库中搜索匹配文本。
### 7.2 输入 Schema
```typescript
const inputSchema = z.object({
pattern: z.string().describe('搜索模式(支持正则)'),
cwd: z.string().optional().describe('搜索目录'),
context: z.number().optional().describe('上下文行数'),
file_pattern: z.string().optional().describe('文件过滤模式'),
})
```
### 7.3 核心逻辑
```typescript
async call({ pattern, cwd, context = 3, file_pattern }, context) {
const args = [
'--json',
'-C', context.toString(),
pattern,
]
if (file_pattern) {
args.push('--glob', file_pattern)
}
args.push(cwd || '.')
const results = await execFile('rg', args)
// 解析 JSON 输出
const matches = JSON.parse(results)
return {
matches: matches.map(parseMatch),
count: matches.length
}
}
```
## 8. WebFetchTool - 网页获取
### 8.1 功能描述
获取网页内容。
### 8.2 输入 Schema
```typescript
const inputSchema = z.object({
url: z.string().url().describe('网页 URL'),
})
```
### 8.3 权限模型
**预批准域名列表**
- anthropic.com
- claude.ai
- github.com
- 主要新闻和文档站点
### 8.4 核心逻辑
```typescript
async call({ url }, context) {
// 1. URL 安全检查
if (!isPreapprovedUrl(url)) {
const decision = await context.requestPrompt('web_fetch', url)
if (!decision.approved) {
throw new Error('URL not approved')
}
}
// 2. 获取网页
const response = await fetch(url)
// 3. 解析 HTML
const text = await extractText(response)
// 4. 清理和格式化
return {
content: cleanHtml(text),
title: extractTitle(response),
url,
}
}
```
## 9. WebSearchTool - 网络搜索
### 9.1 功能描述
执行网络搜索。
### 9.2 输入 Schema
```typescript
const inputSchema = z.object({
query: z.string().describe('搜索查询'),
})
```
### 9.3 核心逻辑
```typescript
async call({ query }, context) {
// 使用搜索引擎 API
const results = await searchEngine.query(query)
return {
results: results.map(r => ({
title: r.title,
url: r.url,
snippet: r.snippet,
})),
total: results.length,
}
}
```
## 10. AgentTool - 子 Agent
### 10.1 功能描述
AgentTool 允许 Claude 创建和管理子 Agent 来并行执行任务。
### 10.2 输入 Schema
```typescript
const inputSchema = z.object({
agent: z.enum(['general', 'plan', 'explore', ...]).describe('Agent 类型'),
prompt: z.string().describe('给 Agent 的指令'),
agentId: z.string().optional().describe('现有 Agent ID用于恢复'),
maxTurns: z.number().optional().describe('最大轮次'),
})
```
### 10.3 Agent 类型
| 类型 | 描述 |
|------|------|
| `general` | 通用任务执行 |
| `plan` | 计划制定 |
| `explore` | 代码探索 |
| `verification` | 验证检查 |
### 10.4 核心逻辑
```typescript
async call({ agent, prompt, maxTurns }, context) {
// 1. 创建或恢复 Agent
const agentId = await createSubAgent({
type: agent,
prompt,
maxTurns,
})
// 2. 执行 Agent
const result = await runAgent(agentId, context)
// 3. 返回结果
return {
output: result.output,
agentId,
turns: result.turns,
}
}
```
## 11. SkillTool - 技能执行
### 11.1 功能描述
SkillTool 用于执行用户定义的技能Skills这些技能以 Markdown 文件形式保存在本地目录中。
### 11.2 输入 Schema
```typescript
const inputSchema = z.object({
name: z.string().describe('技能名称'),
args: z.string().optional().describe('传递给技能的参数'),
})
```
### 11.3 技能定义格式
技能目录结构:
```
~/.claude/skills/my-skill/
└── skill.md
```
skill.md 格式:
```markdown
---
name: my-skill
description: 这个技能做什么
---
# My Skill
这个技能用于执行特定任务...
## 使用方法
执行时会运行以下脚本...
```
### 11.4 核心逻辑
```typescript
async call({ name, args }, context) {
// 1. 查找技能定义
const skill = await findSkill(name)
if (!skill) {
throw new Error(`Skill not found: ${name}`)
}
// 2. 解析技能定义
const { prompt, script } = parseSkillDefinition(skill)
// 3. 执行脚本
const output = await executeScript(script, { args })
return {
output,
skillName: name,
}
}
```
## 12. MCPTool - Model Context Protocol
### 12.1 功能描述
MCPTool 是 MCPModel Context Protocol协议的工具包装器允许调用 MCP 服务器提供的工具。
### 12.2 输入 Schema
```typescript
const inputSchema = z.object({
server: z.string().describe('MCP 服务器名称'),
tool: z.string().describe('工具名称'),
arguments: z.record(z.string(), z.unknown()).optional().describe('工具参数'),
})
```
### 12.3 核心逻辑
```typescript
async call({ server, tool, arguments }, context) {
// 1. 获取 MCP 客户端
const client = context.mcpClients.find(c => c.name === server)
if (!client) {
throw new Error(`MCP server not found: ${server}`)
}
// 2. 发送工具调用请求
const result = await client.callTool(tool, arguments)
// 3. 返回结果
return result
}
```
## 13. LSPTool - 语言服务器协议
### 13.1 功能描述
LSPTool 提供对 Language Server Protocol 的访问,用于代码导航、诊断等。
### 13.2 核心功能
- 跳转到定义 (Go to Definition)
- 查找引用 (Find References)
- 代码补全 (Completions)
- 诊断信息 (Diagnostics)
## 14. NotebookEditTool - Jupyter Notebook 编辑
### 14.1 功能描述
NotebookEditTool 专门用于编辑 Jupyter Notebook 文件。
### 14.2 输入 Schema
```typescript
const inputSchema = z.object({
file_path: z.string().describe('Notebook 文件路径'),
cell_id: z.string().optional().describe('要编辑的单元格 ID'),
new_source: z.string().optional().describe('新单元格内容'),
action: z.enum(['insert', 'delete', 'move']).optional().describe('操作类型'),
})
```
## 15. Task 系列工具
### 15.1 概述
Task 系列工具提供完整的任务管理功能:
| 工具 | 描述 |
|------|------|
| `TaskCreateTool` | 创建新任务 |
| `TaskGetTool` | 获取任务详情 |
| `TaskUpdateTool` | 更新任务状态 |
| `TaskListTool` | 列出任务 |
| `TaskStopTool` | 停止任务 |
| `TaskOutputTool` | 获取任务输出 |
### 15.2 TaskCreateTool 输入 Schema
```typescript
const inputSchema = z.object({
description: z.string().describe('任务描述'),
status: z.enum(['pending', 'in_progress', 'completed']).optional(),
priority: z.enum(['low', 'medium', 'high']).optional(),
})
```
### 15.3 任务状态流转
```
pending ──► in_progress ──► completed
│ │
└──────► failed
```
## 16. SendMessageTool - 团队消息
### 16.1 功能描述
SendMessageTool 用于向团队成员发送消息。
### 16.2 输入 Schema
```typescript
const inputSchema = z.object({
recipient: z.string().describe('收件人标识'),
message: z.string().describe('消息内容'),
})
```
## 17. TeamCreateTool - 创建团队
### 17.1 功能描述
TeamCreateTool 创建一个 Agent 团队,团队成员可以协作完成任务。
### 17.2 输入 Schema
```typescript
const inputSchema = z.object({
name: z.string().describe('团队名称'),
members: z.array(z.object({
name: z.string(),
role: z.enum(['coordinator', 'worker', 'reviewer']),
agentType: z.string().optional(),
})).describe('团队成员'),
})
```
### 17.3 团队角色
| 角色 | 描述 |
|------|------|
| `coordinator` | 协调者,负责分配任务 |
| `worker` | 执行者,负责完成任务 |
| `reviewer` | 审核者,负责检查结果 |
## 18. EnterPlanModeTool / ExitPlanModeTool
### 18.1 功能描述
计划模式允许 Claude 在执行前先制定计划,用户确认后再执行。
### 18.2 输入 Schema
```typescript
// EnterPlanModeTool
const inputSchema = z.object({
prompt: z.string().optional().describe('计划提示'),
})
// ExitPlanModeTool
// 无需参数
```
## 19. EnterWorktreeTool / ExitWorktreeTool
### 19.1 功能描述
用于创建和切换 Git Worktree便于在多个分支上同时工作。
### 19.2 输入 Schema
```typescript
// EnterWorktreeTool
const inputSchema = z.object({
branch: z.string().describe('分支名'),
path: z.string().optional().describe('Worktree 路径'),
})
// ExitWorktreeTool
const inputSchema = z.object({
path: z.string().optional().describe('要删除的 Worktree 路径'),
})
```
## 20. ToolSearchTool - 工具搜索
### 20.1 功能描述
ToolSearchTool 允许模型在运行时搜索可用工具,当工具过多时会延迟加载。
### 20.2 输入 Schema
```typescript
const inputSchema = z.object({
query: z.string().describe('搜索查询'),
})
```
### 20.3 延迟加载机制
```typescript
// 当工具数量超过阈值时启用延迟加载
const TOOL_SEARCH_THRESHOLD = 50
if (totalTools > TOOL_SEARCH_THRESHOLD) {
// 工具标记为 shouldDefer: true
// 首次调用时需要通过 ToolSearchTool 激活
}
```
## 21. CronCreateTool - 定时任务
### 21.1 功能描述
CronCreateTool 创建定时执行的任务。
### 21.2 输入 Schema
```typescript
const inputSchema = z.object({
schedule: z.string().describe('Cron 表达式'),
command: z.string().describe('要执行的命令'),
name: z.string().optional().describe('任务名称'),
})
```
## 22. RemoteTriggerTool - 远程触发
### 22.1 功能描述
RemoteTriggerTool 允许从远程触发任务执行。
### 22.2 输入 Schema
```typescript
const inputSchema = z.object({
trigger_id: z.string().describe('触发器 ID'),
payload: z.record(z.string(), z.unknown()).optional().describe('传递的数据'),
})
```
## 23. SleepTool - 延迟执行
### 23.1 功能描述
SleepTool 用于在任务执行中引入延迟。
### 23.2 输入 Schema
```typescript
const inputSchema = z.object({
duration: z.number().describe('延迟时间(秒)'),
})
```
## 24. SyntheticOutputTool - 结构化输出
### 24.1 功能描述
SyntheticOutputTool 用于提供符合 JSON Schema 的结构化输出。
### 24.2 输入 Schema
```typescript
const inputSchema = z.object({
schema: z.record(z.string(), z.unknown()).describe('JSON Schema'),
data: z.record(z.string(), z.unknown()).describe('输出数据'),
})
```
### 24.3 验证机制
```typescript
async call({ schema, data }, context) {
// 使用 Zod 验证数据
const validator = z.object(schema)
const result = validator.safeParse(data)
if (!result.success) {
throw new Error(`Invalid output: ${result.error.message}`)
}
return { validated: result.data }
}
```
## 25. 工具权限系统总结
### 25.1 权限模式
| 模式 | 描述 | 行为 |
|------|------|------|
| `default` | 默认模式 | 询问危险操作 |
| `auto` | 自动模式 | 基于规则自动决定 |
| `bypass` | 绕过模式 | 允许所有操作 |
| `plan` | 计划模式 | 强制计划模式 |
### 25.2 权限检查流程
```
1. validateInput() - 验证输入有效性
2. checkPermissions() - 检查权限规则
├──► alwaysAllow → 返回允许
├──► alwaysDeny → 返回拒绝
└──► 需要询问 → 等待用户确认
```
### 25.3 权限规则匹配
```typescript
// 权限规则支持通配符模式
const rules = {
'Bash(rm *)': 'deny', // 拒绝所有 rm 命令
'Bash(git *)': 'allow', // 允许所有 git 命令
'Read(/home/user/src/*)': 'allow', // 允许读取特定目录
}
```
## 26. 工具渲染系统
### 26.1 渲染方法
| 方法 | 用途 |
|------|------|
| `renderToolUseMessage` | 渲染工具调用消息 |
| `renderToolUseTag` | 渲染工具标签(如超时标记) |
| `renderToolUseProgressMessage` | 渲染进度消息 |
| `renderToolResultMessage` | 渲染工具结果 |
| `renderToolUseErrorMessage` | 渲染错误消息 |
| `renderToolUseRejectedMessage` | 渲染拒绝消息 |
### 26.2 渲染选项
```typescript
interface RenderOptions {
style?: 'condensed' | 'full'
theme?: ThemeName
verbose?: boolean
isTranscriptMode?: boolean
terminalSize?: { columns: number; rows: number }
}
```
## 27. 总结
Claude Code 的工具系统设计遵循以下原则:
1. **一致性**:所有工具实现统一的 Tool 接口
2. **安全性**:细粒度的权限控制和验证
3. **可扩展性**:支持 MCP、插件、技能等多种扩展机制
4. **用户控制**:用户可精确控制每个工具的使用权限
5. **高性能**:支持流式执行、缓存、去重等优化