@blueking/chat-x 0.0.48-beta.1 → 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.
Files changed (38) hide show
  1. package/dist/ag-ui/types/file.d.ts +23 -0
  2. package/dist/ag-ui/types/index.d.ts +1 -0
  3. package/dist/ag-ui/types/messages.d.ts +2 -0
  4. package/dist/components/chat-message/assistant-message/message-artifacts/artifact-file-card.vue.d.ts +14 -0
  5. package/dist/components/chat-message/assistant-message/message-artifacts/artifact-preview/artifact-preview-host.vue.d.ts +8 -0
  6. package/dist/components/chat-message/assistant-message/message-artifacts/artifact-preview/preview-strategy.d.ts +9 -0
  7. package/dist/components/chat-message/assistant-message/message-artifacts/artifact-preview/renderers/html-preview.vue.d.ts +6 -0
  8. package/dist/components/chat-message/assistant-message/message-artifacts/artifact-preview/renderers/markdown-preview.vue.d.ts +6 -0
  9. package/dist/components/chat-message/assistant-message/message-artifacts/artifact-preview/renderers/txt-preview.vue.d.ts +6 -0
  10. package/dist/components/chat-message/assistant-message/message-artifacts/artifact-preview/renderers/url-iframe-preview.vue.d.ts +6 -0
  11. package/dist/components/chat-message/assistant-message/message-artifacts/artifact-preview/use-artifact-preview-loader.d.ts +21 -0
  12. package/dist/components/chat-message/assistant-message/message-artifacts/file-artifact-panel.vue.d.ts +12 -0
  13. package/dist/components/chat-message/assistant-message/message-artifacts/file-icon.d.ts +29 -0
  14. package/dist/components/chat-message/assistant-message/message-artifacts/message-artifacts.vue.d.ts +10 -0
  15. package/dist/composables/index.d.ts +1 -0
  16. package/dist/composables/use-artifact-preview.d.ts +59 -0
  17. package/dist/composables/use-message-group.d.ts +434 -0
  18. package/dist/icons/file.d.ts +24 -0
  19. package/dist/icons/index.d.ts +1 -0
  20. package/dist/index.css +1 -1
  21. package/dist/index.js +2083 -1600
  22. package/dist/index.js.map +1 -1
  23. package/dist/lang/lang.d.ts +6 -1
  24. package/dist/mcp/generated/docs/activity-message.md +122 -97
  25. package/dist/mcp/generated/docs/assistant-message.md +125 -62
  26. package/dist/mcp/generated/docs/chat-container.md +94 -16
  27. package/dist/mcp/generated/docs/file-artifact-panel.md +279 -0
  28. package/dist/mcp/generated/docs/info-message.md +23 -7
  29. package/dist/mcp/generated/docs/loading-message.md +36 -17
  30. package/dist/mcp/generated/docs/message-render.md +44 -33
  31. package/dist/mcp/generated/docs/reasoning-message.md +15 -11
  32. package/dist/mcp/generated/docs/tool-message.md +61 -45
  33. package/dist/mcp/generated/docs/use-artifact-preview.md +237 -0
  34. package/dist/mcp/generated/docs/use-message-group.md +24 -0
  35. package/dist/mcp/generated/docs/user-message.md +185 -121
  36. package/dist/mcp/generated/index.json +79 -9
  37. package/dist/mcp/index.js +0 -0
  38. package/package.json +20 -21
