@zhin.js/ai 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +564 -0
- package/TOOLS.md +294 -0
- package/package.json +66 -0
- package/src/agent.ts +471 -0
- package/src/context-manager.ts +439 -0
- package/src/index.ts +1432 -0
- package/src/providers/anthropic.ts +375 -0
- package/src/providers/base.ts +173 -0
- package/src/providers/index.ts +13 -0
- package/src/providers/ollama.ts +283 -0
- package/src/providers/openai.ts +167 -0
- package/src/session.ts +537 -0
- package/src/tools.ts +205 -0
- package/src/types.ts +274 -0
- package/tests/agent.test.ts +484 -0
- package/tests/ai-trigger.test.ts +369 -0
- package/tests/context-manager.test.ts +387 -0
- package/tests/integration.test.ts +596 -0
- package/tests/providers.integration.test.ts +227 -0
- package/tests/session.test.ts +243 -0
- package/tests/setup.ts +304 -0
- package/tests/tool.test.ts +800 -0
- package/tests/tools-builtin.test.ts +346 -0
- package/tsconfig.json +23 -0
package/TOOLS.md
ADDED
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
# AI 工具系统
|
|
2
|
+
|
|
3
|
+
@zhin.js/ai 插件支持从多个来源收集和使用 AI 工具,实现更强大的 Agent 能力。
|
|
4
|
+
|
|
5
|
+
## 工具来源
|
|
6
|
+
|
|
7
|
+
### 1. 内置工具 (Builtin Tools)
|
|
8
|
+
|
|
9
|
+
AI 服务内置了一些常用工具:
|
|
10
|
+
|
|
11
|
+
- `get_time`: 获取当前时间
|
|
12
|
+
- `calculate`: 进行数学计算
|
|
13
|
+
- `search_web`: 网页搜索(需配置)
|
|
14
|
+
|
|
15
|
+
### 2. 适配器工具 (Adapter Tools)
|
|
16
|
+
|
|
17
|
+
每个适配器可以提供平台特定的工具:
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
// 适配器继承 Adapter 基类后自动获得 addTool 方法
|
|
21
|
+
class MyAdapter extends Adapter<MyBot> {
|
|
22
|
+
constructor(plugin: Plugin) {
|
|
23
|
+
super(plugin, 'my-platform', config);
|
|
24
|
+
|
|
25
|
+
// 注册默认工具(发送消息、列出 Bot 等)
|
|
26
|
+
this.registerDefaultTools();
|
|
27
|
+
|
|
28
|
+
// 注册自定义工具
|
|
29
|
+
this.addTool({
|
|
30
|
+
name: 'my_platform_get_user',
|
|
31
|
+
description: '获取平台用户信息',
|
|
32
|
+
parameters: {
|
|
33
|
+
type: 'object',
|
|
34
|
+
properties: {
|
|
35
|
+
userId: { type: 'string', description: '用户 ID' }
|
|
36
|
+
},
|
|
37
|
+
required: ['userId']
|
|
38
|
+
},
|
|
39
|
+
execute: async (args) => {
|
|
40
|
+
return await this.getUserInfo(args.userId);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Process 适配器示例工具**:
|
|
48
|
+
- `process_send_message`: 发送消息
|
|
49
|
+
- `process_list_bots`: 列出已连接的 Bot
|
|
50
|
+
- `process_get_info`: 获取进程信息
|
|
51
|
+
- `process_get_env`: 获取环境变量
|
|
52
|
+
- `process_console_log`: 输出到控制台
|
|
53
|
+
|
|
54
|
+
### 3. 插件工具 (Plugin Tools)
|
|
55
|
+
|
|
56
|
+
任何插件都可以注册自己的工具:
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
import { usePlugin, defineTool } from 'zhin.js';
|
|
60
|
+
|
|
61
|
+
const { addTool } = usePlugin();
|
|
62
|
+
|
|
63
|
+
// 使用 defineTool 获得类型支持
|
|
64
|
+
const weatherTool = defineTool({
|
|
65
|
+
name: 'get_weather',
|
|
66
|
+
description: '获取指定城市的天气信息',
|
|
67
|
+
parameters: {
|
|
68
|
+
type: 'object',
|
|
69
|
+
properties: {
|
|
70
|
+
city: { type: 'string', description: '城市名称' },
|
|
71
|
+
unit: {
|
|
72
|
+
type: 'string',
|
|
73
|
+
enum: ['celsius', 'fahrenheit'],
|
|
74
|
+
description: '温度单位'
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
required: ['city']
|
|
78
|
+
},
|
|
79
|
+
execute: async (args) => {
|
|
80
|
+
const { city, unit = 'celsius' } = args;
|
|
81
|
+
// 调用天气 API
|
|
82
|
+
return { city, temperature: 25, unit };
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// 注册工具
|
|
87
|
+
addTool(weatherTool);
|
|
88
|
+
|
|
89
|
+
// 或直接传入对象
|
|
90
|
+
addTool({
|
|
91
|
+
name: 'translate',
|
|
92
|
+
description: '翻译文本',
|
|
93
|
+
parameters: {
|
|
94
|
+
type: 'object',
|
|
95
|
+
properties: {
|
|
96
|
+
text: { type: 'string', description: '要翻译的文本' },
|
|
97
|
+
from: { type: 'string', description: '源语言' },
|
|
98
|
+
to: { type: 'string', description: '目标语言' }
|
|
99
|
+
},
|
|
100
|
+
required: ['text', 'to']
|
|
101
|
+
},
|
|
102
|
+
execute: async (args) => {
|
|
103
|
+
// 翻译逻辑
|
|
104
|
+
return { translated: '...' };
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### 4. 自定义工具 (Custom Tools)
|
|
110
|
+
|
|
111
|
+
直接在 AI 服务中注册工具:
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
import { usePlugin } from 'zhin.js';
|
|
115
|
+
|
|
116
|
+
const { useContext } = usePlugin();
|
|
117
|
+
|
|
118
|
+
useContext('ai', (ai) => {
|
|
119
|
+
// 注册自定义工具
|
|
120
|
+
const dispose = ai.registerTool({
|
|
121
|
+
name: 'custom_tool',
|
|
122
|
+
description: '自定义工具',
|
|
123
|
+
parameters: { type: 'object', properties: {} },
|
|
124
|
+
execute: async () => ({ result: 'custom' })
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
return dispose; // 清理时自动移除
|
|
128
|
+
});
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## 使用工具
|
|
132
|
+
|
|
133
|
+
### 通过 Agent
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
useContext('ai', (ai) => {
|
|
137
|
+
// 创建 Agent 时自动收集所有可用工具
|
|
138
|
+
const agent = ai.createAgent({
|
|
139
|
+
provider: 'openai',
|
|
140
|
+
model: 'gpt-4',
|
|
141
|
+
systemPrompt: '你是一个智能助手',
|
|
142
|
+
// 可选:禁用自动收集外部工具
|
|
143
|
+
// collectExternalTools: false,
|
|
144
|
+
// 可选:禁用内置工具
|
|
145
|
+
// useBuiltinTools: false,
|
|
146
|
+
// 可选:添加额外工具
|
|
147
|
+
tools: [myExtraTool]
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
// 执行任务
|
|
151
|
+
const result = await agent.run('查询北京的天气并用英语描述');
|
|
152
|
+
console.log(result.content);
|
|
153
|
+
console.log(result.toolCalls); // 查看工具调用记录
|
|
154
|
+
});
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### 通过命令
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
# 查看所有可用工具
|
|
161
|
+
/ai.tools
|
|
162
|
+
|
|
163
|
+
# 使用带工具调用的对话
|
|
164
|
+
/chat 帮我查一下现在的时间
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## 工具收集机制
|
|
168
|
+
|
|
169
|
+
AI 服务通过以下方式收集工具:
|
|
170
|
+
|
|
171
|
+
1. **Plugin.collectAllTools()**: 遍历插件树收集所有插件注册的工具
|
|
172
|
+
2. **Adapter.getTools()**: 收集所有适配器注册的工具
|
|
173
|
+
3. **AIService.customTools**: 直接在 AI 服务中注册的工具
|
|
174
|
+
4. **AIService.builtinTools**: 内置工具
|
|
175
|
+
|
|
176
|
+
```
|
|
177
|
+
AIService.createAgent()
|
|
178
|
+
├── builtinTools (内置工具)
|
|
179
|
+
├── customTools (自定义工具)
|
|
180
|
+
├── Plugin.collectAllTools()
|
|
181
|
+
│ ├── 当前插件的工具
|
|
182
|
+
│ └── 所有子插件的工具(递归)
|
|
183
|
+
└── Adapter.getTools()
|
|
184
|
+
├── 默认工具(send_message, list_bots)
|
|
185
|
+
└── 平台特定工具
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## 最佳实践
|
|
189
|
+
|
|
190
|
+
### 工具命名规范
|
|
191
|
+
|
|
192
|
+
- 使用小写字母和下划线
|
|
193
|
+
- 包含来源前缀避免冲突:`platform_action` 或 `plugin_action`
|
|
194
|
+
- 例如:`icqq_get_group_members`, `music_search_song`
|
|
195
|
+
|
|
196
|
+
### 参数设计
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
{
|
|
200
|
+
type: 'object',
|
|
201
|
+
properties: {
|
|
202
|
+
// 必填参数放前面
|
|
203
|
+
userId: {
|
|
204
|
+
type: 'string',
|
|
205
|
+
description: '用户唯一标识符'
|
|
206
|
+
},
|
|
207
|
+
// 可选参数给默认值
|
|
208
|
+
limit: {
|
|
209
|
+
type: 'number',
|
|
210
|
+
description: '返回数量限制',
|
|
211
|
+
default: 10
|
|
212
|
+
},
|
|
213
|
+
// 枚举类型明确列出选项
|
|
214
|
+
format: {
|
|
215
|
+
type: 'string',
|
|
216
|
+
enum: ['json', 'text', 'markdown'],
|
|
217
|
+
description: '返回格式'
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
required: ['userId'] // 明确必填项
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### 错误处理
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
execute: async (args, context) => {
|
|
228
|
+
try {
|
|
229
|
+
const result = await doSomething(args);
|
|
230
|
+
return { success: true, data: result };
|
|
231
|
+
} catch (error) {
|
|
232
|
+
return {
|
|
233
|
+
success: false,
|
|
234
|
+
error: error instanceof Error ? error.message : String(error)
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### 安全考虑
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
execute: async (args, context) => {
|
|
244
|
+
// 检查上下文权限
|
|
245
|
+
if (context?.senderId !== 'admin') {
|
|
246
|
+
return { error: '权限不足' };
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// 过滤敏感操作
|
|
250
|
+
if (args.path?.includes('..')) {
|
|
251
|
+
return { error: '非法路径' };
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// 执行操作
|
|
255
|
+
return await secureOperation(args);
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## 类型定义
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
interface AITool {
|
|
263
|
+
/** 工具名称(唯一标识) */
|
|
264
|
+
name: string;
|
|
265
|
+
/** 工具描述(AI 用于理解用途) */
|
|
266
|
+
description: string;
|
|
267
|
+
/** 参数 JSON Schema */
|
|
268
|
+
parameters: ToolJsonSchema;
|
|
269
|
+
/** 工具执行函数 */
|
|
270
|
+
execute: (args: Record<string, any>, context?: ToolContext) => Promise<any>;
|
|
271
|
+
/** 工具来源标识(自动添加) */
|
|
272
|
+
source?: string;
|
|
273
|
+
/** 工具标签(用于分类过滤) */
|
|
274
|
+
tags?: string[];
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
interface ToolContext {
|
|
278
|
+
platform?: string; // 来源平台
|
|
279
|
+
botId?: string; // Bot ID
|
|
280
|
+
sceneId?: string; // 场景 ID
|
|
281
|
+
senderId?: string; // 发送者 ID
|
|
282
|
+
extra?: Record<string, any>; // 额外数据
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
interface ToolJsonSchema {
|
|
286
|
+
type: string;
|
|
287
|
+
properties?: Record<string, ToolJsonSchema>;
|
|
288
|
+
required?: string[];
|
|
289
|
+
items?: ToolJsonSchema;
|
|
290
|
+
enum?: any[];
|
|
291
|
+
description?: string;
|
|
292
|
+
default?: any;
|
|
293
|
+
}
|
|
294
|
+
```
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zhin.js/ai",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "AI Service for Zhin.js - Multi-model LLM integration with Agent capabilities",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./lib/index.js",
|
|
7
|
+
"types": "./lib/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./lib/index.d.ts",
|
|
11
|
+
"import": "./lib/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./providers/*": {
|
|
14
|
+
"types": "./lib/providers/*.d.ts",
|
|
15
|
+
"import": "./lib/providers/*.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"zhin",
|
|
20
|
+
"bot",
|
|
21
|
+
"service",
|
|
22
|
+
"ai",
|
|
23
|
+
"llm",
|
|
24
|
+
"openai",
|
|
25
|
+
"claude",
|
|
26
|
+
"anthropic",
|
|
27
|
+
"deepseek",
|
|
28
|
+
"ollama",
|
|
29
|
+
"agent",
|
|
30
|
+
"tool-use",
|
|
31
|
+
"function-calling"
|
|
32
|
+
],
|
|
33
|
+
"author": {
|
|
34
|
+
"name": "lc-cn",
|
|
35
|
+
"email": "admin@liucl.cn",
|
|
36
|
+
"url": "https://github.com/lc-cn"
|
|
37
|
+
},
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"repository": {
|
|
40
|
+
"url": "git+https://github.com/zhinjs/zhin.git",
|
|
41
|
+
"type": "git",
|
|
42
|
+
"directory": "packages/ai"
|
|
43
|
+
},
|
|
44
|
+
"publishConfig": {
|
|
45
|
+
"access": "public",
|
|
46
|
+
"registry": "https://registry.npmjs.org"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsc",
|
|
50
|
+
"clean": "rm -rf lib"
|
|
51
|
+
},
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"eventsource-parser": "^3.0.0",
|
|
54
|
+
"segment-matcher": "latest"
|
|
55
|
+
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"@zhin.js/core": "workspace:*",
|
|
58
|
+
"@zhin.js/logger": "workspace:*"
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"@types/node": "latest",
|
|
62
|
+
"typescript": "^5.3.0",
|
|
63
|
+
"@zhin.js/core": "workspace:*",
|
|
64
|
+
"@zhin.js/logger": "workspace:*"
|
|
65
|
+
}
|
|
66
|
+
}
|