Skip to content

Commit 9c724fc

Browse files
committed
feat(tools): 重构工具系统使用 Zod Schema 并简化 API
重构整个工具系统,使用 Zod Schema 替代 JSONSchema7 进行参数验证,并引入新的 createTool API 简化工具创建流程。移除旧的基类系统,统一工具接口,同时更新文档和类型定义。 - 新增 core/createTool.ts 作为主要工具创建 API - 移除 base/ 目录下的旧工具基类 - 更新所有内置工具使用新的 Zod Schema 格式 - 添加工具系统文档和架构说明 - 统一工具错误处理和安全验证 - 优化 MCP 工具集成方式
1 parent 0af2489 commit 9c724fc

72 files changed

Lines changed: 8112 additions & 9143 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/settings.local.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
"Bash(xargs sed:*)",
2424
"WebFetch(domain:gist.github.com)",
2525
"Bash(pnpm update:*)",
26-
"WebFetch(domain:jannesklaas.github.io)"
26+
"WebFetch(domain:jannesklaas.github.io)",
27+
"Bash(npm view:*)"
2728
],
2829
"deny": [],
2930
"ask": [],

docs/TOOL_SYSTEM_ARCHITECTURE.md

Lines changed: 375 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,375 @@
1+
# Blade 工具系统架构文档
2+
3+
> **版本**: v2.0
4+
> **更新时间**: 2025-10-10
5+
> **状态**: ✅ 已完成并优化
6+
7+
## 一、架构概览
8+
9+
Blade 工具系统基于**统一、简洁、类型安全**的设计原则,提供强大而灵活的工具扩展能力。
10+
11+
### 核心特性
12+
13+
-**统一接口**: 所有工具(内置/MCP/自定义)使用相同的 `Tool` 接口
14+
-**类型安全**: 端到端 TypeScript 类型推断,基于 Zod Schema
15+
-**简洁 API**: 通过 `createTool` 函数创建工具,无需复杂继承
16+
-**MCP 集成**: 自动转换 MCP 工具为标准 Tool
17+
-**模块化**: 清晰的目录结构,职责分明
18+
19+
## 二、目录结构
20+
21+
```
22+
src/tools/
23+
├── core/ # 核心工具系统
24+
│ ├── createTool.ts # 统一的工具创建 API ⭐
25+
│ ├── ToolInvocation.ts # 工具调用抽象
26+
│ └── index.ts # 核心导出
27+
28+
├── types/ # 类型定义(统一位置) ⭐
29+
│ ├── ToolTypes.ts # 工具类型(Tool、ToolConfig、ToolDescription)
30+
│ ├── ExecutionTypes.ts # 执行上下文类型
31+
│ ├── SecurityTypes.ts # 安全相关类型(ValidationError等)
32+
│ └── index.ts # 类型统一导出
33+
34+
├── validation/ # 验证系统
35+
│ ├── zod-schemas.ts # Zod Schema 工具函数
36+
│ ├── zod-to-json.ts # Zod → JSON Schema 转换
37+
│ ├── error-formatter.ts # 错误格式化
38+
│ └── index.ts # 验证导出
39+
40+
├── registry/ # 工具注册系统
41+
│ ├── ToolRegistry.ts # 主注册表
42+
│ ├── ToolResolver.ts # 工具解析器
43+
│ └── index.ts # 注册系统导出
44+
45+
├── builtin/ # 内置工具(13个)
46+
│ ├── file/ # 文件操作(4个)
47+
│ │ ├── read.ts # 读取文件
48+
│ │ ├── write.ts # 写入文件
49+
│ │ ├── edit.ts # 编辑文件
50+
│ │ └── multi-edit.ts # 批量编辑
51+
│ ├── search/ # 搜索工具(3个)
52+
│ │ ├── glob.ts # 文件模式匹配
53+
│ │ ├── grep.ts # 内容搜索
54+
│ │ └── find.ts # 文件查找
55+
│ ├── shell/ # Shell 命令(3个)
56+
│ │ ├── bash.ts # Bash 命令
57+
│ │ ├── shell.ts # 通用 Shell
58+
│ │ └── script.ts # 脚本执行
59+
│ ├── web/ # 网络工具(2个)
60+
│ │ ├── web-fetch.ts # 网页抓取
61+
│ │ └── api-call.ts # API 调用
62+
│ ├── task/ # 任务管理(1个)
63+
│ │ └── task.ts # 任务代理
64+
│ └── index.ts # 内置工具导出
65+
66+
└── index.ts # 工具系统统一导出
67+
```
68+
69+
### 架构优化成果
70+
71+
**类型系统优化**
72+
- 所有类型定义统一在 `types/` 文件夹
73+
- **迁移到标准 `@types/json-schema`**: 使用社区标准类型定义
74+
- 删除重复定义:`core/types.ts`(110行)、`McpTypes.ts`(70行)
75+
- 删除自定义 `JSONSchema7` 接口(22行),使用标准定义
76+
- 解决了 `ValidationError`/`ValidationResult` 重复定义问题
77+
- 修复了 `output`/`displayMessage` 字段名称问题
78+
79+
**代码精简**
80+
- 删除未使用代码:`ToolDiscovery.ts`(201行)
81+
- 删除冗余类型定义:`convertZodToJsonSchema` 函数(61行)
82+
- 净删除:442行重复/未使用代码
83+
- 新增:74行辅助函数 + 30行类型守卫
84+
- **总净减少:338行代码**
85+
86+
**依赖优化**
87+
- 新增:`@types/json-schema@7.0.15` (devDependency, ~3KB)
88+
- **零运行时影响**: 类型定义编译后完全消失
89+
- 与生态对齐:兼容 Ajv、json-schema-to-typescript 等库
90+
91+
## 三、核心接口
92+
93+
### Tool 接口
94+
95+
```typescript
96+
export interface Tool<TParams = unknown> {
97+
// 基本信息
98+
readonly name: string;
99+
readonly displayName: string;
100+
readonly kind: ToolKind;
101+
readonly description: ToolDescription;
102+
readonly version: string;
103+
readonly category?: string;
104+
readonly tags: string[];
105+
106+
// 安全控制
107+
readonly requiresConfirmation: boolean;
108+
109+
// 方法
110+
getFunctionDeclaration(): FunctionDeclaration;
111+
getMetadata(): Record<string, unknown>;
112+
build(params: TParams): ToolInvocation<TParams>;
113+
execute(params: TParams, signal?: AbortSignal): Promise<ToolResult>;
114+
}
115+
```
116+
117+
### ToolConfig 接口
118+
119+
```typescript
120+
export interface ToolConfig<TSchema = unknown, TParams = unknown> {
121+
name: string;
122+
displayName: string;
123+
kind: ToolKind;
124+
schema: TSchema; // Zod Schema
125+
description: ToolDescription;
126+
requiresConfirmation?: boolean | ConfirmationCallback<TParams>;
127+
execute: (params: TParams, context: ExecutionContext) => Promise<ToolResult>;
128+
version?: string;
129+
category?: string;
130+
tags?: string[];
131+
}
132+
```
133+
134+
### ToolResult 接口
135+
136+
```typescript
137+
export interface ToolResult {
138+
success: boolean;
139+
llmContent: string | object; // 传递给 LLM 的内容
140+
displayContent: string; // 显示给用户的内容
141+
error?: ToolError;
142+
metadata?: Record<string, unknown>;
143+
}
144+
```
145+
146+
## 四、使用示例
147+
148+
### 创建简单工具
149+
150+
```typescript
151+
import { createTool } from '@/tools/core';
152+
import { ToolKind } from '@/tools/types';
153+
import { z } from 'zod';
154+
155+
export const helloTool = createTool({
156+
name: 'hello',
157+
displayName: 'Hello World',
158+
kind: ToolKind.Other,
159+
160+
schema: z.object({
161+
name: z.string().describe('要打招呼的名字'),
162+
}),
163+
164+
description: {
165+
short: '打招呼的示例工具',
166+
important: ['这是一个演示工具']
167+
},
168+
169+
async execute(params, context) {
170+
return {
171+
success: true,
172+
llmContent: `Hello, ${params.name}!`,
173+
displayContent: `✅ Hello, ${params.name}!`,
174+
};
175+
}
176+
});
177+
```
178+
179+
### MCP 工具集成
180+
181+
```typescript
182+
import { createMcpTool } from '@/mcp/createMcpTool';
183+
184+
// MCP 工具自动转换为标准 Tool
185+
export function createMcpTool(
186+
mcpClient: McpClient,
187+
serverName: string,
188+
toolDef: McpToolDefinition
189+
) {
190+
// 1. JSON Schema → Zod Schema 自动转换
191+
const zodSchema = convertJsonSchemaToZod(toolDef.inputSchema);
192+
193+
// 2. 使用 createTool 创建标准工具
194+
return createTool({
195+
name: `mcp__${serverName}__${toolDef.name}`,
196+
displayName: `${serverName}: ${toolDef.name}`,
197+
kind: ToolKind.External,
198+
schema: zodSchema,
199+
description: {
200+
short: toolDef.description || `MCP 工具: ${toolDef.name}`,
201+
important: [`来自 MCP 服务器: ${serverName}`]
202+
},
203+
requiresConfirmation: true,
204+
205+
async execute(params, context) {
206+
const result = await mcpClient.callTool(toolDef.name, params);
207+
return convertMcpResult(result);
208+
}
209+
});
210+
}
211+
```
212+
213+
## 五、工具注册
214+
215+
```typescript
216+
import { ToolRegistry } from '@/tools/registry';
217+
import { getBuiltinTools } from '@/tools/builtin';
218+
219+
// 创建注册表
220+
const registry = new ToolRegistry();
221+
222+
// 注册内置工具
223+
const builtinTools = await getBuiltinTools();
224+
builtinTools.forEach(tool => registry.register(tool));
225+
226+
// 注册 MCP 工具
227+
const mcpTools = await mcpRegistry.getAvailableTools();
228+
mcpTools.forEach(tool => registry.registerMcpTool(tool));
229+
230+
// 获取所有工具
231+
const allTools = registry.getAll(); // Tool[]
232+
233+
// 获取 LLM 函数声明
234+
const declarations = registry.getFunctionDeclarations();
235+
```
236+
237+
## 六、类型系统
238+
239+
### 类型文件说明
240+
241+
| 文件 | 说明 | 主要类型 |
242+
|------|------|----------|
243+
| `ToolTypes.ts` | 核心工具类型 | `Tool`, `ToolConfig`, `ToolDescription`, `ToolKind`, `ToolResult`, `FunctionDeclaration` |
244+
| `ExecutionTypes.ts` | 执行上下文类型 | `ExecutionContext` |
245+
| `SecurityTypes.ts` | 安全相关类型 | `ValidationError`, `ValidationResult`, `PermissionResult` |
246+
| **`@types/json-schema`** | **JSON Schema 标准类型** | **`JSONSchema7`**, **`JSONSchema7Definition`** |
247+
248+
### 类型导入示例
249+
250+
```typescript
251+
// 从统一入口导入工具类型
252+
import type {
253+
Tool,
254+
ToolConfig,
255+
ToolResult,
256+
ExecutionContext,
257+
} from '@/tools/types';
258+
259+
// JSON Schema 类型需要直接从标准包导入
260+
import type { JSONSchema7 } from 'json-schema';
261+
```
262+
263+
### JSONSchema7 类型使用
264+
265+
**为什么使用标准类型?**
266+
- ✅ 社区标准,广泛兼容
267+
- ✅ 完整的 JSON Schema Draft-07 支持
268+
- ✅ 官方维护,自动跟进规范更新
269+
- ✅ 零运行时开销(编译后消失)
270+
271+
**两种类型:**
272+
```typescript
273+
import type { JSONSchema7, JSONSchema7Definition } from 'json-schema';
274+
275+
// JSONSchema7 - 完整的 schema 对象
276+
const schema: JSONSchema7 = {
277+
type: 'object',
278+
properties: {
279+
name: { type: 'string' }
280+
}
281+
};
282+
283+
// JSONSchema7Definition - 可以是 boolean (JSON Schema 规范允许)
284+
const def1: JSONSchema7Definition = schema; // 对象
285+
const def2: JSONSchema7Definition = true; // true = 接受任何值
286+
const def3: JSONSchema7Definition = false; // false = 拒绝任何值
287+
```
288+
289+
**类型守卫示例:**
290+
```typescript
291+
// 处理 properties 可能是 boolean 的情况
292+
if (schema.properties) {
293+
for (const [key, value] of Object.entries(schema.properties)) {
294+
if (typeof value === 'object' && value !== null) {
295+
// 安全地使用 value as JSONSchema7
296+
processSchema(value as JSONSchema7);
297+
}
298+
}
299+
}
300+
```
301+
302+
## 七、最佳实践
303+
304+
### 1. 工具命名
305+
306+
- 使用小写字母和下划线:`read_file``multi_edit`
307+
- MCP 工具使用前缀:`mcp__server__tool`
308+
309+
### 2. 描述格式
310+
311+
```typescript
312+
description: {
313+
short: '简短描述(1行)',
314+
long: '详细说明(可选)',
315+
usageNotes: [
316+
'使用说明1',
317+
'使用说明2'
318+
],
319+
important: [
320+
'重要提示1',
321+
'重要提示2'
322+
]
323+
}
324+
```
325+
326+
### 3. 返回值格式
327+
328+
```typescript
329+
return {
330+
success: true,
331+
llmContent: data, // 给 LLM 的结构化数据
332+
displayContent: message, // 给用户的友好消息
333+
metadata: { // 元数据(可选)
334+
timestamp: Date.now(),
335+
// ...
336+
}
337+
};
338+
```
339+
340+
### 4. 辅助函数
341+
342+
每个工具应包含 `formatDisplayMessage` 辅助函数:
343+
344+
```typescript
345+
function formatDisplayMessage(
346+
path: string,
347+
metadata: Record<string, unknown>
348+
): string {
349+
// 构建用户友好的消息
350+
return `✅ 操作成功: ${path}`;
351+
}
352+
```
353+
354+
## 八、下一步计划
355+
356+
### 短期任务
357+
- [ ] 完善工具单元测试
358+
- [ ] 添加工具性能监控
359+
- [ ] 实现工具执行管道
360+
361+
### 中期任务
362+
- [ ] 支持更多 MCP 服务器
363+
- [ ] 实现工具权限系统
364+
- [ ] 添加工具缓存机制
365+
366+
### 长期目标
367+
- [ ] 构建工具市场
368+
- [ ] 提供工具开发 SDK
369+
- [ ] 建立工具生态系统
370+
371+
## 九、参考资料
372+
373+
- [工具使用指南](./tools/TOOL_USAGE_GUIDE.md)
374+
- [MCP 协议文档](./protocols/mcp-support.md)
375+
- [源码目录](../src/tools/)

0 commit comments

Comments
 (0)