@huyooo/ai-chat-core 0.1.6 → 0.1.7

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 ADDED
@@ -0,0 +1,423 @@
1
+ # @huyooo/ai-chat-core
2
+
3
+ AI Chat 核心库 - 支持多模型的 Agent 框架,可插拔的工具系统。
4
+
5
+ > 📖 **深入了解**:查看 [技术架构文档](../../ARCHITECTURE.md) 了解流式事件、工具调用、历史管理等核心原理。
6
+
7
+ ## 特性
8
+
9
+ - 🤖 **多模型支持**:ARK (豆包/DeepSeek)、通义千问、Gemini、OpenRouter (Claude)
10
+ - 🔧 **可插拔工具系统**:内置工具 + 自定义工具,完全由用户控制
11
+ - 🔄 **Provider 模式**:统一的模型接口,易于扩展
12
+ - 📡 **流式响应**:支持思考、搜索、工具调用等事件流
13
+
14
+ ## 架构
15
+
16
+ ```
17
+ ┌─────────────────────────────────────────────────────────┐
18
+ │ HybridAgent │
19
+ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
20
+ │ │ Router │ │ Tools │ │ Stateless │ │
21
+ │ │ (模型路由) │ │ (工具注册) │ │ (完全无状态) │ │
22
+ │ └─────────────┘ └─────────────┘ └─────────────────┘ │
23
+ └─────────────────────────┬───────────────────────────────┘
24
+
25
+ ┌───────────────┼───────────────┐
26
+ ▼ ▼ ▼
27
+ ┌──────────┐ ┌──────────┐ ┌──────────┐
28
+ │ ARK │ │ Qwen │ │ Gemini │ ...
29
+ │ Provider │ │ Provider │ │ Provider │
30
+ └──────────┘ └──────────┘ └──────────┘
31
+ ```
32
+
33
+ ## 安装
34
+
35
+ ```bash
36
+ npm install @huyooo/ai-chat-core
37
+ ```
38
+
39
+ ## 快速开始
40
+
41
+ ```typescript
42
+ import { HybridAgent } from '@huyooo/ai-chat-core';
43
+ import {
44
+ getWorkingDirTool,
45
+ executeCommandTool,
46
+ analyzeImageTool,
47
+ generateImageTool,
48
+ analyzeVideoTool
49
+ } from '@huyooo/ai-chat-core';
50
+
51
+ // 创建 Agent
52
+ const agent = new HybridAgent({
53
+ arkApiKey: 'your-ark-api-key',
54
+ geminiApiKey: 'your-gemini-api-key',
55
+ // 注入工具(必须手动注入,不传则无工具)
56
+ tools: [
57
+ getWorkingDirTool,
58
+ executeCommandTool,
59
+ analyzeImageTool,
60
+ ],
61
+ });
62
+
63
+ // 发送消息
64
+ for await (const event of agent.chat('列出当前目录的文件')) {
65
+ switch (event.type) {
66
+ case 'text_delta':
67
+ process.stdout.write(event.data.content);
68
+ break;
69
+ case 'tool_call_start':
70
+ console.log(`\n调用工具: ${event.data.name}`);
71
+ break;
72
+ case 'done':
73
+ console.log('\n完成');
74
+ break;
75
+ }
76
+ }
77
+ ```
78
+
79
+ ## 工具系统
80
+
81
+ ### 内置工具
82
+
83
+ | 工具 | 描述 | 依赖 |
84
+ |------|------|------|
85
+ | `getWorkingDirTool` | 获取当前工作目录 | - |
86
+ | `getPlatformTool` | 获取操作系统平台信息 | - |
87
+ | `executeCommandTool` | 执行 shell 命令 | - |
88
+ | `analyzeImageTool` | 分析图片内容 | Gemini |
89
+ | `generateImageTool` | 生成图片 | Gemini |
90
+ | `analyzeVideoTool` | 分析视频内容 | Gemini |
91
+ | `getWeatherTool` | 查询中国城市天气 | 高德 API (内置 Key) |
92
+
93
+ ### 按需注入
94
+
95
+ ```typescript
96
+ // 只使用部分工具
97
+ import {
98
+ getWorkingDirTool,
99
+ getPlatformTool,
100
+ executeCommandTool,
101
+ getWeatherTool
102
+ } from '@huyooo/ai-chat-core';
103
+
104
+ const agent = new HybridAgent({
105
+ ...config,
106
+ tools: [
107
+ getWorkingDirTool,
108
+ getPlatformTool,
109
+ executeCommandTool,
110
+ getWeatherTool, // 天气查询(支持中国 337 个城市)
111
+ ],
112
+ });
113
+ ```
114
+
115
+ ### 天气工具说明
116
+
117
+ `getWeatherTool` 使用高德天气 API,支持查询中国 337 个主要城市的实时天气:
118
+
119
+ ```typescript
120
+ // 工具参数
121
+ {
122
+ city: string // 城市名称,如 "北京"、"上海"、"深圳"
123
+ }
124
+
125
+ // 返回结构
126
+ {
127
+ city: string // 城市名
128
+ temperature: number // 温度 (°C)
129
+ condition: string // 天气状况 (晴/多云/雨等)
130
+ humidity: number // 湿度 (%)
131
+ wind: string // 风向风力 (如 "西北风 ≤3级")
132
+ }
133
+ ```
134
+
135
+ 支持的城市包括:所有省会城市、直辖市、地级市等。
136
+
137
+ ### 自定义工具
138
+
139
+ ```typescript
140
+ import type { Tool } from '@huyooo/ai-chat-core';
141
+
142
+ const myTool: Tool = {
143
+ name: 'my_tool',
144
+ description: '我的自定义工具',
145
+ parameters: {
146
+ type: 'object',
147
+ properties: {
148
+ input: { type: 'string', description: '输入参数' }
149
+ },
150
+ required: ['input']
151
+ },
152
+ execute: async (args, context) => {
153
+ // context.workingDir - 当前工作目录
154
+ // context.executeCommand - 执行 shell 命令
155
+ // context.geminiClient - Gemini 客户端(可选)
156
+ // context.signal - 取消信号(AbortSignal)
157
+ return `处理结果: ${args.input}`;
158
+ }
159
+ };
160
+
161
+ const agent = new HybridAgent({
162
+ ...config,
163
+ tools: [getWorkingDirTool, executeCommandTool, myTool],
164
+ });
165
+ ```
166
+
167
+ ## 取消功能
168
+
169
+ ### 取消请求
170
+
171
+ 调用 `agent.abort()` 可以中断当前正在进行的请求:
172
+
173
+ ```typescript
174
+ // 开始请求
175
+ const chatGenerator = agent.chat('生成一张图片');
176
+
177
+ // 用户点击取消按钮
178
+ cancelButton.onclick = () => {
179
+ agent.abort(); // 中断请求
180
+ };
181
+
182
+ // 处理事件
183
+ for await (const event of chatGenerator) {
184
+ if (event.type === 'abort') {
185
+ console.log('请求已取消');
186
+ break;
187
+ }
188
+ // 处理其他事件...
189
+ }
190
+ ```
191
+
192
+ ### 取消架构
193
+
194
+ 取消信号 (`AbortSignal`) 从 Agent 层层传递到工具执行:
195
+
196
+ ```
197
+ ┌─────────────┐ abort() ┌─────────────┐ signal ┌─────────────┐
198
+ │ Agent │ ───────────► │ Orchestrator│ ───────────► │ Tool │
199
+ │ AbortCtrl │ │ 检查 aborted │ │context.signal
200
+ └─────────────┘ └─────────────┘ └─────────────┘
201
+
202
+
203
+ ┌─────────────┐
204
+ │ fetch/API │
205
+ │ abortSignal │
206
+ └─────────────┘
207
+ ```
208
+
209
+ ### 自定义工具支持取消
210
+
211
+ 如果你的工具包含**耗时操作**(如网络请求、文件读写),建议支持取消:
212
+
213
+ ```typescript
214
+ const myAsyncTool: Tool = {
215
+ name: 'my_async_tool',
216
+ description: '一个耗时的异步工具',
217
+ parameters: { /* ... */ },
218
+ execute: async (args, context) => {
219
+ // 1. 执行前检查是否已取消
220
+ if (context.signal?.aborted) {
221
+ return '操作已取消';
222
+ }
223
+
224
+ // 2. 网络请求:传递 signal 给 fetch
225
+ const response = await fetch('https://api.example.com/data', {
226
+ signal: context.signal, // fetch 原生支持 AbortSignal
227
+ });
228
+
229
+ // 3. 自定义异步操作:监听 abort 事件
230
+ const result = await new Promise((resolve, reject) => {
231
+ const abortHandler = () => {
232
+ reject(new Error('操作已取消'));
233
+ };
234
+ context.signal?.addEventListener('abort', abortHandler);
235
+
236
+ // 执行异步操作...
237
+ doSomethingAsync().then((data) => {
238
+ context.signal?.removeEventListener('abort', abortHandler);
239
+ resolve(data);
240
+ });
241
+ });
242
+
243
+ return result;
244
+ }
245
+ };
246
+ ```
247
+
248
+ ### 内置工具取消支持
249
+
250
+ | 工具 | 取消方式 | 说明 |
251
+ |------|----------|------|
252
+ | `executeCommandTool` | `spawn` + `kill` | 终止子进程 |
253
+ | `analyzeImageTool` | Gemini `abortSignal` | 中断 API 请求 |
254
+ | `generateImageTool` | Gemini `abortSignal` | 中断 API 请求 |
255
+ | `analyzeVideoTool` | Gemini `abortSignal` | 中断 API 请求 |
256
+ | `getWeatherTool` | `fetch` signal | 中断 HTTP 请求 |
257
+ | `getWorkingDirTool` | - | 瞬时操作,无需取消 |
258
+ | `getPlatformTool` | - | 瞬时操作,无需取消 |
259
+
260
+ ### 何时需要支持取消
261
+
262
+ | 操作类型 | 是否需要支持取消 |
263
+ |----------|-----------------|
264
+ | 网络请求 | ✅ 是 |
265
+ | Shell 命令执行 | ✅ 是 |
266
+ | 大文件读写 | ✅ 是 |
267
+ | 长时间计算 | ✅ 是 |
268
+ | 返回内存变量 | ❌ 否(< 1ms) |
269
+ | 简单字符串操作 | ❌ 否(< 1ms) |
270
+
271
+ ## 配置
272
+
273
+ ```typescript
274
+ interface AgentConfig {
275
+ // API Keys
276
+ arkApiKey: string; // 豆包/DeepSeek (火山引擎)
277
+ qwenApiKey?: string; // 通义千问
278
+ geminiApiKey: string; // Gemini (图片/视频分析)
279
+ openrouterApiKey?: string; // OpenRouter (Claude 等)
280
+
281
+ // 可选配置
282
+ arkApiUrl?: string;
283
+ qwenApiUrl?: string;
284
+ openrouterApiUrl?: string;
285
+ workingDir?: string;
286
+
287
+ // 工具(必须手动注入)
288
+ tools?: Tool[];
289
+ }
290
+ ```
291
+
292
+ ## 聊天选项
293
+
294
+ ```typescript
295
+ /** 聊天历史消息(无状态架构) */
296
+ interface ChatHistoryMessage {
297
+ role: 'user' | 'assistant' | 'system' | 'tool';
298
+ content: string;
299
+ }
300
+
301
+ interface ChatOptions {
302
+ mode?: 'agent' | 'plan' | 'ask'; // 对话模式
303
+ model?: string; // 模型 ID
304
+ enableWebSearch?: boolean; // 联网搜索
305
+ thinkingMode?: 'enabled' | 'disabled'; // 深度思考
306
+ autoRunConfig?: AutoRunConfig; // 自动运行配置
307
+ history?: ChatHistoryMessage[]; // 对话历史(无状态架构)
308
+ }
309
+
310
+ // 自动运行配置
311
+ interface AutoRunConfig {
312
+ mode?: 'run-everything' | 'manual'; // 自动运行模式
313
+ }
314
+
315
+ // 示例:带历史的对话
316
+ const history = [
317
+ { role: 'user', content: '你好' },
318
+ { role: 'assistant', content: '你好!有什么可以帮助你的?' },
319
+ ];
320
+
321
+ for await (const event of agent.chat('继续上次的话题', {
322
+ mode: 'agent',
323
+ model: 'doubao-seed-1-6-251015',
324
+ enableWebSearch: true,
325
+ thinkingMode: 'enabled',
326
+ history, // ← 传入历史,后端无状态
327
+ autoRunConfig: {
328
+ mode: 'run-everything',
329
+ },
330
+ })) {
331
+ // 处理事件
332
+ }
333
+ ```
334
+
335
+ ### 自动运行配置说明
336
+
337
+ `autoRunConfig` 用于控制 Agent 的工具执行行为和安全保护:
338
+
339
+ - **mode**: 自动运行模式
340
+ - `'run-everything'`: 运行所有内容(自动执行)
341
+ - `'manual'`: 手动批准模式(每次执行前询问)
342
+
343
+ ## 事件类型
344
+
345
+ ```typescript
346
+ // 思考事件
347
+ 'thinking_start' | 'thinking_delta' | 'thinking_end'
348
+
349
+ // 搜索事件
350
+ 'search_start' | 'search_result'
351
+
352
+ // 工具事件
353
+ 'tool_call_start' | 'tool_call_result'
354
+
355
+ // 文本事件
356
+ 'text_delta'
357
+
358
+ // 状态事件
359
+ 'done' | 'error' | 'abort'
360
+ ```
361
+
362
+ ## 支持的模型
363
+
364
+ ### 原生模型
365
+
366
+ | 模型 ID | 显示名称 | Provider |
367
+ |---------|----------|----------|
368
+ | `doubao-seed-1-6-251015` | 豆包 Seed 1.6 | ARK |
369
+ | `deepseek-v3-1-terminus` | DeepSeek V3 | ARK |
370
+ | `qwen3-max-preview` | 通义千问 Max | Qwen |
371
+ | `gemini-3-pro-preview` | Gemini 3 Pro | Gemini |
372
+
373
+ ### OpenRouter 模型
374
+
375
+ | 模型 ID | 显示名称 |
376
+ |---------|----------|
377
+ | `openai/gpt-5.2` | GPT-5.2 |
378
+ | `anthropic/claude-opus-4.5` | Claude Opus 4.5 |
379
+ | `google/gemini-3-pro-preview` | Gemini 3 Pro |
380
+
381
+ ## API
382
+
383
+ ### HybridAgent
384
+
385
+ ```typescript
386
+ class HybridAgent {
387
+ constructor(config: AgentConfig);
388
+
389
+ // 聊天(无状态,历史通过 options.history 传入)
390
+ chat(message: string, options?: ChatOptions, images?: string[]): AsyncGenerator<ChatEvent>;
391
+
392
+ // 控制
393
+ abort(): void; // 取消当前请求
394
+ setWorkingDir(dir: string): void; // 设置工作目录
395
+
396
+ // 查询
397
+ getConfig(): RuntimeConfig;
398
+ getModelCapabilities(model: string): ModelCapabilities;
399
+ getSupportedModels(): ModelOption[];
400
+ }
401
+ ```
402
+
403
+ ### 无状态架构说明
404
+
405
+ Agent 采用**完全无状态**设计:
406
+
407
+ - ❌ 不维护对话历史(无 `conversationHistory`)
408
+ - ❌ 无 `clearHistory()` / `getHistory()` / `setHistory()` 方法
409
+ - ✅ 历史通过 `ChatOptions.history` 参数传入
410
+ - ✅ 每次请求独立处理,可水平扩展
411
+
412
+ ```typescript
413
+ // 正确用法:前端负责管理历史
414
+ const history = loadFromDatabase(sessionId);
415
+ for await (const event of agent.chat('问题', { history })) {
416
+ // ...
417
+ }
418
+ saveToDatabase(sessionId, newMessage);
419
+ ```
420
+
421
+ ## License
422
+
423
+ MIT