@@ -0,0 +1,279 @@
1
+ <!-- AI SUMMARY -->
2
+ ## 快速了解
3
+
4
+ 汇总当前会话所有 AssistantMessage 的 artifacts,支持关键词搜索、列表选中与下载; 预览区委托 ArtifactPreviewHost:按类型走 text_from_download(html / markdown / md / txt / json) 或 preview_url_iframe(其余类型);download_url / preview_url 经 onArtifactClick 异步获取。 源码位置:src/components/chat-message/assistant-message/message-artifacts/file-artifact-panel.vue。
5
+
6
+ ### 关联组件
7
+ - **assistant-message** — 文件产物来源于 AssistantMessage.property.artifacts
8
+ - **chat-container** — 面板挂载在侧栏「文件产物」Tab(固定、不可关闭),并通过 onArtifactClick 异步取链
9
+ - **execution-summary** — 同为 ChatContainer 侧栏 Tab 面板,交互形态一致
10
+ - **message-loading** — ArtifactPreviewHost 取链 / 拉取正文过程使用 MessageLoading
11
+
12
+ ---
13
+ <!-- FULL DOC -->
14
+
15
+ # FileArtifactPanel 文件产物预览
16
+
17
+ ## 源码事实
18
+
19
+ - **源码位置**:`src/components/chat-message/assistant-message/message-artifacts/file-artifact-panel.vue`
20
+ - **能力域**:消息系统
21
+ - **能力说明**:汇总当前会话全部文件产物;左侧列表搜索与选中,右侧预览委托内部 `ArtifactPreviewHost`。
22
+
23
+ > **导出说明**:内部侧栏面板组件,**通常不直接使用**;由 `ChatContainer` 在「文件产物」Tab 内自动挂载。预览加载与渲染为同目录下 `artifact-preview/` 内部实现,不单独导出。
24
+
25
+ 点击 AI 回复中的[文件卡片](/components/message/assistant-message)后,`ChatContainer` 侧栏会弹出固定的「文件产物」Tab,聚合展示当前会话**所有** `AssistantMessage` 的文件产物,并命中被点击的文件进行预览。
26
+
27
+ 面板左侧为可搜索的文件列表,右侧为预览区。通常不需要直接使用,由 `ChatContainer` 在侧栏内自动渲染。
28
+
29
+ ## 核心能力
30
+
31
+ - **会话级聚合**:拍平当前会话所有 `AssistantMessage.property.artifacts`,统一在一个列表内展示
32
+ - **唯一命中**:同一会话可能出现多个消息 + 同名文件,文件名不可作唯一键,统一用 `messageUid#消息内下标#outputId` 生成全局唯一 id
33
+ - **关键词搜索**:按文件名实时过滤列表
34
+ - **异步取链**:`AIFileInfo` 本身不含 `url` / `previewUrl`,通过 `ChatContainer` 的 `onArtifactClick` 按 `outputId` 缓存获取 `download_url` / `preview_url`
35
+ - **职责拆分**:
36
+ - **面板本身**:列表、搜索、预览头(文件名 / 图标 / 下载)
37
+ - **`ArtifactPreviewHost`**:按策略加载正文或预览 URL,分派到对应 renderer;展示 loading / empty / error(含重试)
38
+ - **未传 `onArtifactClick`**:下载按钮隐藏,预览区展示无数据
39
+
40
+ ## 基础用法
41
+
42
+ 面板**未从包入口导出**,业务侧请走下方「业务接入」;下列示例仅用于文档站 / 本地调试(与 `ExecutionSummary` 文档站写法一致:相对路径引入 + 自行挂 Provider)。
43
+
44
+ ```vue
45
+ <template>
46
+ <div style="height: 480px; border: 1px solid #dcdee5; border-radius: 8px; overflow: hidden;">
47
+ <FileArtifactPanel
48
+ :active-id="activeArtifactId"
49
+ :artifacts="sessionArtifacts"
50
+ @select="handleSelect"
51
+ />
52
+ </div>
53
+ </template>
54
+
55
+ <script setup lang="ts">
56
+ import { shallowRef } from 'vue'
57
+ import { buildArtifactId, useArtifactPreviewProvider } from '@blueking/chat-x'
58
+ import type { AIFileInfo, SessionArtifact } from '@blueking/chat-x'
59
+ // 内部组件:仅文档 / 调试;业务请用 ChatContainer 自动挂载
60
+ import FileArtifactPanel from './message-artifacts/file-artifact-panel.vue'
61
+
62
+ const files: AIFileInfo[] = [
63
+ { name: '周报.html', outputId: 'a-html', size: 10240, type: 'html' },
64
+ { name: '说明.md', outputId: 'a-md', size: 8192, type: 'md' },
65
+ { name: '纪要.txt', outputId: 'a-txt', size: 4096, type: 'txt' },
66
+ { name: '配置.json', outputId: 'a-json', size: 2048, type: 'json' },
67
+ { name: '立项.pdf', outputId: 'a-pdf', size: 204800, type: 'pdf' },
68
+ ]
69
+
70
+ const sessionArtifacts: SessionArtifact[] = files.map((file, index) => ({
71
+ ...file,
72
+ artifactId: buildArtifactId('msg-1', index, file.outputId),
73
+ messageUid: 'msg-1',
74
+ }))
75
+
76
+ useArtifactPreviewProvider({
77
+ getOnArtifactClick: () => async file => {
78
+ // 文本类返回可 fetch 的 download_url;iframe 类返回 preview_url
79
+ const res = await api.getArtifactUrls(file.outputId)
80
+ return { download_url: res.download_url, preview_url: res.preview_url }
81
+ },
82
+ onOpen: () => {},
83
+ })
84
+
85
+ const activeArtifactId = shallowRef(sessionArtifacts[0].artifactId)
86
+ const handleSelect = (id: string) => {
87
+ activeArtifactId.value = id
88
+ }
89
+ </script>
90
+ ```
91
+
92
+ **渲染效果**(点击左侧列表切换类型;文本类直渲染,PDF 走 iframe。Mock 取链约 600ms)
93
+
94
+ ## 业务接入(ChatContainer)
95
+
96
+ 日常用法是给容器传 `messages`(含 `property.artifacts`)与 `onArtifactClick`,点击文件卡片即可打开侧栏面板:
97
+
98
+ ```vue
99
+ <template>
100
+ <ChatContainer
101
+ v-model="input"
102
+ :messages="messages"
103
+ :on-artifact-click="onArtifactClick"
104
+ @send-message="handleSend"
105
+ />
106
+ </template>
107
+
108
+ <script setup lang="ts">
109
+ import { ref, shallowRef } from 'vue'
110
+ import {
111
+ ChatContainer,
112
+ MessageRole,
113
+ MessageStatus,
114
+ type AIFileInfo,
115
+ type Message,
116
+ } from '@blueking/chat-x'
117
+
118
+ const input = ref('')
119
+ const messages = shallowRef<Message[]>([
120
+ {
121
+ id: 'u1',
122
+ messageId: 'u1',
123
+ role: MessageRole.User,
124
+ status: MessageStatus.Complete,
125
+ content: '整理本周评审材料',
126
+ },
127
+ {
128
+ id: 'a1',
129
+ messageId: 'a1',
130
+ uid: 'assistant-uid-1',
131
+ role: MessageRole.Assistant,
132
+ status: MessageStatus.Complete,
133
+ content: '已生成评审材料,点击卡片可在侧栏预览:',
134
+ property: {
135
+ artifacts: [
136
+ { name: '周报.html', outputId: 'a-html', size: 10240, type: 'html' },
137
+ { name: '说明.md', outputId: 'a-md', size: 8192, type: 'md' },
138
+ { name: '配置.json', outputId: 'a-json', size: 2048, type: 'json' },
139
+ { name: '立项.pdf', outputId: 'a-pdf', size: 204800, type: 'pdf' },
140
+ ] satisfies AIFileInfo[],
141
+ },
142
+ },
143
+ ])
144
+
145
+ const onArtifactClick = async (file: AIFileInfo) => {
146
+ const res = await api.getArtifactUrls(file.outputId)
147
+ return {
148
+ download_url: res.download_url,
149
+ preview_url: res.preview_url,
150
+ }
151
+ }
152
+
153
+ const handleSend = () => {
154
+ /* ... */
155
+ }
156
+ </script>
157
+ ```
158
+
159
+ ## 触发链路
160
+
161
+ ```
162
+ ArtifactFileCard(点击文件卡片)
163
+ └─ useArtifactPreviewConsumer().openPreview({ file, index, messageUid })
164
+ └─ useArtifactPreviewProvider(ChatContainer 内)
165
+ ├─ 记录命中文件 activeArtifactId
166
+ └─ onOpen → addCustomTab('file-artifact') 展开并选中侧栏 Tab
167
+ └─ FileArtifactPanel
168
+ ├─ 列表 @select → setActiveArtifactId
169
+ ├─ 下载 → resolveArtifactUrls + triggerArtifactDownload
170
+ └─ ArtifactPreviewHost
171
+ ├─ useArtifactPreviewLoader(策略 + fetch / 取链,防竞态)
172
+ └─ HtmlPreview | MarkdownPreview | TxtPreview | UrlIframePreview
173
+ ```
174
+
175
+ - 文件卡片通过 `useArtifactPreviewConsumer` 注入预览上下文,无 Provider 时卡片不可点击(兜底 `undefined`)
176
+ - `ChatContainer` 通过 `useArtifactPreviewProvider` 提供上下文,并把「打开侧栏 Tab」这一副作用以 `onOpen` 注入,保持 composable 职责单一
177
+ - 侧栏「文件产物」Tab 固定不可关闭,`order: -1` 排在「执行情况」之前;会话切换或无文件产物时自动移除
178
+
179
+ ## 唯一 id 规则
180
+
181
+ 同一会话可能存在多个 `AssistantMessage`,且不同消息里可能有同名文件,因此**文件名不可作为唯一键**。统一由 `buildArtifactId` 生成:
182
+
183
+ ```typescript
184
+ import { buildArtifactId } from '@blueking/chat-x';
185
+
186
+ // messageUid#消息内下标#outputId
187
+ buildArtifactId('msg-a', 2, 'output-9'); // => 'msg-a#2#output-9'
188
+ ```
189
+
190
+ Provider 侧聚合与文件卡片侧透传必须使用同一规则,保证命中一致。
191
+
192
+ ## 预览机制
193
+
194
+ 预览由内部 `getArtifactPreviewStrategy(type)` 决定 **加载方式** 与 **渲染器**;面板不直接写死类型分支。
195
+
196
+ | 文件类型 | load | 取链字段 | renderer |
197
+ | -------- | ---- | -------- | -------- |
198
+ | `html` | `text_from_download` | `download_url` → `fetch` 正文 | `HtmlPreview`(`<iframe srcdoc>`) |
199
+ | `markdown` / `md` | `text_from_download` | 同上 | `MarkdownPreview`(`MarkdownContent`) |
200
+ | `txt` / `json` | `text_from_download` | 同上 | `TxtPreview`(`<pre>`) |
201
+ | 其余(如 `pdf` / `jpg`) | `preview_url_iframe` | `preview_url` | `UrlIframePreview`(`<iframe src>`,一般为后台转好的 PDF) |
202
+
203
+ > `md`(`AIFileType.Md`)为后台扩展名别名,与 `markdown`(`AIFileType.Markdown`)等价,共用 Markdown 直渲染。
204
+
205
+ ### 加载态
206
+
207
+ | status | 表现 |
208
+ | ------ | ---- |
209
+ | `loading` | 预览区 [MessageLoading](/components/helper/message-loading) |
210
+ | `ready` | 对应 renderer 渲染 |
211
+ | `empty` | 「暂无可预览的文件」(无文件 / 未传 `onArtifactClick` / 缺所需 URL) |
212
+ | `error` | 「预览加载失败」+ 重试按钮 |
213
+
214
+ 切换文件时 `useArtifactPreviewLoader` 用 `loadSeq` + `AbortController` 中断上一次 `fetch`,避免竞态覆盖。下载图标仍由面板用 bkui `Loading` spin 单独表达。
215
+
216
+ ## 内部结构(不导出)
217
+
218
+ ```
219
+ message-artifacts/
220
+ ├── file-artifact-panel.vue # 列表 + 下载头 + 挂载 Host
221
+ └── artifact-preview/
222
+ ├── artifact-preview-host.vue # 状态机 UI + 分派 renderer
223
+ ├── preview-strategy.ts # getArtifactPreviewStrategy
224
+ ├── use-artifact-preview-loader.ts
225
+ └── renderers/
226
+ ├── html-preview.vue
227
+ ├── markdown-preview.vue
228
+ ├── txt-preview.vue
229
+ └── url-iframe-preview.vue
230
+ ```
231
+
232
+ ## API
233
+
234
+ ### Props
235
+
236
+ | 属性名 | 类型 | 必填 | 说明 |
237
+ | --------- | ------------------- | ---- | -------------------------------------- |
238
+ | activeId | `string` | ✓ | 当前命中的文件 id(`messageUid#index#outputId`) |
239
+ | artifacts | `SessionArtifact[]` | ✓ | 当前会话全部文件产物 |
240
+
241
+ ### Events
242
+
243
+ | 事件名 | 参数 | 说明 |
244
+ | ------ | ----------------- | -------------------------- |
245
+ | select | `(id: string)` | 列表内切换选中文件,参数为文件 `artifactId` |
246
+
247
+ ### Slots / Expose
248
+
249
+ 无。
250
+
251
+ ## 类型定义
252
+
253
+ ```typescript
254
+ import type { AIFileInfo, SessionArtifact } from '@blueking/chat-x';
255
+
256
+ // 会话级文件产物:在 AIFileInfo 基础上补充命中所需字段
257
+ type SessionArtifact = AIFileInfo & {
258
+ artifactId: string; // 全局唯一 id:messageUid#index#outputId
259
+ messageUid: string; // 所属 AssistantMessage 的 uid
260
+ };
261
+
262
+ type AIFileInfo = {
263
+ name: string;
264
+ outputId: string;
265
+ size: number;
266
+ type: AIFileType;
267
+ };
268
+ ```
269
+
270
+ ## 关联 Composable
271
+
272
+ 预览**命中与取链**由 [useArtifactPreview](/composables/use-artifact-preview) 提供(Provider / Consumer + `ARTIFACT_PREVIEW_TOKEN`)。**正文加载与渲染**由内部 `useArtifactPreviewLoader` + `ArtifactPreviewHost` 完成,不在该 composable 内。
273
+
274
+ ## 关联组件
275
+
276
+ - [AssistantMessage](/components/message/assistant-message) — 文件产物来源(`property.artifacts`)
277
+ - [ChatContainer](/components/setup/chat-container) — 侧栏「文件产物」Tab 挂载场景,提供 `onArtifactClick`
278
+ - [MessageLoading](/components/helper/message-loading) — Host 预览区异步加载态
279
+ - [ExecutionSummary](/components/agent/execution-summary) — 同为侧栏 Tab 面板
@@ -11,13 +11,14 @@
11
11
  <!-- FULL DOC -->
