@huyooo/ai-chat-frontend-vue 0.1.4 → 0.1.7
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/README.md +367 -0
- package/dist/adapter.d.ts +7 -7
- package/dist/adapter.d.ts.map +1 -1
- package/dist/components/ChatPanel.vue.d.ts +120 -9
- package/dist/components/ChatPanel.vue.d.ts.map +1 -1
- package/dist/components/common/ConfirmDialog.vue.d.ts +30 -0
- package/dist/components/common/ConfirmDialog.vue.d.ts.map +1 -0
- package/dist/components/common/CopyButton.vue.d.ts +18 -0
- package/dist/components/common/CopyButton.vue.d.ts.map +1 -0
- package/dist/components/common/IndexingSettings.vue.d.ts +3 -0
- package/dist/components/common/IndexingSettings.vue.d.ts.map +1 -0
- package/dist/components/common/SettingsPanel.vue.d.ts +16 -0
- package/dist/components/common/SettingsPanel.vue.d.ts.map +1 -0
- package/dist/components/common/Toast.vue.d.ts +18 -0
- package/dist/components/common/Toast.vue.d.ts.map +1 -0
- package/dist/components/common/ToggleSwitch.vue.d.ts +10 -0
- package/dist/components/common/ToggleSwitch.vue.d.ts.map +1 -0
- package/dist/components/{chat/ui → header}/ChatHeader.vue.d.ts +5 -3
- package/dist/components/header/ChatHeader.vue.d.ts.map +1 -0
- package/dist/components/input/AtFilePicker.vue.d.ts +21 -0
- package/dist/components/input/AtFilePicker.vue.d.ts.map +1 -0
- package/dist/components/{ChatInput.vue.d.ts → input/ChatInput.vue.d.ts} +16 -14
- package/dist/components/input/ChatInput.vue.d.ts.map +1 -0
- package/dist/components/input/DropdownSelector.vue.d.ts +42 -0
- package/dist/components/input/DropdownSelector.vue.d.ts.map +1 -0
- package/dist/components/input/ImagePreviewModal.vue.d.ts +17 -0
- package/dist/components/input/ImagePreviewModal.vue.d.ts.map +1 -0
- package/dist/components/input/at-views/AtBranchView.vue.d.ts +18 -0
- package/dist/components/input/at-views/AtBranchView.vue.d.ts.map +1 -0
- package/dist/components/input/at-views/AtBrowserView.vue.d.ts +18 -0
- package/dist/components/input/at-views/AtBrowserView.vue.d.ts.map +1 -0
- package/dist/components/input/at-views/AtChatsView.vue.d.ts +18 -0
- package/dist/components/input/at-views/AtChatsView.vue.d.ts.map +1 -0
- package/dist/components/input/at-views/AtDocsView.vue.d.ts +18 -0
- package/dist/components/input/at-views/AtDocsView.vue.d.ts.map +1 -0
- package/dist/components/input/at-views/AtFilesView.vue.d.ts +23 -0
- package/dist/components/input/at-views/AtFilesView.vue.d.ts.map +1 -0
- package/dist/components/input/at-views/AtTerminalsView.vue.d.ts +18 -0
- package/dist/components/input/at-views/AtTerminalsView.vue.d.ts.map +1 -0
- package/dist/components/message/MessageBubble.vue.d.ts +45 -0
- package/dist/components/message/MessageBubble.vue.d.ts.map +1 -0
- package/dist/components/message/PartsRenderer.vue.d.ts +15 -0
- package/dist/components/message/PartsRenderer.vue.d.ts.map +1 -0
- package/dist/components/message/WelcomeMessage.vue.d.ts +14 -0
- package/dist/components/message/WelcomeMessage.vue.d.ts.map +1 -0
- package/dist/components/message/blocks/CodeBlock.vue.d.ts +11 -0
- package/dist/components/message/blocks/CodeBlock.vue.d.ts.map +1 -0
- package/dist/components/{chat/SearchResultBlock.vue.d.ts → message/blocks/TextBlock.vue.d.ts} +3 -4
- package/dist/components/message/blocks/TextBlock.vue.d.ts.map +1 -0
- package/dist/components/message/blocks/index.d.ts +6 -0
- package/dist/components/message/blocks/index.d.ts.map +1 -0
- package/dist/components/message/parts/CollapsibleCard.vue.d.ts +45 -0
- package/dist/components/message/parts/CollapsibleCard.vue.d.ts.map +1 -0
- package/dist/components/{chat/ToolCallBlock.vue.d.ts → message/parts/ErrorPart.vue.d.ts} +4 -5
- package/dist/components/message/parts/ErrorPart.vue.d.ts.map +1 -0
- package/dist/components/{chat/ThinkingBlock.vue.d.ts → message/parts/ImagePart.vue.d.ts} +3 -3
- package/dist/components/message/parts/ImagePart.vue.d.ts.map +1 -0
- package/dist/components/message/parts/SearchPart.vue.d.ts +12 -0
- package/dist/components/message/parts/SearchPart.vue.d.ts.map +1 -0
- package/dist/components/{chat/messages/ExecutionSteps.vue.d.ts → message/parts/TextPart.vue.d.ts} +2 -9
- package/dist/components/message/parts/TextPart.vue.d.ts.map +1 -0
- package/dist/components/message/parts/ThinkingPart.vue.d.ts +12 -0
- package/dist/components/message/parts/ThinkingPart.vue.d.ts.map +1 -0
- package/dist/components/message/parts/ToolCallPart.vue.d.ts +19 -0
- package/dist/components/message/parts/ToolCallPart.vue.d.ts.map +1 -0
- package/dist/components/message/parts/ToolResultPart.vue.d.ts +14 -0
- package/dist/components/message/parts/ToolResultPart.vue.d.ts.map +1 -0
- package/dist/components/message/parts/index.d.ts +12 -0
- package/dist/components/message/parts/index.d.ts.map +1 -0
- package/dist/components/message/tool-results/DefaultToolResult.vue.d.ts +4 -0
- package/dist/components/message/tool-results/DefaultToolResult.vue.d.ts.map +1 -0
- package/dist/components/message/tool-results/SearchResults.vue.d.ts +4 -0
- package/dist/components/message/tool-results/SearchResults.vue.d.ts.map +1 -0
- package/dist/components/message/tool-results/WeatherCard.vue.d.ts +4 -0
- package/dist/components/message/tool-results/WeatherCard.vue.d.ts.map +1 -0
- package/dist/components/message/tool-results/index.d.ts +7 -0
- package/dist/components/message/tool-results/index.d.ts.map +1 -0
- package/dist/components/message/welcome-types.d.ts +28 -0
- package/dist/components/message/welcome-types.d.ts.map +1 -0
- package/dist/composables/useChat.d.ts +99 -44
- package/dist/composables/useChat.d.ts.map +1 -1
- package/dist/composables/useImageUpload.d.ts +55 -0
- package/dist/composables/useImageUpload.d.ts.map +1 -0
- package/dist/index.d.ts +28 -28
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +55889 -1359
- package/dist/style.css +1 -1
- package/dist/types/index.d.ts +113 -53
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/fileIcon.d.ts +13 -0
- package/dist/utils/fileIcon.d.ts.map +1 -0
- package/package.json +12 -6
- package/src/adapter.ts +12 -70
- package/src/components/ChatPanel.vue +329 -110
- package/src/components/common/ConfirmDialog.vue +208 -0
- package/src/components/common/CopyButton.vue +71 -0
- package/src/components/common/IndexingSettings.vue +580 -0
- package/src/components/common/SettingsPanel.vue +293 -0
- package/src/components/common/Toast.vue +90 -0
- package/src/components/common/ToggleSwitch.vue +75 -0
- package/src/components/{chat/ui → header}/ChatHeader.vue +170 -93
- package/src/components/input/AtFilePicker.vue +657 -0
- package/src/components/input/ChatInput.vue +653 -0
- package/src/components/input/DropdownSelector.vue +322 -0
- package/src/components/input/ImagePreviewModal.vue +238 -0
- package/src/components/input/at-views/AtBranchView.vue +63 -0
- package/src/components/input/at-views/AtBrowserView.vue +63 -0
- package/src/components/input/at-views/AtChatsView.vue +63 -0
- package/src/components/input/at-views/AtDocsView.vue +63 -0
- package/src/components/input/at-views/AtFilesView.vue +255 -0
- package/src/components/input/at-views/AtTerminalsView.vue +63 -0
- package/src/components/message/ContentRenderer.vue +61 -0
- package/src/components/message/MessageBubble.vue +411 -0
- package/src/components/message/PartsRenderer.vue +101 -0
- package/src/components/message/ToolResultRenderer.vue +27 -0
- package/src/components/message/WelcomeMessage.vue +308 -0
- package/src/components/message/blocks/CodeBlock.vue +113 -0
- package/src/components/message/blocks/TextBlock.vue +21 -0
- package/src/components/message/blocks/index.ts +6 -0
- package/src/components/message/parts/CollapsibleCard.vue +135 -0
- package/src/components/message/parts/ErrorPart.vue +51 -0
- package/src/components/message/parts/ImagePart.vue +98 -0
- package/src/components/message/parts/SearchPart.vue +101 -0
- package/src/components/message/parts/TextPart.vue +28 -0
- package/src/components/message/parts/ThinkingPart.vue +54 -0
- package/src/components/message/parts/ToolCallPart.vue +460 -0
- package/src/components/message/parts/ToolResultPart.vue +78 -0
- package/src/components/message/parts/index.ts +13 -0
- package/src/components/message/tool-results/DefaultToolResult.vue +43 -0
- package/src/components/message/tool-results/SearchResults.vue +133 -0
- package/src/components/message/tool-results/WeatherCard.vue +139 -0
- package/src/components/message/tool-results/index.ts +7 -0
- package/src/components/message/welcome-types.ts +47 -0
- package/src/composables/useChat.ts +807 -155
- package/src/composables/useImageUpload.ts +228 -0
- package/src/index.ts +96 -49
- package/src/styles.css +47 -0
- package/src/types/index.ts +146 -98
- package/src/utils/fileIcon.ts +49 -0
- package/dist/components/ChatInput.vue.d.ts.map +0 -1
- package/dist/components/chat/SearchResultBlock.vue.d.ts.map +0 -1
- package/dist/components/chat/ThinkingBlock.vue.d.ts.map +0 -1
- package/dist/components/chat/ToolCallBlock.vue.d.ts.map +0 -1
- package/dist/components/chat/messages/ExecutionSteps.vue.d.ts.map +0 -1
- package/dist/components/chat/messages/MessageBubble.vue.d.ts +0 -28
- package/dist/components/chat/messages/MessageBubble.vue.d.ts.map +0 -1
- package/dist/components/chat/ui/ChatHeader.vue.d.ts.map +0 -1
- package/dist/components/chat/ui/WelcomeMessage.vue.d.ts +0 -7
- package/dist/components/chat/ui/WelcomeMessage.vue.d.ts.map +0 -1
- package/dist/preload/preload.d.ts +0 -6
- package/dist/preload/preload.d.ts.map +0 -1
- package/src/components/ChatInput.vue +0 -649
- package/src/components/chat/SearchResultBlock.vue +0 -155
- package/src/components/chat/ThinkingBlock.vue +0 -109
- package/src/components/chat/ToolCallBlock.vue +0 -213
- package/src/components/chat/messages/ExecutionSteps.vue +0 -281
- package/src/components/chat/messages/MessageBubble.vue +0 -272
- package/src/components/chat/ui/WelcomeMessage.vue +0 -135
- package/src/preload/preload.ts +0 -79
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 图片上传 composable
|
|
3
|
+
* 处理图片选择、粘贴、拖拽、预览等功能
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { ref, computed } from 'vue';
|
|
7
|
+
|
|
8
|
+
/** 内部图片数据结构(包含预览用的 dataUrl) */
|
|
9
|
+
export interface ImageItem {
|
|
10
|
+
dataUrl: string;
|
|
11
|
+
base64: string;
|
|
12
|
+
mimeType: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** 导出给外部使用的图片数据格式 */
|
|
16
|
+
export interface ImageData {
|
|
17
|
+
base64: string;
|
|
18
|
+
mimeType: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** useImageUpload 配置项 */
|
|
22
|
+
interface UseImageUploadOptions {
|
|
23
|
+
/** 最大图片数量,默认 5 */
|
|
24
|
+
maxImages?: number;
|
|
25
|
+
/** 单张图片最大大小(字节),默认 10MB */
|
|
26
|
+
maxSize?: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 图片上传 composable
|
|
31
|
+
* @param options 配置项
|
|
32
|
+
*/
|
|
33
|
+
export function useImageUpload(options: UseImageUploadOptions = {}) {
|
|
34
|
+
const { maxImages = 5, maxSize = 10 * 1024 * 1024 } = options;
|
|
35
|
+
|
|
36
|
+
// 图片列表
|
|
37
|
+
const images = ref<ImageItem[]>([]);
|
|
38
|
+
|
|
39
|
+
// 拖拽状态
|
|
40
|
+
const isDragOver = ref(false);
|
|
41
|
+
|
|
42
|
+
// 预览状态
|
|
43
|
+
const previewVisible = ref(false);
|
|
44
|
+
const previewIndex = ref(0);
|
|
45
|
+
|
|
46
|
+
// 图片 URL 数组(用于预览组件)
|
|
47
|
+
const imageUrls = computed(() => images.value.map((img) => img.dataUrl));
|
|
48
|
+
|
|
49
|
+
// 导出格式的图片数据
|
|
50
|
+
const imageData = computed<ImageData[]>(() =>
|
|
51
|
+
images.value.map((img) => ({
|
|
52
|
+
base64: img.base64,
|
|
53
|
+
mimeType: img.mimeType,
|
|
54
|
+
}))
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
// 是否有图片
|
|
58
|
+
const hasImages = computed(() => images.value.length > 0);
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* 读取图片文件为 base64
|
|
62
|
+
*/
|
|
63
|
+
function readImageFile(file: File): Promise<ImageItem> {
|
|
64
|
+
return new Promise((resolve, reject) => {
|
|
65
|
+
const reader = new FileReader();
|
|
66
|
+
reader.onload = () => {
|
|
67
|
+
const dataUrl = reader.result as string;
|
|
68
|
+
// dataUrl 格式: data:image/png;base64,xxxxx
|
|
69
|
+
const base64 = dataUrl.split(',')[1];
|
|
70
|
+
resolve({
|
|
71
|
+
dataUrl,
|
|
72
|
+
base64,
|
|
73
|
+
mimeType: file.type,
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
reader.onerror = reject;
|
|
77
|
+
reader.readAsDataURL(file);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* 处理文件列表
|
|
83
|
+
*/
|
|
84
|
+
async function processFiles(files: File[]) {
|
|
85
|
+
const remaining = maxImages - images.value.length;
|
|
86
|
+
const toProcess = files.slice(0, remaining);
|
|
87
|
+
|
|
88
|
+
for (const file of toProcess) {
|
|
89
|
+
if (file.size > maxSize) {
|
|
90
|
+
console.warn(`图片 ${file.name} 超过大小限制 (${Math.round(maxSize / 1024 / 1024)}MB)`);
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
const imageItem = await readImageFile(file);
|
|
95
|
+
images.value.push(imageItem);
|
|
96
|
+
} catch (err) {
|
|
97
|
+
console.error('读取图片失败:', err);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* 处理文件选择事件
|
|
104
|
+
*/
|
|
105
|
+
function handleImageSelect(event: Event) {
|
|
106
|
+
const target = event.target as HTMLInputElement;
|
|
107
|
+
const files = target.files;
|
|
108
|
+
if (files) {
|
|
109
|
+
processFiles(Array.from(files));
|
|
110
|
+
}
|
|
111
|
+
// 清空 input 以便再次选择相同文件
|
|
112
|
+
target.value = '';
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* 处理粘贴事件
|
|
117
|
+
*/
|
|
118
|
+
function handlePaste(event: ClipboardEvent) {
|
|
119
|
+
const items = event.clipboardData?.items;
|
|
120
|
+
if (!items) return;
|
|
121
|
+
|
|
122
|
+
const imageFiles: File[] = [];
|
|
123
|
+
for (const item of items) {
|
|
124
|
+
if (item.type.startsWith('image/')) {
|
|
125
|
+
const file = item.getAsFile();
|
|
126
|
+
if (file) imageFiles.push(file);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (imageFiles.length > 0) {
|
|
131
|
+
event.preventDefault();
|
|
132
|
+
processFiles(imageFiles);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* 处理拖拽悬停事件
|
|
138
|
+
*/
|
|
139
|
+
function handleDragOver(event: DragEvent) {
|
|
140
|
+
if (event.dataTransfer?.types.includes('Files')) {
|
|
141
|
+
isDragOver.value = true;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* 处理拖拽离开事件
|
|
147
|
+
*/
|
|
148
|
+
function handleDragLeave() {
|
|
149
|
+
isDragOver.value = false;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* 处理拖拽放下事件
|
|
154
|
+
*/
|
|
155
|
+
function handleDrop(event: DragEvent) {
|
|
156
|
+
isDragOver.value = false;
|
|
157
|
+
const files = event.dataTransfer?.files;
|
|
158
|
+
if (files) {
|
|
159
|
+
const imageFiles = Array.from(files).filter((f) => f.type.startsWith('image/'));
|
|
160
|
+
processFiles(imageFiles);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* 打开图片预览
|
|
166
|
+
*/
|
|
167
|
+
function openPreview(index: number) {
|
|
168
|
+
previewIndex.value = index;
|
|
169
|
+
previewVisible.value = true;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* 关闭图片预览
|
|
174
|
+
*/
|
|
175
|
+
function closePreview() {
|
|
176
|
+
previewVisible.value = false;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* 移除指定索引的图片
|
|
181
|
+
*/
|
|
182
|
+
function removeImage(index: number) {
|
|
183
|
+
images.value.splice(index, 1);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* 清空所有图片
|
|
188
|
+
*/
|
|
189
|
+
function clearImages() {
|
|
190
|
+
images.value = [];
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* 添加图片文件
|
|
195
|
+
*/
|
|
196
|
+
function addImages(files: File[]) {
|
|
197
|
+
processFiles(files);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
// 状态
|
|
202
|
+
images,
|
|
203
|
+
isDragOver,
|
|
204
|
+
previewVisible,
|
|
205
|
+
previewIndex,
|
|
206
|
+
|
|
207
|
+
// 计算属性
|
|
208
|
+
imageUrls,
|
|
209
|
+
imageData,
|
|
210
|
+
hasImages,
|
|
211
|
+
|
|
212
|
+
// 事件处理
|
|
213
|
+
handleImageSelect,
|
|
214
|
+
handlePaste,
|
|
215
|
+
handleDragOver,
|
|
216
|
+
handleDragLeave,
|
|
217
|
+
handleDrop,
|
|
218
|
+
|
|
219
|
+
// 预览控制
|
|
220
|
+
openPreview,
|
|
221
|
+
closePreview,
|
|
222
|
+
|
|
223
|
+
// 图片操作
|
|
224
|
+
removeImage,
|
|
225
|
+
clearImages,
|
|
226
|
+
addImages,
|
|
227
|
+
};
|
|
228
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -2,28 +2,33 @@
|
|
|
2
2
|
* @huyooo/ai-chat-frontend-vue
|
|
3
3
|
*
|
|
4
4
|
* AI Chat 前端组件库 - Vue 版本
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
*
|
|
6
|
+
* 新架构:使用 ContentPart 数组渲染消息内容
|
|
7
|
+
* - 支持流式渲染
|
|
8
|
+
* - 支持自定义工具结果 UI
|
|
9
|
+
* - 支持思考、搜索、工具调用等多种内容类型
|
|
7
10
|
*/
|
|
8
11
|
|
|
9
|
-
//
|
|
12
|
+
// CSS 变量默认值
|
|
13
|
+
import './styles.css'
|
|
14
|
+
|
|
15
|
+
// ==================== 核心类型 ====================
|
|
16
|
+
|
|
17
|
+
// 从 bridge-electron 重新导出通信相关类型
|
|
10
18
|
export type {
|
|
11
19
|
ChatAdapter,
|
|
12
|
-
|
|
13
|
-
|
|
20
|
+
ChatEvent,
|
|
21
|
+
ChatEventType,
|
|
14
22
|
ChatOptions,
|
|
15
23
|
ChatMode,
|
|
16
|
-
ModelConfig,
|
|
17
|
-
ModelProvider,
|
|
18
24
|
ThinkingMode,
|
|
19
25
|
SessionRecord,
|
|
20
26
|
MessageRecord,
|
|
27
|
+
ModelOption,
|
|
28
|
+
ProviderType,
|
|
21
29
|
} from '@huyooo/ai-chat-bridge-electron/renderer'
|
|
22
30
|
|
|
23
|
-
// 导出
|
|
24
|
-
export { createElectronAdapter } from '@huyooo/ai-chat-bridge-electron/renderer'
|
|
25
|
-
|
|
26
|
-
// 导出本地定义的辅助类型
|
|
31
|
+
// 导出 adapter 辅助类型
|
|
27
32
|
export type {
|
|
28
33
|
ThinkingData,
|
|
29
34
|
ToolCallData,
|
|
@@ -33,46 +38,82 @@ export type {
|
|
|
33
38
|
CreateSessionOptions,
|
|
34
39
|
UpdateSessionOptions,
|
|
35
40
|
SaveMessageOptions,
|
|
36
|
-
} from './adapter'
|
|
37
|
-
|
|
41
|
+
} from './adapter'
|
|
42
|
+
|
|
43
|
+
// 导出消息和内容类型
|
|
44
|
+
export type {
|
|
45
|
+
// 消息类型
|
|
46
|
+
ChatMessage,
|
|
47
|
+
// ContentPart 类型
|
|
48
|
+
ContentPart,
|
|
49
|
+
ContentPartType,
|
|
50
|
+
TextPart,
|
|
51
|
+
ThinkingPart,
|
|
52
|
+
SearchPart,
|
|
53
|
+
ToolCallPart,
|
|
54
|
+
ToolResultPart,
|
|
55
|
+
ImagePart,
|
|
56
|
+
ErrorPart,
|
|
57
|
+
// 搜索结果
|
|
58
|
+
SearchResult,
|
|
59
|
+
// 错误详情
|
|
60
|
+
ErrorDetails,
|
|
61
|
+
// 输入配置
|
|
62
|
+
ChatInputOptions,
|
|
63
|
+
} from './types'
|
|
64
|
+
|
|
65
|
+
// 导出工具函数
|
|
66
|
+
export { getMessageText } from './types'
|
|
67
|
+
|
|
68
|
+
// ==================== Composables ====================
|
|
38
69
|
|
|
39
|
-
|
|
40
|
-
export {
|
|
41
|
-
export type { UseChatOptions } from './composables/useChat';
|
|
70
|
+
export { useChat } from './composables/useChat'
|
|
71
|
+
export type { UseChatOptions, ToolCompleteEvent, SideEffect } from './composables/useChat'
|
|
42
72
|
|
|
43
|
-
//
|
|
44
|
-
export { default as ChatPanel } from './components/ChatPanel.vue';
|
|
73
|
+
// ==================== 主组件 ====================
|
|
45
74
|
|
|
46
|
-
|
|
47
|
-
export { default as ChatInput } from './components/ChatInput.vue';
|
|
75
|
+
export { default as ChatPanel } from './components/ChatPanel.vue'
|
|
48
76
|
|
|
49
|
-
//
|
|
50
|
-
export { default as ChatHeader } from './components/chat/ui/ChatHeader.vue';
|
|
77
|
+
// ==================== 消息组件 ====================
|
|
51
78
|
|
|
52
|
-
|
|
53
|
-
export { default as
|
|
79
|
+
export { default as MessageBubble } from './components/message/MessageBubble.vue'
|
|
80
|
+
export { default as PartsRenderer } from './components/message/PartsRenderer.vue'
|
|
54
81
|
|
|
55
|
-
//
|
|
56
|
-
export {
|
|
57
|
-
|
|
82
|
+
// Part 渲染组件
|
|
83
|
+
export {
|
|
84
|
+
TextPart as TextPartComponent,
|
|
85
|
+
ThinkingPart as ThinkingPartComponent,
|
|
86
|
+
SearchPart as SearchPartComponent,
|
|
87
|
+
ToolCallPart as ToolCallPartComponent,
|
|
88
|
+
ToolResultPart as ToolResultPartComponent,
|
|
89
|
+
ErrorPart as ErrorPartComponent,
|
|
90
|
+
} from './components/message/parts'
|
|
58
91
|
|
|
59
|
-
//
|
|
60
|
-
export { default as ThinkingBlock } from './components/chat/ThinkingBlock.vue';
|
|
61
|
-
export { default as ToolCallBlock } from './components/chat/ToolCallBlock.vue';
|
|
62
|
-
export { default as SearchResultBlock } from './components/chat/SearchResultBlock.vue';
|
|
92
|
+
// ==================== 其他组件 ====================
|
|
63
93
|
|
|
64
|
-
//
|
|
94
|
+
// 输入组件
|
|
95
|
+
export { default as ChatInput } from './components/input/ChatInput.vue'
|
|
96
|
+
|
|
97
|
+
// Header 组件
|
|
98
|
+
export { default as ChatHeader } from './components/header/ChatHeader.vue'
|
|
99
|
+
|
|
100
|
+
// 欢迎消息组件
|
|
101
|
+
export { default as WelcomeMessage } from './components/message/WelcomeMessage.vue'
|
|
102
|
+
export type { WelcomeConfig, WelcomeFeature, WelcomeTask } from './components/message/welcome-types'
|
|
103
|
+
export { defaultWelcomeConfig } from './components/message/welcome-types'
|
|
104
|
+
|
|
105
|
+
// 通用组件
|
|
106
|
+
export { default as ConfirmDialog } from './components/common/ConfirmDialog.vue'
|
|
107
|
+
export { default as Toast } from './components/common/Toast.vue'
|
|
108
|
+
|
|
109
|
+
// ==================== 工具渲染器相关 ====================
|
|
110
|
+
|
|
111
|
+
// 从 ai-chat-shared 重新导出(用于自定义工具渲染器)
|
|
65
112
|
export type {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
ChatSession,
|
|
71
|
-
MediaOperation,
|
|
72
|
-
AiModel,
|
|
73
|
-
DiffStat,
|
|
74
|
-
} from './types';
|
|
75
|
-
export { DEFAULT_MODELS, FileType } from './types';
|
|
113
|
+
ToolRendererProps,
|
|
114
|
+
WeatherData,
|
|
115
|
+
SearchResultItem,
|
|
116
|
+
} from '@huyooo/ai-chat-shared'
|
|
76
117
|
|
|
77
118
|
/**
|
|
78
119
|
* 使用说明:
|
|
@@ -80,13 +121,19 @@ export { DEFAULT_MODELS, FileType } from './types';
|
|
|
80
121
|
* 1. 导入样式:
|
|
81
122
|
* import '@huyooo/ai-chat-frontend-vue/style.css'
|
|
82
123
|
*
|
|
83
|
-
* 2.
|
|
84
|
-
* import { ChatPanel
|
|
124
|
+
* 2. 基本使用:
|
|
125
|
+
* import { ChatPanel } from '@huyooo/ai-chat-frontend-vue'
|
|
126
|
+
* import { createElectronAdapter } from '@huyooo/ai-chat-bridge-electron/renderer'
|
|
85
127
|
* const adapter = createElectronAdapter()
|
|
86
|
-
* <ChatPanel :adapter="adapter" />
|
|
128
|
+
* <ChatPanel :adapter="adapter" :working-dir="'/path/to/dir'" />
|
|
87
129
|
*
|
|
88
|
-
* 3.
|
|
89
|
-
* import {
|
|
90
|
-
*
|
|
91
|
-
* const
|
|
130
|
+
* 3. 自定义工具渲染器:
|
|
131
|
+
* import { markRaw } from 'vue'
|
|
132
|
+
* import CustomWeatherCard from './CustomWeatherCard.vue'
|
|
133
|
+
* const toolRenderers = { get_weather: markRaw(CustomWeatherCard) }
|
|
134
|
+
* <ChatPanel :adapter="adapter" :tool-renderers="toolRenderers" />
|
|
135
|
+
*
|
|
136
|
+
* 4. 使用 useChat 自定义 UI:
|
|
137
|
+
* import { useChat } from '@huyooo/ai-chat-frontend-vue'
|
|
138
|
+
* const { messages, sendMessage, ... } = useChat({ adapter })
|
|
92
139
|
*/
|
package/src/styles.css
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Chat 全局样式
|
|
3
|
+
* 仅包含 CSS 变量(组件样式使用 Vue scoped CSS)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/* 导入 Markdown 渲染样式 */
|
|
7
|
+
@import '@huyooo/ai-chat-shared/styles';
|
|
8
|
+
|
|
9
|
+
/* CSS 变量默认值 */
|
|
10
|
+
:root {
|
|
11
|
+
--chat-bg: #1e1e1e;
|
|
12
|
+
--chat-header-bg: #1e1e1e;
|
|
13
|
+
--chat-input-bg: #2d2d2d;
|
|
14
|
+
--chat-dropdown-bg: #252526;
|
|
15
|
+
--chat-muted: #2d2d2d;
|
|
16
|
+
--chat-muted-hover: #3c3c3c;
|
|
17
|
+
--chat-border: #333;
|
|
18
|
+
--chat-text: #ccc;
|
|
19
|
+
--chat-text-muted: #888;
|
|
20
|
+
--chat-primary: #2563eb;
|
|
21
|
+
--chat-primary-hover: #1d4ed8;
|
|
22
|
+
--chat-destructive: #ef4444;
|
|
23
|
+
--chat-destructive-hover: #dc2626;
|
|
24
|
+
--chat-success: #22c55e;
|
|
25
|
+
--chat-code-bg: #1f2937;
|
|
26
|
+
--chat-code-text: #e5e7eb;
|
|
27
|
+
--chat-scrollbar: rgba(255, 255, 255, 0.2);
|
|
28
|
+
--chat-scrollbar-hover: rgba(255, 255, 255, 0.3);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/* 统一滚动条样式 - 任何需要自定义滚动条的元素添加此类 */
|
|
32
|
+
.chat-scrollbar::-webkit-scrollbar {
|
|
33
|
+
width: 6px;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.chat-scrollbar::-webkit-scrollbar-track {
|
|
37
|
+
background: transparent;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.chat-scrollbar::-webkit-scrollbar-thumb {
|
|
41
|
+
background: var(--chat-scrollbar, rgba(255, 255, 255, 0.2));
|
|
42
|
+
border-radius: 3px;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.chat-scrollbar::-webkit-scrollbar-thumb:hover {
|
|
46
|
+
background: var(--chat-scrollbar-hover, rgba(255, 255, 255, 0.3));
|
|
47
|
+
}
|