@blueking/chat-x 0.0.47-beta.3 → 0.0.48-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 (30) hide show
  1. package/dist/components/chat-input/chat-input.vue.d.ts +15 -2
  2. package/dist/components/chat-input/input-attachment/input-attachment.vue.d.ts +4 -2
  3. package/dist/components/chat-input/model-selector/capabilities.d.ts +3 -0
  4. package/dist/components/chat-input/model-selector/index.d.ts +3 -0
  5. package/dist/components/chat-input/model-selector/model-selector-panel.vue.d.ts +26 -0
  6. package/dist/components/chat-input/model-selector/model-selector-trigger.vue.d.ts +14 -0
  7. package/dist/components/chat-input/model-selector/model-selector.vue.d.ts +39 -0
  8. package/dist/components/chat-input/model-selector/types.d.ts +61 -0
  9. package/dist/components/chat-input/model-selector/use-model-selector.d.ts +17 -0
  10. package/dist/components/chat-message/message-container/message-container.vue.d.ts +2 -0
  11. package/dist/components/index.d.ts +3 -1
  12. package/dist/icons/input.d.ts +7 -0
  13. package/dist/index.css +1 -1
  14. package/dist/index.js +2147 -1853
  15. package/dist/index.js.map +1 -1
  16. package/dist/lang/lang.d.ts +5 -1
  17. package/dist/mcp/generated/docs/ai-prompt-list.md +6 -3
  18. package/dist/mcp/generated/docs/ai-skill-list.md +75 -0
  19. package/dist/mcp/generated/docs/ai-slash-input.md +17 -3
  20. package/dist/mcp/generated/docs/chat-container.md +189 -74
  21. package/dist/mcp/generated/docs/chat-input.md +79 -5
  22. package/dist/mcp/generated/docs/input-attachment.md +1 -0
  23. package/dist/mcp/generated/docs/message-container.md +47 -0
  24. package/dist/mcp/generated/docs/message-tools.md +5 -1
  25. package/dist/mcp/generated/docs/model-selector.md +157 -0
  26. package/dist/mcp/generated/docs/tool-btn.md +33 -4
  27. package/dist/mcp/generated/index.json +75 -9
  28. package/dist/mcp/index.js +0 -0
  29. package/dist/types/tool.d.ts +6 -2
  30. package/package.json +21 -20
@@ -8,6 +8,7 @@
8
8
  - **shortcut-btn** — 已选快捷指令以单按钮形式展示并可关闭
9
9
  - **shortcut-render** — 快捷指令含 components 时由外层唤起表单渲染
10
10
  - **chat-container** — 顶层聊天布局中作为输入区子组件
11
+ - **model-selector** — 传入 models 后在发送按钮左侧默认展示模型选择器
11
12
  - **cite-content** — 消息引用区展示选中的上下文片段
12
13
 
13
14
  ---