12
12
 
13
13
  # InfoMessage 信息消息
14
+
14
15
  ## 源码事实
15
16
 
16
17
  - **源码位置**:`src/components/chat-message/info-message/info-message.vue`
17
18
  - **能力域**:消息系统
18
19
  - **能力说明**:渲染居中的系统信息提示。
19
20
 
20
- > **能力域**:消息系统
21
+ > **导出说明**:`InfoMessage` **未**从包入口导出(入口同名是 TS interface)。消费方经 `MessageRender` / `MessageContainer` 使用。下文 `InfoMessageComp` 为文档站内部示例。
21
22
 
22
23
  系统信息分隔组件,在聊天消息列表中以**居中虚线分隔条**的形式展示非对话类信息(会话重置、时间节点、状态变更等)。
23
24
 
@@ -35,13 +36,19 @@
35
36
 
36
37
  ```vue
37
38
  <template>
38
- <InfoMessage :content="content" />
39
+ <MessageRender :message="message" />
39
40
  </template>
40
41
 
41
42
  <script setup lang="ts">
42
- import { InfoMessage } from '@blueking/chat-x';
43
-
44
- const content = '以下是新的对话';
43
+ import { MessageRender, MessageRole, MessageStatus } from '@blueking/chat-x';
44
+
45
+ const message = {
46
+ id: '1',
47
+ messageId: '1',
48
+ role: MessageRole.Info,
49
+ content: '以下是新的对话',
50
+ status: MessageStatus.Complete,
51
+ };
45
52
  </script>
46
53
  ```
