@blueking/chat-helper 0.0.1-beta.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.
Files changed (51) hide show
  1. package/README.md +1112 -0
  2. package/dist/agent/index.d.ts +2 -0
  3. package/dist/agent/index.ts.js +26 -0
  4. package/dist/agent/type.d.ts +87 -0
  5. package/dist/agent/type.ts.js +25 -0
  6. package/dist/agent/use-agent.d.ts +540 -0
  7. package/dist/agent/use-agent.ts.js +102 -0
  8. package/dist/event/ag-ui.d.ts +137 -0
  9. package/dist/event/ag-ui.ts.js +434 -0
  10. package/dist/event/index.d.ts +2 -0
  11. package/dist/event/index.ts.js +26 -0
  12. package/dist/event/type.d.ts +329 -0
  13. package/dist/event/type.ts.js +64 -0
  14. package/dist/http/fetch/fetch.d.ts +84 -0
  15. package/dist/http/fetch/fetch.ts.js +503 -0
  16. package/dist/http/fetch/index.d.ts +6 -0
  17. package/dist/http/fetch/index.ts.js +41 -0
  18. package/dist/http/index.d.ts +38 -0
  19. package/dist/http/index.ts.js +36 -0
  20. package/dist/http/module/agent.d.ts +9 -0
  21. package/dist/http/module/agent.ts.js +36 -0
  22. package/dist/http/module/index.d.ts +36 -0
  23. package/dist/http/module/index.ts.js +41 -0
  24. package/dist/http/module/message.d.ts +14 -0
  25. package/dist/http/module/message.ts.js +52 -0
  26. package/dist/http/module/session.d.ts +25 -0
  27. package/dist/http/module/session.ts.js +67 -0
  28. package/dist/http/transform/agent.d.ts +7 -0
  29. package/dist/http/transform/agent.ts.js +71 -0
  30. package/dist/http/transform/index.d.ts +3 -0
  31. package/dist/http/transform/index.ts.js +27 -0
  32. package/dist/http/transform/message.d.ts +13 -0
  33. package/dist/http/transform/message.ts.js +155 -0
  34. package/dist/http/transform/session.d.ts +37 -0
  35. package/dist/http/transform/session.ts.js +100 -0
  36. package/dist/index.d.ts +3363 -0
  37. package/dist/index.ts.js +40 -0
  38. package/dist/message/index.d.ts +2 -0
  39. package/dist/message/index.ts.js +26 -0
  40. package/dist/message/type.d.ts +277 -0
  41. package/dist/message/type.ts.js +67 -0
  42. package/dist/message/use-message.d.ts +912 -0
  43. package/dist/message/use-message.ts.js +87 -0
  44. package/dist/session/index.d.ts +2 -0
  45. package/dist/session/index.ts.js +26 -0
  46. package/dist/session/type.d.ts +61 -0
  47. package/dist/session/type.ts.js +25 -0
  48. package/dist/session/use-session.d.ts +1898 -0
  49. package/dist/session/use-session.ts.js +144 -0
  50. package/dist/type.d.ts +14 -0
  51. package/package.json +27 -0
