agent-configs 1.0.0

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 (85) hide show
  1. package/README.md +223 -0
  2. package/agents/architect.md +211 -0
  3. package/agents/code-reviewer.md +104 -0
  4. package/agents/planner.md +119 -0
  5. package/agents/refactor-cleaner.md +306 -0
  6. package/agents/security-reviewer.md +545 -0
  7. package/agents/tdd-guide.md +280 -0
  8. package/bundles/bk-chat-bundle/README.md +48 -0
  9. package/bundles/bk-chat-bundle/manifest.json +10 -0
  10. package/bundles/continuous-learning/.claude/commands/evolve.md +190 -0
  11. package/bundles/continuous-learning/.claude/commands/instinct-status.md +64 -0
  12. package/bundles/continuous-learning/.claude/commands/learn.md +83 -0
  13. package/bundles/continuous-learning/.claude/hooks/learning-end.js +85 -0
  14. package/bundles/continuous-learning/.claude/hooks/observe.js +131 -0
  15. package/bundles/continuous-learning/.claude/lib/learning.js +559 -0
  16. package/bundles/continuous-learning/.claude/lib/utils.js +312 -0
  17. package/bundles/continuous-learning/.claude/skills/continuous-learning/SKILL.md +200 -0
  18. package/bundles/continuous-learning/.cursor/hooks/learning-end.js +102 -0
  19. package/bundles/continuous-learning/.cursor/rules/continuous-learning.mdc +34 -0
  20. package/bundles/continuous-learning/.cursor/skills/continuous-learning/SKILL.md +77 -0
  21. package/bundles/continuous-learning/README.md +159 -0
  22. package/bundles/continuous-learning/manifest.json +51 -0
  23. package/bundles/planning-bundle/README.md +34 -0
  24. package/bundles/planning-bundle/manifest.json +10 -0
  25. package/bundles/review-bundle/README.md +43 -0
  26. package/bundles/review-bundle/manifest.json +11 -0
  27. package/bundles/shared-memory/.claude/commands/list-sessions.md +124 -0
  28. package/bundles/shared-memory/.claude/commands/load-session.md +169 -0
  29. package/bundles/shared-memory/.claude/commands/save-session.md +137 -0
  30. package/bundles/shared-memory/.claude/hooks/memory-compact.js +43 -0
  31. package/bundles/shared-memory/.claude/hooks/memory-end.js +42 -0
  32. package/bundles/shared-memory/.claude/hooks/memory-start.js +59 -0
  33. package/bundles/shared-memory/.claude/lib/memory.js +416 -0
  34. package/bundles/shared-memory/.claude/lib/utils.js +209 -0
  35. package/bundles/shared-memory/.claude/skills/shared-memory/SKILL.md +183 -0
  36. package/bundles/shared-memory/.cursor/hooks/memory-start.js +42 -0
  37. package/bundles/shared-memory/.cursor/rules/shared-memory.mdc +37 -0
  38. package/bundles/shared-memory/.cursor/skills/shared-memory/SKILL.md +183 -0
  39. package/bundles/tdd-bundle/README.md +33 -0
  40. package/bundles/tdd-bundle/manifest.json +10 -0
  41. package/cli.js +978 -0
  42. package/commands/build-fix.md +29 -0
  43. package/commands/code-review.md +40 -0
  44. package/commands/e2e.md +363 -0
  45. package/commands/learn.md +114 -0
  46. package/commands/plan.md +113 -0
  47. package/commands/refactor-clean.md +28 -0
  48. package/commands/tdd.md +326 -0
  49. package/commands/test-coverage.md +27 -0
  50. package/commands/update-codemaps.md +17 -0
  51. package/commands/update-docs.md +31 -0
  52. package/configs.json +158 -0
  53. package/hooks/hooks.json +101 -0
  54. package/package.json +58 -0
  55. package/rules/agents.md +49 -0
  56. package/rules/coding-style.md +70 -0
  57. package/rules/git-workflow.md +45 -0
  58. package/rules/hooks.md +46 -0
  59. package/rules/patterns.md +55 -0
  60. package/rules/performance.md +47 -0
  61. package/rules/security.md +36 -0
  62. package/rules/testing.md +30 -0
  63. package/skills/ai-config-architect/SKILL.md +59 -0
  64. package/skills/ai-config-architect/references/agents.md +77 -0
  65. package/skills/ai-config-architect/references/commands.md +66 -0
  66. package/skills/ai-config-architect/references/hooks.md +70 -0
  67. package/skills/ai-config-architect/references/patterns.md +66 -0
  68. package/skills/ai-config-architect/references/platforms.md +82 -0
  69. package/skills/ai-config-architect/references/rules.md +66 -0
  70. package/skills/ai-config-architect/references/skills.md +67 -0
  71. package/skills/bk-chat-helper/SKILL.md +398 -0
  72. package/skills/bk-chat-helper/references/api-reference.md +606 -0
  73. package/skills/bk-chat-helper/references/examples.md +789 -0
  74. package/skills/bk-chat-helper/references/integration-guide.md +583 -0
  75. package/skills/bk-chat-x/SKILL.md +400 -0
  76. package/skills/bk-chat-x/references/components-api.md +340 -0
  77. package/skills/bk-chat-x/references/examples.md +386 -0
  78. package/skills/bk-chat-x/references/shortcuts-guide.md +375 -0
  79. package/skills/coding-standards/SKILL.md +523 -0
  80. package/skills/security-review/SKILL.md +497 -0
  81. package/skills/security-review/references/cloud-infrastructure-security.md +361 -0
  82. package/skills/strategic-compact/SKILL.md +66 -0
  83. package/skills/strategic-compact/scripts/suggest-compact.sh +52 -0
  84. package/skills/tdd-workflow/SKILL.md +412 -0
  85. package/skills/verification-loop/SKILL.md +128 -0