47
54
 
@@ -53,11 +60,20 @@
53
60
 
54
61
  ```vue
55
62
  <template>
56
- <InfoMessage :content="['会话已重置', '以下是新的对话']" />
63
+ <MessageRender :message="message" />
57
64
  </template>
58
65
 
59
66
  <script setup lang="ts">
60
- import { InfoMessage } from '@blueking/chat-x';
67
+ import { MessageRender, MessageRole, MessageStatus } from '@blueking/chat-x';
68
+
69
+ // 运行时 content 兼容 string[](TS 类型声明多为 string)
70
+ const message = {
71
+ id: '1',
72
+ messageId: '1',
73
+ role: MessageRole.Info,
74
+ content: ['会话已重置', '以下是新的对话'],
75
+ status: MessageStatus.Complete,
76
+ };
61
77
  </script>
62
78
  ```
63
79
 
@@ -12,46 +12,60 @@
12
12
  <!-- FULL DOC -->
13
13
 
14
14
  # LoadingMessage 加载中消息
15
+
15
16
  ## 源码事实
16
17
 
17
18
  - **源码位置**:`src/components/chat-message/loading-message/loading-message.vue`
18
19
  - **能力域**:消息系统
19
20
  - **能力说明**:消息列表中的加载占位,默认使用 AiLoading,也支持默认插槽覆盖。