package/README.md ADDED
@@ -0,0 +1,1112 @@
1
+ # @blueking/chat-helper
2
+
3
+ 一个用于 Vue3 的聊天助手工具包,提供完整的 AI 对话功能,支持流式响应、会话管理、消息管理等功能。
4
+
5
+ ## 安装
6
+
7
+ ```bash
8
+ npm install @blueking/chat-helper
9
+ ```
10
+
11
+ ## 快速开始
12
+
13
+ ```typescript
14
+ import { useChatHelper } from '@blueking/chat-helper';
15
+
16
+ // 在 Vue 组件中使用
17
+ const chatHelper = useChatHelper({
18
+ requestData: {
19
+ urlPrefix: 'https://your-api-domain.com/api/',
20
+ headers: {
21
+ Authorization: 'Bearer your-token',
22
+ },
23
+ },
24
+ });
25
+
26
+ // 解构返回的模块
27
+ const { agent, session, message, http } = chatHelper;
28
+ ```
29
+
30
+ ## useChatHelper 返回数据说明
31
+
32
+ `useChatHelper` 返回一个包含四个模块的对象:
33
+
34
+ ### 1. agent - 代理模块
35
+
36
+ 管理 AI 代理相关功能。
37
+
38
+ ```typescript
39
+ const { agent } = chatHelper;
40
+
41
+ // 响应式数据
42
+ agent.info; // Ref<IAgentInfo | null> - agent 信息
43
+ agent.isInfoLoading; // Ref<boolean> - agent 信息加载状态
44
+
45
+ // 方法
46
+ agent.getAgentInfo(); // () => Promise<void> - 获取 agent 信息
47
+ agent.chat(); // () => void - 开始聊天(流式响应)
48
+ agent.stopChat(); // () => Promise<void> - 停止聊天
49
+ ```
50
+
51
+ **使用示例**:
52
+
53
+ ```vue
54
+ <template>
55
+ <div>
56
+ <div v-if="agent.isInfoLoading">加载中...</div>
57
+ <div v-else-if="agent.info">
58
+ <h2>{{ agent.info.name }}</h2>
59
+ <p>{{ agent.info.description }}</p>
60
+ </div>
61
+ <button @click="startChat">开始对话</button>
62
+ <button @click="agent.stopChat">停止对话</button>
63
+ </div>
64
+ </template>
65
+
66
+ <script setup lang="ts">
67
+ import { onMounted } from 'vue';
68
+ import { useChatHelper } from '@blueking/chat-helper';
69
+
70
+ const { agent } = useChatHelper({
71
+ /* ... */
72
+ });
73
+
74
+ onMounted(() => {
75
+ agent.getAgentInfo();
76
+ });
77
+
78
+ const startChat = () => {
79
+ agent.chat();
80
+ };
81
+ </script>
82
+ ```
83
+
84
+ ### 2. session - 会话模块
85
+
86
+ 管理聊天会话的创建、切换、更新和删除。
87
+
88
+ ```typescript
89
+ const { session } = chatHelper;
90
+
91
+ // 响应式数据
92
+ session.list; // Ref<ISession[]> - 会话列表
93
+ session.current; // Ref<ISession | null> - 当前会话
94
+ session.isListLoading; // Ref<boolean> - 列表加载状态
95
+ session.isCurrentLoading; // Ref<boolean> - 当前会话加载状态
96
+ session.isCreateLoading; // Ref<boolean> - 创建会话加载状态
97
+ session.isUpdateLoading; // Ref<boolean> - 更新会话加载状态
98
+ session.isDeleteLoading; // Ref<boolean> - 删除会话加载状态
99
+
100
+ // 方法
101
+ session.getSessions(); // () => Promise<void> - 获取会话列表
102
+ session.chooseSession(sessionCode); // (sessionCode: string) => Promise<void> - 选择会话
103
+ session.getSession(sessionCode); // (sessionCode: string) => Promise<void> - 获取单个会话
104
+ session.createSession(session); // (session: ISession) => Promise<void> - 创建会话
105
+ session.updateSession(session); // (session: ISession) => Promise<void> - 更新会话
106
+ session.deleteSession(sessionCode); // (sessionCode: string) => Promise<void> - 删除会话
107
+ ```
108
+
109
+ **使用示例**:
110
+
111
+ ```vue
112
+ <template>
113
+ <div>
114
+ <ul v-if="!session.isListLoading">
115
+ <li
116
+ v-for="item in session.list"
117
+ :key="item.sessionCode"
118
+ @click="session.chooseSession(item.sessionCode)"
119
+ :class="{ active: session.current?.sessionCode === item.sessionCode }"
120
+ >
121
+ {{ item.title }}
122
+ </li>
123
+ </ul>
124
+ <button @click="createNewSession">新建会话</button>
125
+ </div>
126
+ </template>
127
+
128
+ <script setup lang="ts">
129
+ import { onMounted } from 'vue';
130
+ import { useChatHelper } from '@blueking/chat-helper';
131
+
132
+ const { session } = useChatHelper({
133
+ /* ... */
134
+ });
135
+
136
+ onMounted(() => {
137
+ session.getSessions();
138
+ });
139
+
140
+ const createNewSession = () => {
141
+ session.createSession({
142
+ title: '新会话',
143
+ // ... 其他会话属性
144
+ });
145
+ };
146
+ </script>
147
+ ```
148
+
149
+ ### 3. message - 消息模块
150
+
151
+ 管理聊天消息的获取、添加、修改和删除。
152
+
153
+ ```typescript
154
+ const { message } = chatHelper;
155
+
156
+ // 响应式数据
157
+ message.list; // Ref<IMessage[]> - 消息列表
158
+ message.isListLoading; // Ref<boolean> - 列表加载状态
159
+ message.isDeleteLoading; // Ref<boolean> - 删除加载状态
160
+
161
+ // 方法
162
+ message.getMessages(sessionCode); // (sessionCode: string) => Promise<void> - 获取消息列表
163
+ message.plusMessage(message); // (message: IMessage) => void - 添加消息
164
+ message.modifyMessage(message); // (message: IMessage) => void - 修改消息
165
+ message.deleteMessage(id); // (id: number) => Promise<void> - 删除消息
166
+ message.batchDeleteMessages(ids); // (ids: number[]) => Promise<void> - 批量删除消息
167
+ message.getCurrentLoadingMessage(); // () => IMessage | undefined - 获取当前加载中的消息
168
+ message.getMessageById(id); // (id: number) => IMessage | undefined - 根据 ID 获取消息
169
+ ```
170
+
171
+ **使用示例**:
172
+
173
+ ```vue
174
+ <template>
175
+ <div class="message-list">
176
+ <div
177
+ v-for="msg in message.list"
178
+ :key="msg.id"
179
+ class="message-item"
180
+ >
181
+ <div class="role">{{ msg.role }}</div>
182
+ <div class="content">
183
+ <div
184
+ v-for="(content, index) in msg.content"
185
+ :key="index"
186
+ >
187
+ <template v-if="content.type === 'text'">
188
+ {{ content.data }}
189
+ </template>
190
+ </div>
191
+ </div>
192
+ <button @click="message.deleteMessage(msg.id)">删除</button>
193
+ </div>
194
+ </div>
195
+ </template>
196
+
197
+ <script setup lang="ts">
198
+ import { useChatHelper } from '@blueking/chat-helper';
199
+
200
+ const { message } = useChatHelper({
201
+ /* ... */
202
+ });
203
+ </script>
204
+ ```
205
+
206
+ ### 4. http - HTTP 模块
207
+
208
+ 底层 HTTP 请求模块,提供各种 API 调用方法。
209
+
210
+ ```typescript
211
+ const { http } = chatHelper;
212
+
213
+ // 包含以下子模块:
214
+ http.agent; // Agent API
215
+ http.session; // Session API
216
+ http.message; // Message API
217
+ ```
218
+
219
+ 一般情况下,您不需要直接使用 `http` 模块,因为 `agent`、`session` 和 `message` 模块已经封装了常用的业务逻辑。
220
+
221
+ ## 配置选项
222
+
223
+ ### requestData(必需)
224
+
225
+ 配置 HTTP 请求的基础信息。
226
+
227
+ ```typescript
228
+ useChatHelper({
229
+ requestData: {
230
+ // API 基础路径(必需)
231
+ urlPrefix: 'https://your-api-domain.com/api/',
232
+
233
+ // 额外的请求数据(可选)
234
+ data: {
235
+ appId: 'your-app-id',
236
+ version: '1.0.0',
237
+ },
238
+ // 或者使用函数动态返回
239
+ data: () => ({
240
+ appId: getAppId(),
241
+ timestamp: Date.now(),
242
+ }),
243
+
244
+ // 额外的请求头(可选)
245
+ headers: {
246
+ Authorization: 'Bearer your-token',
247
+ 'X-Custom-Header': 'value',
248
+ },
249
+ // 或者使用函数动态返回
250
+ headers: () => ({
251
+ Authorization: `Bearer ${getToken()}`,
252
+ 'X-Request-ID': generateRequestId(),
253
+ }),
254
+ },
255
+ });
256
+ ```
257
+
258
+ ### interceptors(可选)
259
+
260
+ 配置请求和响应拦截器,用于统一处理请求和响应。
261
+
262
+ ```typescript
263
+ useChatHelper({
264
+ requestData: {
265
+ /* ... */
266
+ },
267
+ interceptors: {
268
+ // 请求拦截器
269
+ request: config => {
270
+ // 在发送请求之前做些什么
271
+ console.log('Request:', config);
272
+
273
+ // 添加自定义请求头
274
+ config.headers = {
275
+ ...config.headers,
276
+ 'X-Request-Time': new Date().toISOString(),
277
+ };
278
+
279
+ // 必须返回 config
280
+ return config;
281
+ },
282
+
283
+ // 响应拦截器
284
+ response: response => {
285
+ // 对响应数据做些什么
286
+ console.log('Response:', response);
287
+
288
+ // 可以在这里做统一的错误处理
289
+ if (response.data.code !== 0) {
290
+ console.error('API Error:', response.data.message);
291
+ }
292
+
293
+ // 必须返回 response
294
+ return response;
295
+ },
296
+ },
297
+ });
298
+ ```
299
+
300
+ **拦截器使用场景**:
301
+
302
+ 1. **请求拦截器**:
303
+
304
+ - 添加认证 token
305
+ - 添加请求时间戳
306
+ - 添加请求 ID
307
+ - 记录请求日志
308
+ - 请求参数加密
309
+
310
+ 2. **响应拦截器**:
311
+ - 统一错误处理
312
+ - 响应数据解密
313
+ - 数据格式转换
314
+ - 记录响应日志
315
+ - 刷新 token
316
+
317
+ ### protocol(可选)
318
+
319
+ 自定义 SSE(Server-Sent Events)协议处理器,用于处理流式响应。
320
+
321
+ #### 使用默认 protocol
322
+
323
+ 如果不提供 `protocol` 配置,系统会使用默认的 `AGUIProtocol`:
324
+
325
+ ```typescript
326
+ useChatHelper({
327
+ requestData: {
328
+ /* ... */
329
+ },
330
+ // 不配置 protocol,使用默认的 AGUIProtocol
331
+ });
332
+ ```
333
+
334
+ #### 使用 protocol 钩子函数
335
+
336
+ `AGUIProtocol` 提供了四个生命周期钩子函数,您可以在创建 protocol 实例时传入:
337
+
338
+ ```typescript
339
+ import { useChatHelper, AGUIProtocol } from '@blueking/chat-helper';
340
+
341
+ const { agent } = useChatHelper({
342
+ requestData: {
343
+ urlPrefix: 'https://your-api-domain.com/api/',
344
+ },
345
+ protocol: new AGUIProtocol({
346
+ // 流式响应开始时调用
347
+ onStart: () => {
348
+ console.log('开始接收流式响应');
349
+ // 显示加载动画
350
+ // 禁用发送按钮
351
+ },
352
+ // 每次接收到事件时调用
353
+ onMessage: event => {
354
+ console.log('接收到事件:', event);
355
+ // 记录事件日志
356
+ // 更新进度条
357
+ // 触发自定义事件
358
+ },
359
+ // 流式响应完成时调用
360
+ onDone: () => {
361
+ console.log('流式响应完成');
362
+ // 隐藏加载动画
363
+ // 启用发送按钮
364
+ // 播放完成提示音
365
+ },
366
+ // 发生错误时调用
367
+ onError: error => {
368
+ console.error('流式响应错误:', error);
369
+ // 显示错误提示
370
+ // 恢复 UI 状态
371
+ // 上报错误日志
372
+ },
373
+ }),
374
+ });
375
+ ```
376
+
377
+ **钩子函数使用场景**:
378
+
379
+ - **onStart**:显示加载状态、禁用输入框、重置 UI 状态
380
+ - **onMessage**:记录事件日志、更新进度、触发自定义事件、实时分析数据
381
+ - **onDone**:隐藏加载状态、启用输入框、播放提示音、保存会话历史
382
+ - **onError**:显示错误提示、恢复 UI 状态、上报错误、重试逻辑
383
+
384
+ #### 自定义 protocol
385
+
386
+ 如果您需要自定义流式响应的处理逻辑,可以实现 `ISSEProtocol` 接口:
387
+
388
+ ```typescript
389
+ import { useChatHelper, type ISSEProtocol, type IMessageModule } from '@blueking/chat-helper';
390
+
391
+ class CustomProtocol implements ISSEProtocol {
392
+ private messageModule: IMessageModule;
393
+
394
+ constructor({ message }: { message: IMessageModule }) {
395
+ this.messageModule = message;
396
+ }
397
+
398
+ onStart() {
399
+ console.log('Stream started');
400
+ // 在流式响应开始时执行
401
+ }
402
+
403
+ onMessage(event: unknown) {
404
+ console.log('Received event:', event);
405
+ // 处理每个 SSE 事件
406
+ // 您可以根据事件类型更新消息列表
407
+ this.messageModule.plusMessage(/* ... */);
408
+ }
409
+
410
+ onDone() {
411
+ console.log('Stream completed');
412
+ // 在流式响应完成时执行
413
+ }
414
+
415
+ onError(error: Error) {
416
+ console.error('Stream error:', error);
417
+ // 处理错误
418
+ }
419
+ }
420
+
421
+ // 使用自定义 protocol
422
+ const { agent, message } = useChatHelper({
423
+ requestData: {
424
+ /* ... */
425
+ },
426
+ protocol: new CustomProtocol({ message }),
427
+ });
428
+ ```
429
+
430
+ #### 扩展默认 protocol - 重写事件处理钩子
431
+
432
+ `AGUIProtocol` 为每种事件类型都提供了对应的处理方法(钩子),您可以继承并重写这些方法来自定义行为:
433
+
434
+ ```typescript
435
+ import {
436
+ AGUIProtocol,
437
+ type ITextMessageChunkEvent,
438
+ type IRunErrorEvent,
439
+ type IThinkingStartEvent,
440
+ type IToolCallStartEvent,
441
+ } from '@blueking/chat-helper';
442
+
443
+ class MyCustomProtocol extends AGUIProtocol {
444
+ // 重写文本消息流式处理
445
+ handleTextMessageChunkEvent(event: ITextMessageChunkEvent) {
446
+ // 自定义处理逻辑
447
+ console.log('接收到文本块:', event.delta);
448
+
449
+ // 调用父类方法(保留默认行为)
450
+ super.handleTextMessageChunkEvent(event);
451
+
452
+ // 额外的自定义逻辑
453
+ // 例如:实时语音播报、敏感词过滤等
454
+ if (event.delta.includes('重要')) {
455
+ this.highlightImportantContent(event.messageId);
456
+ }
457
+ }
458
+
459
+ // 重写思考开始事件
460
+ handleThinkingStartEvent(event: IThinkingStartEvent) {
461
+ console.log('AI 开始思考:', event.title);
462
+
463
+ // 显示思考动画
464
+ this.showThinkingAnimation();
465
+
466
+ // 调用父类方法
467
+ super.handleThinkingStartEvent(event);
468
+ }
469
+
470
+ // 重写工具调用开始事件
471
+ handleToolCallStartEvent(event: IToolCallStartEvent) {
472
+ console.log('调用工具:', event.toolCallName);
473
+
474
+ // 显示工具调用提示
475
+ this.showToolCallNotification(event.toolCallName);
476
+
477
+ // 调用父类方法
478
+ super.handleToolCallStartEvent(event);
479
+ }
480
+
481
+ // 重写错误处理
482
+ handleRunErrorEvent(event: IRunErrorEvent) {
483
+ console.error('运行错误:', event.message);
484
+
485
+ // 自定义错误提示
486
+ this.showCustomErrorMessage(event.message);
487
+
488
+ // 上报错误
489
+ this.reportError(event);
490
+
491
+ // 调用父类方法
492
+ super.handleRunErrorEvent(event);
493
+ }
494
+
495
+ // 自定义辅助方法
496
+ private highlightImportantContent(messageId: string) {
497
+ // 高亮重要内容
498
+ }
499
+
500
+ private showThinkingAnimation() {
501
+ // 显示思考动画
502
+ }
503
+
504
+ private showToolCallNotification(toolName: string) {
505
+ // 显示工具调用通知
506
+ }
507
+
508
+ private showCustomErrorMessage(message: string) {
509
+ // 显示自定义错误消息
510
+ }
511
+
512
+ private reportError(event: IRunErrorEvent) {
513
+ // 上报错误到监控系统
514
+ }
515
+ }
516
+
517
+ const { agent } = useChatHelper({
518
+ requestData: {
519
+ /* ... */
520
+ },
521
+ protocol: new MyCustomProtocol({
522
+ onStart: () => console.log('开始对话'),
523
+ onDone: () => console.log('对话完成'),
524
+ }),
525
+ });
526
+ ```
527
+
528
+ **常用的事件处理钩子**:
529
+
530
+ | 钩子方法 | 说明 | 使用场景 |
531
+ | --------------------------------------- | ------------------ | ---------------------- |
532
+ | `handleRunStartedEvent` | 运行开始 | 创建新消息、初始化状态 |
533
+ | `handleRunFinishedEvent` | 运行完成 | 更新消息状态、保存历史 |
534
+ | `handleRunErrorEvent` | 运行错误 | 错误提示、状态恢复 |
535
+ | `handleTextMessageStartEvent` | 文本消息开始 | 准备文本容器 |
536
+ | `handleTextMessageChunkEvent` | 文本消息块(流式) | 实时显示文本、语音播报 |
537
+ | `handleTextMessageEndEvent` | 文本消息结束 | 完成文本渲染 |
538
+ | `handleThinkingStartEvent` | 思考开始 | 显示思考动画 |
539
+ | `handleThinkingTextMessageContentEvent` | 思考内容 | 显示思考过程 |
540
+ | `handleThinkingEndEvent` | 思考结束 | 隐藏思考动画、统计时间 |
541
+ | `handleToolCallStartEvent` | 工具调用开始 | 显示工具调用提示 |
542
+ | `handleToolCallArgsEvent` | 工具参数 | 显示调用参数 |
543
+ | `handleToolCallResultEvent` | 工具结果 | 显示调用结果 |
544
+ | `handleToolCallEndEvent` | 工具调用结束 | 完成工具调用展示 |
545
+ | `handleMessagesSnapshotEvent` | 消息快照 | 同步多端消息状态 |
546
+ | `handleActivityDeltaEvent` | 活动增量更新 | 实时更新活动状态 |
547
+ | `handleActivitySnapshotEvent` | 活动快照 | 获取完整活动状态 |
548
+
549
+ **实际应用示例**:
550
+
551
+ ```typescript
552
+ class EnhancedProtocol extends AGUIProtocol {
553
+ private audioPlayer: AudioPlayer;
554
+ private analytics: Analytics;
555
+
556
+ constructor(options) {
557
+ super(options);
558
+ this.audioPlayer = new AudioPlayer();
559
+ this.analytics = new Analytics();
560
+ }
561
+
562
+ // 实时语音播报
563
+ handleTextMessageChunkEvent(event: ITextMessageChunkEvent) {
564
+ super.handleTextMessageChunkEvent(event);
565
+
566
+ // 将文本转换为语音播放
567
+ if (this.audioPlayer.isEnabled()) {
568
+ this.audioPlayer.speak(event.delta);
569
+ }
570
+ }
571
+
572
+ // 统计思考时间
573
+ handleThinkingEndEvent(event: IThinkingEndEvent) {
574
+ super.handleThinkingEndEvent(event);
575
+
576
+ // 记录思考时长用于分析
577
+ this.analytics.trackThinkingTime(event.timestamp);
578
+ }
579
+
580
+ // 工具调用监控
581
+ handleToolCallStartEvent(event: IToolCallStartEvent) {
582
+ super.handleToolCallStartEvent(event);
583
+
584
+ // 记录工具使用情况
585
+ this.analytics.trackToolUsage(event.toolCallName);
586
+
587
+ // 显示工具调用进度
588
+ showNotification(`正在调用工具: ${event.toolCallName}`);
589
+ }
590
+ }
591
+ ```
592
+
593
+ **钩子函数最佳实践**:
594
+
595
+ 1. **始终调用父类方法**:重写钩子时,记得调用 `super.handleXxxEvent(event)` 以保留默认行为
596
+ 2. **避免阻塞操作**:钩子函数应该快速执行,避免长时间运行的同步操作
597
+ 3. **错误处理**:在钩子中添加 try-catch,避免错误影响整体流程
598
+ 4. **按需重写**:只重写需要自定义的钩子,不需要重写所有方法
599
+ 5. **类型安全**:使用 TypeScript 类型定义,确保事件参数类型正确
600
+
601
+ ```typescript
602
+ class SafeProtocol extends AGUIProtocol {
603
+ handleTextMessageChunkEvent(event: ITextMessageChunkEvent) {
604
+ try {
605
+ // 自定义逻辑
606
+ this.customLogic(event);
607
+
608
+ // 调用父类方法
609
+ super.handleTextMessageChunkEvent(event);
610
+ } catch (error) {
611
+ console.error('处理文本消息块时出错:', error);
612
+ // 即使出错也要调用父类方法,保证基本功能
613
+ super.handleTextMessageChunkEvent(event);
614
+ }
615
+ }
616
+
617
+ private customLogic(event: ITextMessageChunkEvent) {
618
+ // 您的自定义逻辑
619
+ }
620
+ }
621
+ ```
622
+
623
+ **AGUIProtocol 支持的所有事件类型**:
624
+
625
+ <details>
626
+ <summary>点击展开完整事件列表</summary>
627
+
628
+ **运行相关事件**:
629
+
630
+ - `RunStarted` - 运行开始,创建新的 AI 响应消息
631
+ - `RunFinished` - 运行完成,标记消息为完成状态
632
+ - `RunError` - 运行错误,显示错误信息
633
+
634
+ **文本消息事件**:
635
+
636
+ - `TextMessageStart` - 文本消息开始,创建文本内容容器
637
+ - `TextMessageChunk` - 文本消息块,流式接收文本内容(最常用)
638
+ - `TextMessageContent` - 文本消息内容,追加文本内容
639
+ - `TextMessageEnd` - 文本消息结束,标记文本为完成状态
640
+
641
+ **思考过程事件**:
642
+
643
+ - `ThinkingStart` - 思考开始,显示 AI 思考标题
644
+ - `ThinkingTextMessageStart` - 思考文本开始
645
+ - `ThinkingTextMessageContent` - 思考文本内容,流式接收思考过程
646
+ - `ThinkingTextMessageEnd` - 思考文本结束
647
+ - `ThinkingEnd` - 思考结束,计算思考时长
648
+
649
+ **工具调用事件**:
650
+
651
+ - `ToolCallStart` - 工具调用开始,显示调用的工具名称
652
+ - `ToolCallChunk` - 工具调用块,流式接收调用信息
653
+ - `ToolCallArgs` - 工具参数,接收工具调用参数
654
+ - `ToolCallResult` - 工具结果,接收工具执行结果
655
+ - `ToolCallEnd` - 工具调用结束,标记工具调用完成
656
+
657
+ **步骤相关事件**:
658
+
659
+ - `StepStarted` - 步骤开始,多步骤任务中的单步开始
660
+ - `StepFinished` - 步骤完成,单步任务完成
661
+
662
+ **状态同步事件**:
663
+
664
+ - `MessagesSnapshot` - 消息快照,用于多端消息同步
665
+ - `StateSnapshot` - 状态快照,完整状态信息
666
+ - `StateDelta` - 状态增量更新,使用 JSON Patch 格式
667
+ - `ActivitySnapshot` - 活动快照,完整活动信息
668
+ - `ActivityDelta` - 活动增量更新,使用 JSON Patch 格式
669
+
670
+ **其他事件**:
671
+
672
+ - `Raw` - 原始事件,透传底层 AI 服务的原始事件
673
+ - `Custom` - 自定义事件,用户自定义的事件类型
674
+
675
+ </details>
676
+
677
+ ## 完整示例
678
+
679
+ 以下是一个完整的聊天应用示例:
680
+
681
+ ```vue
682
+ <template>
683
+ <div class="chat-app">
684
+ <!-- 会话列表 -->
685
+ <aside class="session-list">
686
+ <button @click="createNewSession">新建会话</button>
687
+ <ul>
688
+ <li
689
+ v-for="item in session.list"
690
+ :key="item.sessionCode"
691
+ @click="session.chooseSession(item.sessionCode)"
692
+ :class="{ active: session.current?.sessionCode === item.sessionCode }"
693
+ >
694
+ {{ item.title }}
695
+ <button @click.stop="session.deleteSession(item.sessionCode)">删除</button>
696
+ </li>
697
+ </ul>
698
+ </aside>
699
+
700
+ <!-- 消息区域 -->
701
+ <main class="message-area">
702
+ <div v-if="message.isListLoading">加载中...</div>
703
+ <div
704
+ v-else
705
+ class="message-list"
706
+ >
707
+ <div
708
+ v-for="msg in message.list"
709
+ :key="msg.id"
710
+ :class="['message-item', msg.role]"
711
+ >
712
+ <div class="message-content">
713
+ <template
714
+ v-for="(content, index) in msg.content"
715
+ :key="index"
716
+ >
717
+ <!-- 文本消息 -->
718
+ <div
719
+ v-if="content.type === 'text'"
720
+ class="text-content"
721
+ >
722
+ {{ content.data }}
723
+ </div>
724
+
725
+ <!-- 思考过程 -->
726
+ <div
727
+ v-else-if="content.type === 'thinking'"
728
+ class="thinking-content"
729
+ >
730
+ <strong>{{ content.data.title }}</strong>
731
+ <p>{{ content.data.text }}</p>
732
+ </div>
733
+
734
+ <!-- 工具调用 -->
735
+ <div
736
+ v-else-if="content.type === 'tool_call'"
737
+ class="tool-call-content"
738
+ >
739
+ <strong>调用工具: {{ content.data.toolCallName }}</strong>
740
+ <pre>{{ content.data.args }}</pre>
741
+ </div>
742
+ </template>
743
+ </div>
744
+ <button @click="message.deleteMessage(msg.id)">删除</button>
745
+ </div>
746
+ </div>
747
+
748
+ <!-- 输入区域 -->
749
+ <div class="input-area">
750
+ <button
751
+ @click="agent.chat"
752
+ :disabled="isStreaming"
753
+ >
754
+ {{ isStreaming ? '生成中...' : '发送消息' }}
755
+ </button>
756
+ <button
757
+ @click="agent.stopChat"
758
+ :disabled="!isStreaming"
759
+ >
760
+ 停止生成
761
+ </button>
762
+ </div>
763
+ </main>
764
+ </div>
765
+ </template>
766
+
767
+ <script setup lang="ts">
768
+ import { onMounted, ref } from 'vue';
769
+ import { useChatHelper, AGUIProtocol } from '@blueking/chat-helper';
770
+
771
+ const isStreaming = ref(false);
772
+
773
+ const { agent, session } = useChatHelper({
774
+ requestData: {
775
+ urlPrefix: 'https://your-api-domain.com/api/',
776
+ headers: () => ({
777
+ Authorization: `Bearer ${localStorage.getItem('token')}`,
778
+ }),
779
+ },
780
+ interceptors: {
781
+ request: config => {
782
+ console.log('Request:', config.url);
783
+ return config;
784
+ },
785
+ response: response => {
786
+ if (response.data.code !== 0) {
787
+ console.error('API Error:', response.data.message);
788
+ }
789
+ return response;
790
+ },
791
+ },
792
+ protocol: new AGUIProtocol({
793
+ onStart: () => {
794
+ isStreaming.value = true;
795
+ console.log('开始接收 AI 响应');
796
+ },
797
+ onMessage: event => {
798
+ // 可以在这里添加自定义事件处理
799
+ console.log('收到事件:', event.type);
800
+ },
801
+ onDone: () => {
802
+ isStreaming.value = false;
803
+ console.log('AI 响应完成');
804
+ },
805
+ onError: error => {
806
+ isStreaming.value = false;
807
+ console.error('AI 响应错误:', error);
808
+ alert('发生错误,请重试');
809
+ },
810
+ }),
811
+ });
812
+
813
+ onMounted(async () => {
814
+ await agent.getAgentInfo();
815
+ await session.getSessions();
816
+ if (session.list.value.length > 0) {
817
+ await session.chooseSession(session.list.value[0].sessionCode);
818
+ }
819
+ });
820
+
821
+ const createNewSession = () => {
822
+ session.createSession({
823
+ title: `会话 ${new Date().toLocaleString()}`,
824
+ sessionCode: `session_${Date.now()}`,
825
+ });
826
+ };
827
+ </script>
828
+
829
+ <style scoped>
830
+ .chat-app {
831
+ display: flex;
832
+ height: 100vh;
833
+ }
834
+
835
+ .session-list {
836
+ width: 250px;
837
+ border-right: 1px solid #ddd;
838
+ padding: 20px;
839
+ }
840
+
841
+ .message-area {
842
+ flex: 1;
843
+ display: flex;
844
+ flex-direction: column;
845
+ padding: 20px;
846
+ }
847
+
848
+ .message-list {
849
+ flex: 1;
850
+ overflow-y: auto;
851
+ }
852
+
853
+ .message-item {
854
+ margin-bottom: 20px;
855
+ padding: 10px;
856
+ border-radius: 8px;
857
+ }
858
+
859
+ .message-item.user {
860
+ background-color: #e3f2fd;
861
+ margin-left: 20%;
862
+ }
863
+
864
+ .message-item.assistant {
865
+ background-color: #f5f5f5;
866
+ margin-right: 20%;
867
+ }
868
+
869
+ .input-area {
870
+ display: flex;
871
+ gap: 10px;
872
+ padding-top: 20px;
873
+ border-top: 1px solid #ddd;
874
+ }
875
+ </style>
876
+ ```
877
+
878
+ ## 钩子函数综合示例
879
+
880
+ 以下是一个结合所有钩子函数的实际应用示例:
881
+
882
+ ```vue
883
+ <template>
884
+ <div class="chat-container">
885
+ <!-- 状态指示器 -->
886
+ <div
887
+ v-if="status"
888
+ class="status-bar"
889
+ :class="status.type"
890
+ >
891
+ {{ status.message }}
892
+ </div>
893
+
894
+ <!-- 消息列表 -->
895
+ <div class="messages">
896
+ <div
897
+ v-for="msg in message.list"
898
+ :key="msg.id"
899
+ class="message"
900
+ >
901
+ <template
902
+ v-for="content in msg.content"
903
+ :key="content.id"
904
+ >
905
+ <!-- 显示思考过程 -->
906
+ <div
907
+ v-if="content.type === 'thinking'"
908
+ class="thinking"
909
+ >
910
+ <span class="icon">🤔</span>
911
+ <strong>{{ content.data.title }}</strong>
912
+ <span v-if="content.data.duration"> ({{ content.data.duration }}ms) </span>
913
+ </div>
914
+
915
+ <!-- 显示工具调用 -->
916
+ <div
917
+ v-if="content.type === 'tool_call'"
918
+ class="tool-call"
919
+ >
920
+ <span class="icon">🔧</span>
921
+ <strong>{{ content.data.toolCallName }}</strong>
922
+ </div>
923
+
924
+ <!-- 显示文本内容 -->
925
+ <div
926
+ v-if="content.type === 'text'"
927
+ class="text"
928
+ >
929
+ {{ content.data }}
930
+ </div>
931
+ </template>
932
+ </div>
933
+ </div>
934
+
935
+ <!-- 输入区域 -->
936
+ <div class="input-area">
937
+ <button
938
+ @click="sendMessage"
939
+ :disabled="isStreaming"
940
+ >
941
+ 发送
942
+ </button>
943
+ <button
944
+ @click="stopStreaming"
945
+ :disabled="!isStreaming"
946
+ >
947
+ 停止
948
+ </button>
949
+ </div>
950
+ </div>
951
+ </template>
952
+
953
+ <script setup lang="ts">
954
+ import { ref } from 'vue';
955
+ import {
956
+ useChatHelper,
957
+ AGUIProtocol,
958
+ type IThinkingStartEvent,
959
+ type IToolCallStartEvent,
960
+ type IRunErrorEvent,
961
+ } from '@blueking/chat-helper';
962
+
963
+ const isStreaming = ref(false);
964
+ const status = ref<{ type: string; message: string } | null>(null);
965
+
966
+ // 自定义 Protocol,添加各种钩子
967
+ class CustomChatProtocol extends AGUIProtocol {
968
+ // 思考开始时显示通知
969
+ handleThinkingStartEvent(event: IThinkingStartEvent) {
970
+ status.value = {
971
+ type: 'thinking',
972
+ message: `AI 正在思考: ${event.title}`,
973
+ };
974
+ super.handleThinkingStartEvent(event);
975
+ }
976
+
977
+ // 工具调用时显示通知
978
+ handleToolCallStartEvent(event: IToolCallStartEvent) {
979
+ status.value = {
980
+ type: 'tool',
981
+ message: `正在调用工具: ${event.toolCallName}`,
982
+ };
983
+ super.handleToolCallStartEvent(event);
984
+ }
985
+
986
+ // 错误处理
987
+ handleRunErrorEvent(event: IRunErrorEvent) {
988
+ status.value = {
989
+ type: 'error',
990
+ message: `错误: ${event.message}`,
991
+ };
992
+ super.handleRunErrorEvent(event);
993
+
994
+ // 3秒后清除错误提示
995
+ setTimeout(() => {
996
+ status.value = null;
997
+ }, 3000);
998
+ }
999
+ }
1000
+
1001
+ const { agent } = useChatHelper({
1002
+ requestData: {
1003
+ urlPrefix: 'https://your-api-domain.com/api/',
1004
+ },
1005
+ protocol: new CustomChatProtocol({
1006
+ // 开始接收响应
1007
+ onStart: () => {
1008
+ isStreaming.value = true;
1009
+ status.value = {
1010
+ type: 'streaming',
1011
+ message: '正在接收 AI 响应...',
1012
+ };
1013
+ },
1014
+ // 每个事件
1015
+ onMessage: event => {
1016
+ console.log('事件:', event);
1017
+ },
1018
+ // 响应完成
1019
+ onDone: () => {
1020
+ isStreaming.value = false;
1021
+ status.value = {
1022
+ type: 'success',
1023
+ message: 'AI 响应完成',
1024
+ };
1025
+ setTimeout(() => {
1026
+ status.value = null;
1027
+ }, 2000);
1028
+ },
1029
+ // 响应错误
1030
+ onError: error => {
1031
+ isStreaming.value = false;
1032
+ status.value = {
1033
+ type: 'error',
1034
+ message: `连接错误: ${error.message}`,
1035
+ };
1036
+ },
1037
+ }),
1038
+ });
1039
+
1040
+ const sendMessage = () => {
1041
+ agent.chat();
1042
+ };
1043
+
1044
+ const stopStreaming = () => {
1045
+ agent.stopChat();
1046
+ };
1047
+ </script>
1048
+
1049
+ <style scoped>
1050
+ .status-bar {
1051
+ padding: 10px;
1052
+ margin-bottom: 10px;
1053
+ border-radius: 4px;
1054
+ }
1055
+
1056
+ .status-bar.thinking {
1057
+ background-color: #e3f2fd;
1058
+ }
1059
+
1060
+ .status-bar.tool {
1061
+ background-color: #fff3e0;
1062
+ }
1063
+
1064
+ .status-bar.error {
1065
+ background-color: #ffebee;
1066
+ color: #c62828;
1067
+ }
1068
+
1069
+ .status-bar.success {
1070
+ background-color: #e8f5e9;
1071
+ }
1072
+
1073
+ .thinking {
1074
+ background-color: #f5f5f5;
1075
+ padding: 8px;
1076
+ margin: 4px 0;
1077
+ border-radius: 4px;
1078
+ }
1079
+
1080
+ .tool-call {
1081
+ background-color: #fff3e0;
1082
+ padding: 8px;
1083
+ margin: 4px 0;
1084
+ border-radius: 4px;
1085
+ }
1086
+ </style>
1087
+ ```
1088
+
1089
+ ## 类型定义
1090
+
1091
+ 所有类型都已导出,您可以在 TypeScript 项目中使用:
1092
+
1093
+ ```typescript
1094
+ import type {
1095
+ IUseChatHelperOptions,
1096
+ IAgentModule,
1097
+ ISessionModule,
1098
+ IMessageModule,
1099
+ IHttpModule,
1100
+ IMessage,
1101
+ ISession,
1102
+ MessageRole,
1103
+ MessageStatus,
1104
+ MessageContentType,
1105
+ } from '@blueking/chat-helper';
1106
+ ```
1107
+
1108
+ ## License
1109
+
1110
+ MIT License
1111
+
1112
+ Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.