@huyooo/ai-chat-frontend-react 0.2.14 → 0.2.16
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/index.css +0 -1
- package/dist/index.js +1 -5418
- package/package.json +4 -5
- package/dist/index.css.map +0 -1
- package/dist/index.js.map +0 -1
- package/src/adapter.ts +0 -68
- package/src/components/ChatPanel.tsx +0 -553
- package/src/components/common/ConfirmDialog.css +0 -136
- package/src/components/common/ConfirmDialog.tsx +0 -91
- package/src/components/common/CopyButton.css +0 -22
- package/src/components/common/CopyButton.tsx +0 -46
- package/src/components/common/IndexingSettings.css +0 -207
- package/src/components/common/IndexingSettings.tsx +0 -398
- package/src/components/common/SettingsPanel.css +0 -337
- package/src/components/common/SettingsPanel.tsx +0 -215
- package/src/components/common/Toast.css +0 -50
- package/src/components/common/Toast.tsx +0 -38
- package/src/components/common/ToggleSwitch.css +0 -52
- package/src/components/common/ToggleSwitch.tsx +0 -20
- package/src/components/header/ChatHeader.css +0 -285
- package/src/components/header/ChatHeader.tsx +0 -376
- package/src/components/input/AtFilePicker.css +0 -147
- package/src/components/input/AtFilePicker.tsx +0 -519
- package/src/components/input/ChatInput.css +0 -283
- package/src/components/input/ChatInput.tsx +0 -575
- package/src/components/input/DropdownSelector.css +0 -231
- package/src/components/input/DropdownSelector.tsx +0 -333
- package/src/components/input/ImagePreviewModal.css +0 -124
- package/src/components/input/ImagePreviewModal.tsx +0 -118
- package/src/components/input/at-views/AtBranchView.tsx +0 -34
- package/src/components/input/at-views/AtBrowserView.tsx +0 -34
- package/src/components/input/at-views/AtChatsView.tsx +0 -34
- package/src/components/input/at-views/AtDocsView.tsx +0 -34
- package/src/components/input/at-views/AtFilesView.tsx +0 -168
- package/src/components/input/at-views/AtTerminalsView.tsx +0 -34
- package/src/components/input/at-views/AtViewStyles.css +0 -143
- package/src/components/input/at-views/index.ts +0 -9
- package/src/components/message/ContentRenderer.css +0 -9
- package/src/components/message/MessageBubble.css +0 -193
- package/src/components/message/MessageBubble.tsx +0 -240
- package/src/components/message/PartsRenderer.css +0 -12
- package/src/components/message/PartsRenderer.tsx +0 -168
- package/src/components/message/WelcomeMessage.css +0 -221
- package/src/components/message/WelcomeMessage.tsx +0 -93
- package/src/components/message/parts/CollapsibleCard.css +0 -80
- package/src/components/message/parts/CollapsibleCard.tsx +0 -80
- package/src/components/message/parts/ErrorPart.css +0 -9
- package/src/components/message/parts/ErrorPart.tsx +0 -40
- package/src/components/message/parts/ImagePart.css +0 -49
- package/src/components/message/parts/ImagePart.tsx +0 -54
- package/src/components/message/parts/SearchPart.css +0 -44
- package/src/components/message/parts/SearchPart.tsx +0 -63
- package/src/components/message/parts/TextPart.css +0 -579
- package/src/components/message/parts/TextPart.tsx +0 -213
- package/src/components/message/parts/ThinkingPart.css +0 -9
- package/src/components/message/parts/ThinkingPart.tsx +0 -48
- package/src/components/message/parts/ToolCallPart.css +0 -246
- package/src/components/message/parts/ToolCallPart.tsx +0 -289
- package/src/components/message/parts/ToolResultPart.css +0 -67
- package/src/components/message/parts/index.ts +0 -13
- package/src/components/message/parts/visual-predicate.ts +0 -43
- package/src/components/message/parts/visual-render.ts +0 -19
- package/src/components/message/parts/visual.ts +0 -12
- package/src/components/message/welcome-types.ts +0 -46
- package/src/context/AutoRunConfigContext.tsx +0 -13
- package/src/context/ChatAdapterContext.tsx +0 -8
- package/src/context/ChatInputContext.tsx +0 -40
- package/src/context/RenderersContext.tsx +0 -35
- package/src/hooks/useChat.ts +0 -1569
- package/src/hooks/useImageUpload.ts +0 -345
- package/src/hooks/useVoiceInput.ts +0 -454
- package/src/hooks/useVoiceToTextInput.ts +0 -87
- package/src/index.ts +0 -151
- package/src/styles.css +0 -330
- package/src/types/index.ts +0 -196
- package/src/utils/fileIcon.ts +0 -49
package/src/styles.css
DELETED
|
@@ -1,330 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AI Chat 全局样式
|
|
3
|
-
* 仅包含 CSS 变量和 ChatPanel 基础布局
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/* 导入 Markdown / Mermaid 等共享渲染样式(与 vue 版本保持一致) */
|
|
7
|
-
@import "@huyooo/ai-chat-shared/styles";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* 主题协议(跨项目统一):
|
|
11
|
-
* - 使用 document.documentElement 的 data-theme = light | dark
|
|
12
|
-
* - 默认跟随系统 prefers-color-scheme
|
|
13
|
-
* - 组件内部继续使用 --chat-*(ai-chat 自己维护配色,避免被宿主 token “染色”)
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
/* 默认:浅色 */
|
|
17
|
-
:root {
|
|
18
|
-
color-scheme: light;
|
|
19
|
-
|
|
20
|
-
/* ai-chat 专用变量(保持兼容) */
|
|
21
|
-
/* Cursor 官网(Light)白色主题:暖白底 + 橙色强调 */
|
|
22
|
-
--chat-bg: #f7f7f4;
|
|
23
|
-
/* header 与主背景同步,用底部分割线表达层级 */
|
|
24
|
-
--chat-header-bg: var(--chat-bg);
|
|
25
|
-
--chat-input-bg: #f0efeb;
|
|
26
|
-
--chat-dropdown-bg: #f2f1ed;
|
|
27
|
-
--chat-muted: #ebeae5;
|
|
28
|
-
--chat-muted-hover: #e6e5e0;
|
|
29
|
-
--chat-border: #26251e1a;
|
|
30
|
-
--chat-text: #26251eeb;
|
|
31
|
-
--chat-text-strong: #26251e;
|
|
32
|
-
--chat-text-muted: #26251e99;
|
|
33
|
-
/* 主色:light/dark 保持一致(蓝) */
|
|
34
|
-
--chat-primary: #54a9ff;
|
|
35
|
-
/* hover:比主色更深一档,保持可感知的交互反馈 */
|
|
36
|
-
--chat-primary-hover: #2f90ff;
|
|
37
|
-
--chat-destructive: #cf2d56;
|
|
38
|
-
--chat-destructive-hover: #b3003f;
|
|
39
|
-
--chat-success: #1f8a65;
|
|
40
|
-
--chat-code-bg: #f2f1ed;
|
|
41
|
-
--chat-code-text: #26251eeb;
|
|
42
|
-
--chat-scrollbar: rgba(38, 37, 30, 0.2);
|
|
43
|
-
--chat-scrollbar-hover: rgba(38, 37, 30, 0.3);
|
|
44
|
-
/* 悬浮圆形按钮(如 scroll-to-bottom)在浅色下更像 macOS:白底+阴影 */
|
|
45
|
-
--chat-fab-bg: #ffffff;
|
|
46
|
-
--chat-fab-bg-hover: var(--chat-input-bg);
|
|
47
|
-
--chat-fab-shadow: 0 10px 24px rgba(0, 0, 0, 0.12);
|
|
48
|
-
|
|
49
|
-
/* 代码高亮 - GitHub Light 风格 */
|
|
50
|
-
--chat-hljs-keyword: #cf222e;
|
|
51
|
-
--chat-hljs-built-in: #953800;
|
|
52
|
-
--chat-hljs-type: #953800;
|
|
53
|
-
--chat-hljs-function: #8250df;
|
|
54
|
-
--chat-hljs-string: #0a3069;
|
|
55
|
-
--chat-hljs-number: #0550ae;
|
|
56
|
-
--chat-hljs-literal: #0550ae;
|
|
57
|
-
--chat-hljs-comment: #6e7781;
|
|
58
|
-
--chat-hljs-variable: #953800;
|
|
59
|
-
--chat-hljs-attr: #0550ae;
|
|
60
|
-
--chat-hljs-property: #116329;
|
|
61
|
-
--chat-hljs-operator: #cf222e;
|
|
62
|
-
--chat-hljs-punctuation: #24292f;
|
|
63
|
-
--chat-hljs-params: #24292f;
|
|
64
|
-
--chat-hljs-regexp: #116329;
|
|
65
|
-
--chat-hljs-selector: #116329;
|
|
66
|
-
--chat-hljs-tag: #116329;
|
|
67
|
-
--chat-hljs-name: #116329;
|
|
68
|
-
--chat-hljs-deletion: #82071e;
|
|
69
|
-
--chat-hljs-deletion-bg: rgba(255, 129, 130, 0.15);
|
|
70
|
-
--chat-hljs-addition: #116329;
|
|
71
|
-
--chat-hljs-addition-bg: rgba(46, 160, 67, 0.15);
|
|
72
|
-
--chat-hljs-meta: #6e7781;
|
|
73
|
-
--chat-hljs-link: #0a3069;
|
|
74
|
-
--chat-hljs-symbol: #0550ae;
|
|
75
|
-
--chat-hljs-subst: #24292f;
|
|
76
|
-
--chat-hljs-section: #0550ae;
|
|
77
|
-
--chat-hljs-bullet: #953800;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/* 默认跟随系统暗色 */
|
|
81
|
-
@media (prefers-color-scheme: dark) {
|
|
82
|
-
:root {
|
|
83
|
-
color-scheme: dark;
|
|
84
|
-
/* 旧版暗色(深灰底:你更喜欢的观感) */
|
|
85
|
-
--chat-bg: #1e1e1e;
|
|
86
|
-
--chat-header-bg: #1e1e1e;
|
|
87
|
-
--chat-input-bg: #2d2d2d;
|
|
88
|
-
--chat-dropdown-bg: #252526;
|
|
89
|
-
--chat-muted: #2d2d2d;
|
|
90
|
-
--chat-muted-hover: #3c3c3c;
|
|
91
|
-
--chat-border: #333;
|
|
92
|
-
--chat-text: #ccc;
|
|
93
|
-
--chat-text-strong: #fff;
|
|
94
|
-
--chat-text-muted: #888;
|
|
95
|
-
/* 主色:light/dark 保持一致(蓝) */
|
|
96
|
-
--chat-primary: #54a9ff;
|
|
97
|
-
--chat-primary-hover: #2f90ff;
|
|
98
|
-
--chat-destructive: #cf2d56;
|
|
99
|
-
--chat-destructive-hover: #e33b67;
|
|
100
|
-
--chat-success: #1f8a65;
|
|
101
|
-
--chat-code-bg: #1f2937;
|
|
102
|
-
--chat-code-text: #e5e7eb;
|
|
103
|
-
--chat-scrollbar: rgba(255, 255, 255, 0.2);
|
|
104
|
-
--chat-scrollbar-hover: rgba(255, 255, 255, 0.3);
|
|
105
|
-
/* 暗色下保持融入背景 */
|
|
106
|
-
--chat-fab-bg: var(--chat-muted);
|
|
107
|
-
--chat-fab-bg-hover: var(--chat-muted-hover);
|
|
108
|
-
--chat-fab-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
|
109
|
-
|
|
110
|
-
/* 代码高亮 - GitHub Dark 风格 */
|
|
111
|
-
--chat-hljs-keyword: #ff7b72;
|
|
112
|
-
--chat-hljs-built-in: #ffa657;
|
|
113
|
-
--chat-hljs-type: #ffa657;
|
|
114
|
-
--chat-hljs-function: #d2a8ff;
|
|
115
|
-
--chat-hljs-string: #a5d6ff;
|
|
116
|
-
--chat-hljs-number: #79c0ff;
|
|
117
|
-
--chat-hljs-literal: #79c0ff;
|
|
118
|
-
--chat-hljs-comment: #8b949e;
|
|
119
|
-
--chat-hljs-variable: #ffa657;
|
|
120
|
-
--chat-hljs-attr: #79c0ff;
|
|
121
|
-
--chat-hljs-property: #7ee787;
|
|
122
|
-
--chat-hljs-operator: #ff7b72;
|
|
123
|
-
--chat-hljs-punctuation: #e6edf3;
|
|
124
|
-
--chat-hljs-params: #e6edf3;
|
|
125
|
-
--chat-hljs-regexp: #7ee787;
|
|
126
|
-
--chat-hljs-selector: #7ee787;
|
|
127
|
-
--chat-hljs-tag: #7ee787;
|
|
128
|
-
--chat-hljs-name: #7ee787;
|
|
129
|
-
--chat-hljs-deletion: #ffa198;
|
|
130
|
-
--chat-hljs-deletion-bg: rgba(248, 81, 73, 0.15);
|
|
131
|
-
--chat-hljs-addition: #7ee787;
|
|
132
|
-
--chat-hljs-addition-bg: rgba(46, 160, 67, 0.15);
|
|
133
|
-
--chat-hljs-meta: #8b949e;
|
|
134
|
-
--chat-hljs-link: #a5d6ff;
|
|
135
|
-
--chat-hljs-symbol: #79c0ff;
|
|
136
|
-
--chat-hljs-subst: #e6edf3;
|
|
137
|
-
--chat-hljs-section: #79c0ff;
|
|
138
|
-
--chat-hljs-bullet: #ffa657;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/* 显式浅色/暗色覆盖系统 */
|
|
143
|
-
:root[data-theme="light"] {
|
|
144
|
-
color-scheme: light;
|
|
145
|
-
/* 显式 light 必须覆盖 prefers-color-scheme: dark 的变量 */
|
|
146
|
-
--chat-bg: #f7f7f4;
|
|
147
|
-
--chat-header-bg: var(--chat-bg);
|
|
148
|
-
--chat-input-bg: #f0efeb;
|
|
149
|
-
--chat-dropdown-bg: #f2f1ed;
|
|
150
|
-
--chat-muted: #ebeae5;
|
|
151
|
-
--chat-muted-hover: #e6e5e0;
|
|
152
|
-
--chat-border: #26251e1a;
|
|
153
|
-
--chat-text: #26251eeb;
|
|
154
|
-
--chat-text-strong: #26251e;
|
|
155
|
-
--chat-text-muted: #26251e99;
|
|
156
|
-
--chat-primary: #54a9ff;
|
|
157
|
-
--chat-primary-hover: #2f90ff;
|
|
158
|
-
--chat-destructive: #cf2d56;
|
|
159
|
-
--chat-destructive-hover: #b3003f;
|
|
160
|
-
--chat-success: #1f8a65;
|
|
161
|
-
--chat-code-bg: #f2f1ed;
|
|
162
|
-
--chat-code-text: #26251eeb;
|
|
163
|
-
--chat-scrollbar: rgba(38, 37, 30, 0.2);
|
|
164
|
-
--chat-scrollbar-hover: rgba(38, 37, 30, 0.3);
|
|
165
|
-
--chat-fab-bg: #ffffff;
|
|
166
|
-
--chat-fab-bg-hover: var(--chat-input-bg);
|
|
167
|
-
--chat-fab-shadow: 0 10px 24px rgba(0, 0, 0, 0.12);
|
|
168
|
-
|
|
169
|
-
/* 代码高亮 - GitHub Light 风格 */
|
|
170
|
-
--chat-hljs-keyword: #cf222e;
|
|
171
|
-
--chat-hljs-built-in: #953800;
|
|
172
|
-
--chat-hljs-type: #953800;
|
|
173
|
-
--chat-hljs-function: #8250df;
|
|
174
|
-
--chat-hljs-string: #0a3069;
|
|
175
|
-
--chat-hljs-number: #0550ae;
|
|
176
|
-
--chat-hljs-literal: #0550ae;
|
|
177
|
-
--chat-hljs-comment: #6e7781;
|
|
178
|
-
--chat-hljs-variable: #953800;
|
|
179
|
-
--chat-hljs-attr: #0550ae;
|
|
180
|
-
--chat-hljs-property: #116329;
|
|
181
|
-
--chat-hljs-operator: #cf222e;
|
|
182
|
-
--chat-hljs-punctuation: #24292f;
|
|
183
|
-
--chat-hljs-params: #24292f;
|
|
184
|
-
--chat-hljs-regexp: #116329;
|
|
185
|
-
--chat-hljs-selector: #116329;
|
|
186
|
-
--chat-hljs-tag: #116329;
|
|
187
|
-
--chat-hljs-name: #116329;
|
|
188
|
-
--chat-hljs-deletion: #82071e;
|
|
189
|
-
--chat-hljs-deletion-bg: rgba(255, 129, 130, 0.15);
|
|
190
|
-
--chat-hljs-addition: #116329;
|
|
191
|
-
--chat-hljs-addition-bg: rgba(46, 160, 67, 0.15);
|
|
192
|
-
--chat-hljs-meta: #6e7781;
|
|
193
|
-
--chat-hljs-link: #0a3069;
|
|
194
|
-
--chat-hljs-symbol: #0550ae;
|
|
195
|
-
--chat-hljs-subst: #24292f;
|
|
196
|
-
--chat-hljs-section: #0550ae;
|
|
197
|
-
--chat-hljs-bullet: #953800;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
:root[data-theme="dark"] {
|
|
201
|
-
color-scheme: dark;
|
|
202
|
-
/* 旧版暗色(深灰底:你更喜欢的观感) */
|
|
203
|
-
--chat-bg: #1e1e1e;
|
|
204
|
-
--chat-header-bg: #1e1e1e;
|
|
205
|
-
--chat-input-bg: #2d2d2d;
|
|
206
|
-
--chat-dropdown-bg: #252526;
|
|
207
|
-
--chat-muted: #2d2d2d;
|
|
208
|
-
--chat-muted-hover: #3c3c3c;
|
|
209
|
-
--chat-border: #333;
|
|
210
|
-
--chat-text: #ccc;
|
|
211
|
-
--chat-text-strong: #fff;
|
|
212
|
-
--chat-text-muted: #888;
|
|
213
|
-
/* 主色:light/dark 保持一致(蓝) */
|
|
214
|
-
--chat-primary: #54a9ff;
|
|
215
|
-
--chat-primary-hover: #2f90ff;
|
|
216
|
-
--chat-destructive: #cf2d56;
|
|
217
|
-
--chat-destructive-hover: #e33b67;
|
|
218
|
-
--chat-success: #1f8a65;
|
|
219
|
-
--chat-code-bg: #1f2937;
|
|
220
|
-
--chat-code-text: #e5e7eb;
|
|
221
|
-
--chat-scrollbar: rgba(255, 255, 255, 0.2);
|
|
222
|
-
--chat-scrollbar-hover: rgba(255, 255, 255, 0.3);
|
|
223
|
-
--chat-fab-bg: var(--chat-muted);
|
|
224
|
-
--chat-fab-bg-hover: var(--chat-muted-hover);
|
|
225
|
-
--chat-fab-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
|
226
|
-
|
|
227
|
-
/* 代码高亮 - GitHub Dark 风格 */
|
|
228
|
-
--chat-hljs-keyword: #ff7b72;
|
|
229
|
-
--chat-hljs-built-in: #ffa657;
|
|
230
|
-
--chat-hljs-type: #ffa657;
|
|
231
|
-
--chat-hljs-function: #d2a8ff;
|
|
232
|
-
--chat-hljs-string: #a5d6ff;
|
|
233
|
-
--chat-hljs-number: #79c0ff;
|
|
234
|
-
--chat-hljs-literal: #79c0ff;
|
|
235
|
-
--chat-hljs-comment: #8b949e;
|
|
236
|
-
--chat-hljs-variable: #ffa657;
|
|
237
|
-
--chat-hljs-attr: #79c0ff;
|
|
238
|
-
--chat-hljs-property: #7ee787;
|
|
239
|
-
--chat-hljs-operator: #ff7b72;
|
|
240
|
-
--chat-hljs-punctuation: #e6edf3;
|
|
241
|
-
--chat-hljs-params: #e6edf3;
|
|
242
|
-
--chat-hljs-regexp: #7ee787;
|
|
243
|
-
--chat-hljs-selector: #7ee787;
|
|
244
|
-
--chat-hljs-tag: #7ee787;
|
|
245
|
-
--chat-hljs-name: #7ee787;
|
|
246
|
-
--chat-hljs-deletion: #ffa198;
|
|
247
|
-
--chat-hljs-deletion-bg: rgba(248, 81, 73, 0.15);
|
|
248
|
-
--chat-hljs-addition: #7ee787;
|
|
249
|
-
--chat-hljs-addition-bg: rgba(46, 160, 67, 0.15);
|
|
250
|
-
--chat-hljs-meta: #8b949e;
|
|
251
|
-
--chat-hljs-link: #a5d6ff;
|
|
252
|
-
--chat-hljs-symbol: #79c0ff;
|
|
253
|
-
--chat-hljs-subst: #e6edf3;
|
|
254
|
-
--chat-hljs-section: #79c0ff;
|
|
255
|
-
--chat-hljs-bullet: #ffa657;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
/* 统一滚动条样式 - 任何需要自定义滚动条的元素添加此类 */
|
|
259
|
-
.chat-scrollbar::-webkit-scrollbar {
|
|
260
|
-
width: 6px;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
.chat-scrollbar::-webkit-scrollbar-track {
|
|
264
|
-
background: transparent;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
.chat-scrollbar::-webkit-scrollbar-thumb {
|
|
268
|
-
background: var(--chat-scrollbar, rgba(255, 255, 255, 0.2));
|
|
269
|
-
border-radius: 3px;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
.chat-scrollbar::-webkit-scrollbar-thumb:hover {
|
|
273
|
-
background: var(--chat-scrollbar-hover, rgba(255, 255, 255, 0.3));
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
/* ChatPanel 基础布局 */
|
|
277
|
-
.chat-panel {
|
|
278
|
-
display: flex;
|
|
279
|
-
flex-direction: column;
|
|
280
|
-
width: 100%;
|
|
281
|
-
height: 100%;
|
|
282
|
-
background: var(--chat-bg, #1e1e1e);
|
|
283
|
-
overflow: hidden;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
.messages-wrapper {
|
|
287
|
-
flex: 1;
|
|
288
|
-
min-height: 0;
|
|
289
|
-
position: relative;
|
|
290
|
-
display: flex;
|
|
291
|
-
flex-direction: column;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
.messages-container {
|
|
295
|
-
flex: 1;
|
|
296
|
-
min-height: 0;
|
|
297
|
-
overflow-y: auto;
|
|
298
|
-
padding: 12px;
|
|
299
|
-
scroll-behavior: smooth;
|
|
300
|
-
display: flex;
|
|
301
|
-
flex-direction: column;
|
|
302
|
-
gap: 8px;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
/* 滚动到底部按钮 */
|
|
306
|
-
.scroll-to-bottom-btn {
|
|
307
|
-
position: absolute;
|
|
308
|
-
bottom: 16px;
|
|
309
|
-
right: 16px;
|
|
310
|
-
display: flex;
|
|
311
|
-
align-items: center;
|
|
312
|
-
justify-content: center;
|
|
313
|
-
width: 32px;
|
|
314
|
-
height: 32px;
|
|
315
|
-
border-radius: 50%;
|
|
316
|
-
background: var(--chat-fab-bg, var(--chat-muted));
|
|
317
|
-
border: 1px solid var(--chat-border);
|
|
318
|
-
color: var(--chat-text-muted);
|
|
319
|
-
cursor: pointer;
|
|
320
|
-
transition: all 0.2s ease;
|
|
321
|
-
box-shadow: var(--chat-fab-shadow, 0 2px 8px rgba(0, 0, 0, 0.3));
|
|
322
|
-
z-index: 10;
|
|
323
|
-
pointer-events: auto;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
.scroll-to-bottom-btn:hover {
|
|
327
|
-
background: var(--chat-fab-bg-hover, var(--chat-muted-hover));
|
|
328
|
-
color: var(--chat-text);
|
|
329
|
-
transform: scale(1.1);
|
|
330
|
-
}
|
package/src/types/index.ts
DELETED
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AI Chat 前端类型定义
|
|
3
|
-
* 核心类型从 bridge-electron 导出,保持类型一致性
|
|
4
|
-
*
|
|
5
|
-
* 架构:消息内容使用 ContentPart 数组,支持流式渲染和自定义 UI
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
// 从 bridge-electron 导入类型
|
|
9
|
-
import type {
|
|
10
|
-
ChatMode as ChatModeType,
|
|
11
|
-
ThinkingMode as ThinkingModeType,
|
|
12
|
-
SessionRecord as SessionRecordType,
|
|
13
|
-
MessageRecord as MessageRecordType,
|
|
14
|
-
ModelOption as ModelOptionType,
|
|
15
|
-
ProviderType as ProviderTypeType,
|
|
16
|
-
} from '@huyooo/ai-chat-bridge-electron/renderer'
|
|
17
|
-
|
|
18
|
-
// 重新导出核心类型
|
|
19
|
-
export type ChatMode = ChatModeType
|
|
20
|
-
export type ThinkingMode = ThinkingModeType
|
|
21
|
-
export type SessionRecord = SessionRecordType
|
|
22
|
-
export type MessageRecord = MessageRecordType
|
|
23
|
-
export type ModelOption = ModelOptionType
|
|
24
|
-
export type ProviderType = ProviderTypeType
|
|
25
|
-
|
|
26
|
-
// ==================== Content Part 类型 ====================
|
|
27
|
-
//
|
|
28
|
-
// 架构说明:
|
|
29
|
-
// 1. 内置类型:text, code, thinking, search, tool_call, image, error
|
|
30
|
-
// 2. 扩展类型:weather, stock 等业务类型(通过 partRenderers 注册渲染器)
|
|
31
|
-
// 3. 工具执行完成后,如果定义了 resultType,直接生成对应类型的 Part(如 weather)
|
|
32
|
-
// 4. 前端通过 partRenderers 统一渲染所有 Part 类型
|
|
33
|
-
|
|
34
|
-
/** 搜索结果 */
|
|
35
|
-
export interface SearchResult {
|
|
36
|
-
title: string
|
|
37
|
-
url: string
|
|
38
|
-
snippet: string
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/** 文本内容 Part */
|
|
42
|
-
export interface TextPart {
|
|
43
|
-
type: 'text'
|
|
44
|
-
text: string
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/** 代码块 Part(从 text 中解析,或直接返回)*/
|
|
48
|
-
export interface CodePart {
|
|
49
|
-
type: 'code'
|
|
50
|
-
content: string
|
|
51
|
-
language?: string
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/** 思考过程 Part */
|
|
55
|
-
export interface ThinkingPart {
|
|
56
|
-
type: 'thinking'
|
|
57
|
-
text: string
|
|
58
|
-
status: 'running' | 'done'
|
|
59
|
-
duration?: number // 秒
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/** 搜索 Part */
|
|
63
|
-
export interface SearchPart {
|
|
64
|
-
type: 'search'
|
|
65
|
-
query?: string
|
|
66
|
-
results?: SearchResult[]
|
|
67
|
-
status: 'running' | 'done'
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/** 工具调用 Part(仅展示执行过程,结果由具体类型 Part 渲染)*/
|
|
71
|
-
export interface ToolCallPart {
|
|
72
|
-
type: 'tool_call'
|
|
73
|
-
id: string
|
|
74
|
-
name: string
|
|
75
|
-
args?: Record<string, unknown>
|
|
76
|
-
status: 'pending' | 'running' | 'done' | 'error' | 'cancelled' | 'skipped'
|
|
77
|
-
// 注意:不再有 result 字段,结果由工具的 resultType 指定的 Part 类型渲染
|
|
78
|
-
/** 工具执行输出(用于 execute_command 等需要展示 stdout/stderr 的工具) */
|
|
79
|
-
output?: {
|
|
80
|
-
stdout?: string
|
|
81
|
-
stderr?: string
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/** 图片 Part */
|
|
86
|
-
export interface ImagePart {
|
|
87
|
-
type: 'image'
|
|
88
|
-
url: string
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/** 错误 Part */
|
|
92
|
-
export interface ErrorPart {
|
|
93
|
-
type: 'error'
|
|
94
|
-
message: string
|
|
95
|
-
category?: string
|
|
96
|
-
retryable?: boolean
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// ==================== 扩展 Part 类型(业务类型)====================
|
|
100
|
-
|
|
101
|
-
/** 天气 Part(由 get_weather 工具生成)*/
|
|
102
|
-
export interface WeatherPart {
|
|
103
|
-
type: 'weather'
|
|
104
|
-
city: string
|
|
105
|
-
temperature: number
|
|
106
|
-
condition: string
|
|
107
|
-
humidity: number
|
|
108
|
-
wind: string
|
|
109
|
-
reportTime?: string
|
|
110
|
-
province?: string
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/** 自定义 Part 基础接口(用于扩展)*/
|
|
114
|
-
export interface CustomPart {
|
|
115
|
-
type: string
|
|
116
|
-
[key: string]: unknown
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/** 内置 Part 联合类型 */
|
|
120
|
-
export type BuiltinPart =
|
|
121
|
-
| TextPart
|
|
122
|
-
| CodePart
|
|
123
|
-
| ThinkingPart
|
|
124
|
-
| SearchPart
|
|
125
|
-
| ToolCallPart
|
|
126
|
-
| ImagePart
|
|
127
|
-
| ErrorPart
|
|
128
|
-
|
|
129
|
-
/** 内容 Part 联合类型(包含内置和扩展类型)*/
|
|
130
|
-
export type ContentPart = BuiltinPart | WeatherPart | CustomPart
|
|
131
|
-
|
|
132
|
-
/** 内置 Part 类型字符串 */
|
|
133
|
-
export type BuiltinPartType = BuiltinPart['type']
|
|
134
|
-
|
|
135
|
-
/** 内容 Part 类型字符串 */
|
|
136
|
-
export type ContentPartType = string
|
|
137
|
-
|
|
138
|
-
/** 步骤折叠模式 */
|
|
139
|
-
export type StepsExpandedType = 'open' | 'close' | 'auto'
|
|
140
|
-
|
|
141
|
-
// ==================== 消息类型 ====================
|
|
142
|
-
|
|
143
|
-
/** 错误详情(结构化错误信息) */
|
|
144
|
-
export interface ErrorDetails {
|
|
145
|
-
category?: string
|
|
146
|
-
message: string
|
|
147
|
-
code?: string
|
|
148
|
-
statusCode?: number
|
|
149
|
-
retryable?: boolean
|
|
150
|
-
retryAfter?: number
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/** 聊天消息(前端显示用)- 新架构:基于 parts 数组 */
|
|
154
|
-
export interface ChatMessage {
|
|
155
|
-
id: string
|
|
156
|
-
role: 'user' | 'assistant'
|
|
157
|
-
/** 内容 parts 数组 - 核心渲染数据 */
|
|
158
|
-
parts: ContentPart[]
|
|
159
|
-
/** 生成此消息时使用的模型 */
|
|
160
|
-
model?: string
|
|
161
|
-
/** 生成此消息时使用的模式 (ask/agent) */
|
|
162
|
-
mode?: string
|
|
163
|
-
/** 生成此消息时是否启用 web 搜索 */
|
|
164
|
-
webSearchEnabled?: boolean
|
|
165
|
-
/** 生成此消息时是否启用深度思考 */
|
|
166
|
-
thinkingEnabled?: boolean
|
|
167
|
-
/** 用户上传的图片(仅用户消息) */
|
|
168
|
-
images?: string[]
|
|
169
|
-
/** 是否正在加载 */
|
|
170
|
-
loading?: boolean
|
|
171
|
-
/** 是否已复制 */
|
|
172
|
-
copied?: boolean
|
|
173
|
-
/** 消息时间戳 */
|
|
174
|
-
timestamp?: number
|
|
175
|
-
/** 错误详情(如果有错误) */
|
|
176
|
-
error?: ErrorDetails
|
|
177
|
-
/** 是否被用户中止 */
|
|
178
|
-
aborted?: boolean
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
/** 获取消息的纯文本内容(用于复制、保存等) */
|
|
182
|
-
export function getMessageText(message: ChatMessage): string {
|
|
183
|
-
return message.parts
|
|
184
|
-
.filter((p): p is TextPart => p.type === 'text')
|
|
185
|
-
.map(p => p.text)
|
|
186
|
-
.join('')
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
/** 输入区配置快照(用于历史回溯/重发) */
|
|
190
|
-
export interface ChatInputOptions {
|
|
191
|
-
mode: ChatMode
|
|
192
|
-
model: string
|
|
193
|
-
webSearchEnabled: boolean
|
|
194
|
-
thinkingEnabled: boolean
|
|
195
|
-
}
|
|
196
|
-
|
package/src/utils/fileIcon.ts
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 根据文件名或路径获取对应的图标
|
|
3
|
-
*/
|
|
4
|
-
export function getFileIcon(nameOrPath: string): string {
|
|
5
|
-
const name = basename(nameOrPath).toLowerCase();
|
|
6
|
-
const ext = name.includes('.') ? name.slice(name.lastIndexOf('.')) : '';
|
|
7
|
-
|
|
8
|
-
if (ext === '.vue') return 'vscode-icons:file-type-vue';
|
|
9
|
-
if (ext === '.tsx') return 'vscode-icons:file-type-reactts';
|
|
10
|
-
if (ext === '.jsx') return 'vscode-icons:file-type-reactjs';
|
|
11
|
-
if (ext === '.ts') return 'vscode-icons:file-type-typescript';
|
|
12
|
-
if (ext === '.js') return 'vscode-icons:file-type-js';
|
|
13
|
-
if (ext === '.css') return 'vscode-icons:file-type-css';
|
|
14
|
-
if (ext === '.scss' || ext === '.sass') return 'vscode-icons:file-type-scss';
|
|
15
|
-
if (ext === '.less') return 'vscode-icons:file-type-less';
|
|
16
|
-
if (ext === '.json') return 'vscode-icons:file-type-json';
|
|
17
|
-
if (ext === '.yaml' || ext === '.yml') return 'vscode-icons:file-type-yaml';
|
|
18
|
-
if (ext === '.xml') return 'vscode-icons:file-type-xml';
|
|
19
|
-
if (ext === '.md') return 'vscode-icons:file-type-markdown';
|
|
20
|
-
if (ext === '.txt') return 'vscode-icons:file-type-text';
|
|
21
|
-
if (['.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg', '.ico'].includes(ext)) {
|
|
22
|
-
return 'vscode-icons:file-type-image';
|
|
23
|
-
}
|
|
24
|
-
if (ext === '.html' || ext === '.htm') return 'vscode-icons:file-type-html';
|
|
25
|
-
if (ext === '.py') return 'vscode-icons:file-type-python';
|
|
26
|
-
if (ext === '.go') return 'vscode-icons:file-type-go';
|
|
27
|
-
if (ext === '.rs') return 'vscode-icons:file-type-rust';
|
|
28
|
-
if (ext === '.sh' || ext === '.bash' || ext === '.zsh') return 'vscode-icons:file-type-shell';
|
|
29
|
-
|
|
30
|
-
return 'lucide:file';
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* 获取路径的文件名部分
|
|
35
|
-
*/
|
|
36
|
-
export function basename(p: string): string {
|
|
37
|
-
const normalized = p.replace(/\\/g, '/');
|
|
38
|
-
const idx = normalized.lastIndexOf('/');
|
|
39
|
-
return idx >= 0 ? normalized.slice(idx + 1) || normalized : normalized;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* 获取路径的目录部分
|
|
44
|
-
*/
|
|
45
|
-
export function dirname(p: string): string {
|
|
46
|
-
const normalized = p.replace(/\\/g, '/');
|
|
47
|
-
const idx = normalized.lastIndexOf('/');
|
|
48
|
-
return idx > 0 ? normalized.slice(0, idx) : '';
|
|
49
|
-
}
|