20
21
 
21
- > **能力域**:消息系统
22
+ > **导出说明**:`LoadingMessage` **未**从包入口导出。消费方经 `MessageRender`(`role: 'loading'`)或由 `MessageContainer` 自动注入。下文 `LoadingMessageComp` 为文档站内部示例。
22
23
 
23
- 加载等待状态组件,展示 AI 正在处理请求时的过渡动画。由旋转渐变环 + 脉冲星形图标(蓝→紫→粉渐变)和"请求中..."文案组成。支持通过默认插槽自定义加载文案。
24
+ 加载等待状态组件:`AiLoading`(18px)+ 默认文案「请求中...」。可通过默认插槽自定义文案。
24
25
 
25
- > **提示**:此组件通常**不需要手动使用**,`MessageContainer` 会在满足条件时自动注入。
26
+ > **提示**:通常**不需要手动使用**,`MessageContainer` / `useMessageGroup` 会在满足条件时自动注入。
26
27
 
27
28
  ## 渲染效果
28
29
 
29
30
  ## 基础用法
30
31
 
31
- 组件无 Props,直接引入渲染即可:
32
+ 组件无 Props。文档站内部示例:
33
+
34
+ ```vue
35
+ <template>
36
+ <LoadingMessageComp />
37
+ </template>
38
+ ```
39
+
40
+ 消费方经 `MessageRender`:
32
41
 
