@blueking/chat-x 2.4.1 → 3.0.0-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.
@@ -200,7 +200,7 @@ AI 可在一次回复中发起多个工具调用,组件依次渲染:
200
200
 
201
201
  ### MCP 工具调用
202
202
 
203
- `function.type` 为 `'mcp'`(或旧数据仅有 `mcpName`)时,`ToolCallRender` 头部显示为「调用 MCP {mcpName} / {name}」:
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
- type: 'mcp', // 调用类型,缺省时有 mcpName 也会兼容判定为 MCP
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
- 点击消息工具栏的「分享」按钮后进入分享模式,底部出现 `SelectionFooter` 操作栏:
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. 编辑态菜单下发**:`menuSources` 经 [useGlobalConfig](/composables/use-global-config) 注入,用户消息进入编辑态时就地渲染的 `ChatInput` 也能拿到同一份数据源。`supportUpload` 同样下发,编辑态输入框也会出现内置「文件」项。
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
- | triggerSendMessage | `() => void` | 手动触发发送逻辑 |
540
+ | getUploadFiles | `() => Partial<UploadFile>[]` | 当前待发送附件快照(编辑态取消时据此清理本次新文件) |
541
+ | triggerSendMessage | `() => Promise<boolean>` | 手动触发发送;真正发出返回 `true`,上传中/失败拦截返回 `false` |
541
542
  | uploadedArtifacts | `AIFileInfo[]` | 已上传且带 `outputId` 的附件列表(只读) |
542
543
 
543
544
  ## 键盘快捷键
@@ -227,7 +227,7 @@ type FunctionCall = {
227
227
  description?: string;
228
228
  mcpName?: string;
229
229
  // 决定 ToolcallRender 头部前缀(调用工具 / 调用 MCP / 读取 Skill)
230
- type?: FunctionCallType;
230
+ function_type?: FunctionCallType;
231
231
  };
232
232
 
233
233
  // 示例
@@ -104,20 +104,20 @@ isPending = !isSuccess && !isError; // 其余(含 pending / streaming / stop /
104
104
 
105
105
  ## 调用类型前缀
106
106
 
107
- 非进行中态的前缀由 `function.type` 决定;进行中态工具 / MCP 显示「正在调用」,Skill 显示「正在读取」:
107
+ 非进行中态的前缀由 `function.function_type` 决定;进行中态工具 / MCP 显示「正在调用」,Skill 显示「正在读取」:
108
108
 