@@ -0,0 +1,340 @@
1
+ # 组件 API 详细参考
2
+
3
+ ## ChatInput 聊天输入框
4
+
5
+ ### Props
6
+
7
+ | 属性名 | 类型 | 默认值 | 说明 |
8
+ |--------|------|--------|------|
9
+ | modelValue | `string \| TagSchema` | - | 输入框的值,支持 v-model |
10
+ | cite | `string` | `''` | 引用内容,支持 v-model:cite |
11
+ | messageStatus | `MessageStatus` | - | 消息状态,控制发送按钮状态 |
12
+ | placeholder | `string` | 见下方 | 输入框占位符 |
13
+ | prompts | `string[]` | `[]` | Prompt 列表,输入 `/` 触发 |
14
+ | resources | `IAiSlashMenuItem[]` | `[]` | 资源列表,输入 `@` 触发 |
15
+ | shortcuts | `Shortcut[]` | `[]` | 快捷指令列表 |
16
+ | shortcutId | `string` | - | 当前选中的快捷指令 ID |
17
+ | onSendMessage | `(value: string, docSchema: TagSchema) => Promise<void>` | - | 发送消息回调 |
18
+ | onStopSending | `() => Promise<void>` | - | 停止发送回调 |
19
+
20
+ **默认占位符:**
21
+ ```
22
+ 输入 "/" 唤出 Prompt
23
+ 输入 "@" 唤出工具
24
+ 通过 Shift + Enter 进行换行输入
25
+ ```
26
+
27
+ ### Events
28
+
29
+ | 事件名 | 参数 | 说明 |
30
+ |--------|------|------|
31
+ | select-shortcut | `(shortcut: Shortcut, text?: string)` | 选择快捷指令 |
32
+ | delete-shortcut | - | 删除当前快捷指令 |
33
+
34
+ ### Slots
35
+
36
+ | 插槽名 | 说明 |
37
+ |--------|------|
38
+ | top | 输入框容器顶部 |
39
+ | input-header | 输入框头部,默认显示引用 |
40
+ | attachment | 附件区域 |
41
+ | send-icon | 发送按钮图标 |
42
+
43
+ ### 键盘快捷键
44
+
45
+ | 快捷键 | 说明 |
46
+ |--------|------|
47
+ | `Enter` | 发送消息 |
48
+ | `Shift + Enter` | 换行 |
49
+ | `/` | 唤出 Prompt 列表 |
50
+ | `@` | 唤出资源列表 |
51
+ | `↑` / `↓` | 菜单导航 |
52
+ | `Esc` | 关闭菜单 |
53
+
54
+ ---
55
+
56
+ ## MessageContainer 消息容器
57
+
58
+ ### Props
59
+
60
+ | 属性名 | 类型 | 默认值 | 说明 |
61
+ |--------|------|--------|------|
62
+ | messages | `Message[]` | - | **必填**,消息列表 |
63
+ | messageStatus | `MessageStatus` | - | 当前消息状态 |
64
+ | enableSelection | `boolean` | `false` | 是否启用多选模式 |
65
+ | onAgentAction | `(tool: IToolBtn) => Promise<string[] \| void>` | - | AI 消息工具操作回调 |
66
+ | onUserAction | `(tool: IToolBtn) => Promise<void>` | - | 用户消息工具操作回调 |
67
+
68
+ ### v-model
69
+
70
+ | 属性名 | 类型 | 说明 |
71
+ |--------|------|------|
72
+ | selectedMessages | `Message[]` | 选中的消息列表 |
73
+
74
+ ### Events
75
+
76
+ | 事件名 | 参数 | 说明 |
77
+ |--------|------|------|
78
+ | stopStreaming | - | 点击停止按钮 |
79
+
80
+ ### Slots
81
+
82
+ | 插槽名 | 参数 | 说明 |
83
+ |--------|------|------|
84
+ | default | `{ message: Message }` | 自定义消息渲染 |
85
+
86
+ ### 消息分组规则
87
+
88
+ - 连续的 AI 消息(Assistant、Reasoning、Tool)分为一组
89
+ - 每个用户消息单独一组
90
+ - 启用多选时,选中用户消息会自动关联 AI 回复
91
+
92
+ ---
93
+
94
+ ## MessageRender 消息渲染器
95
+
96
+ ### Props
97
+
98
+ | 属性名 | 类型 | 默认值 | 说明 |
99
+ |--------|------|--------|------|
100
+ | message | `Partial<Message>` | - | **必填**,消息对象 |
101
+ | onAction | `(tool: IToolBtn) => Promise<void>` | - | 工具操作回调 |
102
+
103
+ ### Slots
104
+
105
+ | 插槽名 | 参数 | 说明 |
106
+ |--------|------|------|
107
+ | default | `{ content: string, status: MessageStatus }` | 自定义 Assistant 消息内容 |
108
+
109
+ ### 消息类型映射
110
+
111
+ | MessageRole | 渲染组件 |
112
+ |-------------|----------|
113
+ | `User` | UserMessage |
114
+ | `Assistant` | AssistantMessage |
115
+ | `Reasoning` | ReasoningMessage |
116
+ | `Tool` | ToolMessage |
117
+ | `Info` | InfoMessage |
118
+ | `Activity` | ActivityMessage |
119
+
120
+ ---
121
+
122
+ ## ContentRender 内容渲染器
123
+
124
+ ### Props
125
+
126
+ | 属性名 | 类型 | 默认值 | 说明 |
127
+ |--------|------|--------|------|
128
+ | content | `string \| Record<string, unknown>[]` | - | **必填**,内容 |
129
+ | status | `MessageStatus` | - | 消息状态 |
130
+ | type | `ContentType` | - | 内容类型 |
131
+
132
+ ### 内容类型
133
+
134
+ | 类型 | 条件 | 渲染组件 |
135
+ |------|------|----------|
136
+ | Text | `typeof content === 'string'` | MarkdownContent |
137
+ | Reference | `Array.isArray(content)` | ReferenceContent |
138
+
139
+ ### Markdown 支持
140
+
141
+ - **基础语法**:标题、加粗、斜体、链接、图片
142
+ - **扩展语法**:表格、任务列表
143
+ - **代码高亮**:支持 180+ 种语言
144
+ - **LaTeX 公式**:`$...$` 行内,`$$...$$` 块级
145
+ - **Mermaid 图表**:流程图、时序图、甘特图
146
+
147
+ ---
148
+
149
+ ## AiSelection AI 划词选择
150
+
151
+ ### Props
152
+
153
+ | 属性名 | 类型 | 默认值 | 说明 |
154
+ |--------|------|--------|------|
155
+ | visible | `boolean` | - | 控制显示 (v-model:visible) |
156
+ | shortcuts | `Shortcut[]` | `[{ id: 'ask-whale', name: '问问小鲸' }]` | 快捷指令列表 |
157
+ | maxShortcutCount | `number` | `3` | 最多显示数量 |
158
+ | offset | `number` | `10` | 弹窗垂直间距 |
159
+
160
+ ### Events
161
+
162
+ | 事件名 | 参数 | 说明 |
163
+ |--------|------|------|
164
+ | selectShortcut | `(shortcut: Shortcut, text: string)` | 选择快捷指令 |
165
+ | selectionChange | `(text: string)` | 选区文本变化 |
166
+
167
+ ### Slots
168
+
169
+ | 插槽名 | 参数 | 说明 |
170
+ |--------|------|------|
171
+ | default | `{ shortcuts: Shortcut[] }` | 自定义弹窗内容 |
172
+
173
+ ---
174
+
175
+ ## ShortcutRender 快捷指令表单
176
+
177
+ ### Props
178
+
179
+ | 属性名 | 类型 | 默认值 | 说明 |
180
+ |--------|------|--------|------|
181
+ | name | `string` | - | 快捷指令名称 |
182
+ | components | `ShortcutComponent[]` | - | 表单组件配置 |
183
+ | formModel | `Record<string, unknown>` | - | 表单初始值 |
184
+ | description | `string` | - | 描述 |
185
+
186
+ ### Events
187
+
188
+ | 事件名 | 参数 | 说明 |
189
+ |--------|------|------|
190
+ | close | - | 点击关闭按钮 |
191
+ | submit | `(formModel: Record<string, unknown>)` | 表单提交 |
192
+
193
+ ---
194
+
195
+ ## ShortcutBtns 快捷指令按钮组
196
+
197
+ ### Props
198
+
199
+ | 属性名 | 类型 | 默认值 | 说明 |
200
+ |--------|------|--------|------|
201
+ | shortcuts | `Shortcut[]` | - | 快捷指令列表 |
202
+
203
+ ### Events
204
+
205
+ | 事件名 | 参数 | 说明 |
206
+ |--------|------|------|
207
+ | selectShortcut | `(shortcut: Shortcut)` | 选择快捷指令 |
208
+
209
+ ---
210
+
211
+ ## 类型定义
212
+
213
+ ### Message 消息
214
+
215
+ ```typescript
216
+ interface BaseMessage<T extends MessageType, C = string> {
217
+ id: string; // 客户端唯一 ID
218
+ messageId: number | string; // 服务端返回 ID
219
+ role: T; // 消息角色
220
+ content: C; // 消息内容
221
+ status: MessageStatus; // 消息状态
222
+ name?: string; // 名称
223
+ property?: {
224
+ extra?: {
225
+ cite: string | { title: string; data: { key: string; value: string }[] };
226
+ command: string;
227
+ context: Record<string, any>[];
228
+ shortcut?: Shortcut;
229
+ };
230
+ };
231
+ }
232
+
233
+ // 具体消息类型
234
+ type UserMessage = BaseMessage<MessageRole.User, InputContent[] | string>;
235
+
236
+ interface AssistantMessage extends BaseMessage<MessageRole.Assistant> {
237
+ toolCalls?: ToolCall[];
238
+ }
239
+
240
+ interface ReasoningMessage extends BaseMessage<MessageRole.Reasoning, string[]> {
241
+ duration?: number; // 推理耗时 (毫秒)
242
+ }
243
+
244
+ interface ToolMessage extends BaseMessage<MessageRole.Tool, string> {
245
+ toolCallId: string; // 对应 toolCalls[].id
246
+ duration: number; // 执行耗时
247
+ error?: string;
248
+ }
249
+
250
+ interface ActivityMessage extends BaseMessage<MessageRole.Activity, Record<string, unknown>[]> {
251
+ activityType: string;
252
+ }
253
+
254
+ type InfoMessage = BaseMessage<MessageRole.Info, string>;
255
+ ```
256
+
257
+ ### ToolCall 工具调用
258
+
259
+ ```typescript
260
+ type ToolCall = {
261
+ id: string;
262
+ type: MessageContentType.Function;
263
+ function: {
264
+ name: string;
265
+ arguments: string;
266
+ description?: string;
267
+ };
268
+ };
269
+ ```
270
+
271
+ ### IToolBtn 工具按钮
272
+
273
+ ```typescript
274
+ interface IToolBtn {
275
+ id: 'copy' | 'cite' | 'rebuild' | 'share' | 'like' | 'unlike' | 'edit' | 'delete';
276
+ name: string;
277
+ description: string;
278
+ }
279
+ ```
280
+
281
+ ### TagSchema 输入标签结构
282
+
283
+ ```typescript
284
+ type TagSchema = Array<Array<{
285
+ type: 'text' | 'tag';
286
+ text?: string;
287
+ data?: {
288
+ type: string;
289
+ label: string;
290
+ value: string;
291
+ };
292
+ }>>;
293
+ ```
294
+
295
+ ### IAiSlashMenuItem 资源菜单项
296
+
297
+ ```typescript
298
+ interface IAiSlashMenuItem {
299
+ id: string;
300
+ name: string;
301
+ type: string;
302
+ [key: string]: any;
303
+ }
304
+ ```
305
+
306
+ ---
307
+
308
+ ## 常量
309
+
310
+ ```typescript
311
+ // 默认 AI 消息工具
312
+ const CONST_MESSAGE_TOOLS: IToolBtn[] = [
313
+ { id: 'copy', name: '复制', description: '复制' },
314
+ { id: 'cite', name: '引用', description: '引用' },
315
+ { id: 'rebuild', name: '重新生成', description: '重新生成' },
316
+ { id: 'share', name: '分享', description: '分享' },
317
+ ];
318
+
319
+ // 默认用户消息工具
320
+ const CONST_USER_MESSAGE_TOOLS: IToolBtn[] = [
321
+ { id: 'copy', name: '复制', description: '复制' },
322
+ { id: 'cite', name: '引用', description: '引用' },
323
+ { id: 'edit', name: '编辑', description: '编辑' },
324
+ { id: 'delete', name: '删除', description: '删除' },
325
+ ];
326
+
327
+ // 反馈工具
328
+ const CONST_UPDATE_TOOLS: IToolBtn[] = [
329
+ { id: 'like', name: '点赞', description: '点赞' },
330
+ { id: 'unlike', name: '不满意', description: '不满意' },
331
+ { id: 'delete', name: '删除', description: '删除' },
332
+ ];
333
+
334
+ // Z-Index 层级
335
+ const CHAT_Z_INDEX = 9999;
336
+ const EDITOR_Z_INDEX = 10000;
337
+ const EDITOR_MENU_Z_INDEX = 10001;
338
+ const SHORTCUT_MENU_Z_INDEX = 10002;
339
+ const SELECTION_Z_INDEX = 10003;
340
+ ```
@@ -0,0 +1,386 @@
1
+ # 完整示例
2
+
3
+ ## AI 聊天页面完整实现
4
+
5
+ ```vue
6
+ <template>
7
+ <div class="chat-page">
8
+ <!-- 快捷指令 (空消息时显示) -->
9
+ <ShortcutBtns
10
+ v-if="messages.length === 0"
11
+ :shortcuts="shortcuts"
12
+ @select-shortcut="handleSelectShortcut"
13
+ />
14
+
15
+ <!-- 消息列表 -->
16
+ <MessageContainer
17
+ v-else
18
+ :messages="messages"
19
+ :message-status="messageStatus"
20
+ :on-agent-action="handleAgentAction"
21
+ :on-user-action="handleUserAction"
22
+ @stop-streaming="handleStopStreaming"
23
+ />
24
+
25
+ <!-- 快捷指令表单 (与 ChatInput 互斥) -->
26
+ <ShortcutRender
27
+ v-if="selectedShortcut?.components?.length"
28
+ v-bind="selectedShortcut"
29
+ @close="handleCloseShortcut"
30
+ @submit="handleSubmitShortcut"
31
+ />
32
+
33
+ <!-- 输入框 -->
34
+ <ChatInput
35
+ v-else
36
+ v-model="userInput"
37
+ v-model:cite="citeContent"
38
+ :message-status="messageStatus"
39
+ :shortcuts="shortcuts"
40
+ :shortcut-id="selectedShortcut?.id"
41
+ :on-send-message="handleSendMessage"
42
+ :on-stop-sending="handleStopSending"
43
+ @select-shortcut="handleSelectShortcut"
44
+ @delete-shortcut="handleDeleteShortcut"
45
+ />
46
+
47
+ <!-- 划词选择 -->
48
+ <AiSelection
49
+ v-model:visible="aiSelectionVisible"
50
+ :shortcuts="shortcuts"
51
+ @select-shortcut="handleSelectShortcut"
52
+ />
53
+ </div>
54
+ </template>
55
+
56
+ <script setup lang="ts">
57
+ import { ref } from 'vue';
58
+ import {
59
+ ChatInput,
60
+ MessageContainer,
61
+ ShortcutBtns,
62
+ ShortcutRender,
63
+ AiSelection,
64
+ MessageRole,
65
+ MessageStatus,
66
+ type Message,
67
+ type Shortcut,
68
+ type IToolBtn,
69
+ type TagSchema,
70
+ } from '@blueking/chat-x';
71
+
72
+ // 状态
73
+ const messages = ref<Message[]>([]);
74
+ const userInput = ref<string | TagSchema>('');
75
+ const citeContent = ref('');
76
+ const messageStatus = ref(MessageStatus.Complete);
77
+ const selectedShortcut = ref<Shortcut | null>(null);
78
+ const aiSelectionVisible = ref(false);
79
+
80
+ // 快捷指令配置
81
+ const shortcuts = ref<Shortcut[]>([
82
+ { id: 'ask', name: '问问小鲸' },
83
+ {
84
+ id: 'translate',
85
+ name: '翻译',
86
+ components: [
87
+ {
88
+ type: 'select',
89
+ key: 'targetLang',
90
+ name: '目标语言',
91
+ props: { options: [{ label: '英文', value: 'en' }] }
92
+ },
93
+ { type: 'textarea', key: 'content', name: '内容', fillBack: true }
94
+ ]
95
+ },
96
+ ]);
97
+
98
+ // 发送消息
99
+ const handleSendMessage = async (value: string, docSchema: TagSchema) => {
100
+ if (!value.trim()) return;
101
+
102
+ const userMsgId = Date.now().toString();
103
+ const assistantMsgId = (Date.now() + 1).toString();
104
+
105
+ // 添加用户消息
106
+ messages.value.push({
107
+ id: userMsgId,
108
+ messageId: userMsgId,
109
+ role: MessageRole.User,
110
+ content: value,
111
+ status: MessageStatus.Complete,
112
+ property: citeContent.value ? { extra: { cite: citeContent.value } } : undefined,
113
+ });
114
+
115
+ // 清空输入
116
+ userInput.value = '';
117
+ citeContent.value = '';
118
+
119
+ // 添加 AI 消息占位
120
+ messages.value.push({
121
+ id: assistantMsgId,
122
+ messageId: assistantMsgId,
123
+ role: MessageRole.Assistant,
124
+ content: '',
125
+ status: MessageStatus.Pending,
126
+ });
127
+
128
+ messageStatus.value = MessageStatus.Streaming;
129
+
130
+ try {
131
+ // 调用 AI API 并流式更新
132
+ const response = await callAIAPI(value);
133
+ const lastMsg = messages.value[messages.value.length - 1];
134
+
135
+ for await (const chunk of response) {
136
+ lastMsg.content += chunk;
137
+ lastMsg.status = MessageStatus.Streaming;
138
+ }
139
+
140
+ lastMsg.status = MessageStatus.Complete;
141
+ messageStatus.value = MessageStatus.Complete;
142
+ } catch (error) {
143
+ const lastMsg = messages.value[messages.value.length - 1];
144
+ lastMsg.status = MessageStatus.Error;
145
+ lastMsg.content = '请求失败,请重试';
146
+ messageStatus.value = MessageStatus.Error;
147
+ }
148
+ };
149
+
150
+ // 停止发送
151
+ const handleStopSending = async () => {
152
+ messageStatus.value = MessageStatus.Stop;
153
+ const lastMsg = messages.value[messages.value.length - 1];
154
+ if (lastMsg) lastMsg.status = MessageStatus.Stop;
155
+ };
156
+
157
+ // 停止流式
158
+ const handleStopStreaming = () => {
159
+ handleStopSending();
160
+ };
161
+
162
+ // AI 消息操作
163
+ const handleAgentAction = async (tool: IToolBtn) => {
164
+ if (tool.id === 'like') return ['回答准确', '信息全面'];
165
+ if (tool.id === 'unlike') return ['信息错误', '回答不相关'];
166
+ };
167
+
168
+ // 用户消息操作
169
+ const handleUserAction = async (tool: IToolBtn) => {
170
+ console.log('用户操作:', tool.id);
171
+ };
172
+
173
+ // 快捷指令
174
+ const handleSelectShortcut = (shortcut: Shortcut, text?: string) => {
175
+ selectedShortcut.value = shortcut;
176
+ if (text) userInput.value = text;
177
+ };
178
+
179
+ const handleDeleteShortcut = () => {
180
+ selectedShortcut.value = null;
181
+ };
182
+
183
+ const handleCloseShortcut = () => {
184
+ selectedShortcut.value = null;
185
+ };
186
+
187
+ const handleSubmitShortcut = (formModel: Record<string, unknown>) => {
188
+ console.log('提交:', formModel);
189
+ selectedShortcut.value = null;
190
+ };
191
+
192
+ // 模拟 AI API
193
+ async function* callAIAPI(prompt: string) {
194
+ const response = `这是对 "${prompt}" 的回复`;
195
+ for (const char of response) {
196
+ await new Promise(r => setTimeout(r, 30));
197
+ yield char;
198
+ }
199
+ }
200
+ </script>
201
+
202
+ <style scoped>
203
+ .chat-page {
204
+ display: flex;
205
+ flex-direction: column;
206
+ height: 100vh;
207
+ padding: 16px;
208
+ }
209
+ </style>
210
+ ```
211
+
212
+ ## 流式消息处理
213
+
214
+ ```typescript
215
+ // 创建流式消息
216
+ const createStreamMessage = () => {
217
+ const msgId = Date.now().toString();
218
+
219
+ messages.value.push({
220
+ id: msgId,
221
+ messageId: msgId,
222
+ role: MessageRole.Assistant,
223
+ content: '',
224
+ status: MessageStatus.Pending,
225
+ });
226
+
227
+ return messages.value[messages.value.length - 1];
228
+ };
229
+
230
+ // 更新流式消息
231
+ const updateStreamMessage = (msg: Message, chunk: string) => {
232
+ msg.content += chunk;
233
+ msg.status = MessageStatus.Streaming;
234
+ };
235
+
236
+ // 完成流式消息
237
+ const completeStreamMessage = (msg: Message) => {
238
+ msg.status = MessageStatus.Complete;
239
+ messageStatus.value = MessageStatus.Complete;
240
+ };
241
+
242
+ // 使用示例
243
+ const streamMessage = createStreamMessage();
244
+ messageStatus.value = MessageStatus.Streaming;
245
+
246
+ for await (const chunk of aiStream) {
247
+ updateStreamMessage(streamMessage, chunk);
248
+ }
249
+
250
+ completeStreamMessage(streamMessage);
251
+ ```
252
+
253
+ ## 推理过程消息
254
+
255
+ ```typescript
256
+ // 添加推理消息
257
+ messages.value.push({
258
+ id: 'reasoning-1',
259
+ messageId: 'reasoning-1',
260
+ role: MessageRole.Reasoning,
261
+ content: [
262
+ '分析用户问题...',
263
+ '检索相关知识...',
264
+ '组织回答内容...',
265
+ ],
266
+ status: MessageStatus.Complete,
267
+ duration: 3500, // 推理耗时 (毫秒)
268
+ });
269
+ ```
270
+
271
+ ## 工具调用消息
272
+
273
+ ```typescript
274
+ // AI 消息带工具调用
275
+ messages.value.push({
276
+ id: 'assistant-1',
277
+ messageId: 'assistant-1',
278
+ role: MessageRole.Assistant,
279
+ content: '我来帮你查询天气...',
280
+ status: MessageStatus.Complete,
281
+ toolCalls: [
282
+ {
283
+ id: 'call_weather',
284
+ type: MessageContentType.Function,
285
+ function: {
286
+ name: 'get_weather',
287
+ arguments: '{"city": "北京"}',
288
+ description: '查询天气',
289
+ },
290
+ },
291
+ ],
292
+ });
293
+
294
+ // 工具调用结果
295
+ messages.value.push({
296
+ id: 'tool-1',
297
+ messageId: 'tool-1',
298
+ role: MessageRole.Tool,
299
+ content: '{"temperature": 25, "weather": "晴天"}',
300
+ status: MessageStatus.Complete,
301
+ toolCallId: 'call_weather',
302
+ duration: 1200,
303
+ });
304
+ ```
305
+
306
+ ## 引用消息
307
+
308
+ ```typescript
309
+ // 用户消息带引用
310
+ messages.value.push({
311
+ id: 'user-1',
312
+ messageId: 'user-1',
313
+ role: MessageRole.User,
314
+ content: '解释一下这段话',
315
+ status: MessageStatus.Complete,
316
+ property: {
317
+ extra: {
318
+ cite: '这里是引用的文本内容...',
319
+ // 或结构化引用
320
+ // cite: {
321
+ // title: '引用标题',
322
+ // type: 'structured',
323
+ // data: [
324
+ // { key: '来源', value: 'xxx文档' },
325
+ // ],
326
+ // },
327
+ },
328
+ },
329
+ });
330
+ ```
331
+
332
+ ## 自定义消息类型
333
+
334
+ ```typescript
335
+ // 1. 声明自定义消息类型
336
+ declare global {
337
+ interface AIBluekingMessageMap {
338
+ flow: BaseMessage<'flow', FlowContent>;
339
+ chart: BaseMessage<'chart', ChartData>;
340
+ }
341
+ }
342
+
343
+ // 2. 创建自定义消息组件
344
+ // FlowMessage.vue
345
+ <template>
346
+ <div class="flow-message">
347
+ <div v-for="step in content.steps" :key="step.id">
348
+ {{ step.name }}
349
+ </div>
350
+ </div>
351
+ </template>
352
+
353
+ // 3. 在 MessageContainer 中使用
354
+ <MessageContainer :messages="messages">
355
+ <template #default="{ message }">
356
+ <FlowMessage v-if="message.role === 'flow'" :content="message.content" />
357
+ <ChartMessage v-else-if="message.role === 'chart'" :content="message.content" />
358
+ <MessageRender v-else :message="message" />
359
+ </template>
360
+ </MessageContainer>
361
+ ```
362
+
363
+ ## 消息多选导出
364
+
365
+ ```typescript
366
+ // 启用多选
367
+ const enableSelection = ref(true);
368
+ const selectedMessages = ref<Message[]>([]);
369
+
370
+ // 导出选中消息
371
+ const exportMessages = () => {
372
+ const exportData = selectedMessages.value.map(msg => ({
373
+ role: msg.role,
374
+ content: msg.content,
375
+ timestamp: msg.messageId,
376
+ }));
377
+
378
+ // 下载为 JSON
379
+ const blob = new Blob([JSON.stringify(exportData, null, 2)], { type: 'application/json' });
380
+ const url = URL.createObjectURL(blob);
381
+ const a = document.createElement('a');
382
+ a.href = url;
383
+ a.download = 'chat-export.json';
384
+ a.click();
385
+ };
386
+ ```