33
42
  ```vue
34
43
  <template>
35
- <LoadingMessage />
44
+ <MessageRender
45
+ :message="{
46
+ id: 'loading',
47
+ messageId: '',
48
+ role: MessageRole.Loading,
49
+ content: '',
50
+ status: MessageStatus.Pending,
51
+ }"
52
+ />
36
53
  </template>
37
54
 
38
55
  <script setup lang="ts">
39
- import { LoadingMessage } from '@blueking/chat-x';
56
+ import { MessageRender, MessageRole, MessageStatus } from '@blueking/chat-x';
40
57
  </script>
41
58
  ```
42
59
 
43
60
  ## 自定义加载文案
44
61
 
45
- 通过默认插槽可覆盖默认的"请求中..."文案:
62
+ 通过默认插槽覆盖「请求中...」:
46
63
 
47
64
  ```vue
48
65
  <template>
49
- <LoadingMessage>正在思考中,请稍候...</LoadingMessage>
66
+ <!-- 文档站内部示例 -->
67
+ <LoadingMessageComp>正在思考中,请稍候...</LoadingMessageComp>
50
68
  </template>
51
-
52
- <script setup lang="ts">
53
- import { LoadingMessage } from '@blueking/chat-x';
54
- </script>
55
69
  ```
56
70
 
57
71
  ## 动画说明
@@ -67,15 +81,18 @@
67
81
 
68
82
  ## 在 MessageContainer 中的自动注入
69
83
 
70
- `MessageContainer` 在构建消息分组列表时,检测到**消息列表最后一条为用户消息**(`role === 'user'`)时,自动在末尾追加一个 Loading 消息组:
84
+ `useMessageGroup` 构建分组时,若**最后一条为用户消息**且 **`renderMode !== RenderMode.Share`**,自动在末尾追加 Loading 组:
71
85
 
72
86
  ```typescript
73
- // MessageContainer 内部逻辑(简化)
74
- if (messages.at(-1)?.role === MessageRole.User) {
87
+ // use-message-group.ts(简化)
88
+ const shouldAppendLoading =
89
+ messages.at(-1)?.role === MessageRole.User && renderMode !== RenderMode.Share;
90
+
91
+ if (shouldAppendLoading) {
75
92
  list.push({
76
93
  messages: [
77
94
  {
78
- role: MessageRole.Loading, // 'loading'
95
+ role: MessageRole.Loading,
79
96
  content: '',
80
97
  status: MessageStatus.Pending,
81
98
  id: 'loading',
@@ -87,7 +104,8 @@ if (messages.at(-1)?.role === MessageRole.User) {
87
104
  }
88
105
  ```
89
106
 