109
- | `function.type` | 前缀 | 说明 |
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?.type ?? (fn?.mcpName ? 'mcp' : 'function');
116
+ const callType = fn?.function_type ?? (fn?.mcpName ? 'mcp' : 'function');
117
117
  ```
118
118
 
119
- - **旧数据兼容**:未下发 `type` 时,有 `mcpName` 仍按 MCP 判定,历史消息展示不变
120
- - **`type` 优先**:显式 `type: 'function'` 不会被 `mcpName` 覆盖回 MCP,但标题仍是 `{mcpName} / {name}`
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.type` 为 `'mcp'`(或旧数据仅有 `mcpName`)时,前缀为「调用 MCP」,标题格式变为 `{mcpName} / {functionName}`:
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
- type: 'mcp', // ← 前缀显示「调用 MCP」;缺省时有 mcpName 也会兼容判定为 MCP
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}",缺省 type 时兼容判定为 MCP
333
- type?: FunctionCallType; // 调用类型,决定头部前缀;不传按 mcpName 兼容判定
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?: ComputedRef<AiSizeMode>、supportUpload: ComputedRef<boolean>、timezone?: ComputedRef<string | undefined>、menuSources?: ComputedRef<IInputMenuItem[]>),以 GLOBAL_CONFIG_TOKEN provide 给后代; injectGlobalConfig 在子组件中取出配置,无 Provider 时返回 undefined。ChatContainer 在 setup 中调用 useGlobalConfig 注入 size、supportUpload、timezone 与 menuSources; 后代组件可通过 injectGlobalConfig 读取配置;字号主题主要通过根节点 data-ai-size 与 CSS 变量生效。
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` 与 `menuSources`
155
- - [UserMessage](../components/message/user-message) — 编辑态读取 `supportUpload` 与 `menuSources`
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 "发送" → chatInputRef.triggerSendMessage() + isEdit=false
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` 与 `menuSources`(通常由 `ChatContainer` 注册)。自定义 `#message` 插槽时须把同一配置链路保留,否则编辑态会与主输入区不一致(菜单为空、无法上传)。
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`(缺省为空数组,即编辑态无菜单)。祖先需已 `useGlobalConfig()`(通常由 `ChatContainer` 注册)。
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-21T11:36:57.667Z",
3
+ "generatedAt": "2026-09-23T07:00:56.590Z",
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?: ComputedRef<AiSizeMode>、supportUpload: ComputedRef<boolean>、timezone?: ComputedRef<string | undefined>、menuSources?: ComputedRef<IInputMenuItem[]>),以 GLOBAL_CONFIG_TOKEN provide 给后代; injectGlobalConfig 在子组件中取出配置,无 Provider 时返回 undefined。ChatContainer 在 setup 中调用 useGlobalConfig 注入 size、supportUpload、timezone 与 menuSources; 后代组件可通过 injectGlobalConfig 读取配置;字号主题主要通过根节点 data-ai-size 与 CSS 变量生效。",
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": "2.4.1",
3
+ "version": "3.0.0-beta.2",
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": "3.0.0-beta.1"
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.type` 为 `'mcp'`(或旧数据仅有 `mcpName`)时,`ToolCallRender` 头部显示为「调用 MCP {mcpName} / {name}」:
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
- type: 'mcp', // 调用类型,缺省时有 mcpName 也会兼容判定为 MCP
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.type` 决定;进行中态工具 / MCP 显示「正在调用」,Skill 显示「正在读取」:
104
+ 非进行中态的前缀由 `function.function_type` 决定;进行中态工具 / MCP 显示「正在调用」,Skill 显示「正在读取」:
105
105
 
106
- | `function.type` | 前缀 | 说明 |
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?.type ?? (fn?.mcpName ? 'mcp' : 'function');
113
+ const callType = fn?.function_type ?? (fn?.mcpName ? 'mcp' : 'function');
114
114
  ```
115
115
 
116
- - **旧数据兼容**:未下发 `type` 时,有 `mcpName` 仍按 MCP 判定,历史消息展示不变
117
- - **`type` 优先**:显式 `type: 'function'` 不会被 `mcpName` 覆盖回 MCP,但标题仍是 `{mcpName} / {name}`
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.type` 为 `'mcp'`(或旧数据仅有 `mcpName`)时,前缀为「调用 MCP」,标题格式变为 `{mcpName} / {functionName}`:
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
- type: 'mcp', // ← 前缀显示「调用 MCP」;缺省时有 mcpName 也会兼容判定为 MCP
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}",缺省 type 时兼容判定为 MCP
330
- type?: FunctionCallType; // 调用类型,决定头部前缀;不传按 mcpName 兼容判定
329
+ mcpName?: string; // MCP 服务名;有值时标题格式变为 "{mcpName} / {name}",缺省 function_type 时兼容判定为 MCP
330
+ function_type?: FunctionCallType; // 调用类型,决定头部前缀;不传按 mcpName 兼容判定
331
331
  };
332
332
 
333
333
  // ToolMessage —— 工具返回消息
@@ -224,7 +224,7 @@ type FunctionCall = {
224
224
  description?: string;
225
225
  mcpName?: string;
226
226
  // 决定 ToolcallRender 头部前缀(调用工具 / 调用 MCP / 读取 Skill)
227
- type?: FunctionCallType;
227
+ function_type?: FunctionCallType;
228
228
  };
229
229
 
230
230
  // 示例