@blueking/chat-x 0.0.5 → 0.0.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/dist/components/ai-selection/ai-selection.vue.d.ts +2 -2
- package/dist/components/index.d.ts +2 -1
- package/dist/index.css +1 -1
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/dist/mcp/generated/docs/activity-message.md +428 -0
- package/dist/mcp/generated/docs/ai-image.md +227 -0
- package/dist/mcp/generated/docs/ai-loading.md +129 -0
- package/dist/mcp/generated/docs/ai-selection.md +436 -0
- package/dist/mcp/generated/docs/animation-text.md +199 -0
- package/dist/mcp/generated/docs/assistant-message.md +424 -0
- package/dist/mcp/generated/docs/chat-container.md +402 -0
- package/dist/mcp/generated/docs/chat-input.md +625 -0
- package/dist/mcp/generated/docs/cite-content.md +138 -0
- package/dist/mcp/generated/docs/code-content.md +199 -0
- package/dist/mcp/generated/docs/common-error-content.md +70 -0
- package/dist/mcp/generated/docs/constants.md +216 -0
- package/dist/mcp/generated/docs/content-render.md +238 -0
- package/dist/mcp/generated/docs/delete-tool.md +188 -0
- package/dist/mcp/generated/docs/desc-panel.md +139 -0
- package/dist/mcp/generated/docs/execution-summary.md +126 -0
- package/dist/mcp/generated/docs/file-content.md +300 -0
- package/dist/mcp/generated/docs/file-upload-btn.md +174 -0
- package/dist/mcp/generated/docs/flow-message.md +305 -0
- package/dist/mcp/generated/docs/highlight-keyword.md +144 -0
- package/dist/mcp/generated/docs/image-content.md +178 -0
- package/dist/mcp/generated/docs/image-preview-group.md +181 -0
- package/dist/mcp/generated/docs/image-preview.md +224 -0
- package/dist/mcp/generated/docs/info-message.md +124 -0
- package/dist/mcp/generated/docs/key-value-content.md +124 -0
- package/dist/mcp/generated/docs/latex-content.md +196 -0
- package/dist/mcp/generated/docs/loading-message.md +171 -0
- package/dist/mcp/generated/docs/markdown-content.md +186 -0
- package/dist/mcp/generated/docs/markdown-latex.md +208 -0
- package/dist/mcp/generated/docs/markdown-mermaid.md +250 -0
- package/dist/mcp/generated/docs/mermaid-content.md +185 -0
- package/dist/mcp/generated/docs/message-container.md +534 -0
- package/dist/mcp/generated/docs/message-render.md +329 -0
- package/dist/mcp/generated/docs/message-tools.md +376 -0
- package/dist/mcp/generated/docs/messages.md +472 -0
- package/dist/mcp/generated/docs/overflow-tips.md +209 -0
- package/dist/mcp/generated/docs/reasoning-message.md +233 -0
- package/dist/mcp/generated/docs/reference-content.md +132 -0
- package/dist/mcp/generated/docs/scroll-btn.md +155 -0
- package/dist/mcp/generated/docs/selection-footer.md +75 -0
- package/dist/mcp/generated/docs/shortcut-btn.md +202 -0
- package/dist/mcp/generated/docs/shortcut-btns.md +264 -0
- package/dist/mcp/generated/docs/shortcut-render.md +418 -0
- package/dist/mcp/generated/docs/text-content.md +74 -0
- package/dist/mcp/generated/docs/theme.md +388 -0
- package/dist/mcp/generated/docs/tool-btn.md +254 -0
- package/dist/mcp/generated/docs/tool-message.md +217 -0
- package/dist/mcp/generated/docs/toolcall-render.md +299 -0
- package/dist/mcp/generated/docs/use-animation-text.md +198 -0
- package/dist/mcp/generated/docs/use-clipboard.md +206 -0
- package/dist/mcp/generated/docs/use-command-selection.md +128 -0
- package/dist/mcp/generated/docs/use-container-scroll.md +56 -0
- package/dist/mcp/generated/docs/use-custom-tab.md +122 -0
- package/dist/mcp/generated/docs/use-global-config.md +154 -0
- package/dist/mcp/generated/docs/use-menu-keydown.md +164 -0
- package/dist/mcp/generated/docs/use-message-group.md +175 -0
- package/dist/mcp/generated/docs/use-observer-visible-list.md +189 -0
- package/dist/mcp/generated/docs/use-parent-scrolling.md +46 -0
- package/dist/mcp/generated/docs/user-feedback.md +229 -0
- package/dist/mcp/generated/docs/user-message.md +347 -0
- package/dist/mcp/generated/index.json +1311 -0
- package/dist/mcp/index.d.ts +2 -0
- package/dist/mcp/index.js +42 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/server.d.ts +2 -0
- package/dist/mcp/server.js +43 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools/get-component-doc.d.ts +19 -0
- package/dist/mcp/tools/get-component-doc.js +60 -0
- package/dist/mcp/tools/get-component-doc.js.map +1 -0
- package/dist/mcp/tools/list-components.d.ts +35 -0
- package/dist/mcp/tools/list-components.js +147 -0
- package/dist/mcp/tools/list-components.js.map +1 -0
- package/dist/mcp/tools/search-docs.d.ts +14 -0
- package/dist/mcp/tools/search-docs.js +82 -0
- package/dist/mcp/tools/search-docs.js.map +1 -0
- package/dist/mcp/utils/doc-loader.d.ts +35 -0
- package/dist/mcp/utils/doc-loader.js +64 -0
- package/dist/mcp/utils/doc-loader.js.map +1 -0
- package/package.json +5 -7
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
<!-- AI SUMMARY -->
|
|
2
|
+
## 快速了解
|
|
3
|
+
|
|
4
|
+
AnimationText 将文本拆成 chunk 并以淡入 keyframes 逐段显示,适合短文案一次性展示。 props.text 仅在挂载时参与动画;持续流式场景应直接使用 useAnimationText 或自行 watch Ref。 与 Markdown 流式渐显等场景可组合使用。
|
|
5
|
+
|
|
6
|
+
### 关联组件
|
|
7
|
+
- **use-animation-text** — 提供 chunk 拆分与 animationStyle 的 composable
|
|
8
|
+
- **markdown-content** — 流式 Markdown 中可与渐显策略配合
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
<!-- FULL DOC -->
|
|
12
|
+
|
|
13
|
+
# AnimationText 动画文本
|
|
14
|
+
|
|
15
|
+
> **层级**:原子组件 · **功能域**:内容渲染
|
|
16
|
+
|
|
17
|
+
动画文本原子组件,将文本以**淡入(fade-in)**方式渐显。内部由 `useAnimationText` composable 驱动,核心能力是将增量文本拆分为独立 chunk,每个 chunk 单独触发一次淡入动画,适用于流式文本的逐段渐显效果。
|
|
18
|
+
|
|
19
|
+
## 组件结构
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
AnimationText
|
|
23
|
+
└── <span v-for="chunk in chunks" :style="animationStyle">
|
|
24
|
+
{{ chunk }}
|
|
25
|
+
</span>
|
|
26
|
+
|
|
27
|
+
animationStyle = {
|
|
28
|
+
animation: `ai-markdown-fade-in {fadeDuration}ms {easing} forwards`,
|
|
29
|
+
color: 'inherit',
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@keyframes ai-markdown-fade-in {
|
|
33
|
+
0% { opacity: 0; }
|
|
34
|
+
100% { opacity: 1; }
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
> **注意**:`AnimationText` 组件将 `props.text`(字符串原始值)传给 `useAnimationText`,watch 只触发一次(挂载时),**prop 变化后不会触发新动画**。若需响应式流式效果,请直接使用 `useAnimationText` composable,并传入 `Ref<string>`。
|
|
39
|
+
|
|
40
|
+
## 基础用法
|
|
41
|
+
|
|
42
|
+
挂载时文本以淡入方式显示,适合一次性展示的短文本动画:
|
|
43
|
+
|
|
44
|
+
```vue
|
|
45
|
+
<template>
|
|
46
|
+
<AnimationText text="这是一段带动画效果的文本" />
|
|
47
|
+
</template>
|
|
48
|
+
|
|
49
|
+
<script setup lang="ts">
|
|
50
|
+
import { AnimationText } from '@blueking/chat-x';
|
|
51
|
+
</script>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## 流式文本(推荐使用 composable)
|
|
55
|
+
|
|
56
|
+
对于流式输出场景,需直接使用 `useAnimationText` 并传入响应式 `Ref<string>`:
|
|
57
|
+
|
|
58
|
+
```vue
|
|
59
|
+
<template>
|
|
60
|
+
<span
|
|
61
|
+
v-for="(chunk, index) in streamChunks"
|
|
62
|
+
:key="index"
|
|
63
|
+
:style="streamAnimStyle"
|
|
64
|
+
>{{ chunk }}</span
|
|
65
|
+
>
|
|
66
|
+
</template>
|
|
67
|
+
|
|
68
|
+
<script setup lang="ts">
|
|
69
|
+
import { ref, watch } from 'vue';
|
|
70
|
+
|
|
71
|
+
const streamText = ref('');
|
|
72
|
+
const streamChunks = ref<string[]>([]);
|
|
73
|
+
const streamAnimStyle = {
|
|
74
|
+
animation: 'ai-markdown-fade-in 200ms ease-in-out forwards',
|
|
75
|
+
color: 'inherit',
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// 直接 watch Ref(Vue 自动追踪 .value 变化)
|
|
79
|
+
// ⚠️ 不能写成 watch(() => streamText, ...),那样 getter 每次返回同一个 Ref 引用,永远不触发
|
|
80
|
+
watch(streamText, (newVal, oldVal) => {
|
|
81
|
+
if (!oldVal || !newVal.startsWith(oldVal)) {
|
|
82
|
+
streamChunks.value = [newVal]; // 内容替换 → 整体重置
|
|
83
|
+
} else {
|
|
84
|
+
const chunk = newVal.slice(oldVal.length);
|
|
85
|
+
if (chunk) streamChunks.value = [...streamChunks.value, chunk]; // 追加 → 新 chunk 淡入
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// 模拟流式追加
|
|
90
|
+
async function receiveStream() {
|
|
91
|
+
streamText.value = '';
|
|
92
|
+
streamChunks.value = [];
|
|
93
|
+
for (const char of '来自 AI 的流式回复内容...') {
|
|
94
|
+
streamText.value += char;
|
|
95
|
+
await new Promise(r => setTimeout(r, 80));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
</script>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**效果演示**(点击按钮触发流式输出)
|
|
102
|
+
|
|
103
|
+
## chunk 增量算法
|
|
104
|
+
|
|
105
|
+
`useAnimationText` 内部通过**前缀检测**将文本变化拆分为增量 chunk:
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
新文本以旧文本为前缀(即纯追加)→ 截取增量部分 → 追加新 chunk(触发新动画)
|
|
109
|
+
新文本与旧文本无前缀关系(内容替换)→ 清空所有 chunk → 用完整新文本创建单一 chunk
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
// watch 内部逻辑(简化)
|
|
114
|
+
if (newText === prevText) return; // 无变化,跳过
|
|
115
|
+
|
|
116
|
+
if (prevText && newText.startsWith(prevText)) {
|
|
117
|
+
// 追加模式:只有新增部分触发淡入
|
|
118
|
+
const newChunk = newText.slice(prevText.length);
|
|
119
|
+
chunks.value = [...chunks.value, newChunk];
|
|
120
|
+
} else {
|
|
121
|
+
// 重置模式:内容替换,整体重新淡入
|
|
122
|
+
chunks.value = [newText];
|
|
123
|
+
}
|
|
124
|
+
prevText = newText;
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
| 场景 | 示例 | 行为 |
|
|
128
|
+
| --------------- | ------------------------------------------ | ------------------------------ |
|
|
129
|
+
| 流式追加(SSE) | `"Hello"` → `"Hello Wo"` → `"Hello World"` | 每次增量部分单独淡入 |
|
|
130
|
+
| 内容完全替换 | `"旧文本"` → `"新文本"` | 清空所有 chunk,新文本整体淡入 |
|
|
131
|
+
| 相同内容 | `"文本"` → `"文本"` | 不做任何处理,跳过 |
|
|
132
|
+
|
|
133
|
+
## 自定义动画参数
|
|
134
|
+
|
|
135
|
+
`useAnimationText` 支持通过第二个参数自定义动画时长和缓动:
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
import { ref } from 'vue';
|
|
139
|
+
import { useAnimationText } from '@blueking/chat-x';
|
|
140
|
+
|
|
141
|
+
const text = ref('');
|
|
142
|
+
const { chunks, animationStyle } = useAnimationText(text, {
|
|
143
|
+
fadeDuration: 400, // 动画时长(ms),默认 200
|
|
144
|
+
easing: 'ease-out', // CSS easing,默认 'ease-in-out'
|
|
145
|
+
});
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
生成的 `animationStyle`:
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
// animationStyle 是 computed,格式为:
|
|
152
|
+
{
|
|
153
|
+
animation: `ai-markdown-fade-in ${fadeDuration}ms ${easing} forwards`,
|
|
154
|
+
color: 'inherit',
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
> **关键帧**:`ai-markdown-fade-in` 定义在库的全局样式中,仅做透明度变化(`opacity: 0 → 1`),无位移或缩放。
|
|
159
|
+
|
|
160
|
+
## API
|
|
161
|
+
|
|
162
|
+
### AnimationText Props
|
|
163
|
+
|
|
164
|
+
| 属性名 | 类型 | 必填 | 说明 |
|
|
165
|
+
| ------ | -------- | ---- | ----------------------------------------------- |
|
|
166
|
+
| text | `string` | ✓ | 要显示的文本;仅挂载时触发动画,prop 更新后无效 |
|
|
167
|
+
|
|
168
|
+
### useAnimationText
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
function useAnimationText(
|
|
172
|
+
text: MaybeRef<string>, // 字符串或 Ref<string>,传 Ref 才能响应变化
|
|
173
|
+
options?: AnimationConfig,
|
|
174
|
+
): {
|
|
175
|
+
chunks: Ref<string[]>; // 分割后的文本块数组,v-for 遍历渲染
|
|
176
|
+
animationStyle: ComputedRef<{
|
|
177
|
+
// 应用到每个 <span> 的 inline style
|
|
178
|
+
animation: string;
|
|
179
|
+
color: 'inherit';
|
|
180
|
+
}>;
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
interface AnimationConfig {
|
|
184
|
+
fadeDuration?: number; // 动画时长(ms),默认 200
|
|
185
|
+
easing?: string; // CSS easing,默认 'ease-in-out'
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## 注意事项
|
|
190
|
+
|
|
191
|
+
1. **`AnimationText` 不响应 prop 更新**:组件内部传的是字符串原始值,若需动态响应,直接用 `watch(myRef, ...)` 手动实现 chunk 逻辑
|
|
192
|
+
2. **流式场景不要使用 `useAnimationText`**:该 composable 内部使用 `watch(() => text, ...)` 的 getter 形式,当传入 `Ref<string>` 时,getter 每次返回同一个 Ref 引用,Vue 无法检测到 `.value` 变化,watch 只触发一次(immediate)。正确做法是直接 `watch(streamText, callback)` 绑定 Ref
|
|
193
|
+
3. **动画 keyframe 依赖全局样式**:使用 `@blueking/chat-x` 时会自动引入;独立使用时需确保 `ai-markdown-fade-in` 已定义
|
|
194
|
+
4. **chunks 只增不减**(追加模式下):流式结束后 chunks 保留所有历史分段,若需复用,手动清空 `chunks.value = []` 再重置文本即可
|
|
195
|
+
|
|
196
|
+
## 关联组件
|
|
197
|
+
|
|
198
|
+
- [useAnimationText](../../composables/use-animation-text.md) — chunk 与动画样式逻辑
|
|
199
|
+
- [MarkdownContent](./markdown-content.md) — 流式正文渲染时可配合渐显
|
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
<!-- AI SUMMARY -->
|
|
2
|
+
## 快速了解
|
|
3
|
+
|
|
4
|
+
AssistantMessage 渲染 AI 助手回复:正文由 ContentRender(可被默认插槽替换)与 ToolCallRender 展示工具调用及 MCP 标记。 toolCalls[].toolMessage 可内联工具执行结果。用于 MessageRender 分发的 assistant 角色,流式场景配合 streaming 状态更新。
|
|
5
|
+
|
|
6
|
+
### 关联组件
|
|
7
|
+
- **message-render** — 由 MessageRender 在 role 为 assistant 时创建
|
|
8
|
+
- **tool-message** — 工具结果通过 toolCall.toolMessage 内联或独立 tool 消息关联展示
|
|
9
|
+
- **toolcall-render** — 多条工具调用由 ToolcallRender 统一渲染
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
<!-- FULL DOC -->
|
|
13
|
+
|
|
14
|
+
# AssistantMessage AI 助手消息
|
|
15
|
+
|
|
16
|
+
> **层级**:分子组件 · **功能域**:消息展示
|
|
17
|
+
|
|
18
|
+
AI 助手消息展示组件,负责渲染 AI 回复的文本内容和工具调用(Tool Calls)结果。
|
|
19
|
+
|
|
20
|
+
## 渲染管线
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
AssistantMessage
|
|
24
|
+
├── assistant-message-content(内容区)
|
|
25
|
+
│ └── [default slot] 或 ContentRender → MarkdownContent(Markdown 渲染)
|
|
26
|
+
└── ToolCallRender × N(每个 toolCall 独立渲染,不受 slot 影响)
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
- **内容区**:`content` 字符串传入 `ContentRender`,内部固定使用 `MessageContentType.Text` 类型,最终由 `MarkdownContent` 渲染 Markdown
|
|
30
|
+
- **工具调用区**:`toolCalls` 数组中每一项渲染一个 `ToolCallRender`,位于内容区**下方**,与 slot 无关
|
|
31
|
+
|
|
32
|
+
## 基础用法
|
|
33
|
+
|
|
34
|
+
```vue
|
|
35
|
+
<template>
|
|
36
|
+
<AssistantMessage
|
|
37
|
+
:content="content"
|
|
38
|
+
:status="status"
|
|
39
|
+
/>
|
|
40
|
+
</template>
|
|
41
|
+
|
|
42
|
+
<script setup lang="ts">
|
|
43
|
+
import { AssistantMessage, MessageStatus } from '@blueking/chat-x';
|
|
44
|
+
|
|
45
|
+
const content = '你好!我是 AI 助手,有什么可以帮助你的吗?';
|
|
46
|
+
const status = MessageStatus.Complete;
|
|
47
|
+
</script>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**渲染效果**
|
|
51
|
+
|
|
52
|
+
## Markdown 内容渲染
|
|
53
|
+
|
|
54
|
+
`content` 支持 Markdown 格式,组件内部通过 `MarkdownContent` 自动渲染标题、列表、代码块、链接等:
|
|
55
|
+
|
|
56
|
+
```vue
|
|
57
|
+
<template>
|
|
58
|
+
<AssistantMessage
|
|
59
|
+
:content="markdownContent"
|
|
60
|
+
status="complete"
|
|
61
|
+
/>
|
|
62
|
+
</template>
|
|
63
|
+
|
|
64
|
+
<script setup lang="ts">
|
|
65
|
+
import { AssistantMessage } from '@blueking/chat-x';
|
|
66
|
+
|
|
67
|
+
const markdownContent = `## Vue 3 核心特性
|
|
68
|
+
|
|
69
|
+
Vue 3 引入了多项重要更新:
|
|
70
|
+
|
|
71
|
+
1. **Composition API**:提供更灵活的逻辑组织方式
|
|
72
|
+
2. **性能优化**:虚拟 DOM 重写,编译时优化
|
|
73
|
+
3. **TypeScript 支持**:内置完整的类型定义
|
|
74
|
+
|
|
75
|
+
\\\`\\\`\\\`typescript
|
|
76
|
+
import { ref, computed } from 'vue';
|
|
77
|
+
|
|
78
|
+
const count = ref(0);
|
|
79
|
+
const doubled = computed(() => count.value * 2);
|
|
80
|
+
\\\`\\\`\\\`
|
|
81
|
+
|
|
82
|
+
> 更多详情请参考 [Vue 3 官方文档](https://vuejs.org)。`;
|
|
83
|
+
</script>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**渲染效果**
|
|
87
|
+
|
|
88
|
+
## 消息状态
|
|
89
|
+
|
|
90
|
+
`status` 影响两处渲染:**内容区**和**工具调用状态标题**。
|
|
91
|
+
|
|
92
|
+
| `status` | 内容区效果 | ToolCallRender 标题 |
|
|
93
|
+
| ----------- | ----------------------------------- | ------------------- |
|
|
94
|
+
| `pending` | 正常渲染(通常 content 为空) | Loading + "调用中" |
|
|
95
|
+
| `streaming` | Markdown 自动补全未闭合语法 | Loading + "调用中" |
|
|
96
|
+
| `complete` | 正常渲染完整 Markdown | "调用成功" + 耗时 |
|
|
97
|
+
| `error` | 红色错误图标 + content 作为错误提示 | "调用失败" |
|
|
98
|
+
| `stop` | 正常渲染(内容停留在中止时的状态) | "调用成功" |
|
|
99
|
+
|
|
100
|
+
### Pending
|
|
101
|
+
|
|
102
|
+
### Streaming
|
|
103
|
+
|
|
104
|
+
流式输出中,`MarkdownContent` 自动补全未闭合的 Markdown 语法(代码块、列表等),适合逐字/逐段追加内容:
|
|
105
|
+
|
|
106
|
+
### Complete
|
|
107
|
+
|
|
108
|
+
### Error
|
|
109
|
+
|
|
110
|
+
渲染为错误信息样式(红色错误图标),`content` 作为错误提示文案展示:
|
|
111
|
+
|
|
112
|
+
### Stop
|
|
113
|
+
|
|
114
|
+
用户手动中止生成,内容停留在中止时的状态,与 `complete` 表现相同:
|
|
115
|
+
|
|
116
|
+
## 工具调用
|
|
117
|
+
|
|
118
|
+
当 AI 回复中包含工具调用时,传入 `toolCalls` 数组,每项自动渲染为 `ToolCallRender`,位于内容区下方。`status` 会同步传递给每个 `ToolCallRender` 以反映调用状态。
|
|
119
|
+
|
|
120
|
+
### 单个工具调用
|
|
121
|
+
|
|
122
|
+
```vue
|
|
123
|
+
<template>
|
|
124
|
+
<AssistantMessage
|
|
125
|
+
content="让我帮你查询一下天气信息。"
|
|
126
|
+
:status="MessageStatus.Complete"
|
|
127
|
+
:tool-calls="toolCalls"
|
|
128
|
+
/>
|
|
129
|
+
</template>
|
|
130
|
+
|
|
131
|
+
<script setup lang="ts">
|
|
132
|
+
import { AssistantMessage, MessageStatus } from '@blueking/chat-x';
|
|
133
|
+
|
|
134
|
+
const toolCalls = [
|
|
135
|
+
{
|
|
136
|
+
id: 'call_1',
|
|
137
|
+
type: 'function',
|
|
138
|
+
function: {
|
|
139
|
+
name: 'get_weather',
|
|
140
|
+
arguments: '{"city": "北京", "unit": "celsius"}',
|
|
141
|
+
description: '获取指定城市的天气信息',
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
];
|
|
145
|
+
</script>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**渲染效果**
|
|
149
|
+
|
|
150
|
+
### 多个工具调用
|
|
151
|
+
|
|
152
|
+
AI 可在一次回复中发起多个工具调用,组件依次渲染:
|
|
153
|
+
|
|
154
|
+
```vue
|
|
155
|
+
<script setup lang="ts">
|
|
156
|
+
const toolCalls = [
|
|
157
|
+
{
|
|
158
|
+
id: 'call_1',
|
|
159
|
+
type: 'function',
|
|
160
|
+
function: {
|
|
161
|
+
name: 'search_documents',
|
|
162
|
+
arguments: '{"query": "Vue 3 Composition API"}',
|
|
163
|
+
description: '搜索知识库中的相关文档',
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
id: 'call_2',
|
|
168
|
+
type: 'function',
|
|
169
|
+
function: {
|
|
170
|
+
name: 'get_code_snippet',
|
|
171
|
+
arguments: '{"language": "typescript", "topic": "ref vs reactive"}',
|
|
172
|
+
description: '获取代码示例片段',
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
];
|
|
176
|
+
</script>
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
**渲染效果**
|
|
180
|
+
|
|
181
|
+
### MCP 工具调用
|
|
182
|
+
|
|
183
|
+
`function.mcpName` 标识 MCP 服务名称,`ToolCallRender` 的标题会显示为「调用 MCP:{mcpName} / {name}」:
|
|
184
|
+
|
|
185
|
+
```vue
|
|
186
|
+
<script setup lang="ts">
|
|
187
|
+
const toolCalls = [
|
|
188
|
+
{
|
|
189
|
+
id: 'call_mcp_1',
|
|
190
|
+
type: 'function',
|
|
191
|
+
function: {
|
|
192
|
+
name: 'query_database',
|
|
193
|
+
arguments: '{"sql": "SELECT * FROM users LIMIT 10"}',
|
|
194
|
+
description: '执行数据库查询',
|
|
195
|
+
mcpName: 'database-server', // MCP 服务名
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
];
|
|
199
|
+
</script>
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
**渲染效果**
|
|
203
|
+
|
|
204
|
+
### 携带执行结果
|
|
205
|
+
|
|
206
|
+
`toolMessage` 字段包含工具的执行结果;`ToolCallRender` 会展示返回内容(JSON 自动解析为键值对)和执行耗时:
|
|
207
|
+
|
|
208
|
+
```vue
|
|
209
|
+
<script setup lang="ts">
|
|
210
|
+
const toolCalls = [
|
|
211
|
+
{
|
|
212
|
+
id: 'call_1',
|
|
213
|
+
type: 'function',
|
|
214
|
+
function: {
|
|
215
|
+
name: 'get_weather',
|
|
216
|
+
arguments: '{"city": "北京"}',
|
|
217
|
+
description: '获取天气信息',
|
|
218
|
+
},
|
|
219
|
+
toolMessage: {
|
|
220
|
+
role: 'tool',
|
|
221
|
+
content: '{"weather":"晴","temperature":"22°C","humidity":"45%","wind":"东北风 3 级"}',
|
|
222
|
+
status: 'complete',
|
|
223
|
+
duration: 1200, // 毫秒
|
|
224
|
+
toolCallId: 'call_1',
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
];
|
|
228
|
+
</script>
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
**渲染效果**(点击展开箭头可查看返回结果)
|
|
232
|
+
|
|
233
|
+
### 工具调用失败
|
|
234
|
+
|
|
235
|
+
`toolMessage.error` 不为空时,`ToolCallRender` 显示错误信息:
|
|
236
|
+
|
|
237
|
+
```vue
|
|
238
|
+
<script setup lang="ts">
|
|
239
|
+
const toolCalls = [
|
|
240
|
+
{
|
|
241
|
+
id: 'call_1',
|
|
242
|
+
type: 'function',
|
|
243
|
+
function: {
|
|
244
|
+
name: 'get_weather',
|
|
245
|
+
arguments: '{"city": "北京"}',
|
|
246
|
+
description: '获取天气信息',
|
|
247
|
+
},
|
|
248
|
+
toolMessage: {
|
|
249
|
+
role: 'tool',
|
|
250
|
+
content: '',
|
|
251
|
+
status: 'error',
|
|
252
|
+
error: 'API rate limit exceeded',
|
|
253
|
+
duration: 350,
|
|
254
|
+
toolCallId: 'call_1',
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
];
|
|
258
|
+
</script>
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
**渲染效果**
|
|
262
|
+
|
|
263
|
+
### 工具调用状态随消息状态变化
|
|
264
|
+
|
|
265
|
+
`ToolCallRender` 的状态标题直接来自 `AssistantMessage` 的 `status` prop:
|
|
266
|
+
|
|
267
|
+
**调用中**(`status = "streaming"`):
|
|
268
|
+
|
|
269
|
+
**调用成功**(`status = "complete"` + `toolMessage`):
|
|
270
|
+
|
|
271
|
+
## 自定义内容渲染
|
|
272
|
+
|
|
273
|
+
默认插槽替换**内容区**的渲染(即 `ContentRender` 部分),工具调用仍在内容区外独立渲染,不受插槽影响:
|
|
274
|
+
|
|
275
|
+
```
|
|
276
|
+
[自定义 slot 内容] ← 替换这里
|
|
277
|
+
[ToolCallRender] ← 不受影响,仍正常渲染
|
|
278
|
+
[ToolCallRender]
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
```vue
|
|
282
|
+
<template>
|
|
283
|
+
<AssistantMessage
|
|
284
|
+
:content="content"
|
|
285
|
+
:tool-calls="toolCalls"
|
|
286
|
+
>
|
|
287
|
+
<template #default="{ content }">
|
|
288
|
+
<div style="padding: 12px; background: #f0f9ff; border-left: 3px solid #3a84ff; border-radius: 4px;">
|
|
289
|
+
🤖 {{ content }}
|
|
290
|
+
</div>
|
|
291
|
+
</template>
|
|
292
|
+
</AssistantMessage>
|
|
293
|
+
</template>
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
> **注意**:使用默认插槽后,内置的 `MarkdownContent`(Markdown 渲染)被替换,需要自行处理内容格式化。
|
|
297
|
+
|
|
298
|
+
**渲染效果**
|
|
299
|
+
|
|
300
|
+
## 在 MessageContainer 中使用
|
|
301
|
+
|
|
302
|
+
`AssistantMessage` 通常不需要单独引入,`MessageContainer` 会对 `role: 'assistant'` 的消息自动渲染:
|
|
303
|
+
|
|
304
|
+
```vue
|
|
305
|
+
<template>
|
|
306
|
+
<MessageContainer :messages="messages" />
|
|
307
|
+
</template>
|
|
308
|
+
|
|
309
|
+
<script setup lang="ts">
|
|
310
|
+
import { MessageContainer } from '@blueking/chat-x';
|
|
311
|
+
|
|
312
|
+
const messages = [
|
|
313
|
+
{
|
|
314
|
+
id: '1',
|
|
315
|
+
messageId: '1',
|
|
316
|
+
role: 'user',
|
|
317
|
+
content: '北京今天天气怎么样?',
|
|
318
|
+
status: 'complete',
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
id: '2',
|
|
322
|
+
messageId: '2',
|
|
323
|
+
role: 'assistant',
|
|
324
|
+
content: '让我帮你查询一下天气信息。',
|
|
325
|
+
status: 'complete',
|
|
326
|
+
toolCalls: [
|
|
327
|
+
{
|
|
328
|
+
id: 'call_1',
|
|
329
|
+
type: 'function',
|
|
330
|
+
function: {
|
|
331
|
+
name: 'get_weather',
|
|
332
|
+
arguments: '{"city": "北京"}',
|
|
333
|
+
description: '获取天气',
|
|
334
|
+
},
|
|
335
|
+
toolMessage: {
|
|
336
|
+
role: 'tool',
|
|
337
|
+
content: '{"weather":"晴","temperature":"22°C"}',
|
|
338
|
+
status: 'complete',
|
|
339
|
+
duration: 800,
|
|
340
|
+
toolCallId: 'call_1',
|
|
341
|
+
},
|
|
342
|
+
},
|
|
343
|
+
],
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
id: '3',
|
|
347
|
+
messageId: '3',
|
|
348
|
+
role: 'assistant',
|
|
349
|
+
content: '北京今天天气晴朗,气温 22°C,适合出行。',
|
|
350
|
+
status: 'complete',
|
|
351
|
+
},
|
|
352
|
+
];
|
|
353
|
+
</script>
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
## API
|
|
357
|
+
|
|
358
|
+
### Props
|
|
359
|
+
|
|
360
|
+
组件 Props 来自 `Partial<AssistantMessage>`(所有字段均可选):
|
|
361
|
+
|
|
362
|
+
| 属性名 | 类型 | 说明 |
|
|
363
|
+
| --------- | ----------------------- | -------------------------------------------------------------- |
|
|
364
|
+
| content | `string` | AI 回复的文本内容,支持 Markdown,`undefined` 时渲染为空字符串 |
|
|
365
|
+
| status | `MessageStatus` | 消息状态,影响 Markdown 渲染模式和 ToolCallRender 的状态标题 |
|
|
366
|
+
| toolCalls | `ToolCall[]` | 工具调用列表,每项渲染一个 `ToolCallRender` |
|
|
367
|
+
| id | `number \| string` | 消息 ID |
|
|
368
|
+
| messageId | `number \| string` | 消息唯一标识 |
|
|
369
|
+
| name | `string` | 消息发送者名称(可选) |
|
|
370
|
+
| role | `MessageRole.Assistant` | 消息角色,固定为 `'assistant'` |
|
|
371
|
+
| property | `object` | 消息附加属性,本组件不使用,由父组件(`MessageContainer`)消费 |
|
|
372
|
+
|
|
373
|
+
### Slots
|
|
374
|
+
|
|
375
|
+
| 插槽名 | 参数 | 说明 |
|
|
376
|
+
| ------- | --------------------- | ---------------------------------------------------- |
|
|
377
|
+
| default | `{ content: string }` | 替换内容区渲染,toolCalls 在内容区外独立渲染不受影响 |
|
|
378
|
+
|
|
379
|
+
## 类型定义
|
|
380
|
+
|
|
381
|
+
```typescript
|
|
382
|
+
import type { AssistantMessage, ToolCall, FunctionCall, ToolMessage } from '@blueking/chat-x';
|
|
383
|
+
|
|
384
|
+
interface AssistantMessage extends BaseMessage<MessageRole.Assistant> {
|
|
385
|
+
toolCalls?: ToolCall[];
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// 工具调用
|
|
389
|
+
type ToolCall = {
|
|
390
|
+
id: string;
|
|
391
|
+
type: MessageContentType.Function; // 固定为 'function'
|
|
392
|
+
function: FunctionCall;
|
|
393
|
+
toolMessage?: Partial<ToolMessage>; // 工具执行结果(可选)
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
// 函数调用信息
|
|
397
|
+
type FunctionCall = {
|
|
398
|
+
name: string; // 函数名
|
|
399
|
+
arguments: string; // JSON 字符串格式的参数
|
|
400
|
+
description?: string; // 函数描述
|
|
401
|
+
mcpName?: string; // MCP 服务名(存在时标题显示 "调用 MCP")
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
// 工具执行结果
|
|
405
|
+
interface ToolMessage extends BaseMessage<MessageRole.Tool, string> {
|
|
406
|
+
toolCallId: string; // 对应的 ToolCall.id
|
|
407
|
+
duration: number; // 执行耗时(ms)
|
|
408
|
+
error?: string; // 错误信息(存在时 ToolCallRender 显示失败状态)
|
|
409
|
+
}
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
## 使用场景
|
|
413
|
+
|
|
414
|
+
- **文本消息展示**:聊天界面渲染 AI 回复的 Markdown 文本
|
|
415
|
+
- **工具调用过程展示**:展示 Function Call / MCP 调用的参数、状态和返回结果
|
|
416
|
+
- **流式输出**:`streaming` 状态下 Markdown 自动补全未闭合语法,配合流式响应实时更新
|
|
417
|
+
- **自动渲染**:通过 `MessageContainer` 对 `role: 'assistant'` 消息自动处理,无需手动引入
|
|
418
|
+
- **自定义内容渲染**:通过默认插槽替换内置 Markdown 渲染器,保留工具调用渲染
|
|
419
|
+
|
|
420
|
+
## 关联组件
|
|
421
|
+
|
|
422
|
+
- [MessageRender](./message-render.md) — assistant 角色由其实例化
|
|
423
|
+
- [ToolMessage](./tool-message.md) — 工具执行结果可通过 toolCall.toolMessage 内联
|
|
424
|
+
- [ToolcallRender](./toolcall-render.md) — 工具调用列表渲染
|