@blueking/chat-x 0.0.49-beta.1 → 0.0.49-beta.2
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/constants.d.ts +1 -0
- package/dist/ag-ui/types/file.d.ts +1 -1
- package/dist/components/chat-message/assistant-message/assistant-message.vue.d.ts +12 -1
- package/dist/components/chat-message/assistant-message/message-artifacts/artifact-file-card.vue.d.ts +0 -2
- package/dist/components/chat-message/assistant-message/message-artifacts/artifact-preview/artifact-preview-host.vue.d.ts +1 -2
- package/dist/components/chat-message/assistant-message/message-artifacts/artifact-preview/use-artifact-preview-loader.d.ts +4 -2
- package/dist/components/chat-message/assistant-message/message-artifacts/message-artifacts.vue.d.ts +0 -1
- package/dist/components/chat-message/interrupt-message/user-question/use-user-question.d.ts +7 -2
- package/dist/components/chat-message/user-message/user-message.vue.d.ts +14 -2
- package/dist/composables/use-artifact-preview.d.ts +17 -20
- package/dist/composables/use-custom-tab.d.ts +2 -0
- package/dist/composables/use-message-group.d.ts +1 -2
- package/dist/index.css +1 -1
- package/dist/index.js +514 -469
- package/dist/index.js.map +1 -1
- package/dist/lang/lang.d.ts +3 -1
- package/dist/mcp/generated/docs/assistant-message.md +1 -1
- package/dist/mcp/generated/docs/chat-container.md +7 -6
- package/dist/mcp/generated/docs/chat-input.md +2 -10
- package/dist/mcp/generated/docs/constants.md +3 -1
- package/dist/mcp/generated/docs/content-render.md +2 -10
- package/dist/mcp/generated/docs/file-artifact-panel.md +32 -36
- package/dist/mcp/generated/docs/info-message.md +6 -5
- package/dist/mcp/generated/docs/interrupt.md +1 -0
- package/dist/mcp/generated/docs/message-container.md +4 -21
- package/dist/mcp/generated/docs/message-render.md +4 -27
- package/dist/mcp/generated/docs/messages.md +5 -0
- package/dist/mcp/generated/docs/reasoning-message.md +2 -9
- package/dist/mcp/generated/docs/toolcall-render.md +8 -8
- package/dist/mcp/generated/docs/use-artifact-preview.md +45 -50
- package/dist/mcp/generated/docs/use-custom-tab.md +18 -5
- package/dist/mcp/generated/docs/use-message-group.md +13 -8
- package/dist/mcp/generated/docs/user-question-card.md +6 -3
- package/dist/mcp/generated/index.json +7 -7
- package/package.json +2 -2
package/dist/lang/lang.d.ts
CHANGED
|
@@ -145,6 +145,8 @@ export declare const lang: {
|
|
|
145
145
|
readonly 单选: "Single";
|
|
146
146
|
readonly 多选: "Multiple";
|
|
147
147
|
readonly 其他: "Others";
|
|
148
|
+
readonly 已完成: "Completed";
|
|
149
|
+
readonly 题: "question(s)";
|
|
148
150
|
readonly 回答内容: "Answers";
|
|
149
151
|
readonly 已回复: "Replied";
|
|
150
152
|
readonly '\u8BF7\u8F93\u5165...': "Please enter...";
|
|
@@ -154,4 +156,4 @@ export declare const lang: {
|
|
|
154
156
|
readonly 预览加载失败: "Failed to load preview";
|
|
155
157
|
readonly 暂无可预览的文件: "No file to preview";
|
|
156
158
|
};
|
|
157
|
-
export declare const t: (key: keyof typeof lang) => "Send" | "Stop" | "Ask AI" | "Copy" | "Share" | "Like" | "Unsatisfied" | "Delete" | "Quote" | "Regenerate" | "Regenerating will clear the content below" | "Submit" | "Cancel" | "Preview Content" | "Jump to Detail" | "Call Tool:" | "Calling..." | "Call Success" | "Call Failed" | "Tell us your thoughts" | "What makes you satisfied?" | "What makes you dissatisfied?" | "Return Content" | "Edit" | "Deep Thinking" | "Quick Thinking" | "Image to Text" | "Loading image..." | "Failed to load image" | "Thinking..." | "Thinking Completed" | "Thinking Failed" | "Copy Success" | "Copy Failed" | "Return to bottom" | "Stop generating" | "Stopping" | "Duration" | "Parameters" | "Description" | "Execution Status" | "Running" | "Success" | "Failed" | "Pending" | "To Be Executed" | "Details" | "Retry" | "Retrying" | "Skipping" | "The task is retrying and cannot be skipped" | "The task is skipping and cannot be retried" | "Node" | "Node Config" | "Node Output" | "Basic Info" | "Flow Template" | "Node Name" | "Step Name" | "Execution Plan" | "Optional" | "Failure Handler" | "Timeout Control" | "Yes" | "No" | "Input Params" | "Output Params" | "Param Name" | "Param Value" | "Name" | "Structured Output" | "Manual Skip" | "No Data" | "Call MCP:" | "More" | "Algorithm Plan Review Ticket" | "Reviewing" | "Approving" | "Abandoned" | "Approved" | "Cancelled" | "Expired" | "Rejected" | "Revoked" | "Ticket No." | "Submitted At" | "Current Handler" | "None" | "View Ticket Detail" | "Copy Ticket" | "Copy Ticket Link" | "Cancel Approval" | "Approval Cancelled" | "Refresh Ticket Status" | "This ticket has been rejected and cannot be cancelled" | "This ticket has been approved and cannot be cancelled" | "This ticket has been cancelled, no need to click again" | "Approval cannot be cancelled in the current status" | "There are {count} pending approval tickets in the current conversation. To continue, cancel approval first." | "Unsupported interrupt message" | "Searching" | "Search Completed" | "Upload File" | "Select model" | "Search models" | "Requesting..." | "Cancel satisfied" | "Cancel dissatisfied" | "Confirm delete this answer?" | "This operation cannot be undone. Please proceed with caution!" | "Preview" | "Zoom Out" | "Zoom In" | "Rotate" | "Download" | "Sorry, image loading failed. Please try reloading." | "Reset" | "Reload" | "W" | "H" | "Upload Image" | "Search keyword" | "Select date" | "Locate in Chat" | "Select All" | "Confirm" | "Upload Image, up to 3 images supported, max 2.4MB each" | "Hello, I am BlueKing AI Bot" | "Clear Search" | "Search Result is Empty" | "Valid Evidence" | "Full Screen" | "Exit Full Screen" | "Please choose to continue" | "Continue" | "Received: " | "Done" | "Skip" | "Single" | "Multiple" | "Others" | "Answers" | "Replied" | "Please enter..." | "File Artifacts" | "File List" | "Search file keyword" | "Failed to load preview" | "No file to preview" | "发送" | "停止" | "问问小鲸" | "复制" | "分享" | "点赞" | "不满意" | "删除" | "引用" | "重新生成" | "重新生成将清空下文内容" | "提交" | "取消" | "预览内容" | "跳转详情" | "调用工具:" | "调用中" | "调用成功" | "调用失败" | "说出您的想法" | "什么原因让你满意?" | "什么原因让你不满意?" | "返回内容" | "编辑" | "深度思考" | "快速思考" | "图生文" | "图片加载中..." | "图片加载失败" | "思考中" | "已思考完成" | "思考失败" | "复制成功" | "复制失败" | "返回底部" | "停止生成" | "正在停止" | "耗时" | "参数" | "描述" | "执行情况" | "执行中" | "成功" | "失败" | "挂起" | "待执行" | "详情" | "重试" | "重试中" | "跳过中" | "任务正在重试中,不可跳过" | "任务正在跳过中,不可重试" | "节点" | "节点配置" | "节点输出" | "基础信息" | "流程模板" | "节点名称" | "步骤名称" | "执行方案" | "是否可选" | "失败处理" | "超时控制" | "是" | "否" | "输入参数" | "输出参数" | "参数名" | "参数值" | "名称" | "变量说明" | "结构化输出" | "手动跳过" | "暂无数据" | "调用 MCP:" | "更多" | "算法方案评审单" | "评审中" | "审批中" | "已废弃" | "已批准" | "已通过" | "已取消" | "已过期" | "已拒绝" | "已撤销" | "单据编号" | "提交时间" | "当前处理人" | "无" | "查看单据详情" | "复制单据" | "复制单据链接" | "取消审批" | "已取消审批" | "刷新单据状态" | "单据已取消审批" | "该单据已被拒绝,无法取消" | "该单据已通过,无法取消" | "单据已取消,无需重复点击" | "当前状态无法取消审批" | "当前会话有 {count} 个待审批单,如需继续,请先取消审批" | "暂不支持的中断消息" | "检索中" | "检索完成" | "上传文件" | "选择模型" | "搜索模型关键字" | "请求中..." | "取消满意" | "取消不满意" | "确认删除该回答?" | "删除操作无法撤回,请谨慎操作!" | "预览" | "缩小" | "放大" | "旋转" | "下载" | "抱歉,图片加载失败,可尝试重新加载" | "重置" | "重新加载" | "宽" | "高" | "上传图片" | "搜索 关键字" | "选择日期" | "在对话中定位" | "全选" | "确定" | "上传图片, 最多支持上传 3 个, 最大支持 2.4MB" | "你好,我是小鲸" | "清空搜索" | "搜索结果为空" | "有效证据" | "全屏" | "退出全屏" | "请选择以继续" | "继续" | "收到信息:" | "待审批" | "已审批" | "完成" | "跳过" | "单选" | "多选" | "其他" | "回答内容" | "已回复" | "请输入..." | "文件产物" | "文件列表" | "搜索文件关键字" | "预览加载失败" | "暂无可预览的文件";
|
|
159
|
+
export declare const t: (key: keyof typeof lang) => "Send" | "Stop" | "Ask AI" | "Copy" | "Share" | "Like" | "Unsatisfied" | "Delete" | "Quote" | "Regenerate" | "Regenerating will clear the content below" | "Submit" | "Cancel" | "Preview Content" | "Jump to Detail" | "Call Tool:" | "Calling..." | "Call Success" | "Call Failed" | "Tell us your thoughts" | "What makes you satisfied?" | "What makes you dissatisfied?" | "Return Content" | "Edit" | "Deep Thinking" | "Quick Thinking" | "Image to Text" | "Loading image..." | "Failed to load image" | "Thinking..." | "Thinking Completed" | "Thinking Failed" | "Copy Success" | "Copy Failed" | "Return to bottom" | "Stop generating" | "Stopping" | "Duration" | "Parameters" | "Description" | "Execution Status" | "Running" | "Success" | "Failed" | "Pending" | "To Be Executed" | "Details" | "Retry" | "Retrying" | "Skipping" | "The task is retrying and cannot be skipped" | "The task is skipping and cannot be retried" | "Node" | "Node Config" | "Node Output" | "Basic Info" | "Flow Template" | "Node Name" | "Step Name" | "Execution Plan" | "Optional" | "Failure Handler" | "Timeout Control" | "Yes" | "No" | "Input Params" | "Output Params" | "Param Name" | "Param Value" | "Name" | "Structured Output" | "Manual Skip" | "No Data" | "Call MCP:" | "More" | "Algorithm Plan Review Ticket" | "Reviewing" | "Approving" | "Abandoned" | "Approved" | "Cancelled" | "Expired" | "Rejected" | "Revoked" | "Ticket No." | "Submitted At" | "Current Handler" | "None" | "View Ticket Detail" | "Copy Ticket" | "Copy Ticket Link" | "Cancel Approval" | "Approval Cancelled" | "Refresh Ticket Status" | "This ticket has been rejected and cannot be cancelled" | "This ticket has been approved and cannot be cancelled" | "This ticket has been cancelled, no need to click again" | "Approval cannot be cancelled in the current status" | "There are {count} pending approval tickets in the current conversation. To continue, cancel approval first." | "Unsupported interrupt message" | "Searching" | "Search Completed" | "Upload File" | "Select model" | "Search models" | "Requesting..." | "Cancel satisfied" | "Cancel dissatisfied" | "Confirm delete this answer?" | "This operation cannot be undone. Please proceed with caution!" | "Preview" | "Zoom Out" | "Zoom In" | "Rotate" | "Download" | "Sorry, image loading failed. Please try reloading." | "Reset" | "Reload" | "W" | "H" | "Upload Image" | "Search keyword" | "Select date" | "Locate in Chat" | "Select All" | "Confirm" | "Upload Image, up to 3 images supported, max 2.4MB each" | "Hello, I am BlueKing AI Bot" | "Clear Search" | "Search Result is Empty" | "Valid Evidence" | "Full Screen" | "Exit Full Screen" | "Please choose to continue" | "Continue" | "Received: " | "Done" | "Skip" | "Single" | "Multiple" | "Others" | "Completed" | "question(s)" | "Answers" | "Replied" | "Please enter..." | "File Artifacts" | "File List" | "Search file keyword" | "Failed to load preview" | "No file to preview" | "发送" | "停止" | "问问小鲸" | "复制" | "分享" | "点赞" | "不满意" | "删除" | "引用" | "重新生成" | "重新生成将清空下文内容" | "提交" | "取消" | "预览内容" | "跳转详情" | "调用工具:" | "调用中" | "调用成功" | "调用失败" | "说出您的想法" | "什么原因让你满意?" | "什么原因让你不满意?" | "返回内容" | "编辑" | "深度思考" | "快速思考" | "图生文" | "图片加载中..." | "图片加载失败" | "思考中" | "已思考完成" | "思考失败" | "复制成功" | "复制失败" | "返回底部" | "停止生成" | "正在停止" | "耗时" | "参数" | "描述" | "执行情况" | "执行中" | "成功" | "失败" | "挂起" | "待执行" | "详情" | "重试" | "重试中" | "跳过中" | "任务正在重试中,不可跳过" | "任务正在跳过中,不可重试" | "节点" | "节点配置" | "节点输出" | "基础信息" | "流程模板" | "节点名称" | "步骤名称" | "执行方案" | "是否可选" | "失败处理" | "超时控制" | "是" | "否" | "输入参数" | "输出参数" | "参数名" | "参数值" | "名称" | "变量说明" | "结构化输出" | "手动跳过" | "暂无数据" | "调用 MCP:" | "更多" | "算法方案评审单" | "评审中" | "审批中" | "已废弃" | "已批准" | "已通过" | "已取消" | "已过期" | "已拒绝" | "已撤销" | "单据编号" | "提交时间" | "当前处理人" | "无" | "查看单据详情" | "复制单据" | "复制单据链接" | "取消审批" | "已取消审批" | "刷新单据状态" | "单据已取消审批" | "该单据已被拒绝,无法取消" | "该单据已通过,无法取消" | "单据已取消,无需重复点击" | "当前状态无法取消审批" | "当前会话有 {count} 个待审批单,如需继续,请先取消审批" | "暂不支持的中断消息" | "检索中" | "检索完成" | "上传文件" | "选择模型" | "搜索模型关键字" | "请求中..." | "取消满意" | "取消不满意" | "确认删除该回答?" | "删除操作无法撤回,请谨慎操作!" | "预览" | "缩小" | "放大" | "旋转" | "下载" | "抱歉,图片加载失败,可尝试重新加载" | "重置" | "重新加载" | "宽" | "高" | "上传图片" | "搜索 关键字" | "选择日期" | "在对话中定位" | "全选" | "确定" | "上传图片, 最多支持上传 3 个, 最大支持 2.4MB" | "你好,我是小鲸" | "清空搜索" | "搜索结果为空" | "有效证据" | "全屏" | "退出全屏" | "请选择以继续" | "继续" | "收到信息:" | "待审批" | "已审批" | "完成" | "跳过" | "单选" | "多选" | "其他" | "已完成" | "题" | "回答内容" | "已回复" | "请输入..." | "文件产物" | "文件列表" | "搜索文件关键字" | "预览加载失败" | "暂无可预览的文件";
|
|
@@ -381,7 +381,7 @@ AI 可在一次回复中发起多个工具调用,组件依次渲染:
|
|
|
381
381
|
| `html` / `markdown` / `md` / `txt` / `json` | `download_url` | 正文直渲染(srcdoc / MarkdownContent / `<pre>`) |
|
|
382
382
|
| `pdf` / `jpg` 等 | `preview_url` | iframe(一般为后台转好的 PDF) |
|
|
383
383
|
|
|
384
|
-
`md` 与 `markdown` 等价(见 `AIFileType.Md` / `AIFileType.Markdown
|
|
384
|
+
`md` 与 `markdown` 等价(见 `AIFileType.Md` / `AIFileType.Markdown`)。预览重载、`force` 重试与取链约定见 [FileArtifactPanel 预览机制](/components/message/file-artifact-panel#预览机制)。
|
|
385
385
|
|
|
386
386
|
```vue
|
|
387
387
|
<template>
|
|
@@ -241,13 +241,14 @@ ai-chat-container(:data-ai-size="size")
|
|
|
241
241
|
|
|
242
242
|
### 内置「文件产物」Tab
|
|
243
243
|
|
|
244
|
-
除「执行情况」外,容器内置一个按需出现的固定 Tab —— **「文件产物」**(`name: 'file-artifact'`),用于聚合预览当前会话所有 `AssistantMessage.property.artifacts
|
|
244
|
+
除「执行情况」外,容器内置一个按需出现的固定 Tab —— **「文件产物」**(`name: 'file-artifact'`),用于聚合预览当前会话所有 `AssistantMessage.property.artifacts`(按 `outputId` 去重):
|
|
245
245
|
|
|
246
|
-
-
|
|
246
|
+
- **静默挂载**:会话已有文件产物时,容器通过 `ensureCustomTab` 挂上该 Tab,**不展开侧栏、不切换当前选中**(避免从「执行情况」展开时被抢走焦点),并保证命中态有效(默认第一个 `outputId`)
|
|
247
|
+
- **主动打开**:点击 AI 回复中的文件卡片([ArtifactFileCard](/components/message/assistant-message))时,容器通过 `useArtifactPreviewProvider` 以 `outputId` 命中该文件,再 `addCustomTab` 展开侧栏并选中「文件产物」
|
|
247
248
|
- **排序 / 关闭**:`order: -1` 排在「执行情况」之前,`closable: false` 不可关闭
|
|
248
249
|
- **显隐解耦**:该 Tab 存在时,侧栏展示不再受「`executionGroups` 为空」约束(即使当前会话没有执行类消息,也能独立展示文件产物侧栏);会话切换或无文件产物时自动移除并重置命中态
|
|
249
|
-
- **内容**:由 [FileArtifactPanel](/components/message/file-artifact-panel) 渲染列表与下载头,预览委托内部 `ArtifactPreviewHost`;`download_url` / `preview_url` 通过 `onArtifactClick` 异步获取。文本类(`html` / `markdown` / `md` / `txt` / `json`)拉 `download_url` 正文直渲染(`md` 与 `markdown` 等价);其余类型用 `preview_url` iframe(一般为后台转好的 PDF
|
|
250
|
-
- **状态管理**:命中、切换与 URL 缓存由 [useArtifactPreview](/composables/use-artifact-preview) 提供(Provider 在容器内、Consumer 在文件卡片 / 面板内);正文加载与分类型渲染由 Host
|
|
250
|
+
- **内容**:由 [FileArtifactPanel](/components/message/file-artifact-panel) 渲染列表与下载头,预览委托内部 `ArtifactPreviewHost`;`download_url` / `preview_url` 通过 `onArtifactClick` 异步获取。文本类(`html` / `markdown` / `md` / `txt` / `json`)拉 `download_url` 正文直渲染(`md` 与 `markdown` 等价);其余类型用 `preview_url` iframe(一般为后台转好的 PDF)。预览重载键为 `outputId:type`;失败重试会 `force` 绕过 URL 缓存
|
|
251
|
+
- **状态管理**:命中、切换与 URL 缓存由 [useArtifactPreview](/composables/use-artifact-preview) 提供(Provider 在容器内、Consumer 在文件卡片 / 面板内);正文加载与分类型渲染由 Host 内部完成;常规取链只传 `file`,勿传 `undefined` 作为第二参
|
|
251
252
|
- **未传 `onArtifactClick`**:下载按钮隐藏,预览区展示无数据
|
|
252
253
|
|
|
253
254
|
详见 [FileArtifactPanel 文件产物预览](/components/message/file-artifact-panel) 与 [useArtifactPreview 文件产物预览](/composables/use-artifact-preview)。
|
|
@@ -453,9 +454,9 @@ ai-chat-container(:data-ai-size="size")
|
|
|
453
454
|
|
|
454
455
|
## 用户问题中断
|
|
455
456
|
|
|
456
|
-
当会话中最近一条待处理 interrupt 包含 `InterruptReason.UserQuestion` 时,`ChatContainer` 会在 `ChatInput` 上方显示 [UserQuestionCard](/components/agent/user-question-card)
|
|
457
|
+
当会话中最近一条待处理 interrupt 包含 `InterruptReason.UserQuestion` 时,`ChatContainer` 会在 `ChatInput` 上方显示 [UserQuestionCard](/components/agent/user-question-card)(一次一题,标题栏可切换题目)。
|
|
457
458
|
|
|
458
|
-
-
|
|
459
|
+
- **结构化作答**:用户在卡片内逐题选择(单选可自动跳下一题),点击「完成」或「跳过」后通过 `onInterruptResume(payload, interrupt)` 回传 `UserQuestionResume`。
|
|
459
460
|
- **输入框发送**:用户也可在输入框直接点击发送;容器会调用 `onSendMessage(content, docSchema, options)`,其中 `options.interrupt` 为当前激活的 UserQuestion,`options.payload` 为 `buildSkipResumePayload` 生成的 skip resume(`status: 'cancelled'`,`answers: []`)。此时**不会自动清空**输入框,由业务侧在 `onSendMessage` 内决定如何处理 `content` 与中断恢复。
|
|
460
461
|
|
|
461
462
|
```vue
|
|
@@ -654,19 +654,11 @@ const handleSendMessage = async (
|
|
|
654
654
|
|
|
655
655
|
## 类型定义
|
|
656
656
|
|
|
657
|
+
> `MessageStatus` 完整取值见 [常量枚举](../../types/constants)。与输入区相关:`pending` / `streaming` / `fetching` → 停止按钮;`complete` / `completed` / `error` / `stop` → 发送;`disabled` → 置灰。
|
|
658
|
+
|
|
657
659
|
```typescript
|
|
658
660
|
import type { UserMessage } from '@blueking/chat-x';
|
|
659
661
|
|
|
660
|
-
// 消息状态
|
|
661
|
-
enum MessageStatus {
|
|
662
|
-
Pending = 'pending', // 等待中(显示停止按钮)
|
|
663
|
-
Streaming = 'streaming', // 流式输出中(显示停止按钮)
|
|
664
|
-
Complete = 'complete', // 完成(显示发送按钮)
|
|
665
|
-
Error = 'error', // 错误(显示发送按钮)
|
|
666
|
-
Stop = 'stop', // 已停止(显示发送按钮)
|
|
667
|
-
Disabled = 'disabled', // 禁用(发送按钮置灰)
|
|
668
|
-
}
|
|
669
|
-
|
|
670
662
|
// 上传状态
|
|
671
663
|
enum UploadStatus {
|
|
672
664
|
Pending = 'pending', // 上传中
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<!-- AI SUMMARY -->
|
|
2
2
|
## 快速了解
|
|
3
3
|
|
|
4
|
-
汇总 MessageRole、MessageStatus(含 Fetching
|
|
4
|
+
汇总 MessageRole、MessageStatus(含 Fetching 请求中、Complete/Completed 完成态兼容)、MessageContentType、MessageToolsStatus、MessageState、Z-Index 与 CONST_MESSAGE_TOOLS 等导出常量。 用于构造消息、配置 MessageContainer 工具栏与输入态,以及层级与默认快捷指令。与类型 messages 配套使用。
|
|
5
5
|
|
|
6
6
|
### 关联组件
|
|
7
7
|
- **message-tools** — 默认工具 ID 与展示
|
|
@@ -58,6 +58,7 @@ enum MessageRole {
|
|
|
58
58
|
```typescript
|
|
59
59
|
enum MessageStatus {
|
|
60
60
|
Complete = 'complete',
|
|
61
|
+
Completed = 'completed', // 与 Complete 同为完成态,兼容后端/协议返回的 completed
|
|
61
62
|
Disabled = 'disabled',
|
|
62
63
|
Error = 'error',
|
|
63
64
|
Fetching = 'fetching', // 请求中(例如已发用户消息、尚未开始流式,与末尾 Loading 占位一致)
|
|
@@ -71,6 +72,7 @@ enum MessageStatus {
|
|
|
71
72
|
|
|
72
73
|
| 枚举值 | 说明 |
|
|
73
74
|
| --------------- | ---- |
|
|
75
|
+
| `Complete` / `Completed` | 已完成。`complete` 为库内常用值;`completed` 与之语义相同,用于兼容外部协议或后端返回。`ToolcallRender` 等将二者与 `success` 一并视为成功态。 |
|
|
74
76
|
| `Fetching` | 请求中:与 `useMessageGroup` 在末尾用户消息后注入的 Loading 占位(`LOADING_MESSAGE_ID`)配合时,`ChatContainer` 会将传入输入区与列表底部的状态推导为该值,便于展示「停止」与禁止重复发送。 |
|
|
75
77
|
|
|
76
78
|
### InterruptReason
|
|
@@ -216,18 +216,10 @@ enum MessageContentType {
|
|
|
216
216
|
KnowledgeRag = 'knowledge_rag',
|
|
217
217
|
Other = 'other',
|
|
218
218
|
}
|
|
219
|
-
|
|
220
|
-
// 消息状态
|
|
221
|
-
enum MessageStatus {
|
|
222
|
-
Pending = 'pending',
|
|
223
|
-
Streaming = 'streaming',
|
|
224
|
-
Complete = 'complete',
|
|
225
|
-
Error = 'error',
|
|
226
|
-
Stop = 'stop',
|
|
227
|
-
Disabled = 'disabled',
|
|
228
|
-
}
|
|
229
219
|
```
|
|
230
220
|
|
|
221
|
+
> `MessageStatus` 完整取值见 [常量枚举](../../types/constants);本组件主要关心 `error`(错误内容)与流式相关状态。
|
|
222
|
+
|
|
231
223
|
## 使用场景
|
|
232
224
|
|
|
233
225
|
- **AI 文本回复渲染**:`AssistantMessage` 内部用 `ContentRender` 渲染 AI 回复内容,`status` 配合流式响应
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<!-- AI SUMMARY -->
|
|
2
2
|
## 快速了解
|
|
3
3
|
|
|
4
|
-
汇总当前会话所有 AssistantMessage 的 artifacts
|
|
4
|
+
汇总当前会话所有 AssistantMessage 的 artifacts(按 outputId 去重),支持关键词搜索、列表选中与下载; 预览区委托 ArtifactPreviewHost:按类型走 text_from_download(html / markdown / md / txt / json) 或 preview_url_iframe(其余类型);download_url / preview_url 经 onArtifactClick 异步获取(TTL 缓存,重试 force); 预览重载键为 outputId:type;常规 resolveArtifactUrls 只传 file。 源码位置:src/components/chat-message/assistant-message/message-artifacts/file-artifact-panel.vue。
|
|
5
5
|
|
|
6
6
|
### 关联组件
|
|
7
7
|
- **assistant-message** — 文件产物来源于 AssistantMessage.property.artifacts
|
|
@@ -22,16 +22,16 @@
|
|
|
22
22
|
|
|
23
23
|
> **导出说明**:内部侧栏面板组件,**通常不直接使用**;由 `ChatContainer` 在「文件产物」Tab 内自动挂载。预览加载与渲染为同目录下 `artifact-preview/` 内部实现,不单独导出。
|
|
24
24
|
|
|
25
|
-
点击 AI 回复中的[文件卡片](/components/message/assistant-message)后,`ChatContainer` 侧栏会弹出固定的「文件产物」Tab,聚合展示当前会话**所有** `AssistantMessage`
|
|
25
|
+
点击 AI 回复中的[文件卡片](/components/message/assistant-message)后,`ChatContainer` 侧栏会弹出固定的「文件产物」Tab,聚合展示当前会话**所有** `AssistantMessage` 的文件产物(按 `outputId` 去重),并命中被点击的文件进行预览。
|
|
26
26
|
|
|
27
27
|
面板左侧为可搜索的文件列表,右侧为预览区。通常不需要直接使用,由 `ChatContainer` 在侧栏内自动渲染。
|
|
28
28
|
|
|
29
29
|
## 核心能力
|
|
30
30
|
|
|
31
|
-
- **会话级聚合**:拍平当前会话所有 `AssistantMessage.property.artifacts
|
|
32
|
-
-
|
|
31
|
+
- **会话级聚合**:拍平当前会话所有 `AssistantMessage.property.artifacts`,以 `outputId` 去重后统一在一个列表内展示
|
|
32
|
+
- **唯一命中**:以 `outputId` 作为会话内唯一键(同 `outputId` 视为同一文件);文件名可能重复,不可作唯一键
|
|
33
33
|
- **关键词搜索**:按文件名实时过滤列表
|
|
34
|
-
- **异步取链**:`AIFileInfo` 本身不含 `url` / `previewUrl`,通过 `ChatContainer` 的 `onArtifactClick` 按 `outputId`
|
|
34
|
+
- **异步取链**:`AIFileInfo` 本身不含 `url` / `previewUrl`,通过 `ChatContainer` 的 `onArtifactClick` 按 `outputId` 获取 `download_url` / `preview_url`(TTL 8 分钟缓存;预览重试会 `force` 刷新)
|
|
35
35
|
- **职责拆分**:
|
|
36
36
|
- **面板本身**:列表、搜索、预览头(文件名 / 图标 / 下载)
|
|
37
37
|
- **`ArtifactPreviewHost`**:按策略加载正文或预览 URL,分派到对应 renderer;展示 loading / empty / error(含重试)
|
|
@@ -54,12 +54,12 @@
|
|
|
54
54
|
|
|
55
55
|
<script setup lang="ts">
|
|
56
56
|
import { shallowRef } from 'vue'
|
|
57
|
-
import {
|
|
57
|
+
import { useArtifactPreviewProvider } from '@blueking/chat-x'
|
|
58
58
|
import type { AIFileInfo, SessionArtifact } from '@blueking/chat-x'
|
|
59
59
|
// 内部组件:仅文档 / 调试;业务请用 ChatContainer 自动挂载
|
|
60
60
|
import FileArtifactPanel from './message-artifacts/file-artifact-panel.vue'
|
|
61
61
|
|
|
62
|
-
const
|
|
62
|
+
const sessionArtifacts: SessionArtifact[] = [
|
|
63
63
|
{ name: '周报.html', outputId: 'a-html', size: 10240, type: 'html' },
|
|
64
64
|
{ name: '说明.md', outputId: 'a-md', size: 8192, type: 'md' },
|
|
65
65
|
{ name: '纪要.txt', outputId: 'a-txt', size: 4096, type: 'txt' },
|
|
@@ -67,12 +67,6 @@
|
|
|
67
67
|
{ name: '立项.pdf', outputId: 'a-pdf', size: 204800, type: 'pdf' },
|
|
68
68
|
]
|
|
69
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
70
|
useArtifactPreviewProvider({
|
|
77
71
|
getOnArtifactClick: () => async file => {
|
|
78
72
|
// 文本类返回可 fetch 的 download_url;iframe 类返回 preview_url
|
|
@@ -82,7 +76,7 @@
|
|
|
82
76
|
onOpen: () => {},
|
|
83
77
|
})
|
|
84
78
|
|
|
85
|
-
const activeArtifactId = shallowRef(sessionArtifacts[0].
|
|
79
|
+
const activeArtifactId = shallowRef(sessionArtifacts[0].outputId)
|
|
86
80
|
const handleSelect = (id: string) => {
|
|
87
81
|
activeArtifactId.value = id
|
|
88
82
|
}
|
|
@@ -160,34 +154,32 @@
|
|
|
160
154
|
|
|
161
155
|
```
|
|
162
156
|
ArtifactFileCard(点击文件卡片)
|
|
163
|
-
└─ useArtifactPreviewConsumer().openPreview({ file
|
|
157
|
+
└─ useArtifactPreviewConsumer().openPreview({ file })
|
|
164
158
|
└─ useArtifactPreviewProvider(ChatContainer 内)
|
|
165
|
-
├─ 记录命中文件 activeArtifactId
|
|
159
|
+
├─ 记录命中文件 activeArtifactId = file.outputId
|
|
166
160
|
└─ onOpen → addCustomTab('file-artifact') 展开并选中侧栏 Tab
|
|
167
161
|
└─ FileArtifactPanel
|
|
168
|
-
├─ 列表 @select → setActiveArtifactId
|
|
162
|
+
├─ 列表 @select → setActiveArtifactId(outputId)
|
|
169
163
|
├─ 下载 → resolveArtifactUrls + triggerArtifactDownload
|
|
170
164
|
└─ ArtifactPreviewHost
|
|
171
165
|
├─ useArtifactPreviewLoader(策略 + fetch / 取链,防竞态)
|
|
172
166
|
└─ HtmlPreview | MarkdownPreview | TxtPreview | UrlIframePreview
|
|
167
|
+
|
|
168
|
+
sessionArtifacts 有产物时
|
|
169
|
+
└─ ensureCustomTab('file-artifact') 静默挂上,不抢当前选中(如执行情况)
|
|
173
170
|
```
|
|
174
171
|
|
|
175
172
|
- 文件卡片通过 `useArtifactPreviewConsumer` 注入预览上下文,无 Provider 时卡片不可点击(兜底 `undefined`)
|
|
176
173
|
- `ChatContainer` 通过 `useArtifactPreviewProvider` 提供上下文,并把「打开侧栏 Tab」这一副作用以 `onOpen` 注入,保持 composable 职责单一
|
|
177
174
|
- 侧栏「文件产物」Tab 固定不可关闭,`order: -1` 排在「执行情况」之前;会话切换或无文件产物时自动移除
|
|
178
175
|
|
|
179
|
-
##
|
|
176
|
+
## 唯一键规则
|
|
180
177
|
|
|
181
|
-
|
|
178
|
+
会话内以 **`outputId`** 作为文件产物唯一键:
|
|
182
179
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
// messageUid#消息内下标#outputId
|
|
187
|
-
buildArtifactId('msg-a', 2, 'output-9'); // => 'msg-a#2#output-9'
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
Provider 侧聚合与文件卡片侧透传必须使用同一规则,保证命中一致。
|
|
180
|
+
- 同一 `outputId` 在多条消息中出现时,聚合列表去重并保留最后一次出现的文件信息
|
|
181
|
+
- `activeId`、列表 `:key`、`select` 事件参数均使用 `outputId`
|
|
182
|
+
- 文件名可能重复,**不可**作为唯一键
|
|
191
183
|
|
|
192
184
|
## 预览机制
|
|
193
185
|
|
|
@@ -211,7 +203,14 @@ Provider 侧聚合与文件卡片侧透传必须使用同一规则,保证命
|
|
|
211
203
|
| `empty` | 「暂无可预览的文件」(无文件 / 未传 `onArtifactClick` / 缺所需 URL) |
|
|
212
204
|
| `error` | 「预览加载失败」+ 重试按钮 |
|
|
213
205
|
|
|
214
|
-
|
|
206
|
+
### 重载与取链约定
|
|
207
|
+
|
|
208
|
+
- **重载键**:`ArtifactPreviewHost` 以 `` `${outputId}:${type}` `` 监听文件变化;`outputId` 或 `type` 任一变化会重新 `load()`,仅改文件名等其它字段不会
|
|
209
|
+
- **常规取链**:`resolveArtifactUrls(file)`,只传文件,不传第二参
|
|
210
|
+
- **重试 / 强刷**:错误态点击重试走 `load({ force: true })` → `resolveArtifactUrls(file, { force: true })`,绕过 TTL 缓存重新取链
|
|
211
|
+
- **竞态**:切换文件时 `useArtifactPreviewLoader` 用 `loadSeq` + `AbortController` 中断上一次 `fetch`,避免过期结果覆盖最新内容
|
|
212
|
+
|
|
213
|
+
下载图标仍由面板用 bkui `Loading` spin 单独表达。
|
|
215
214
|
|
|
216
215
|
## 内部结构(不导出)
|
|
217
216
|
|
|
@@ -235,14 +234,14 @@ message-artifacts/
|
|
|
235
234
|
|
|
236
235
|
| 属性名 | 类型 | 必填 | 说明 |
|
|
237
236
|
| --------- | ------------------- | ---- | -------------------------------------- |
|
|
238
|
-
| activeId | `string` | ✓ | 当前命中的文件
|
|
239
|
-
| artifacts | `SessionArtifact[]` | ✓ |
|
|
237
|
+
| activeId | `string` | ✓ | 当前命中的文件 `outputId` |
|
|
238
|
+
| artifacts | `SessionArtifact[]` | ✓ | 当前会话全部文件产物(已按 `outputId` 去重) |
|
|
240
239
|
|
|
241
240
|
### Events
|
|
242
241
|
|
|
243
242
|
| 事件名 | 参数 | 说明 |
|
|
244
243
|
| ------ | ----------------- | -------------------------- |
|
|
245
|
-
| select | `(id: string)` | 列表内切换选中文件,参数为文件 `
|
|
244
|
+
| select | `(id: string)` | 列表内切换选中文件,参数为文件 `outputId` |
|
|
246
245
|
|
|
247
246
|
### Slots / Expose
|
|
248
247
|
|
|
@@ -253,11 +252,8 @@ message-artifacts/
|
|
|
253
252
|
```typescript
|
|
254
253
|
import type { AIFileInfo, SessionArtifact } from '@blueking/chat-x';
|
|
255
254
|
|
|
256
|
-
//
|
|
257
|
-
type SessionArtifact = AIFileInfo
|
|
258
|
-
artifactId: string; // 全局唯一 id:messageUid#index#outputId
|
|
259
|
-
messageUid: string; // 所属 AssistantMessage 的 uid
|
|
260
|
-
};
|
|
255
|
+
// 会话级文件产物:拍平去重后即为 AIFileInfo
|
|
256
|
+
type SessionArtifact = AIFileInfo;
|
|
261
257
|
|
|
262
258
|
type AIFileInfo = {
|
|
263
259
|
name: string;
|
|
@@ -20,16 +20,17 @@
|
|
|
20
20
|
|
|
21
21
|
> **导出说明**:`InfoMessage` **未**从包入口导出(入口同名是 TS interface)。消费方经 `MessageRender` / `MessageContainer` 使用。下文 `InfoMessageComp` 为文档站内部示例。
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
系统信息分隔组件,在聊天消息列表中以**左右虚线夹中文案**的形式展示非对话类信息(会话重置、时间节点、状态变更等)。
|
|
24
24
|
|
|
25
25
|
## 视觉原理
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
根节点 `.ai-info-message` 为横向 flex:两侧通过 `::before` / `::after` 拉伸出虚线(主题边框色),中间 `.ai-info-message-body` 承载文案(主题次要文案色)。整块正常占位,避免旧实现 `height: 0` 导致内容被裁切遮挡:
|
|
28
28
|
|
|
29
29
|
```
|
|
30
|
-
|
|
30
|
+
─────── 以下是新的对话 ───────
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
+
多行时,多条 `.ai-info-message-content` 在 body 内纵向排列(`gap: 4px`),两侧虚线仍夹住整块文案区域。
|
|
33
34
|
## 基础用法
|
|
34
35
|
|
|
35
36
|
`content` 传入字符串,渲染单行分隔信息:
|
|
@@ -56,7 +57,7 @@
|
|
|
56
57
|
|
|
57
58
|
## 多行信息
|
|
58
59
|
|
|
59
|
-
`content`
|
|
60
|
+
`content` 传入字符串数组时,每个元素渲染为一行居中文案,在中间 body 内纵向排列,两侧虚线夹住整块区域:
|
|
60
61
|
|
|
61
62
|
```vue
|
|
62
63
|
<template>
|
|
@@ -134,7 +135,7 @@
|
|
|
134
135
|
|
|
135
136
|
| 属性名 | 类型 | 说明 |
|
|
136
137
|
| --------- | -------------------- | ------------------------------------------------------------------ |
|
|
137
|
-
| content | `string \| string[]` |
|
|
138
|
+
| content | `string \| string[]` | 信息内容。字符串渲染单行;数组在中间区域纵向多行展示,两侧虚线夹住整块 |
|
|
138
139
|
| id | `number \| string` | 消息 ID(接收但不使用,由 MessageContainer 管理) |
|
|
139
140
|
| messageId | `number \| string` | 消息唯一标识(接收但不使用) |
|
|
140
141
|
| status | `MessageStatus` | 消息状态(接收但不使用,组件无状态相关渲染逻辑) |
|
|
@@ -138,6 +138,7 @@ type UserQuestionOptionItem = {
|
|
|
138
138
|
- 前端会为每道**选择题**追加 `label: 'others'` 的自由输入项;后端无需重复下发该选项。
|
|
139
139
|
- 当用户选择 Others 时,`answer[].description` 为用户输入文本。
|
|
140
140
|
- 业务可通过 `UserQuestionCard` 的 `#question` slot 渲染自定义表单;作答有效时调用 `setAnswer` 回传 `UserQuestionAnswerItem`,无效时传 `undefined`。
|
|
141
|
+
- UI 一次只展示一题:标题栏 `< 当前题 / 总题数 >` 切换;单选预设选项作答后自动跳下一题,多选 / Others 需手动切换(协议字段不变)。
|
|
141
142
|
|
|
142
143
|
## Interrupt
|
|
143
144
|
|
|
@@ -613,29 +613,12 @@ enum MessageToolsStatus {
|
|
|
613
613
|
Hidden = 'hidden',
|
|
614
614
|
}
|
|
615
615
|
|
|
616
|
-
// 消息角色
|
|
617
|
-
|
|
618
|
-
User = 'user',
|
|
619
|
-
Assistant = 'assistant',
|
|
620
|
-
Tool = 'tool',
|
|
621
|
-
Reasoning = 'reasoning',
|
|
622
|
-
Activity = 'activity',
|
|
623
|
-
Info = 'info',
|
|
624
|
-
Interrupt = 'interrupt',
|
|
625
|
-
Loading = 'loading',
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
// 消息状态
|
|
629
|
-
enum MessageStatus {
|
|
630
|
-
Pending = 'pending',
|
|
631
|
-
Streaming = 'streaming',
|
|
632
|
-
Complete = 'complete',
|
|
633
|
-
Error = 'error',
|
|
634
|
-
Stop = 'stop',
|
|
635
|
-
Disabled = 'disabled',
|
|
636
|
-
}
|
|
616
|
+
// 消息角色 / 消息状态完整枚举见常量文档,勿在此维护副本
|
|
617
|
+
// MessageRole、MessageStatus → ../../types/constants
|
|
637
618
|
```
|
|
638
619
|
|
|
620
|
+
> `MessageRole` / `MessageStatus` 完整取值见 [常量枚举](../../types/constants)。
|
|
621
|
+
|
|
639
622
|
## 关联组件
|
|
640
623
|
|
|
641
624
|
- [MessageRender](/components/message/message-render) — 按组渲染每条消息时委托使用
|
|
@@ -315,35 +315,12 @@ h(ContentRender, { content: message.content || '', status: message.status }, /*
|
|
|
315
315
|
```typescript
|
|
316
316
|
import { MessageRole, MessageStatus, MessageToolsStatus, type Message, type IToolBtn } from '@blueking/chat-x';
|
|
317
317
|
|
|
318
|
-
//
|
|
319
|
-
|
|
320
|
-
User = 'user',
|
|
321
|
-
Assistant = 'assistant',
|
|
322
|
-
Info = 'info',
|
|
323
|
-
Reasoning = 'reasoning',
|
|
324
|
-
Tool = 'tool',
|
|
325
|
-
Activity = 'activity',
|
|
326
|
-
Loading = 'loading',
|
|
327
|
-
Interrupt = 'interrupt',
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
// 消息状态
|
|
331
|
-
enum MessageStatus {
|
|
332
|
-
Pending = 'pending',
|
|
333
|
-
Streaming = 'streaming',
|
|
334
|
-
Complete = 'complete',
|
|
335
|
-
Error = 'error',
|
|
336
|
-
Stop = 'stop',
|
|
337
|
-
Disabled = 'disabled',
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
// 工具按钮状态(仅转发给 UserMessage)
|
|
341
|
-
enum MessageToolsStatus {
|
|
342
|
-
Disabled = 'disabled',
|
|
343
|
-
Hidden = 'hidden',
|
|
344
|
-
}
|
|
318
|
+
// MessageRole / MessageStatus 完整枚举见 ../../types/constants
|
|
319
|
+
// MessageToolsStatus:Disabled | Hidden(仅转发给 UserMessage)
|
|
345
320
|
```
|
|
346
321
|
|
|
322
|
+
> `MessageRole` / `MessageStatus` 完整取值见 [常量枚举](../../types/constants)。
|
|
323
|
+
|
|
347
324
|
## 关联组件
|
|
348
325
|
|
|
349
326
|
- [MessageContainer](/components/setup/message-container) — 内部按组调用以渲染每条消息
|
|
@@ -144,6 +144,9 @@ enum MessageStatus {
|
|
|
144
144
|
// 已完成
|
|
145
145
|
Complete = 'complete',
|
|
146
146
|
|
|
147
|
+
// 已完成(与 Complete 同义,兼容协议/后端返回的 completed)
|
|
148
|
+
Completed = 'completed',
|
|
149
|
+
|
|
147
150
|
// 已禁用
|
|
148
151
|
Disabled = 'disabled',
|
|
149
152
|
|
|
@@ -170,6 +173,8 @@ enum MessageStatus {
|
|
|
170
173
|
}
|
|
171
174
|
```
|
|
172
175
|
|
|
176
|
+
完整取值与说明见 [常量枚举 · MessageStatus](./constants#messagestatus)。
|
|
177
|
+
|
|
173
178
|
## 具体消息类型
|
|
174
179
|
|
|
175
180
|
### UserMessage
|
|
@@ -224,17 +224,10 @@ interface ReasoningMessage {
|
|
|
224
224
|
duration?: number; // 推理耗时(毫秒)
|
|
225
225
|
name?: string;
|
|
226
226
|
}
|
|
227
|
-
|
|
228
|
-
enum MessageStatus {
|
|
229
|
-
Pending = 'pending',
|
|
230
|
-
Streaming = 'streaming',
|
|
231
|
-
Complete = 'complete',
|
|
232
|
-
Success = 'success',
|
|
233
|
-
Error = 'error',
|
|
234
|
-
Stop = 'stop',
|
|
235
|
-
}
|
|
236
227
|
```
|
|
237
228
|
|
|
229
|
+
> `MessageStatus` 完整取值见 [常量枚举](../../types/constants)。本组件完成态识别 `complete` / `success`(与标题文案表一致)。
|
|
230
|
+
|
|
238
231
|
## 关联组件
|
|
239
232
|
|
|
240
233
|
- [MessageRender](/components/message/message-render) — reasoning 角色由其实例化
|
|
@@ -78,14 +78,14 @@
|
|
|
78
78
|
|
|
79
79
|
`status` prop 同时控制头部的 CSS class(`toolcall-status-{status}`)、背景/边框颜色、状态文案和 Loading 动画:
|
|
80
80
|
|
|
81
|
-
| `status`
|
|
82
|
-
|
|
|
83
|
-
| `pending` / `streaming`
|
|
84
|
-
| `complete` / `success` | 调用成功 | `#ebfaf0` | `#a1e3ba` | - |
|
|
85
|
-
| `error`
|
|
86
|
-
| 其他 / `undefined`
|
|
87
|
-
|
|
88
|
-
> **说明**:`statusTitle`
|
|
81
|
+
| `status` | 状态文案 | 背景色 | 边框色 | Loading |
|
|
82
|
+
| ------------------------------------- | -------- | ----------------- | --------- | ------- |
|
|
83
|
+
| `pending` / `streaming` | 调用中 | `#fafbfd` | `#dcdee5` | ✓ |
|
|
84
|
+
| `complete` / `completed` / `success` | 调用成功 | `#ebfaf0` | `#a1e3ba` | - |
|
|
85
|
+
| `error` | 调用失败 | `#fff0f0` | `#f8b4b4` | - |
|
|
86
|
+
| 其他 / `undefined` | 调用中 | —(无匹配 class) | — | - |
|
|
87
|
+
|
|
88
|
+
> **说明**:`statusTitle` 将 `Completed`(`completed`)与 `Complete` / `Success` 一并视为成功;主题 `$toolcallStatusMap` 同步提供 `completed` 色值。`default` 与 `case Pending` 共享「调用中」文案,`streaming` 与未知 status 命中 `default`。Loading 由 `v-if="status === 'pending' || status === 'streaming'"` 控制。
|
|
89
89
|
|
|
90
90
|
**三种状态对比**
|
|
91
91
|
|