@blueking/chat-x 2.4.1 → 3.0.0-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/messages.d.ts +1 -1
- package/dist/components/chat-input/chat-input.vue.d.ts +5 -2
- package/dist/components/chat-message/user-message/user-message.vue.d.ts +1 -0
- package/dist/components/image-preview/image.vue.d.ts +2 -2
- package/dist/composables/use-global-config.d.ts +8 -0
- package/dist/composables/use-message-group.d.ts +3 -3
- package/dist/index.js +72 -41
- package/dist/index.js.map +1 -1
- package/dist/mcp/generated/docs/assistant-message.md +3 -2
- package/dist/mcp/generated/docs/chat-container.md +4 -4
- package/dist/mcp/generated/docs/chat-input.md +4 -3
- package/dist/mcp/generated/docs/messages.md +1 -1
- package/dist/mcp/generated/docs/toolcall-render.md +9 -9
- package/dist/mcp/generated/docs/use-global-config.md +14 -5
- package/dist/mcp/generated/docs/user-message.md +7 -4
- package/dist/mcp/generated/index.json +3 -3
- package/dist/mcp/index.js +0 -0
- package/package.json +21 -22
- package/skills/blueking-chat-x/references/components/assistant-message.md +3 -2
- package/skills/blueking-chat-x/references/components/toolcall-render.md +9 -9
- package/skills/blueking-chat-x/references/types/messages.md +1 -1
|
@@ -200,7 +200,7 @@ AI 可在一次回复中发起多个工具调用,组件依次渲染:
|
|
|
200
200
|
|
|
201
201
|
### MCP 工具调用
|
|
202
202
|
|
|
203
|
-
`function.
|
|
203
|
+
`function.function_type` 为 `'mcp'`(或旧数据仅有 `mcpName`)时,`ToolCallRender` 头部显示为「调用 MCP {mcpName} / {name}」:
|
|
204
204
|
|
|
205
205
|
```vue
|
|
206
206
|
<script setup lang="ts">
|
|
@@ -209,7 +209,7 @@ AI 可在一次回复中发起多个工具调用,组件依次渲染:
|
|
|
209
209
|
id: 'call_mcp_1',
|
|
210
210
|
type: 'function',
|
|
211
211
|
function: {
|
|
212
|
-
|
|
212
|
+
function_type: 'mcp', // 调用类型,缺省时有 mcpName 也会兼容判定为 MCP
|
|
213
213
|
name: 'query_database',
|
|
214
214
|
arguments: '{"sql": "SELECT * FROM users LIMIT 10"}',
|
|
215
215
|
description: '执行数据库查询',
|
|
@@ -482,6 +482,7 @@ type FunctionCall = {
|
|
|
482
482
|
arguments: string; // JSON 字符串格式的参数
|
|
483
483
|
description?: string; // 函数描述
|
|
484
484
|
mcpName?: string; // MCP 服务名(存在时标题显示 "调用 MCP")
|
|
485
|
+
function_type?: 'function' | 'mcp' | 'skill'; // 调用类型,决定头部前缀;不传时有 mcpName 按 MCP 判定
|
|
485
486
|
};
|
|
486
487
|
|
|
487
488
|
// 工具执行结果
|
|
@@ -550,7 +550,7 @@ ai-chat-container(:data-ai-size="size")
|
|
|
550
550
|
|
|
551
551
|
## 分享模式
|
|
552
552
|
|
|
553
|
-
|
|
553
|
+
点击消息工具栏的「分享」按钮后进入分享模式,并默认勾选当前轮次;底部出现 `SelectionFooter` 操作栏:
|
|
554
554
|
|
|
555
555
|
```vue
|
|
556
556
|
<template>
|
|
@@ -618,7 +618,7 @@ ai-chat-container(:data-ai-size="size")
|
|
|
618
618
|
**分享流程**:
|
|
619
619
|
|
|
620
620
|
1. 用户点击消息工具栏中的「分享」按钮(或任意 `triggerSelection: true` 的自定义按钮)
|
|
621
|
-
2.
|
|
621
|
+
2. 进入多选模式,并默认勾选当前轮次(用户问题 + 对应回复);`enterShareMode()` 进入时不预选
|
|
622
622
|
3. 底部 `SelectionFooter` 提供全选、取消、确认操作
|
|
623
623
|
4. 确认后触发 `confirmShare` 事件,携带选中的消息列表与触发按钮对象(`source`)
|
|
624
624
|
|
|
@@ -630,7 +630,7 @@ ai-chat-container(:data-ai-size="size")
|
|
|
630
630
|
|
|
631
631
|
**2. 资源引用入口**:容器通过 [useInputMention](/composables/use-input-mention) 提供 `insertMention`,消息区的文件卡片与侧栏产物面板因此能直接把文件「@ 进输入框」,无需逐层透传输入框实例。没有输入框的场景(`Share` 只读态)自动不显示引用按钮。
|
|
632
632
|
|
|
633
|
-
**3.
|
|
633
|
+
**3. 编辑态菜单与上传下发**:`menuSources` 经 [useGlobalConfig](/composables/use-global-config) 注入,用户消息进入编辑态时就地渲染的 `ChatInput` 也能拿到同一份数据源。`supportUpload` 同样下发,编辑态输入框也会出现内置「文件」项。主输入框的 `onUpload` 与 `deleteFile` 一并注入,编辑态新选文件会走同一套 upload / DELETE,无需再向 `UserMessage` 透传。
|
|
634
634
|
|
|
635
635
|
```vue
|
|
636
636
|
<template>
|
|
@@ -804,7 +804,7 @@ ChatContainer 的 Props 继承自 `ChatInputProps` 和 `MessageContainerProps`
|
|
|
804
804
|
| addCustomTab | `(tab: CustomTab) => void` | 添加自定义 Tab |
|
|
805
805
|
| removeCustomTab | `(tabName: string) => void` | 移除自定义 Tab |
|
|
806
806
|
| selectCustomTab | `(tab: CustomTab) => void` | 切换到指定 Tab |
|
|
807
|
-
| enterShareMode | `() => void` |
|
|
807
|
+
| enterShareMode | `() => void` | 手动进入分享多选模式(不预选消息) |
|
|
808
808
|
| exitShareMode | `() => void` | 退出分享多选模式,并清空已选消息 |
|
|
809
809
|
|
|
810
810
|
## 渲染模式
|
|
@@ -44,7 +44,7 @@ ai-chat-input-container(padding: 0 16px 16px)
|
|
|
44
44
|
└── slot#send-icon(默认:发送 / 停止图标)
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
> `slot#attachment` 只替换快捷指令区,`AddMenuBtn` 在其外部,使用该插槽不会移除 + 号。`slot#send-icon`
|
|
47
|
+
> `slot#attachment` 只替换快捷指令区,`AddMenuBtn` 在其外部,使用该插槽不会移除 + 号。`slot#send-icon` 替换发送区;未传入时仍用默认发送 / 停止图标。自定义该插槽时需自行处理禁用,作用域参数 `sendDisabledTip` 为上传中 / 失败等拦截文案。
|
|
48
48
|
|
|
49
49
|
## 基础用法
|
|
50
50
|
|
|
@@ -527,7 +527,7 @@ const defaultFiles: UploadFile[] = [
|
|
|
527
527
|
| files | `{ files: Partial<UploadFile>[] }` | 文件预览区 |
|
|
528
528
|
| attachment | - | 底部快捷指令区,`AddMenuBtn` 在其左侧,不受此插槽影响 |
|
|
529
529
|
| model-selector | `{ models: IModelOption[]; selectedModel: string \| undefined }` | 发送按钮左侧模型选择区,默认渲染 `ModelSelector` |
|
|
530
|
-
| send-icon |
|
|
530
|
+
| send-icon | `{ sendDisabledTip?: string }` | 替换发送区;自定义时需自行处理禁用,拦截文案见 `sendDisabledTip` |
|
|
531
531
|
|
|
532
532
|
### Expose
|
|
533
533
|
|
|
@@ -537,7 +537,8 @@ const defaultFiles: UploadFile[] = [
|
|
|
537
537
|
| ------------------ | --------------------------------- | ------------------------------------------------ |
|
|
538
538
|
| focus | `() => void` | 聚焦编辑器并把光标置于末尾 |
|
|
539
539
|
| insertMention | `(item: IInputMenuItem) => void` | 把条目以标签形式追加到文档末尾(不依赖当前光标) |
|
|
540
|
-
|
|
|
540
|
+
| getUploadFiles | `() => Partial<UploadFile>[]` | 当前待发送附件快照(编辑态取消时据此清理本次新文件) |
|
|
541
|
+
| triggerSendMessage | `() => Promise<boolean>` | 手动触发发送;真正发出返回 `true`,上传中/失败拦截返回 `false` |
|
|
541
542
|
| uploadedArtifacts | `AIFileInfo[]` | 已上传且带 `outputId` 的附件列表(只读) |
|
|
542
543
|
|
|
543
544
|
## 键盘快捷键
|
|
@@ -104,20 +104,20 @@ isPending = !isSuccess && !isError; // 其余(含 pending / streaming / stop /
|
|
|
104
104
|
|
|
105
105
|
## 调用类型前缀
|
|
106
106
|
|
|
107
|
-
非进行中态的前缀由 `function.
|
|
107
|
+
非进行中态的前缀由 `function.function_type` 决定;进行中态工具 / MCP 显示「正在调用」,Skill 显示「正在读取」:
|
|
108
108
|
|
|
109
|
-
| `function.
|
|
109
|
+
| `function.function_type` | 前缀 | 说明 |
|
|
110
110
|
| ------------------------ | ----------- | ---------------------------------------- |
|
|
111
111
|
| `'function'` / 不传 | 调用工具 | 普通函数调用 |
|
|
112
112
|
| `'mcp'` | 调用 MCP | MCP 调用,通常同时带 `mcpName` |
|
|
113
113
|
| `'skill'` | 读取 Skill | Skill 读取 |
|
|
114
114
|
|
|
115
115
|
```typescript
|
|
116
|
-
const callType = fn?.
|
|
116
|
+
const callType = fn?.function_type ?? (fn?.mcpName ? 'mcp' : 'function');
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
-
- **旧数据兼容**:未下发 `
|
|
120
|
-
- **`
|
|
119
|
+
- **旧数据兼容**:未下发 `function_type` 时,有 `mcpName` 仍按 MCP 判定,历史消息展示不变
|
|
120
|
+
- **`function_type` 优先**:显式 `function_type: 'function'` 不会被 `mcpName` 覆盖回 MCP,但标题仍是 `{mcpName} / {name}`
|
|
121
121
|
|
|
122
122
|
**三种前缀对比**
|
|
123
123
|
|
|
@@ -194,14 +194,14 @@ const toolCallWithDuration: ToolCall = {
|
|
|
194
194
|
|
|
195
195
|
## MCP 调用
|
|
196
196
|
|
|
197
|
-
`function.
|
|
197
|
+
`function.function_type` 为 `'mcp'`(或旧数据仅有 `mcpName`)时,前缀为「调用 MCP」,标题格式变为 `{mcpName} / {functionName}`:
|
|
198
198
|
|
|
199
199
|
```typescript
|
|
200
200
|
const mcpToolCall: ToolCall = {
|
|
201
201
|
id: 'call_mcp_1',
|
|
202
202
|
type: 'function',
|
|
203
203
|
function: {
|
|
204
|
-
|
|
204
|
+
function_type: 'mcp', // ← 前缀显示「调用 MCP」;缺省时有 mcpName 也会兼容判定为 MCP
|
|
205
205
|
name: 'query_table',
|
|
206
206
|
arguments: JSON.stringify({ table: 'events', limit: 50 }),
|
|
207
207
|
description: '通过 MCP 协议查询蓝鲸数据平台中的事件数据',
|
|
@@ -329,8 +329,8 @@ type FunctionCall = {
|
|
|
329
329
|
name: string; // 函数名;为空时标题 fallback 为 toolCall.id
|
|
330
330
|
arguments: string; // 调用参数(通常为 JSON 字符串)
|
|
331
331
|
description?: string; // 工具描述;为空时"描述"区块保留但内容为空白
|
|
332
|
-
mcpName?: string; // MCP 服务名;有值时标题格式变为 "{mcpName} / {name}",缺省
|
|
333
|
-
|
|
332
|
+
mcpName?: string; // MCP 服务名;有值时标题格式变为 "{mcpName} / {name}",缺省 function_type 时兼容判定为 MCP
|
|
333
|
+
function_type?: FunctionCallType; // 调用类型,决定头部前缀;不传按 mcpName 兼容判定
|
|
334
334
|
};
|
|
335
335
|
|
|
336
336
|
// ToolMessage —— 工具返回消息
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<!-- AI SUMMARY -->
|
|
2
2
|
## 快速了解
|
|
3
3
|
|
|
4
|
-
useGlobalConfig 接收 GlobalConfig(含 size
|
|
4
|
+
useGlobalConfig 接收 GlobalConfig(含 size、supportUpload、timezone、menuSources、onUpload、onDeleteFile),以 GLOBAL_CONFIG_TOKEN provide 给后代; injectGlobalConfig 在子组件中取出配置,无 Provider 时返回 undefined。ChatContainer 在 setup 中调用 useGlobalConfig 注入 size、supportUpload、timezone、menuSources 以及主输入框同源的 onUpload / onDeleteFile; 后代组件可通过 injectGlobalConfig 读取配置;字号主题主要通过根节点 data-ai-size 与 CSS 变量生效。
|
|
5
5
|
|
|
6
6
|
### 关联组件
|
|
7
7
|
- **chat-container** — 根容器调用 useGlobalConfig 注入 supportUpload
|
|
@@ -97,6 +97,10 @@ export type GlobalConfig = {
|
|
|
97
97
|
timezone?: ComputedRef<string | undefined>;
|
|
98
98
|
/** 输入框菜单数据源;消息编辑态的内嵌输入框据此渲染 @ / \ 与 + 号菜单 */
|
|
99
99
|
menuSources?: ComputedRef<IInputMenuItem[]>;
|
|
100
|
+
/** 编辑态内嵌输入框复用主输入框的上传实现 */
|
|
101
|
+
onUpload?: (files: File[]) => Promise<ChatInputUploadResult | ChatInputUploadResult[]>;
|
|
102
|
+
/** 取消编辑态草稿里本次新选的附件;与主输入框 `@delete-file` 同源 */
|
|
103
|
+
onDeleteFile?: (file: Partial<UploadFile>) => void;
|
|
100
104
|
};
|
|
101
105
|
|
|
102
106
|
export function useGlobalConfig(options: GlobalConfig): {
|
|
@@ -104,6 +108,8 @@ export function useGlobalConfig(options: GlobalConfig): {
|
|
|
104
108
|
supportUpload: ComputedRef<boolean>;
|
|
105
109
|
timezone?: ComputedRef<string | undefined>;
|
|
106
110
|
menuSources?: ComputedRef<IInputMenuItem[]>;
|
|
111
|
+
onUpload?: GlobalConfig['onUpload'];
|
|
112
|
+
onDeleteFile?: GlobalConfig['onDeleteFile'];
|
|
107
113
|
};
|
|
108
114
|
|
|
109
115
|
export function injectGlobalConfig(): GlobalConfig | undefined;
|
|
@@ -121,9 +127,10 @@ export function injectGlobalConfig(): GlobalConfig | undefined;
|
|
|
121
127
|
| --------------- | ------------------------------------------------------------------------ |
|
|
122
128
|
| `size` | 可选。字号主题档位 `normal`(14px)/ `small`(12px),与 `ChatContainer.size` 对齐 |
|
|
123
129
|
| `supportUpload` | 是否支持上传,与根容器 `ChatContainer` 的 `supportUpload` 等展示策略对齐 |
|
|
124
|
-
| `menuSources` | 可选。输入框菜单数据源,供消息编辑态的内嵌 `ChatInput` 使用 |
|
|
125
|
-
| `timezone` | 可选。消息时间展示所用的 IANA 时区名,与 `ChatContainer.timezone` 对齐;未配置时 `MessageTime` 按浏览器时区展示 |
|
|
126
130
|
| `menuSources` | 可选。输入框菜单数据源,与 `ChatInput.menuSources` 同源(`ChatContainer` 传入的是补齐会话产物后的结果);[UserMessage](../components/message/user-message) 编辑态据此渲染菜单,未配置时编辑态无菜单 |
|
|
131
|
+
| `timezone` | 可选。消息时间展示所用的 IANA 时区名,与 `ChatContainer.timezone` 对齐;未配置时 `MessageTime` 按浏览器时区展示 |
|
|
132
|
+
| `onUpload` | 可选。编辑态内嵌 `ChatInput` 复用主输入框的上传回调,类型与 `ChatInput.onUpload` 一致 |
|
|
133
|
+
| `onDeleteFile` | 可选。编辑态取消/删除本次新选附件时调用,与主输入框 `@delete-file` 同源 |
|
|
127
134
|
|
|
128
135
|
### `useGlobalConfig(options)`
|
|
129
136
|
|
|
@@ -132,6 +139,8 @@ export function injectGlobalConfig(): GlobalConfig | undefined;
|
|
|
132
139
|
| `options.size` | 可选。字号主题档位,建议使用 `computed(() => props.size ?? 'small')` 与根 props 同步 |
|
|
133
140
|
| `options.supportUpload` | 是否支持上传,建议使用 `computed(() => props.supportUpload ?? false)` 与根 props 同步 |
|
|
134
141
|
| `options.timezone` | 可选。消息时间时区,建议使用 `computed(() => props.timezone)` 与根 props 同步;不设默认值,交由 `MessageTime` 回退浏览器时区 |
|
|
142
|
+
| `options.onUpload` | 可选。建议传入根容器已有的 `onUpload` prop,供编辑态复用 |
|
|
143
|
+
| `options.onDeleteFile` | 可选。建议转发根容器 `deleteFile` 事件,供编辑态清理本次新文件 |
|
|
135
144
|
|
|
136
145
|
- 调用后立即 `provide(GLOBAL_CONFIG_TOKEN, options)`。
|
|
137
146
|
- 必须在具有组件实例上下文的 `setup` 中调用(与 Vue `provide` 要求一致)。
|
|
@@ -151,7 +160,7 @@ export function injectGlobalConfig(): GlobalConfig | undefined;
|
|
|
151
160
|
|
|
152
161
|
## 关联组件
|
|
153
162
|
|
|
154
|
-
- [ChatContainer](../components/setup/chat-container) — 调用 `useGlobalConfig` 注入 `size`、`supportUpload`、`timezone`
|
|
155
|
-
- [UserMessage](../components/message/user-message) — 编辑态读取 `supportUpload` 与 `
|
|
163
|
+
- [ChatContainer](../components/setup/chat-container) — 调用 `useGlobalConfig` 注入 `size`、`supportUpload`、`timezone`、`menuSources` 以及 `onUpload` / `onDeleteFile`
|
|
164
|
+
- [UserMessage](../components/message/user-message) — 编辑态读取 `supportUpload`、`menuSources`、`onUpload` 与 `onDeleteFile`
|
|
156
165
|
- [MessageTime](../components/feedback/message-time) — 读取 `timezone` 展示消息时间
|
|
157
166
|
- [主题配置](../theme/theme) — `data-ai-size` 与 CSS 变量说明
|
|
@@ -72,8 +72,9 @@
|
|
|
72
72
|
defaultUploadFiles: binaryFiles
|
|
73
73
|
menuSources: injectGlobalConfig().menuSources
|
|
74
74
|
#send-icon slot → .user-edit-footer
|
|
75
|
-
Button "取消" → isEdit=false
|
|
76
|
-
Button primary "发送" →
|
|
75
|
+
Button "取消" → 清理本次新上传文件 + isEdit=false
|
|
76
|
+
Button primary "发送" → 有 sendDisabledTip 时禁用并提示;否则 triggerSendMessage(),仅真正发出时 isEdit=false
|
|
77
|
+
onUpload / @delete-file 来自 injectGlobalConfig()(与主输入框同源)
|
|
77
78
|
```
|
|
78
79
|
|
|
79
80
|
## 资源标签回显与正文折叠
|
|
@@ -351,7 +352,9 @@ binaryFiles 有值 → 进入编辑模式(editContent 可为空)
|
|
|
351
352
|
|
|
352
353
|
## 全局配置透传
|
|
353
354
|
|
|
354
|
-
编辑态 `ChatInput` 的上传能力与菜单数据源都来自 `injectGlobalConfig()`——`supportUpload` 与 `
|
|
355
|
+
编辑态 `ChatInput` 的上传能力与菜单数据源都来自 `injectGlobalConfig()`——`supportUpload`、`menuSources`、`onUpload` 与 `onDeleteFile`(通常由 `ChatContainer` 注册)。自定义 `#message` 插槽时须把同一配置链路保留,否则编辑态会与主输入区不一致(菜单为空、无法调用 upload 接口)。
|
|
356
|
+
|
|
357
|
+
删除原消息回填附件(无本地 `File`)只影响即将重发的草稿,不立刻 DELETE 远端;删除本次新选文件或点「取消」时,才对带 `File` 的附件调用 `onDeleteFile`。上传未完成或存在失败项时 `triggerSendMessage` 返回 `false`,保持编辑态;`#send-icon` 的 `sendDisabledTip` 会禁用「发送」并展示拦截文案。成功发送不调用 `onDeleteFile`。
|
|
355
358
|
|
|
356
359
|
```vue
|
|
357
360
|
<template>
|
|
@@ -397,7 +400,7 @@ binaryFiles 有值 → 进入编辑模式(editContent 可为空)
|
|
|
397
400
|
|
|
398
401
|
### 全局配置依赖
|
|
399
402
|
|
|
400
|
-
编辑态 `ChatInput` 通过 `injectGlobalConfig()` 读取 `supportUpload` 与 `menuSources
|
|
403
|
+
编辑态 `ChatInput` 通过 `injectGlobalConfig()` 读取 `supportUpload`、`menuSources`、`onUpload` 与 `onDeleteFile`(`menuSources` 缺省为空数组,即编辑态无菜单)。祖先需已 `useGlobalConfig()`(通常由 `ChatContainer` 注册)。
|
|
401
404
|
|
|
402
405
|
## 类型定义
|
|
403
406
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "2.0.0",
|
|
3
|
-
"generatedAt": "2026-09-
|
|
3
|
+
"generatedAt": "2026-09-23T04:00:43.775Z",
|
|
4
4
|
"domains": {
|
|
5
5
|
"setup": {
|
|
6
6
|
"label": "对话搭建",
|
|
@@ -1881,8 +1881,8 @@
|
|
|
1881
1881
|
"name": "useGlobalConfig",
|
|
1882
1882
|
"slug": "use-global-config",
|
|
1883
1883
|
"kind": "composable",
|
|
1884
|
-
"description": "在聊天根容器与子组件之间通过 provide/inject
|
|
1885
|
-
"aiSummary": "useGlobalConfig 接收 GlobalConfig(含 size
|
|
1884
|
+
"description": "在聊天根容器与子组件之间通过 provide/inject 共享全局展示配置(字号主题档位、是否支持上传、消息时间时区、输入框菜单数据源、编辑态上传/删除回调)。",
|
|
1885
|
+
"aiSummary": "useGlobalConfig 接收 GlobalConfig(含 size、supportUpload、timezone、menuSources、onUpload、onDeleteFile),以 GLOBAL_CONFIG_TOKEN provide 给后代; injectGlobalConfig 在子组件中取出配置,无 Provider 时返回 undefined。ChatContainer 在 setup 中调用 useGlobalConfig 注入 size、supportUpload、timezone、menuSources 以及主输入框同源的 onUpload / onDeleteFile; 后代组件可通过 injectGlobalConfig 读取配置;字号主题主要通过根节点 data-ai-size 与 CSS 变量生效。",
|
|
1886
1886
|
"relatedComponents": [
|
|
1887
1887
|
{
|
|
1888
1888
|
"slug": "chat-container",
|
package/dist/mcp/index.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,26 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blueking/chat-x",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0-beta.1",
|
|
4
4
|
"description": "蓝鲸智云 AI Chat 组件库 —— 遵循 AG-UI,为 AI Agent 和人类开发者共同设计的对话 UI 组件库。",
|
|
5
5
|
"main": "index.js",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"prepublishOnly": "vite --config vite.config.ts build && pnpm dts && pnpm mcp:build",
|
|
8
|
-
"dev": "vite --config vite.config.ts",
|
|
9
|
-
"dts": "vue-tsc --project tsconfig.dts.json",
|
|
10
|
-
"build": "vitest && vite --config vite.config.ts build && pnpm dts",
|
|
11
|
-
"preview": "vite --config vite.config.ts build --mode preview && pnpm dts",
|
|
12
|
-
"lint:script": "eslint . --ext .vue,.ts --fix",
|
|
13
|
-
"lint:style": "stylelint \"**/*.{scss,css,vue}\" --fix",
|
|
14
|
-
"lint:all": "pnpm lint:script && pnpm lint:style",
|
|
15
|
-
"test": "vitest",
|
|
16
|
-
"test:coverage": "vitest run --coverage",
|
|
17
|
-
"wiki:dev": "vitepress dev wikis",
|
|
18
|
-
"wiki:build": "vitepress build wikis",
|
|
19
|
-
"mcp:build:index": "tsx mcp/scripts/build-index.ts",
|
|
20
|
-
"mcp:build": "tsc -p mcp/tsconfig.json && pnpm mcp:build:index",
|
|
21
|
-
"mcp:start": "node dist/mcp/index.js",
|
|
22
|
-
"mcp:dev": "tsx mcp/src/index.ts"
|
|
23
|
-
},
|
|
24
6
|
"bin": {
|
|
25
7
|
"chat-x-mcp": "dist/mcp/index.js"
|
|
26
8
|
},
|
|
@@ -69,7 +51,6 @@
|
|
|
69
51
|
"zod": "^4.3.6"
|
|
70
52
|
},
|
|
71
53
|
"devDependencies": {
|
|
72
|
-
"@blueking/chat-helper": "workspace:*",
|
|
73
54
|
"@types/katex": "^0.16.7",
|
|
74
55
|
"@types/lodash": "^4.17.23",
|
|
75
56
|
"@types/markdown-it": "^14.1.2",
|
|
@@ -98,6 +79,24 @@
|
|
|
98
79
|
"vite-bundle-analyzer": "^1.3.2",
|
|
99
80
|
"vitepress": "2.0.0-alpha.16",
|
|
100
81
|
"vitest": "^4.0.18",
|
|
101
|
-
"vue-tsc": "^3.1.4"
|
|
82
|
+
"vue-tsc": "^3.1.4",
|
|
83
|
+
"@blueking/chat-helper": "2.4.0"
|
|
84
|
+
},
|
|
85
|
+
"scripts": {
|
|
86
|
+
"dev": "vite --config vite.config.ts",
|
|
87
|
+
"dts": "vue-tsc --project tsconfig.dts.json",
|
|
88
|
+
"build": "vitest && vite --config vite.config.ts build && pnpm dts",
|
|
89
|
+
"preview": "vite --config vite.config.ts build --mode preview && pnpm dts",
|
|
90
|
+
"lint:script": "eslint . --ext .vue,.ts --fix",
|
|
91
|
+
"lint:style": "stylelint \"**/*.{scss,css,vue}\" --fix",
|
|
92
|
+
"lint:all": "pnpm lint:script && pnpm lint:style",
|
|
93
|
+
"test": "vitest",
|
|
94
|
+
"test:coverage": "vitest run --coverage",
|
|
95
|
+
"wiki:dev": "vitepress dev wikis",
|
|
96
|
+
"wiki:build": "vitepress build wikis",
|
|
97
|
+
"mcp:build:index": "tsx mcp/scripts/build-index.ts",
|
|
98
|
+
"mcp:build": "tsc -p mcp/tsconfig.json && pnpm mcp:build:index",
|
|
99
|
+
"mcp:start": "node dist/mcp/index.js",
|
|
100
|
+
"mcp:dev": "tsx mcp/src/index.ts"
|
|
102
101
|
}
|
|
103
|
-
}
|
|
102
|
+
}
|
|
@@ -196,7 +196,7 @@ AI 可在一次回复中发起多个工具调用,组件依次渲染:
|
|
|
196
196
|
|
|
197
197
|
### MCP 工具调用
|
|
198
198
|
|
|
199
|
-
`function.
|
|
199
|
+
`function.function_type` 为 `'mcp'`(或旧数据仅有 `mcpName`)时,`ToolCallRender` 头部显示为「调用 MCP {mcpName} / {name}」:
|
|
200
200
|
|
|
201
201
|
```vue
|
|
202
202
|
<script setup lang="ts">
|
|
@@ -205,7 +205,7 @@ AI 可在一次回复中发起多个工具调用,组件依次渲染:
|
|
|
205
205
|
id: 'call_mcp_1',
|
|
206
206
|
type: 'function',
|
|
207
207
|
function: {
|
|
208
|
-
|
|
208
|
+
function_type: 'mcp', // 调用类型,缺省时有 mcpName 也会兼容判定为 MCP
|
|
209
209
|
name: 'query_database',
|
|
210
210
|
arguments: '{"sql": "SELECT * FROM users LIMIT 10"}',
|
|
211
211
|
description: '执行数据库查询',
|
|
@@ -478,6 +478,7 @@ type FunctionCall = {
|
|
|
478
478
|
arguments: string; // JSON 字符串格式的参数
|
|
479
479
|
description?: string; // 函数描述
|
|
480
480
|
mcpName?: string; // MCP 服务名(存在时标题显示 "调用 MCP")
|
|
481
|
+
function_type?: 'function' | 'mcp' | 'skill'; // 调用类型,决定头部前缀;不传时有 mcpName 按 MCP 判定
|
|
481
482
|
};
|
|
482
483
|
|
|
483
484
|
// 工具执行结果
|
|
@@ -101,20 +101,20 @@ isPending = !isSuccess && !isError; // 其余(含 pending / streaming / stop /
|
|
|
101
101
|
|
|
102
102
|
## 调用类型前缀
|
|
103
103
|
|
|
104
|
-
非进行中态的前缀由 `function.
|
|
104
|
+
非进行中态的前缀由 `function.function_type` 决定;进行中态工具 / MCP 显示「正在调用」,Skill 显示「正在读取」:
|
|
105
105
|
|
|
106
|
-
| `function.
|
|
106
|
+
| `function.function_type` | 前缀 | 说明 |
|
|
107
107
|
| ------------------------ | ----------- | ---------------------------------------- |
|
|
108
108
|
| `'function'` / 不传 | 调用工具 | 普通函数调用 |
|
|
109
109
|
| `'mcp'` | 调用 MCP | MCP 调用,通常同时带 `mcpName` |
|
|
110
110
|
| `'skill'` | 读取 Skill | Skill 读取 |
|
|
111
111
|
|
|
112
112
|
```typescript
|
|
113
|
-
const callType = fn?.
|
|
113
|
+
const callType = fn?.function_type ?? (fn?.mcpName ? 'mcp' : 'function');
|
|
114
114
|
```
|
|
115
115
|
|
|
116
|
-
- **旧数据兼容**:未下发 `
|
|
117
|
-
- **`
|
|
116
|
+
- **旧数据兼容**:未下发 `function_type` 时,有 `mcpName` 仍按 MCP 判定,历史消息展示不变
|
|
117
|
+
- **`function_type` 优先**:显式 `function_type: 'function'` 不会被 `mcpName` 覆盖回 MCP,但标题仍是 `{mcpName} / {name}`
|
|
118
118
|
|
|
119
119
|
**三种前缀对比**
|
|
120
120
|
|
|
@@ -191,14 +191,14 @@ const toolCallWithDuration: ToolCall = {
|
|
|
191
191
|
|
|
192
192
|
## MCP 调用
|
|
193
193
|
|
|
194
|
-
`function.
|
|
194
|
+
`function.function_type` 为 `'mcp'`(或旧数据仅有 `mcpName`)时,前缀为「调用 MCP」,标题格式变为 `{mcpName} / {functionName}`:
|
|
195
195
|
|
|
196
196
|
```typescript
|
|
197
197
|
const mcpToolCall: ToolCall = {
|
|
198
198
|
id: 'call_mcp_1',
|
|
199
199
|
type: 'function',
|
|
200
200
|
function: {
|
|
201
|
-
|
|
201
|
+
function_type: 'mcp', // ← 前缀显示「调用 MCP」;缺省时有 mcpName 也会兼容判定为 MCP
|
|
202
202
|
name: 'query_table',
|
|
203
203
|
arguments: JSON.stringify({ table: 'events', limit: 50 }),
|
|
204
204
|
description: '通过 MCP 协议查询蓝鲸数据平台中的事件数据',
|
|
@@ -326,8 +326,8 @@ type FunctionCall = {
|
|
|
326
326
|
name: string; // 函数名;为空时标题 fallback 为 toolCall.id
|
|
327
327
|
arguments: string; // 调用参数(通常为 JSON 字符串)
|
|
328
328
|
description?: string; // 工具描述;为空时"描述"区块保留但内容为空白
|
|
329
|
-
mcpName?: string; // MCP 服务名;有值时标题格式变为 "{mcpName} / {name}",缺省
|
|
330
|
-
|
|
329
|
+
mcpName?: string; // MCP 服务名;有值时标题格式变为 "{mcpName} / {name}",缺省 function_type 时兼容判定为 MCP
|
|
330
|
+
function_type?: FunctionCallType; // 调用类型,决定头部前缀;不传按 mcpName 兼容判定
|
|
331
331
|
};
|
|
332
332
|
|
|
333
333
|
// ToolMessage —— 工具返回消息
|