90
- 当下一条 AI 消息(`role: 'assistant'`)到来后,最后一条不再是用户消息,Loading 组自动消失。
107
+ - 下一条 AI 消息到来后,末尾不再是 user,Loading 组自动消失
108
+ - **分享预览**(`renderMode === RenderMode.Share`)**不会**注入 Loading,避免分享页出现「请求中」占位
91
109
 
92
110
  **触发示例**:
93
111
 
@@ -127,6 +145,7 @@ if (messages.at(-1)?.role === MessageRole.User) {
127
145
  - **默认插槽**:可通过默认插槽自定义加载文案,未传入时显示内置的 "请求中..."
128
146
  - **i18n 支持**:默认文案 "请求中..." 通过内置 `t()` 函数处理,英文环境自动显示 "Requesting..."
129
147
  - **选择模式**:`MessageContainer` 开启 `enableSelection` 时,Loading 消息组不显示复选框
148
+ - **分享模式**:`renderMode === RenderMode.Share` 时不自动注入 Loading
130
149
  - **自动生命周期**:Loading 组随消息列表变化自动插入/移除,无需手动控制
131
150
 
132
151
  ## API
@@ -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` 字段自动派发到对应的子组件。整个渲染过程由一个 `computed` 属性完成,无额外状态。
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'` 时,`AssistantMessage` 内部展示打字光标,内容可实时追加:
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`。未提供 slot 时回退渲染 `<ContentRender :content="message.content" :status="message.status" />`。
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
- :message="message"
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
- slot 参数类型与 `AssistantMessage` 的 slot 保持一致(`Partial<AssistantMessage>`),主要使用:
229
+ | 参数 | 类型 | 说明 |
230
+ | --------- | -------- | ---------------------------- |
231
+ | `content` | `string` | 消息内容(运行时保证) |
225
232
 
226
- | 参数 | 类型 | 说明 |
227
- | --------- | --------------- | ------------ |
228
- | `content` | `string` | 消息内容 |
229
- | `status` | `MessageStatus` | 当前消息状态 |
233
+ ## MessageContainer / ChatContainer 配合
230
234
 
231
- ## MessageContainer 配合
232
-
233
- 在 `MessageContainer` 的 `default` slot 中使用,可替换默认的 `MessageRender` 渲染逻辑:
235
+ 自定义 `ChatContainer` 的 `#message` 时,插槽参数只有 `message` / `messageToolsStatus` / `onInterruptResume`。用户消息工具相关回调需由外层自行绑定透传,否则删除/编辑/复制/引用会失效(AI 消息工具栏在 `MessageContainer` 内渲染,不受 `#message` 影响):
234
236
 
235
237
  ```vue
236
238
  <template>
237
- <MessageContainer
239
+ <ChatContainer
238
240
  :messages="messages"
239
241
  :message-status="messageStatus"
240
242
  :on-agent-action="handleAgentAction"
241
243
  :on-user-action="handleUserAction"
242
- @stop-streaming="handleStopStreaming"
244
+ :common-tippy-options="commonTippyOptions"
243
245
  >
244
- <template #default="{ message, messageToolsStatus }">
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="handleInputConfirm"
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, status }"
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
- </MessageContainer>
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 }` | 自定义 UserQuestion 已回答回显,透传给 InterruptMessageRender → UserQuestionAnsweredCard 的 `#answer` |
286
- | codeHeader | `{ language: string; token: Token[] }` | 代码块头部自定义操作区域,透传给 ContentRender → MarkdownContent → CodeContent;**仅对 assistant 生效** |
287
- | default | `{ content: string, status: MessageStatus }` | 替换 AssistantMessage 的内容区域渲染;**仅对 `role: 'assistant'` 生效** |
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
  // 消息状态
@@ -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
- <ReasoningMessage
48
- :content="content"
49
- :status="status"
50
- />
48
+ <MessageRender :message="message" />
51
49
  </template>
52
50
 
53
51
  <script setup lang="ts">
54
- import { ReasoningMessage, MessageStatus } from '@blueking/chat-x';
55
-
56
- const status = MessageStatus.Complete;
57
- const content = ['让我分析一下这个问题...', '首先需要考虑以下几个方面...'];
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
- <ReasoningMessage
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 { ReasoningMessage, MessageStatus } from '@blueking/chat-x';
134
+ import { MessageStatus } from '@blueking/chat-x';
131
135
 
132
136
  const collapsed = ref(false);
133
137
  const status = MessageStatus.Complete;