@@ -38,6 +39,7 @@ ai-chat-input-container
38
39
  ├── FileUploadBtn(仅当 supportUpload 为 true 时显示,在 slot#attachment 外部)
39
40
  ├── 分隔线(仅当 supportUpload 为 true 且有快捷指令时显示)
40
41
  ├── slot#attachment(默认:ShortcutBtns 或已选 ShortcutBtn + 关闭图标)
42
+ ├── slot#before-send(默认:传入 models 时渲染 ModelSelector)
41
43
  └── slot#send-icon(默认:发送/停止图标,仅替换图标,按钮容器保留)
42
44
  ```
43
45
 
@@ -183,9 +185,24 @@ const handleSendMessage = async (
183
185
 
184
186
  **渲染效果**(顶部引用区,点击右侧 × 关闭引用)
185
187
 
186
- ## Prompt 模板(`/` 触发)
188
+ ## Skill 列表(`/` 触发)
187
189
 
188
- 通过 `prompts` 传入字符串数组,用户在编辑器中输入 `/` 唤出 Prompt 菜单,支持模糊搜索,选择后自动填入编辑器:
190
+ 通过 `skills` 传入 Skill 列表,用户在编辑器中输入 `/` 唤出 [AiSkillList](/components/input/ai-skill-list) 菜单,支持按名称/编码模糊搜索,选择后以 Skill 标签嵌入编辑器。无 icon 或 icon 加载失败时展示首字母 fallback。已插入的 Skill 不会再出现在下拉菜单中(自动去重)。
191
+
192
+ ```vue
193
+ <script setup lang="ts">
194
+ import type { ISkillListItem } from '@blueking/chat-x';
195
+
196
+ const skills: ISkillListItem[] = [
197
+ { skill_code: 'translate', skill_name: '翻译', description: '翻译文本', icon: '' },
198
+ { skill_code: 'summarize', skill_name: '总结', description: '总结内容', icon: 'https://example.com/icon.png' },
199
+ ];
200
+ </script>
201
+ ```
202
+
203
+ ## Prompt 模板(`\` 触发)
204
+
205
+ 通过 `prompts` 传入字符串数组,用户在编辑器中输入 `\` 唤出 Prompt 菜单,支持模糊搜索,选择后自动填入编辑器:
189
206
 
190
207
  ```vue
191
208
  <script setup lang="ts">
@@ -483,6 +500,57 @@ const handleSendMessage = async (
483
500
 
484
501
  **渲染效果**(顶部自定义模型信息与中断提示)
485
502
 
503
+ ## 模型选择
504
+
505
+ 传入 `models` 后,会在发送按钮左侧展示 [ModelSelector](/components/input/model-selector)。选中值(模型的 `llm_name`)通过 `v-model:selected-model` 双向绑定,`@model-change` 可获取完整模型对象。能力标签由组件依据 `property` 自动派生。
506
+
507
+ ```vue
508
+ <template>
509
+ <ChatInput
510
+ v-model="inputValue"
511
+ v-model:selected-model="selectedModel"
512
+ :message-status="messageStatus"
513
+ :models="models"
514
+ :on-send-message="handleSendMessage"
515
+ @model-change="handleModelChange"
516
+ />
517
+ </template>
518
+
519
+ <script setup lang="ts">
520
+ import { ref } from 'vue';
521
+ import { ChatInput, MessageStatus, type IModelOption, type TagSchema } from '@blueking/chat-x';
522
+
523
+ const inputValue = ref('');
524
+ // 选中值为 llm_name
525
+ const selectedModel = ref('GPT-4');
526
+ const messageStatus = ref(MessageStatus.Complete);
527
+ const models: IModelOption[] = [
528
+ { id: 1, llm_name: 'GPT-4', property: { support_thinking: true } },
529
+ { id: 2, llm_name: 'Claude 3', property: {} },
530
+ ];
531
+
532
+ const handleSendMessage = async (content: string, docSchema: TagSchema) => {
533
+ /* 发送时可读取 selectedModel.value */
534
+ };
535
+
536
+ const handleModelChange = (model: IModelOption) => {
537
+ console.log('切换模型:', model);
538
+ };
539
+ </script>
540
+ ```
541
+
542
+ 也可通过 `#model-selector` 插槽完全自定义选择器,插槽参数为 `{ models, selectedModel }`:
543
+
544
+ ```vue
545
+ <template>
546
+ <ChatInput v-model="inputValue" :models="models">
547
+ <template #model-selector="{ models, selectedModel }">
548
+ <span>当前:{{ selectedModel || '未选择' }}(共 {{ models.length }} 个)</span>
549
+ </template>
550
+ </ChatInput>
551
+ </template>
552
+ ```
553
+
486
554
  ## Expose(模板引用)
487
555
 
488
556
  通过 `ref` 获取组件实例后可调用以下方法:
@@ -517,11 +585,14 @@ const handleSendMessage = async (
517
585
  | 属性名 | 类型 | 默认值 | 必填 | 说明 |
518
586
  | ------------------ | -------------------------------------------------------------------------- | -------- | ---- | ------------------------------------------------------- |
519
587
  | modelValue | `string \| TagSchema` | - | ✅ | 编辑器的值,支持 `v-model` |
588
+ | selectedModel | `string` | - | - | 当前选中模型的 `llm_name`,支持 `v-model:selected-model` |
520
589
  | messageStatus | `MessageStatus` | - | - | 消息状态,控制按钮;输入为空时内部强制 `disabled` |
521
590
  | cite | `string` | `''` | - | 引用内容,支持 `v-model:cite`,不为空时显示引用区 |
522
- | prompts | `string[]` | `[]` | - | Prompt 模板列表,输入 `/` 触发 |
591
+ | skills | `ISkillListItem[]` | `[]` | - | Skill 列表,输入 `/` 触发,选中后插入 Skill 标签 |
592
+ | prompts | `string[]` | `[]` | - | Prompt 模板列表,输入 `\` 触发 |
523
593
  | resources | `IAiSlashMenuItem[]` | `[]` | - | 资源列表,输入 `@` 触发,按 `type` 分组展示 |
524
594
  | shortcuts | `Shortcut[]` | - | - | 快捷指令列表,显示在底部工具栏 |
595
+ | models | `IModelOption[]` | - | - | 可选模型列表,传入后在发送按钮左侧展示模型选择器 |
525
596
  | shortcutId | `string` | - | - | 当前选中的快捷指令 ID,匹配时列表收起为已选样式 |
526
597
  | placeholder | `string` | 见默认值 | - | 编辑器占位符,支持多行 |
527
598
  | inputMaxHeight | `number` | `200` | - | 框体最大高度(px),有文件时自动加上文件预览区高度 |
@@ -536,8 +607,9 @@ const handleSendMessage = async (
536
607
  ### 默认占位符
537
608
 
538
609
  ```
539
- 输入 "/"唤出 Prompt
540
- 输入"@"唤出工具
610
+ 输入 "/" 唤出 Skill
611
+ 输入 "\" 唤出 Prompt
612
+ 输入 "@" 唤出 工具和 MCP
541
613
  通过 Shift + Enter 进行换行输入
542
614
  ```
543
615
 
@@ -546,6 +618,7 @@ const handleSendMessage = async (
546
618
  | 事件名 | 参数 | 触发时机 |
547
619
  | ----------------- | ------------------------------------------------------------------------ | --------------------------------------------------------- |
548
620
  | update:modelValue | `(value: string \| TagSchema, selectedResourceList: IAiSlashMenuItem[])` | 编辑器值变化时触发;第二个参数为当前已选中的 `@` 资源列表 |
621
+ | modelChange | `(model: IModelOption)` | 用户切换模型时触发 |
549
622
  | selectShortcut | `(shortcut: Shortcut)` | 点击底部快捷指令按钮 |
550
623
  | deleteShortcut | - | 点击已选快捷指令旁的关闭按钮 |
551
624
 
@@ -558,6 +631,7 @@ const handleSendMessage = async (
558
631
  | input-header | - | 框体内顶部,替换引用区(`CiteContent`) |
559
632
  | files | `{ files: Partial<UploadFile>[] }` | 文件预览区 |
560
633
  | attachment | - | 底部快捷指令区,`FileUploadBtn` 在其左侧,不受此 slot 影响 |
634
+ | model-selector | `{ models: IModelOption[]; selectedModel: string \| undefined }` | 发送按钮左侧模型选择区,默认渲染 ModelSelector |
561
635
  | send-icon | - | 发送按钮内图标,按钮的点击逻辑和样式仍由组件控制 |
562
636
 
563
637
  ### Expose
@@ -32,6 +32,7 @@ ChatInput 底部附件区布局,承载快捷按钮、文件与发送图标。
32
32
  ### Slots
33
33
 
34
34
  - `default`
35
+ - `before-send`(发送按钮左侧区域,ChatInput 默认在此渲染 ModelSelector)
35
36
  - `send-icon`
36
37
 
37
38
  ### Expose
@@ -301,6 +301,51 @@ AI 回复状态为 `error` 时,消息以错误样式展示:
301
301
 
302
302
  连续多轮问答,组件按角色自动分组,每个 AI 组独立显示工具栏:
303
303
 
304
+ ## 自定义消息工具栏
305
+
306
+ `messageTools`(左侧)与 `updateTools`(右侧反馈区)用于在**内置工具的基础上做增量定制**,无需重写整份列表。二者分别与内置 `CONST_MESSAGE_TOOLS`、`CONST_UPDATE_TOOLS` 按 `id` 合并,规则如下:
307
+
308
+ - **覆盖**:`id` 命中内置项时,做字段级浅合并(仅覆盖传入的字段,其余保留),不新增条目
309
+ - **追加**:`id` 为内置列表中不存在的新值时,追加到该组末尾(如自定义「保存」「收藏」按钮)
310
+ - **隐藏**:传入 `{ id: 'xxx', hidden: true }` 可移除对应内置项(如隐藏「分享」)
311
+ - **自定义图标**:通过 `icon`(组件/VNode)为自定义按钮提供图标,优先级高于内置 `ToolIconsMap`
312
+ - 不传 `messageTools` / `updateTools` 时,各自使用内置默认列表
313
+
314
+ ```vue
315
+ <template>
316
+ <MessageContainer
317
+ :messages="messages"
318
+ :message-groups="messageGroups"
319
+ message-status="complete"
320
+ :message-tools="customMessageTools"
321
+ :update-tools="customUpdateTools"
322
+ :on-agent-action="handleAgentAction"
323
+ @stop-streaming="handleStopStreaming"
324
+ />
325
+ </template>
326
+
327
+ <script setup lang="ts">
328
+ import { MessageContainer, DownloadIcon, type IToolBtn, type Message } from '@blueking/chat-x';
329
+
330
+ const customMessageTools: IToolBtn[] = [
331
+ { id: 'save', name: '保存', description: '保存该回答', icon: DownloadIcon }, // 追加新按钮
332
+ { id: 'copy', description: '复制全文' }, // 覆盖内置 copy 的 description
333
+ { id: 'share', hidden: true }, // 隐藏内置「分享」
334
+ ];
335
+ const customUpdateTools: IToolBtn[] = [
336
+ { id: 'collect', name: '收藏', description: '收藏到我的空间', icon: DownloadIcon },
337
+ ];
338
+
339
+ const handleAgentAction = async (tool: IToolBtn, messages: Message[]) => {
340
+ if (tool.id === 'save') {
341
+ // 处理保存
342
+ }
343
+ };
344
+ </script>
345
+ ```
346
+
347
+ > **合并优先级**:`RenderMode.Test` 下仍会额外过滤掉「分享」按钮(即便合并后存在);即测试模式对 `share` 的过滤在自定义合并之后生效。
348
+
304
349
  ## 工具栏状态控制
305
350
 
306
351
  通过 `messageToolsStatus` 控制消息工具栏的显示状态。常见用法:流式输出期间禁用工具栏:
@@ -501,6 +546,8 @@ AI 回复状态为 `error` 时,消息以错误样式展示:
501
546
  | messages | `Message[]` | — | **必填**,消息列表 |
502
547
  | messageGroups | `MessageGroup[]` | — | 预计算的消息分组;传入时跳过内部分组逻辑,由 `ChatContainer` 通过 `useMessageGroup` 提供 |
503
548
  | messageStatus | `MessageStatus` | — | 当前整体消息状态,控制底部「停止生成」按钮显示;`ChatContainer` 会结合末尾 Loading 占位推导 `fetching` 等再传入 |
549
+ | messageTools | `IToolBtn[]` | — | AI 消息左侧工具(复制/引用等)的自定义配置;按 `id` 与内置 `CONST_MESSAGE_TOOLS` 合并(覆盖同 id、追加新 id、`hidden` 过滤),详见「自定义消息工具栏」 |
550
+ | updateTools | `IToolBtn[]` | — | AI 消息右侧反馈工具(点赞/踩/删除等)的自定义配置;按 `id` 与内置 `CONST_UPDATE_TOOLS` 合并,规则同上 |
504
551
  | messageToolsStatus | `MessageToolsStatus` | — | 工具栏状态,透传给 `MessageTools` 和 `MessageRender` |
505
552
  | messageToolsTippyOptions | `AITippyProps` | — | 透传给 `MessageTools` 和 `MessageRender`(进而透传给 `UserMessage` 的工具栏)的 Tippy 配置,用于自定义 tooltip 挂载点、位置等(如 `appendTo`、`placement`、`zIndex`) |
506
553
  | enableSelection | `boolean` | `false` | 是否启用多选模式 |
@@ -361,11 +361,15 @@ const CONST_UPDATE_TOOLS = [
361
361
 
362
362
  ```typescript
363
363
  import { MessageToolsStatus, type IToolBtn } from '@blueking/chat-x';
364
+ import type { Component, VNode } from 'vue';
364
365
 
365
366
  interface IToolBtn {
366
- id?: keyof typeof ToolIconsMap; // 工具唯一标识;与 ToolIconsMap 匹配时显示内置图标,否则显示 name 文本
367
+ id?: (string & {}) | ToolIcons; // 工具唯一标识;命中 ToolIconsMap 显示内置图标,否则显示 name 文本;支持业务自定义字符串
367
368
  name?: string; // 工具名称,无对应图标时显示;也用作 tooltip fallback
368
369
  description?: string; // tooltip 文本
370
+ icon?: Component | VNode; // 自定义图标(组件/VNode),优先级高于内置 ToolIconsMap[id]
371
+ hidden?: boolean; // 按 id 合并时隐藏该按钮(仅在 MessageContainer/ChatContainer 合并语义下生效)
372
+ triggerSelection?: boolean; // 标记点击后进入多选态(复用 share 选择流程),确认走 confirmShare
369
373
  }
370
374
 
371
375
  enum MessageToolsStatus {
@@ -0,0 +1,157 @@
1
+ <!-- AI SUMMARY -->
2
+ ## 快速了解
3
+
4
+ 聊天输入区的模型下拉选择器,支持搜索过滤、能力标签与键盘导航。 源码位置:src/components/chat-input/model-selector/model-selector.vue。
5
+
6
+ ### 关联组件
7
+ - **chat-input** — 传入 models 后在发送按钮左侧默认渲染
8
+ - **input-attachment** — 通过 before-send 插槽与发送按钮成组布局
9
+
10
+ ---
11
+ <!-- FULL DOC -->
12
+
13
+ # ModelSelector 模型选择器
14
+
15
+ ## 源码事实
16
+
17
+ - **源码位置**:`src/components/chat-input/model-selector/model-selector.vue`
18
+ - **能力域**:输入交互
19
+ - **能力说明**:基于 Tippy 下拉的模型选择器,包含触发器、搜索面板与能力标签展示;数据过滤逻辑由 `useModelSelector` composable 承担。
20
+
21
+ > **能力域**:输入交互
22
+
23
+ 可在 [ChatInput](/components/input/chat-input) 传入 `models` 后自动出现在发送按钮左侧,也可单独使用。
24
+
25
+ ## 组件结构
26
+
27
+ ```
28
+ ModelSelector(Tippy 容器,theme: ai-model-selector)
29
+ ├── ModelSelectorTrigger(触发器:图标 + 名称 + 箭头)
30
+ └── ModelSelectorPanel(下拉面板)
31
+ ├── 搜索框(展开后自动聚焦)
32
+ └── 模型列表(支持键盘导航、选中态、禁用态、能力标签)
33
+ ```
34
+
35
+ ## 基础用法
36
+
37
+ 选中值为模型的 `llm_name`;能力标签由组件依据 `property`(`support_thinking` / `support_thinking_quick` / `support_vision`)自动派生,无需调用方传入。
38
+
39
+ ```vue
40
+ <template>
41
+ <ModelSelector
42
+ v-model="selectedModel"
43
+ :models="models"
44
+ @change="handleModelChange"
45
+ />
46
+ </template>
47
+
48
+ <script setup lang="ts">
49
+ import { ref } from 'vue';
50
+ import { ModelSelector, type IModelOption } from '@blueking/chat-x';
51
+
52
+ // 选中值为 llm_name
53
+ const selectedModel = ref('DeepSeek-V4-Pro-Online-32k');
54
+ const models: IModelOption[] = [
55
+ {
56
+ id: 119,
57
+ llm_code: 'DeepSeek-V4-Pro-Online-32k',
58
+ llm_name: 'DeepSeek-V4-Pro-Online-32k',
59
+ llm_type: 'chat.completion',
60
+ space_auth_mode: 'APPLY',
61
+ user_auth_mode: 'PUBLIC',
62
+ max_token_size: 4096,
63
+ icon: 'https://example.com/deepseek.png',
64
+ description: 'DeepSeek-V4-Pro 旗舰版本,支持超长上下文与复杂任务处理',
65
+ base_model: 'deepseek',
66
+ tag_names: [],
67
+ // support_thinking → 深度思考、support_vision → 图生文
68
+ property: { support_thinking: true, support_vision: true, max_model_len: 32000 },
69
+ },
70
+ ];
71
+
72
+ const handleModelChange = (model: IModelOption) => {
73
+ console.log('选中模型:', model);
74
+ };
75
+ </script>
76
+ ```
77
+
78
+ ## API
79
+
80
+ ### Props
81
+
82
+ | 属性名 | 类型 | 默认值 | 说明 |
83
+ | ----------------- | -------------------------------------------------------------------------- | ---------------- | -------------------------------------- |
84
+ | disabled | `boolean` | `false` | 是否禁用整个选择器 |
85
+ | models | `IModelOption[]` | `[]` | 可选模型列表 |
86
+ | placeholder | `string` | `选择模型` | trigger 无选中时的占位文案 |
87
+ | searchPlaceholder | `string` | `搜索模型关键字` | 搜索框占位文案 |
88
+ | tippyOptions | `Partial<Omit<TippyOptions, 'getReferenceClientRect' \| 'triggerTarget'>>` | — | 透传给 Tippy 的额外配置 |
89
+
90
+ ### v-model
91
+
92
+ | 属性名 | 类型 | 说明 |
93
+ | ------ | -------- | ----------------------------- |
94
+ | — | `string` | 当前选中模型的 `llm_name` 值 |
95
+
96
+ ### Events
97
+
98
+ | 事件名 | 参数 | 说明 |
99
+ | ------ | ----------------------- | -------------------- |
100
+ | change | `(model: IModelOption)` | 用户选中模型时触发 |
101
+
102
+ ## 类型定义
103
+
104
+ ```typescript
105
+ import type { IModelCapability, IModelOption, IModelProperty, ModelCapabilityTheme } from '@blueking/chat-x';
106
+
107
+ type ModelCapabilityTheme = 'default' | 'primary' | 'success' | 'warning';
108
+
109
+ // 能力标签由组件依据 property 派生(文案走内置 i18n)
110
+ interface IModelCapability {
111
+ theme?: ModelCapabilityTheme;
112
+ text: string;
113
+ }
114
+
115
+ // 模型能力属性,决定派生出的能力标签
116
+ interface IModelProperty {
117
+ agent_type?: string;
118
+ default?: boolean;
119
+ is_self_host?: boolean;
120
+ max_model_len?: number;
121
+ support_summary?: boolean;
122
+ support_thinking?: boolean; // → 深度思考
123
+ support_thinking_quick?: boolean; // → 快速思考
124
+ support_tools?: boolean;
125
+ support_vision?: boolean; // → 图生文
126
+ support_window?: boolean;
127
+ }
128
+
129
+ // 模型选项,贴合后端模型接口结构
130
+ interface IModelOption {
131
+ base_model?: string;
132
+ description?: string; // 选项 hover 的 title 提示
133
+ disabled?: boolean; // 前端扩展字段,禁用项不可选中
134
+ icon?: string;
135
+ id: number;
136
+ llm_code: string;
137
+ llm_name: string; // 展示名,同时作为选中值
138
+ llm_type: string;
139
+ max_token_size: number;
140
+ property: IModelProperty;
141
+ space_auth_mode: string;
142
+ tag_names?: string[];
143
+ user_auth_mode: string;
144
+ }
145
+ ```
146
+
147
+ ## 注意事项
148
+
149
+ 1. `models` 为空或 `disabled` 为 `true` 时,下拉不会展开。
150
+ 2. 选中值为模型的 `llm_name`;能力标签由组件依据 `property` 的 `support_thinking` / `support_thinking_quick` / `support_vision` 派生,文案走内置 i18n。
151
+ 3. `description` 会作为选项 hover 的 `title` 提示展示。
152
+ 4. 展开面板后会自动聚焦搜索框;列表支持键盘上下选择与 Enter 确认(复用 `useMenuKeydown`)。
153
+
154
+ ## 关联组件
155
+
156
+ - [ChatInput](/components/input/chat-input):传入 `models` 后默认在发送按钮左侧渲染本组件,也可通过 `#model-selector` 插槽完全自定义。
157
+ - [ChatContainer](/components/setup/chat-container):透传 `models` 与 `v-model:selected-model`,并向上 emit `modelChange`。
@@ -30,8 +30,9 @@ div.ai-tool-btn(v-tippy,flex,min-width: 20px,height: 20px,border-radiu
30
30
  disabled=true → .is-disabled(color: #979ba5; cursor: not-allowed)
31
31
  :not(.is-disabled):hover → color: #4d4f56; background: #eaebf0
32
32
 
33
- └── <slot>(默认内容,可完全自定义)
34
- ├── [id && id in ToolIconsMap] → <component :is="ToolIconsMap[id]" />(SVG 图标)
33
+ └── <slot>(默认内容,可完全自定义;优先级最高)
34
+ ├── [icon] → <component :is="icon" />(自定义图标组件/VNode,优先级高于内置图标)
35
+ ├── [id && id in ToolIconsMap] → <component :is="ToolIconsMap[id]" />(内置 SVG 图标)
35
36
  └── [其他] → <div>{{ name }}</div>(文本回退,XSS 安全)
36
37
 
37
38
  Tippy:content=description, theme='ai-chat-box', disabled=true 时 onShow 返回 false 不显示
@@ -195,6 +196,28 @@ click 事件:disabled=true 时被 JS 拦截,不触发 emit
195
196
 
196
197
  `id` 不在 `ToolIconsMap` 时渲染 `name` 文本,适用于自定义扩展场景:
197
198
 
199
+ ## 自定义图标(icon 属性)
200
+
201
+ 当内置 `ToolIconsMap` 未覆盖所需图标时,可通过 `icon` 传入自定义图标组件或 VNode(如业务新增的「保存」按钮)。`icon` 的渲染优先级高于内置图标,因此即便 `id` 命中内置图标,也会以 `icon` 为准。
202
+
203
+ ```vue
204
+ <template>
205
+ <ToolBtn
206
+ id="save"
207
+ name="保存"
208
+ description="保存该回答"
209
+ :icon="DownloadIcon"
210
+ @click="handleClick"
211
+ />
212
+ </template>
213
+
214
+ <script setup lang="ts">
215
+ import { ToolBtn, DownloadIcon } from '@blueking/chat-x';
216
+ </script>
217
+ ```
218
+
219
+ > 优先级从高到低:默认插槽 `>` `icon` 属性 `>` 内置 `ToolIconsMap[id]` `>` `name` 文本回退。
220
+
198
221
  ## 自定义插槽内容
199
222
 
200
223
  通过默认插槽可完全替换内置图标/文本,适用于预置 `ToolIconsMap` 未覆盖的图标场景(如侧栏全屏按钮):
@@ -225,9 +248,10 @@ click 事件:disabled=true 时被 JS 拦截,不触发 emit
225
248
 
226
249
  | 属性名 | 类型 | 必填 | 默认值 | 说明 |
227
250
  | ------------ | -------------------------------------------------------------------------- | ---- | ------ | ------------------------------------------------------------------------------------------------------------------ |
228
- | id | `keyof typeof ToolIconsMap` | 否 | — | 按钮标识;在 `ToolIconsMap` 中时渲染对应 SVG 图标,否则渲染 `name` 文本;使用插槽自定义内容时可省略 |
251
+ | id | `(string & {}) \| ToolIcons` | 否 | — | 按钮标识;命中 `ToolIconsMap` 时渲染对应 SVG 图标,否则渲染 `name` 文本;支持业务自定义任意字符串(如 `save`) |
229
252
  | name | `string` | 否 | — | 按钮名称;`id` 无对应图标时作为文本内容渲染 |
230
253
  | description | `string` | 否 | — | Tippy tooltip 内容;`disabled=true` 时不显示 tooltip |
254
+ | icon | `Component \| VNode` | 否 | — | 自定义图标组件或 VNode;优先级高于内置 `ToolIconsMap[id]`,低于默认插槽 |
231
255
  | active | `boolean` | 否 | — | 激活态;`true` 时追加 `.is-active`(字色由 `id` 决定:`like`/`activeLike` 为蓝色 `#3a84ff`,其他为红色 `#E71818`) |
232
256
  | disabled | `boolean` | 否 | — | 禁用态;`true` 时追加 `.is-disabled`,阻止 click 事件,隐藏 tooltip |
233
257
  | tippyOptions | `Partial<Omit<TippyOptions, 'getReferenceClientRect' \| 'triggerTarget'>>` | 否 | — | 自定义 Tippy 配置,与内部默认配置合并;可用于控制 `content`、`appendTo`、`placement` 等 |
@@ -247,11 +271,16 @@ click 事件:disabled=true 时被 JS 拦截,不触发 emit
247
271
  ## 类型定义
248
272
 
249
273
  ```typescript
274
+ import type { Component, VNode } from 'vue';
275
+
250
276
  // 来自 @blueking/chat-x 导出
251
277
  interface IToolBtn {
252
- id?: keyof typeof ToolIconsMap; // 预置 ID;省略时走 name 文本或插槽
278
+ id?: (string & {}) | ToolIcons; // 内置 ID 保留自动补全,同时允许业务自定义任意字符串(如 'save')
253
279
  name?: string;
254
280
  description?: string;
281
+ icon?: Component | VNode; // 自定义图标,优先级高于内置 ToolIconsMap
282
+ hidden?: boolean; // 按 id 合并时隐藏该按钮(如 { id: 'share', hidden: true } 移除内置项)
283
+ triggerSelection?: boolean; // 标记点击后进入多选态(复用 share 选择流程),确认走 confirmShare
255
284
  }
256
285
 
257
286
  // ToolBtn 完整 Props
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": "2.0.0",
3
- "generatedAt": "2026-07-14T03:37:54.931Z",
3
+ "generatedAt": "2026-07-27T02:31:49.169Z",
4
4
  "domains": {
5
5
  "setup": {
6
6
  "label": "对话搭建",
@@ -44,6 +44,7 @@
44
44
  "components": [
45
45
  "ai-prompt-list",
46
46
  "ai-selection",
47
+ "ai-skill-list",
47
48
  "ai-slash-editor",
48
49
  "ai-slash-input",
49
50
  "ai-slash-menu",
@@ -51,6 +52,7 @@
51
52
  "file-upload-btn",
52
53
  "input-attachment",
53
54
  "input-info-alert",
55
+ "model-selector",
54
56
  "selection-footer",
55
57
  "shortcut-btn",
56
58
  "shortcut-btns",
@@ -671,9 +673,14 @@
671
673
  "name": "AiPromptList Prompt 列表",
672
674
  "slug": "ai-prompt-list",
673
675
  "kind": "component",
674
- "description": "/ Prompt 选择列表,供 AiSlashInput 插入模板文本。",
675
- "aiSummary": "/ Prompt 选择列表,供 AiSlashInput 插入模板文本。 源码位置:src/components/chat-input/ai-slash-input/ai-prompt-list/ai-prompt-list.vue。",
676
- "relatedComponents": [],
676
+ "description": "\\ Prompt 选择列表,供 AiSlashInput 插入模板文本。",
677
+ "aiSummary": "\\ Prompt 选择列表,供 AiSlashInput 插入模板文本。 源码位置:src/components/chat-input/ai-slash-input/ai-prompt-list/ai-prompt-list.vue。",
678
+ "relatedComponents": [
679
+ {
680
+ "slug": "ai-slash-input",
681
+ "relation": "输入 \\ 时由 AiSlashInput tippy 菜单渲染"
682
+ }
683
+ ],
677
684
  "docFile": "docs/ai-prompt-list.md",
678
685
  "domain": "input"
679
686
  },
@@ -696,6 +703,25 @@
696
703
  "docFile": "docs/ai-selection.md",
697
704
  "domain": "input"
698
705
  },
706
+ {
707
+ "name": "AiSkillList Skill 列表",
708
+ "slug": "ai-skill-list",
709
+ "kind": "component",
710
+ "description": "/ Skill 选择列表,供 AiSlashInput 插入 Skill 标签。",
711
+ "aiSummary": "/ Skill 选择列表,供 AiSlashInput 插入 Skill 标签。 无 icon 或 icon 加载失败时展示 skill_name 首字母 fallback。 源码位置:src/components/chat-input/ai-slash-input/ai-skill-list/ai-skill-list.vue。",
712
+ "relatedComponents": [
713
+ {
714
+ "slug": "ai-slash-input",
715
+ "relation": "输入 / 时由 AiSlashInput tippy 菜单渲染"
716
+ },
717
+ {
718
+ "slug": "chat-input",
719
+ "relation": "经 ChatInput.skills 透传数据源"
720
+ }
721
+ ],
722
+ "docFile": "docs/ai-skill-list.md",
723
+ "domain": "input"
724
+ },
699
725
  {
700
726
  "name": "AiSlashEditor 富文本编辑器",
701
727
  "slug": "ai-slash-editor",
@@ -710,9 +736,22 @@
710
736
  "name": "AiSlashInput 富文本命令输入",
711
737
  "slug": "ai-slash-input",
712
738
  "kind": "component",
713
- "description": "ChatInput 内部富文本输入,支持 / Prompt 与 @ 资源标签。",
714
- "aiSummary": "ChatInput 内部富文本输入,支持 / Prompt 与 @ 资源标签。 源码位置:src/components/chat-input/ai-slash-input/ai-slash-input.vue。",
715
- "relatedComponents": [],
739
+ "description": "ChatInput 内部富文本输入,支持 / Skill、\\ Prompt 与 @ 资源标签。",
740
+ "aiSummary": "ChatInput 内部富文本输入,支持 / Skill、\\ Prompt 与 @ 资源标签。 源码位置:src/components/chat-input/ai-slash-input/ai-slash-input.vue。",
741
+ "relatedComponents": [
742
+ {
743
+ "slug": "ai-skill-list",
744
+ "relation": "输入 / 时渲染 Skill 选择列表"
745
+ },
746
+ {
747
+ "slug": "ai-prompt-list",
748
+ "relation": "输入 \\ 时渲染 Prompt 选择列表"
749
+ },
750
+ {
751
+ "slug": "ai-slash-menu",
752
+ "relation": "输入 @ 时渲染资源选择菜单"
753
+ }
754
+ ],
716
755
  "docFile": "docs/ai-slash-input.md",
717
756
  "domain": "input"
718
757
  },
@@ -749,6 +788,10 @@
749
788
  "slug": "chat-container",
750
789
  "relation": "顶层聊天布局中作为输入区子组件"
751
790
  },
791
+ {
792
+ "slug": "model-selector",
793
+ "relation": "传入 models 后在发送按钮左侧默认展示模型选择器"
794
+ },
752
795
  {
753
796
  "slug": "cite-content",
754
797
  "relation": "消息引用区展示选中的上下文片段"
@@ -796,6 +839,25 @@
796
839
  "docFile": "docs/input-info-alert.md",
797
840
  "domain": "input"
798
841
  },
842
+ {
843
+ "name": "ModelSelector 模型选择器",
844
+ "slug": "model-selector",
845
+ "kind": "component",
846
+ "description": "聊天输入区的模型下拉选择器,支持搜索过滤、能力标签与键盘导航。",
847
+ "aiSummary": "聊天输入区的模型下拉选择器,支持搜索过滤、能力标签与键盘导航。 源码位置:src/components/chat-input/model-selector/model-selector.vue。",
848
+ "relatedComponents": [
849
+ {
850
+ "slug": "chat-input",
851
+ "relation": "传入 models 后在发送按钮左侧默认渲染"
852
+ },
853
+ {
854
+ "slug": "input-attachment",
855
+ "relation": "通过 before-send 插槽与发送按钮成组布局"
856
+ }
857
+ ],
858
+ "docFile": "docs/model-selector.md",
859
+ "domain": "input"
860
+ },
799
861
  {
800
862
  "name": "SelectionFooter 多选操作栏",
801
863
  "slug": "selection-footer",
@@ -1393,8 +1455,8 @@
1393
1455
  "name": "ChatContainer 聊天容器",
1394
1456
  "slug": "chat-container",
1395
1457
  "kind": "component",
1396
- "description": "完整对话容器,组合消息列表、输入区、快捷指令、执行摘要、分享选择和自定义 Tab。",
1397
- "aiSummary": "完整对话容器,组合消息列表、输入区、快捷指令、执行摘要、分享选择和自定义 Tab。 源码位置:src/components/chat-container/chat-container.vue。",
1458
+ "description": "完整对话容器,组合消息列表、输入区、模型选择、快捷指令、执行摘要、分享选择和自定义 Tab。",
1459
+ "aiSummary": "完整对话容器,组合消息列表、输入区、模型选择、快捷指令、执行摘要、分享选择和自定义 Tab。 透传 models / selectedModel;支持 welcomeTitle 与 #welcome。 源码位置:src/components/chat-container/chat-container.vue。",
1398
1460
  "relatedComponents": [
1399
1461
  {
1400
1462
  "slug": "message-container",
@@ -1404,6 +1466,10 @@
1404
1466
  "slug": "chat-input",
1405
1467
  "relation": "对话输入与快捷指令入口"
1406
1468
  },
1469
+ {
1470
+ "slug": "model-selector",
1471
+ "relation": "透传 models / selectedModel,在输入区展示模型选择器"
1472
+ },
1407
1473
  {
1408
1474
  "slug": "shortcut-render",
1409
1475
  "relation": "快捷指令表单浮层"
package/dist/mcp/index.js CHANGED
File without changes
@@ -1,4 +1,5 @@
1
- import type { ToolIconsMap } from '../icons/tools';
1
+ import type { Component, VNode } from 'vue';
2
+ import type { ToolIcons } from '../icons/tools';
2
3
  import type { TippyOptions } from 'vue-tippy';
3
4
  export declare enum MessageToolsStatus {
4
5
  Disabled = "disabled",// 禁用
@@ -7,6 +8,9 @@ export declare enum MessageToolsStatus {
7
8
  export type AITippyProps = Partial<Pick<TippyOptions, 'appendTo' | 'placement' | 'zIndex'>>;
8
9
  export interface IToolBtn {
9
10
  description?: string;
10
- id?: keyof typeof ToolIconsMap;
11
+ hidden?: boolean;
12
+ icon?: Component | VNode;
13
+ id?: (string & {}) | ToolIcons;
11
14
  name?: string;
15
+ triggerSelection?: boolean;
12
16
  }