@blueking/chat-x 0.0.47-beta.4 → 0.0.49-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.
- package/dist/ag-ui/types/file.d.ts +23 -0
- package/dist/ag-ui/types/index.d.ts +1 -0
- package/dist/ag-ui/types/messages.d.ts +2 -0
- package/dist/components/chat-input/chat-input.vue.d.ts +15 -2
- package/dist/components/chat-input/input-attachment/input-attachment.vue.d.ts +4 -2
- package/dist/components/chat-input/model-selector/capabilities.d.ts +3 -0
- package/dist/components/chat-input/model-selector/index.d.ts +3 -0
- package/dist/components/chat-input/model-selector/model-selector-panel.vue.d.ts +26 -0
- package/dist/components/chat-input/model-selector/model-selector-trigger.vue.d.ts +14 -0
- package/dist/components/chat-input/model-selector/model-selector.vue.d.ts +39 -0
- package/dist/components/chat-input/model-selector/types.d.ts +61 -0
- package/dist/components/chat-input/model-selector/use-model-selector.d.ts +17 -0
- package/dist/components/chat-message/assistant-message/message-artifacts/artifact-file-card.vue.d.ts +14 -0
- package/dist/components/chat-message/assistant-message/message-artifacts/artifact-preview/artifact-preview-host.vue.d.ts +8 -0
- package/dist/components/chat-message/assistant-message/message-artifacts/artifact-preview/preview-strategy.d.ts +9 -0
- package/dist/components/chat-message/assistant-message/message-artifacts/artifact-preview/renderers/html-preview.vue.d.ts +6 -0
- package/dist/components/chat-message/assistant-message/message-artifacts/artifact-preview/renderers/markdown-preview.vue.d.ts +6 -0
- package/dist/components/chat-message/assistant-message/message-artifacts/artifact-preview/renderers/txt-preview.vue.d.ts +6 -0
- package/dist/components/chat-message/assistant-message/message-artifacts/artifact-preview/renderers/url-iframe-preview.vue.d.ts +6 -0
- package/dist/components/chat-message/assistant-message/message-artifacts/artifact-preview/use-artifact-preview-loader.d.ts +21 -0
- package/dist/components/chat-message/assistant-message/message-artifacts/file-artifact-panel.vue.d.ts +12 -0
- package/dist/components/chat-message/assistant-message/message-artifacts/file-icon.d.ts +29 -0
- package/dist/components/chat-message/assistant-message/message-artifacts/message-artifacts.vue.d.ts +10 -0
- package/dist/components/chat-message/message-container/message-container.vue.d.ts +2 -0
- package/dist/components/index.d.ts +3 -1
- package/dist/composables/index.d.ts +1 -0
- package/dist/composables/use-artifact-preview.d.ts +59 -0
- package/dist/composables/use-message-group.d.ts +434 -0
- package/dist/icons/file.d.ts +24 -0
- package/dist/icons/index.d.ts +1 -0
- package/dist/icons/input.d.ts +7 -0
- package/dist/index.css +1 -1
- package/dist/index.js +2761 -1984
- package/dist/index.js.map +1 -1
- package/dist/lang/lang.d.ts +10 -1
- package/dist/mcp/generated/docs/activity-message.md +122 -97
- package/dist/mcp/generated/docs/assistant-message.md +125 -62
- package/dist/mcp/generated/docs/chat-container.md +269 -76
- package/dist/mcp/generated/docs/chat-input.md +57 -0
- package/dist/mcp/generated/docs/file-artifact-panel.md +279 -0
- package/dist/mcp/generated/docs/info-message.md +23 -7
- package/dist/mcp/generated/docs/input-attachment.md +1 -0
- package/dist/mcp/generated/docs/loading-message.md +36 -17
- package/dist/mcp/generated/docs/message-container.md +47 -0
- package/dist/mcp/generated/docs/message-render.md +44 -33
- package/dist/mcp/generated/docs/message-tools.md +5 -1
- package/dist/mcp/generated/docs/model-selector.md +157 -0
- package/dist/mcp/generated/docs/reasoning-message.md +15 -11
- package/dist/mcp/generated/docs/tool-btn.md +33 -4
- package/dist/mcp/generated/docs/tool-message.md +61 -45
- package/dist/mcp/generated/docs/use-artifact-preview.md +237 -0
- package/dist/mcp/generated/docs/use-message-group.md +24 -0
- package/dist/mcp/generated/docs/user-message.md +185 -121
- package/dist/mcp/generated/index.json +109 -11
- package/dist/types/tool.d.ts +6 -2
- package/package.json +2 -2
|
@@ -13,15 +13,16 @@
|
|
|
13
13
|
<!-- FULL DOC -->
|
|
14
14
|
|
|
15
15
|
# MessageRender 消息渲染器
|
|
16
|
+
|
|
16
17
|
## 源码事实
|
|
17
18
|
|
|
18
19
|
- **源码位置**:`src/components/chat-message/message-render/message-render.vue`
|
|
19
20
|
- **能力域**:消息系统
|
|
20
|
-
- **能力说明**:按 message.role 分发到用户、助手、工具、推理、活动、中断等消息组件。
|
|
21
|
+
- **能力说明**:按 `message.role` 分发到用户、助手、工具、推理、活动、中断等消息组件。
|
|
21
22
|
|
|
22
|
-
>
|
|
23
|
+
> **导出说明**:`MessageRender` **已**从 `@blueking/chat-x` 包入口导出,消费方可直接 import。下文 `MessageRenderComp` 为文档站相对路径 demo,与包入口行为一致。
|
|
23
24
|
|
|
24
|
-
统一的消息渲染入口,通过 `message.role`
|
|
25
|
+
统一的消息渲染入口,通过 `message.role` 派发到对应子组件;由单个 `computed` 完成,无额外状态。
|
|
25
26
|
|
|
26
27
|
## 渲染架构
|
|
27
28
|
|
|
@@ -151,7 +152,7 @@ MessageRender
|
|
|
151
152
|
|
|
152
153
|
### 流式输出(streaming)
|
|
153
154
|
|
|
154
|
-
`status: 'streaming'`
|
|
155
|
+
`status: 'streaming'` 时,默认回退的 `ContentRender` / `MarkdownContent` 会按流式规则补全未闭合语法;内容由外部逐步追加:
|
|
155
156
|
|
|
156
157
|
```vue
|
|
157
158
|
<script setup lang="ts">
|
|
@@ -202,65 +203,74 @@ MessageRender
|
|
|
202
203
|
|
|
203
204
|
## 自定义内容渲染(default slot)
|
|
204
205
|
|
|
205
|
-
`default` slot **仅对 `role: 'assistant'` 生效**,用于替换默认的 `ContentRender
|
|
206
|
+
`default` slot **仅对 `role: 'assistant'` 生效**,用于替换默认的 `ContentRender`。
|
|
207
|
+
|
|
208
|
+
未提供 slot 时,内部回退为:
|
|
209
|
+
|
|
210
|
+
```ts
|
|
211
|
+
h(ContentRender, { content: message.content || '', status: message.status }, /* codeHeader */)
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
自定义 slot 时,运行时参数来自 `AssistantMessage` 的 `v-bind`,**仅保证 `{ content }`**。需要 `status` 时请从外层 `message.status` 读取(不要依赖 slot 内的 `status`)。
|
|
206
215
|
|
|
207
216
|
```vue
|
|
208
217
|
<template>
|
|
209
|
-
<MessageRender
|
|
210
|
-
|
|
211
|
-
:on-action="handleAction"
|
|
212
|
-
>
|
|
213
|
-
<template #default="{ content, status }">
|
|
214
|
-
<!-- 完全接管内容区域渲染 -->
|
|
218
|
+
<MessageRender :message="message">
|
|
219
|
+
<template #default="{ content }">
|
|
215
220
|
<MyMarkdownRenderer
|
|
216
221
|
:content="content"
|
|
217
|
-
:streaming="status === 'streaming'"
|
|
222
|
+
:streaming="message.status === 'streaming'"
|
|
218
223
|
/>
|
|
219
224
|
</template>
|
|
220
225
|
</MessageRender>
|
|
221
226
|
</template>
|
|
222
227
|
```
|
|
223
228
|
|
|
224
|
-
|
|
229
|
+
| 参数 | 类型 | 说明 |
|
|
230
|
+
| --------- | -------- | ---------------------------- |
|
|
231
|
+
| `content` | `string` | 消息内容(运行时保证) |
|
|
225
232
|
|
|
226
|
-
|
|
227
|
-
| --------- | --------------- | ------------ |
|
|
228
|
-
| `content` | `string` | 消息内容 |
|
|
229
|
-
| `status` | `MessageStatus` | 当前消息状态 |
|
|
233
|
+
## 与 MessageContainer / ChatContainer 配合
|
|
230
234
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
在 `MessageContainer` 的 `default` slot 中使用,可替换默认的 `MessageRender` 渲染逻辑:
|
|
235
|
+
自定义 `ChatContainer` 的 `#message` 时,插槽参数只有 `message` / `messageToolsStatus` / `onInterruptResume`。用户消息工具相关回调需由外层自行绑定透传,否则删除/编辑/复制/引用会失效(AI 消息工具栏在 `MessageContainer` 内渲染,不受 `#message` 影响):
|
|
234
236
|
|
|
235
237
|
```vue
|
|
236
238
|
<template>
|
|
237
|
-
<
|
|
239
|
+
<ChatContainer
|
|
238
240
|
:messages="messages"
|
|
239
241
|
:message-status="messageStatus"
|
|
240
242
|
:on-agent-action="handleAgentAction"
|
|
241
243
|
:on-user-action="handleUserAction"
|
|
242
|
-
|
|
244
|
+
:common-tippy-options="commonTippyOptions"
|
|
243
245
|
>
|
|
244
|
-
<template #
|
|
245
|
-
<!-- 自定义 MessageRender 的行为 -->
|
|
246
|
+
<template #message="{ message, messageToolsStatus, onInterruptResume }">
|
|
246
247
|
<MessageRender
|
|
247
248
|
:message="message"
|
|
248
249
|
:message-tools-status="messageToolsStatus"
|
|
249
250
|
:on-action="handleUserAction"
|
|
250
|
-
:on-input-confirm="
|
|
251
|
+
:on-input-confirm="(content, docSchema) => handleUserInputConfirm(message, content, docSchema)"
|
|
252
|
+
:on-shortcut-confirm="formModel => handleUserShortcutConfirm(message, formModel)"
|
|
253
|
+
:tippy-options="commonTippyOptions"
|
|
254
|
+
:on-interrupt-resume="onInterruptResume"
|
|
251
255
|
>
|
|
252
256
|
<template
|
|
253
257
|
v-if="message.role === 'assistant'"
|
|
254
|
-
#default="{ content
|
|
258
|
+
#default="{ content }"
|
|
255
259
|
>
|
|
256
260
|
<MyCustomContent
|
|
257
261
|
:content="content"
|
|
258
|
-
:status="status"
|
|
262
|
+
:status="message.status"
|
|
263
|
+
/>
|
|
264
|
+
</template>
|
|
265
|
+
<template #codeHeader="{ language, token }">
|
|
266
|
+
<MyCodeActions
|
|
267
|
+
:language="language"
|
|
268
|
+
:token="token"
|
|
259
269
|
/>
|
|
260
270
|
</template>
|
|
261
271
|
</MessageRender>
|
|
262
272
|
</template>
|
|
263
|
-
</
|
|
273
|
+
</ChatContainer>
|
|
264
274
|
</template>
|
|
265
275
|
```
|
|
266
276
|
|
|
@@ -280,11 +290,11 @@ slot 参数类型与 `AssistantMessage` 的 slot 保持一致(`Partial<Assista
|
|
|
280
290
|
|
|
281
291
|
### Slots
|
|
282
292
|
|
|
283
|
-
| 插槽名 | 参数
|
|
284
|
-
| ---------------- |
|
|
285
|
-
| answeredQuestion | `{ item, index, status }`
|
|
286
|
-
| codeHeader | `{ language: string; token: Token[] }`
|
|
287
|
-
| default | `{ content: string
|
|
293
|
+
| 插槽名 | 参数 | 说明 |
|
|
294
|
+
| ---------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------- |
|
|
295
|
+
| answeredQuestion | `{ item, index, status }` | 自定义 UserQuestion 已回答回显,透传给 InterruptMessageRender → UserQuestionAnsweredCard 的 `#answer` |
|
|
296
|
+
| codeHeader | `{ language: string; token: Token[] }` | 代码块头部自定义操作区域,透传给 ContentRender → MarkdownContent → CodeContent;**仅对 assistant 生效** |
|
|
297
|
+
| default | `{ content: string }` | 替换 AssistantMessage 内容区;**仅对 assistant 生效**;运行时仅保证 `content`(`status` 请读外层 message) |
|
|
288
298
|
|
|
289
299
|
## 消息类型映射
|
|
290
300
|
|
|
@@ -314,6 +324,7 @@ enum MessageRole {
|
|
|
314
324
|
Tool = 'tool',
|
|
315
325
|
Activity = 'activity',
|
|
316
326
|
Loading = 'loading',
|
|
327
|
+
Interrupt = 'interrupt',
|
|
317
328
|
}
|
|
318
329
|
|
|
319
330
|
// 消息状态
|
|
@@ -361,11 +361,15 @@ const CONST_UPDATE_TOOLS = [
|
|
|
361
361
|
|
|
362
362
|
```typescript
|
|
363
363
|
import { MessageToolsStatus, type IToolBtn } from '@blueking/chat-x';
|
|
364
|
+
import type { Component, VNode } from 'vue';
|
|
364
365
|
|
|
365
366
|
interface IToolBtn {
|
|
366
|
-
id?:
|
|
367
|
+
id?: (string & {}) | ToolIcons; // 工具唯一标识;命中 ToolIconsMap 显示内置图标,否则显示 name 文本;支持业务自定义字符串
|
|
367
368
|
name?: string; // 工具名称,无对应图标时显示;也用作 tooltip fallback
|
|
368
369
|
description?: string; // tooltip 文本
|
|
370
|
+
icon?: Component | VNode; // 自定义图标(组件/VNode),优先级高于内置 ToolIconsMap[id]
|
|
371
|
+
hidden?: boolean; // 按 id 合并时隐藏该按钮(仅在 MessageContainer/ChatContainer 合并语义下生效)
|
|
372
|
+
triggerSelection?: boolean; // 标记点击后进入多选态(复用 share 选择流程),确认走 confirmShare
|
|
369
373
|
}
|
|
370
374
|
|
|
371
375
|
enum MessageToolsStatus {
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
<!-- AI SUMMARY -->
|
|
2
|
+
## 快速了解
|
|
3
|
+
|
|
4
|
+
聊天输入区的模型下拉选择器,支持搜索过滤、能力标签与键盘导航。 源码位置:src/components/chat-input/model-selector/model-selector.vue。
|
|
5
|
+
|
|
6
|
+
### 关联组件
|
|
7
|
+
- **chat-input** — 传入 models 后在发送按钮左侧默认渲染
|
|
8
|
+
- **input-attachment** — 通过 before-send 插槽与发送按钮成组布局
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
<!-- FULL DOC -->
|
|
12
|
+
|
|
13
|
+
# ModelSelector 模型选择器
|
|
14
|
+
|
|
15
|
+
## 源码事实
|
|
16
|
+
|
|
17
|
+
- **源码位置**:`src/components/chat-input/model-selector/model-selector.vue`
|
|
18
|
+
- **能力域**:输入交互
|
|
19
|
+
- **能力说明**:基于 Tippy 下拉的模型选择器,包含触发器、搜索面板与能力标签展示;数据过滤逻辑由 `useModelSelector` composable 承担。
|
|
20
|
+
|
|
21
|
+
> **能力域**:输入交互
|
|
22
|
+
|
|
23
|
+
可在 [ChatInput](/components/input/chat-input) 传入 `models` 后自动出现在发送按钮左侧,也可单独使用。
|
|
24
|
+
|
|
25
|
+
## 组件结构
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
ModelSelector(Tippy 容器,theme: ai-model-selector)
|
|
29
|
+
├── ModelSelectorTrigger(触发器:图标 + 名称 + 箭头)
|
|
30
|
+
└── ModelSelectorPanel(下拉面板)
|
|
31
|
+
├── 搜索框(展开后自动聚焦)
|
|
32
|
+
└── 模型列表(支持键盘导航、选中态、禁用态、能力标签)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## 基础用法
|
|
36
|
+
|
|
37
|
+
选中值为模型的 `llm_name`;能力标签由组件依据 `property`(`support_thinking` / `support_thinking_quick` / `support_vision`)自动派生,无需调用方传入。
|
|
38
|
+
|
|
39
|
+
```vue
|
|
40
|
+
<template>
|
|
41
|
+
<ModelSelector
|
|
42
|
+
v-model="selectedModel"
|
|
43
|
+
:models="models"
|
|
44
|
+
@change="handleModelChange"
|
|
45
|
+
/>
|
|
46
|
+
</template>
|
|
47
|
+
|
|
48
|
+
<script setup lang="ts">
|
|
49
|
+
import { ref } from 'vue';
|
|
50
|
+
import { ModelSelector, type IModelOption } from '@blueking/chat-x';
|
|
51
|
+
|
|
52
|
+
// 选中值为 llm_name
|
|
53
|
+
const selectedModel = ref('DeepSeek-V4-Pro-Online-32k');
|
|
54
|
+
const models: IModelOption[] = [
|
|
55
|
+
{
|
|
56
|
+
id: 119,
|
|
57
|
+
llm_code: 'DeepSeek-V4-Pro-Online-32k',
|
|
58
|
+
llm_name: 'DeepSeek-V4-Pro-Online-32k',
|
|
59
|
+
llm_type: 'chat.completion',
|
|
60
|
+
space_auth_mode: 'APPLY',
|
|
61
|
+
user_auth_mode: 'PUBLIC',
|
|
62
|
+
max_token_size: 4096,
|
|
63
|
+
icon: 'https://example.com/deepseek.png',
|
|
64
|
+
description: 'DeepSeek-V4-Pro 旗舰版本,支持超长上下文与复杂任务处理',
|
|
65
|
+
base_model: 'deepseek',
|
|
66
|
+
tag_names: [],
|
|
67
|
+
// support_thinking → 深度思考、support_vision → 图生文
|
|
68
|
+
property: { support_thinking: true, support_vision: true, max_model_len: 32000 },
|
|
69
|
+
},
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
const handleModelChange = (model: IModelOption) => {
|
|
73
|
+
console.log('选中模型:', model);
|
|
74
|
+
};
|
|
75
|
+
</script>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## API
|
|
79
|
+
|
|
80
|
+
### Props
|
|
81
|
+
|
|
82
|
+
| 属性名 | 类型 | 默认值 | 说明 |
|
|
83
|
+
| ----------------- | -------------------------------------------------------------------------- | ---------------- | -------------------------------------- |
|
|
84
|
+
| disabled | `boolean` | `false` | 是否禁用整个选择器 |
|
|
85
|
+
| models | `IModelOption[]` | `[]` | 可选模型列表 |
|
|
86
|
+
| placeholder | `string` | `选择模型` | trigger 无选中时的占位文案 |
|
|
87
|
+
| searchPlaceholder | `string` | `搜索模型关键字` | 搜索框占位文案 |
|
|
88
|
+
| tippyOptions | `Partial<Omit<TippyOptions, 'getReferenceClientRect' \| 'triggerTarget'>>` | — | 透传给 Tippy 的额外配置 |
|
|
89
|
+
|
|
90
|
+
### v-model
|
|
91
|
+
|
|
92
|
+
| 属性名 | 类型 | 说明 |
|
|
93
|
+
| ------ | -------- | ----------------------------- |
|
|
94
|
+
| — | `string` | 当前选中模型的 `llm_name` 值 |
|
|
95
|
+
|
|
96
|
+
### Events
|
|
97
|
+
|
|
98
|
+
| 事件名 | 参数 | 说明 |
|
|
99
|
+
| ------ | ----------------------- | -------------------- |
|
|
100
|
+
| change | `(model: IModelOption)` | 用户选中模型时触发 |
|
|
101
|
+
|
|
102
|
+
## 类型定义
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
import type { IModelCapability, IModelOption, IModelProperty, ModelCapabilityTheme } from '@blueking/chat-x';
|
|
106
|
+
|
|
107
|
+
type ModelCapabilityTheme = 'default' | 'primary' | 'success' | 'warning';
|
|
108
|
+
|
|
109
|
+
// 能力标签由组件依据 property 派生(文案走内置 i18n)
|
|
110
|
+
interface IModelCapability {
|
|
111
|
+
theme?: ModelCapabilityTheme;
|
|
112
|
+
text: string;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// 模型能力属性,决定派生出的能力标签
|
|
116
|
+
interface IModelProperty {
|
|
117
|
+
agent_type?: string;
|
|
118
|
+
default?: boolean;
|
|
119
|
+
is_self_host?: boolean;
|
|
120
|
+
max_model_len?: number;
|
|
121
|
+
support_summary?: boolean;
|
|
122
|
+
support_thinking?: boolean; // → 深度思考
|
|
123
|
+
support_thinking_quick?: boolean; // → 快速思考
|
|
124
|
+
support_tools?: boolean;
|
|
125
|
+
support_vision?: boolean; // → 图生文
|
|
126
|
+
support_window?: boolean;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// 模型选项,贴合后端模型接口结构
|
|
130
|
+
interface IModelOption {
|
|
131
|
+
base_model?: string;
|
|
132
|
+
description?: string; // 选项 hover 的 title 提示
|
|
133
|
+
disabled?: boolean; // 前端扩展字段,禁用项不可选中
|
|
134
|
+
icon?: string;
|
|
135
|
+
id: number;
|
|
136
|
+
llm_code: string;
|
|
137
|
+
llm_name: string; // 展示名,同时作为选中值
|
|
138
|
+
llm_type: string;
|
|
139
|
+
max_token_size: number;
|
|
140
|
+
property: IModelProperty;
|
|
141
|
+
space_auth_mode: string;
|
|
142
|
+
tag_names?: string[];
|
|
143
|
+
user_auth_mode: string;
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## 注意事项
|
|
148
|
+
|
|
149
|
+
1. `models` 为空或 `disabled` 为 `true` 时,下拉不会展开。
|
|
150
|
+
2. 选中值为模型的 `llm_name`;能力标签由组件依据 `property` 的 `support_thinking` / `support_thinking_quick` / `support_vision` 派生,文案走内置 i18n。
|
|
151
|
+
3. `description` 会作为选项 hover 的 `title` 提示展示。
|
|
152
|
+
4. 展开面板后会自动聚焦搜索框;列表支持键盘上下选择与 Enter 确认(复用 `useMenuKeydown`)。
|
|
153
|
+
|
|
154
|
+
## 关联组件
|
|
155
|
+
|
|
156
|
+
- [ChatInput](/components/input/chat-input):传入 `models` 后默认在发送按钮左侧渲染本组件,也可通过 `#model-selector` 插槽完全自定义。
|
|
157
|
+
- [ChatContainer](/components/setup/chat-container):透传 `models` 与 `v-model:selected-model`,并向上 emit `modelChange`。
|
|
@@ -12,13 +12,14 @@
|
|
|
12
12
|
<!-- FULL DOC -->
|
|
13
13
|
|
|
14
14
|
# ReasoningMessage 推理消息
|
|
15
|
+
|
|
15
16
|
## 源码事实
|
|
16
17
|
|
|
17
18
|
- **源码位置**:`src/components/chat-message/reasoning-message/reasoning-message.vue`
|
|
18
19
|
- **能力域**:消息系统
|
|
19
20
|
- **能力说明**:渲染推理过程,覆盖加载、错误与 Markdown 内容展示。
|
|
20
21
|
|
|
21
|
-
>
|
|
22
|
+
> **导出说明**:`ReasoningMessage` **未**从包入口导出(入口同名是 TS interface)。消费方经 `MessageRender` / `MessageContainer` 使用。下文 `ReasoningMessageComp` 为文档站内部示例。
|
|
22
23
|
|
|
23
24
|
AI 思维链(Chain-of-Thought)推理过程展示组件。由**可点击标题栏**和**内容区域**组成,内容区支持 Markdown 渲染。`duration` 传入后自动折叠一次,用户可随时点击标题展开/收起。
|
|
24
25
|
|
|
@@ -44,17 +45,19 @@ AI 思维链(Chain-of-Thought)推理过程展示组件。由**可点击标
|
|
|
44
45
|
|
|
45
46
|
```vue
|
|
46
47
|
<template>
|
|
47
|
-
<
|
|
48
|
-
:content="content"
|
|
49
|
-
:status="status"
|
|
50
|
-
/>
|
|
48
|
+
<MessageRender :message="message" />
|
|
51
49
|
</template>
|
|
52
50
|
|
|
53
51
|
<script setup lang="ts">
|
|
54
|
-
import {
|
|
55
|
-
|
|
56
|
-
const
|
|
57
|
-
|
|
52
|
+
import { MessageRender, MessageRole, MessageStatus } from '@blueking/chat-x';
|
|
53
|
+
|
|
54
|
+
const message = {
|
|
55
|
+
id: '1',
|
|
56
|
+
messageId: '1',
|
|
57
|
+
role: MessageRole.Reasoning,
|
|
58
|
+
status: MessageStatus.Complete,
|
|
59
|
+
content: ['让我分析一下这个问题...', '首先需要考虑以下几个方面...'],
|
|
60
|
+
};
|
|
58
61
|
</script>
|
|
59
62
|
```
|
|
60
63
|
|
|
@@ -113,11 +116,12 @@ const { stop } = watch(
|
|
|
113
116
|
通过 `v-model:collapsed` 从外部读取或设置折叠状态:
|
|
114
117
|
|
|
115
118
|
```vue
|
|
119
|
+
<!-- 文档站内部示例:组件本体支持 v-model:collapsed;消费方一般经 MessageRender 渲染 -->
|
|
116
120
|
<template>
|
|
117
121
|
<button @click="collapsed = !collapsed">
|
|
118
122
|
{{ collapsed ? '展开推理' : '收起推理' }}
|
|
119
123
|
</button>
|
|
120
|
-
<
|
|
124
|
+
<ReasoningMessageComp
|
|
121
125
|
v-model:collapsed="collapsed"
|
|
122
126
|
:content="content"
|
|
123
127
|
:status="status"
|
|
@@ -127,7 +131,7 @@ const { stop } = watch(
|
|
|
127
131
|
|
|
128
132
|
<script setup lang="ts">
|
|
129
133
|
import { ref } from 'vue';
|
|
130
|
-
import {
|
|
134
|
+
import { MessageStatus } from '@blueking/chat-x';
|
|
131
135
|
|
|
132
136
|
const collapsed = ref(false);
|
|
133
137
|
const status = MessageStatus.Complete;
|
|
@@ -30,8 +30,9 @@ div.ai-tool-btn(v-tippy,flex,min-width: 20px,height: 20px,border-radiu
|
|
|
30
30
|
disabled=true → .is-disabled(color: #979ba5; cursor: not-allowed)
|
|
31
31
|
:not(.is-disabled):hover → color: #4d4f56; background: #eaebf0
|
|
32
32
|
│
|
|
33
|
-
└── <slot
|
|
34
|
-
├── [
|
|
33
|
+
└── <slot>(默认内容,可完全自定义;优先级最高)
|
|
34
|
+
├── [icon] → <component :is="icon" />(自定义图标组件/VNode,优先级高于内置图标)
|
|
35
|
+
├── [id && id in ToolIconsMap] → <component :is="ToolIconsMap[id]" />(内置 SVG 图标)
|
|
35
36
|
└── [其他] → <div>{{ name }}</div>(文本回退,XSS 安全)
|
|
36
37
|
|
|
37
38
|
Tippy:content=description, theme='ai-chat-box', disabled=true 时 onShow 返回 false 不显示
|
|
@@ -195,6 +196,28 @@ click 事件:disabled=true 时被 JS 拦截,不触发 emit
|
|
|
195
196
|
|
|
196
197
|
`id` 不在 `ToolIconsMap` 时渲染 `name` 文本,适用于自定义扩展场景:
|
|
197
198
|
|
|
199
|
+
## 自定义图标(icon 属性)
|
|
200
|
+
|
|
201
|
+
当内置 `ToolIconsMap` 未覆盖所需图标时,可通过 `icon` 传入自定义图标组件或 VNode(如业务新增的「保存」按钮)。`icon` 的渲染优先级高于内置图标,因此即便 `id` 命中内置图标,也会以 `icon` 为准。
|
|
202
|
+
|
|
203
|
+
```vue
|
|
204
|
+
<template>
|
|
205
|
+
<ToolBtn
|
|
206
|
+
id="save"
|
|
207
|
+
name="保存"
|
|
208
|
+
description="保存该回答"
|
|
209
|
+
:icon="DownloadIcon"
|
|
210
|
+
@click="handleClick"
|
|
211
|
+
/>
|
|
212
|
+
</template>
|
|
213
|
+
|
|
214
|
+
<script setup lang="ts">
|
|
215
|
+
import { ToolBtn, DownloadIcon } from '@blueking/chat-x';
|
|
216
|
+
</script>
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
> 优先级从高到低:默认插槽 `>` `icon` 属性 `>` 内置 `ToolIconsMap[id]` `>` `name` 文本回退。
|
|
220
|
+
|
|
198
221
|
## 自定义插槽内容
|
|
199
222
|
|
|
200
223
|
通过默认插槽可完全替换内置图标/文本,适用于预置 `ToolIconsMap` 未覆盖的图标场景(如侧栏全屏按钮):
|
|
@@ -225,9 +248,10 @@ click 事件:disabled=true 时被 JS 拦截,不触发 emit
|
|
|
225
248
|
|
|
226
249
|
| 属性名 | 类型 | 必填 | 默认值 | 说明 |
|
|
227
250
|
| ------------ | -------------------------------------------------------------------------- | ---- | ------ | ------------------------------------------------------------------------------------------------------------------ |
|
|
228
|
-
| id | `
|
|
251
|
+
| id | `(string & {}) \| ToolIcons` | 否 | — | 按钮标识;命中 `ToolIconsMap` 时渲染对应 SVG 图标,否则渲染 `name` 文本;支持业务自定义任意字符串(如 `save`) |
|
|
229
252
|
| name | `string` | 否 | — | 按钮名称;`id` 无对应图标时作为文本内容渲染 |
|
|
230
253
|
| description | `string` | 否 | — | Tippy tooltip 内容;`disabled=true` 时不显示 tooltip |
|
|
254
|
+
| icon | `Component \| VNode` | 否 | — | 自定义图标组件或 VNode;优先级高于内置 `ToolIconsMap[id]`,低于默认插槽 |
|
|
231
255
|
| active | `boolean` | 否 | — | 激活态;`true` 时追加 `.is-active`(字色由 `id` 决定:`like`/`activeLike` 为蓝色 `#3a84ff`,其他为红色 `#E71818`) |
|
|
232
256
|
| disabled | `boolean` | 否 | — | 禁用态;`true` 时追加 `.is-disabled`,阻止 click 事件,隐藏 tooltip |
|
|
233
257
|
| tippyOptions | `Partial<Omit<TippyOptions, 'getReferenceClientRect' \| 'triggerTarget'>>` | 否 | — | 自定义 Tippy 配置,与内部默认配置合并;可用于控制 `content`、`appendTo`、`placement` 等 |
|
|
@@ -247,11 +271,16 @@ click 事件:disabled=true 时被 JS 拦截,不触发 emit
|
|
|
247
271
|
## 类型定义
|
|
248
272
|
|
|
249
273
|
```typescript
|
|
274
|
+
import type { Component, VNode } from 'vue';
|
|
275
|
+
|
|
250
276
|
// 来自 @blueking/chat-x 导出
|
|
251
277
|
interface IToolBtn {
|
|
252
|
-
id?:
|
|
278
|
+
id?: (string & {}) | ToolIcons; // 内置 ID 保留自动补全,同时允许业务自定义任意字符串(如 'save')
|
|
253
279
|
name?: string;
|
|
254
280
|
description?: string;
|
|
281
|
+
icon?: Component | VNode; // 自定义图标,优先级高于内置 ToolIconsMap
|
|
282
|
+
hidden?: boolean; // 按 id 合并时隐藏该按钮(如 { id: 'share', hidden: true } 移除内置项)
|
|
283
|
+
triggerSelection?: boolean; // 标记点击后进入多选态(复用 share 选择流程),确认走 confirmShare
|
|
255
284
|
}
|
|
256
285
|
|
|
257
286
|
// ToolBtn 完整 Props
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<!-- AI SUMMARY -->
|
|
2
2
|
## 快速了解
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
渲染工具返回内容;DescPanel 解析 JSON 为 key-value,嵌套值 JSON.stringify 后经 HighlightKeyword 展示。 源码位置:src/components/chat-message/tool-message/tool-message.vue。
|
|
5
5
|
|
|
6
6
|
### 关联组件
|
|
7
7
|
- **assistant-message** — 结果常作为 assistant 消息中 toolCall.toolMessage 内联展示
|
|
@@ -12,51 +12,57 @@
|
|
|
12
12
|
<!-- FULL DOC -->
|
|
13
13
|
|
|
14
14
|
# ToolMessage 工具消息
|
|
15
|
+
|
|
15
16
|
## 源码事实
|
|
16
17
|
|
|
17
18
|
- **源码位置**:`src/components/chat-message/tool-message/tool-message.vue`
|
|
18
19
|
- **能力域**:消息系统
|
|
19
|
-
- **能力说明**:渲染工具返回内容,JSON 场景交给 DescPanel 展示。
|
|
20
|
+
- **能力说明**:渲染工具返回内容,JSON 场景交给 DescPanel + HighlightKeyword 展示。
|
|
20
21
|
|
|
21
|
-
>
|
|
22
|
+
> **导出说明**:`ToolMessage` **未**从包入口导出(入口同名是 TS interface)。消费方经 `MessageRender` / `ToolcallRender` 使用。下文 `ToolMessageComp` 为文档站内部示例。
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
工具执行结果展示组件。内部通过 `DescPanel` 渲染,标题固定为「返回内容」,可解析 JSON 为 key-value 列表。
|
|
24
25
|
|
|
25
|
-
>
|
|
26
|
+
> **通常不需要直接使用**。`ToolcallRender` 在 `toolCall.toolMessage` 有值时内联渲染;`role: 'tool'` 也可由 `MessageRender` 渲染。
|
|
26
27
|
|
|
27
28
|
## 渲染架构
|
|
28
29
|
|
|
29
30
|
```
|
|
30
31
|
ToolMessage
|
|
31
|
-
└── DescPanel(desc=
|
|
32
|
-
├── JSON.parse
|
|
33
|
-
│ └── key-value
|
|
34
|
-
│
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
└── DescPanel(desc = content || (typeof error === 'string' ? error : undefined),title="返回内容")
|
|
33
|
+
├── JSON.parse 成功且结果为 object/array(排除 null)
|
|
34
|
+
│ └── key-value 列表
|
|
35
|
+
│ · key / value 均经 HighlightKeyword 展示
|
|
36
|
+
│ · 嵌套 object/array:JSON.stringify 后展示(无 overflow-tips)
|
|
37
|
+
└── 其他(parse 失败 / 标量)
|
|
38
|
+
└── HighlightKeyword 纯文本
|
|
37
39
|
```
|
|
38
40
|
|
|
39
41
|
## 基础用法
|
|
40
42
|
|
|
41
43
|
```vue
|
|
42
44
|
<template>
|
|
43
|
-
<
|
|
44
|
-
:content="content"
|
|
45
|
-
tool-call-id="call_1"
|
|
46
|
-
:duration="850"
|
|
47
|
-
/>
|
|
45
|
+
<MessageRender :message="message" />
|
|
48
46
|
</template>
|
|
49
47
|
|
|
50
48
|
<script setup lang="ts">
|
|
51
|
-
import {
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
49
|
+
import { MessageRender, MessageRole, MessageStatus } from '@blueking/chat-x';
|
|
50
|
+
|
|
51
|
+
const message = {
|
|
52
|
+
id: 't1',
|
|
53
|
+
messageId: 't1',
|
|
54
|
+
role: MessageRole.Tool,
|
|
55
|
+
status: MessageStatus.Complete,
|
|
56
|
+
toolCallId: 'call_1',
|
|
57
|
+
duration: 850,
|
|
58
|
+
content: JSON.stringify({
|
|
59
|
+
city: '北京',
|
|
60
|
+
temperature: 22,
|
|
61
|
+
weather: '晴',
|
|
62
|
+
humidity: '45%',
|
|
63
|
+
wind: '东北风 3 级',
|
|
64
|
+
}),
|
|
65
|
+
};
|
|
60
66
|
</script>
|
|
61
67
|
```
|
|
62
68
|
|
|
@@ -70,18 +76,22 @@ ToolMessage
|
|
|
70
76
|
|
|
71
77
|
```vue
|
|
72
78
|
<template>
|
|
73
|
-
<
|
|
74
|
-
content=""
|
|
75
|
-
:error="error"
|
|
76
|
-
tool-call-id="call_3"
|
|
77
|
-
:duration="5000"
|
|
78
|
-
/>
|
|
79
|
+
<MessageRender :message="message" />
|
|
79
80
|
</template>
|
|
80
81
|
|
|
81
82
|
<script setup lang="ts">
|
|
82
|
-
import {
|
|
83
|
-
|
|
84
|
-
const
|
|
83
|
+
import { MessageRender, MessageRole, MessageStatus } from '@blueking/chat-x';
|
|
84
|
+
|
|
85
|
+
const message = {
|
|
86
|
+
id: 't3',
|
|
87
|
+
messageId: 't3',
|
|
88
|
+
role: MessageRole.Tool,
|
|
89
|
+
status: MessageStatus.Error,
|
|
90
|
+
toolCallId: 'call_3',
|
|
91
|
+
duration: 5000,
|
|
92
|
+
content: '',
|
|
93
|
+
error: 'Connection timeout: database server is unreachable (timeout: 5000ms)',
|
|
94
|
+
};
|
|
85
95
|
</script>
|
|
86
96
|
```
|
|
87
97
|
|
|
@@ -98,25 +108,27 @@ ToolMessage
|
|
|
98
108
|
| 解析失败(非法 JSON) | 捕获异常,返回原字符串 | 纯文本 |
|
|
99
109
|
| `content` 和 `error` 均为空 | `''` → 解析失败 | 空内容区 |
|
|
100
110
|
|
|
101
|
-
> **注意**:JSON
|
|
111
|
+
> **注意**:JSON 数组 `typeof [] === 'object'`,会以 `0:`、`1:`、`2:` 为键渲染为列表,而非整段纯文本。
|
|
102
112
|
|
|
103
|
-
|
|
113
|
+
**嵌套对象 / 数组值**:`DescPanel` 用 `JSON.stringify(value)` 转成字符串后交给 `HighlightKeyword`,**不再**使用 overflow-tips。
|
|
104
114
|
|
|
105
115
|
```typescript
|
|
106
|
-
//
|
|
116
|
+
// key-value 列表
|
|
107
117
|
const jsonObject = '{"city":"北京","temperature":22}';
|
|
108
118
|
|
|
109
|
-
//
|
|
119
|
+
// index-keyed 列表(0: item1, 1: item2)
|
|
110
120
|
const jsonArray = '["item1","item2","item3"]';
|
|
111
121
|
|
|
112
|
-
//
|
|
113
|
-
const
|
|
114
|
-
const jsonBool = 'true';
|
|
122
|
+
// 嵌套值 stringify 展示
|
|
123
|
+
const nested = '{"result":"success","data":{"city":"北京","meta":{"humidity":45}}}';
|
|
115
124
|
|
|
116
|
-
//
|
|
125
|
+
// 标量 / 非法 JSON → 纯文本
|
|
126
|
+
const jsonNumber = '42';
|
|
117
127
|
const plainText = '查询成功,共返回 10 条记录。';
|
|
118
128
|
```
|
|
119
129
|
|
|
130
|
+
**嵌套 JSON 渲染效果**
|
|
131
|
+
|
|
120
132
|
## 与 ToolcallRender 的关系
|
|
121
133
|
|
|
122
134
|
`ToolcallRender` 在详情面板展开时,若 `toolCall.toolMessage` 有值,会在底部内联渲染 `ToolMessage`:
|
|
@@ -186,8 +198,8 @@ const messages = [
|
|
|
186
198
|
|
|
187
199
|
| 属性名 | 类型 | 说明 |
|
|
188
200
|
| ---------- | ------------------ | ------------------------------------------------------------------------------- |
|
|
189
|
-
| content | `string`
|
|
190
|
-
| error | `string`
|
|
201
|
+
| content | `string` | 工具执行返回内容;与 `error` 通过 `\|\|` 决定优先级,**truthy 时 error 被忽略** |
|
|
202
|
+
| error | `boolean \| string` | 类型上可为 boolean;**仅当为 `string` 且 content 为 falsy 时**才会展示 |
|
|
191
203
|
| toolCallId | `string` | 关联的工具调用 ID(透传,组件内不使用) |
|
|
192
204
|
| duration | `number` | 工具执行耗时(毫秒,透传,组件内不使用) |
|
|
193
205
|
| status | `MessageStatus` | 消息状态(透传,组件内不使用) |
|
|
@@ -210,11 +222,15 @@ interface ToolMessage {
|
|
|
210
222
|
content: string;
|
|
211
223
|
toolCallId: string; // 关联的 ToolCall.id
|
|
212
224
|
duration: number; // 工具执行耗时(毫秒)
|
|
213
|
-
error?: string; //
|
|
225
|
+
error?: boolean | string; // 仅 string 会展示在 DescPanel
|
|
214
226
|
name?: string;
|
|
215
227
|
}
|
|
216
228
|
```
|
|
217
229
|
|
|
230
|
+
### Events / Slots / Expose
|
|
231
|
+
|
|
232
|
+
无。
|
|
233
|
+
|
|
218
234
|
## 关联组件
|
|
219
235
|
|
|
220
236
|
- [AssistantMessage](/components/message/assistant-message) — toolCall.toolMessage 内联场景
|