@huyooo/ai-chat-frontend-vue 0.1.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.
Files changed (45) hide show
  1. package/dist/adapter.d.ts +87 -0
  2. package/dist/adapter.d.ts.map +1 -0
  3. package/dist/components/ChatInput.vue.d.ts +54 -0
  4. package/dist/components/ChatInput.vue.d.ts.map +1 -0
  5. package/dist/components/ChatPanel.vue.d.ts +38 -0
  6. package/dist/components/ChatPanel.vue.d.ts.map +1 -0
  7. package/dist/components/chat/SearchResultBlock.vue.d.ts +8 -0
  8. package/dist/components/chat/SearchResultBlock.vue.d.ts.map +1 -0
  9. package/dist/components/chat/ThinkingBlock.vue.d.ts +7 -0
  10. package/dist/components/chat/ThinkingBlock.vue.d.ts.map +1 -0
  11. package/dist/components/chat/ToolCallBlock.vue.d.ts +9 -0
  12. package/dist/components/chat/ToolCallBlock.vue.d.ts.map +1 -0
  13. package/dist/components/chat/messages/ExecutionSteps.vue.d.ts +13 -0
  14. package/dist/components/chat/messages/ExecutionSteps.vue.d.ts.map +1 -0
  15. package/dist/components/chat/messages/MessageBubble.vue.d.ts +28 -0
  16. package/dist/components/chat/messages/MessageBubble.vue.d.ts.map +1 -0
  17. package/dist/components/chat/ui/ChatHeader.vue.d.ts +34 -0
  18. package/dist/components/chat/ui/ChatHeader.vue.d.ts.map +1 -0
  19. package/dist/components/chat/ui/WelcomeMessage.vue.d.ts +7 -0
  20. package/dist/components/chat/ui/WelcomeMessage.vue.d.ts.map +1 -0
  21. package/dist/composables/useChat.d.ts +96 -0
  22. package/dist/composables/useChat.d.ts.map +1 -0
  23. package/dist/index.d.ts +37 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +1497 -0
  26. package/dist/preload/preload.d.ts +6 -0
  27. package/dist/preload/preload.d.ts.map +1 -0
  28. package/dist/style.css +1 -0
  29. package/dist/types/index.d.ts +107 -0
  30. package/dist/types/index.d.ts.map +1 -0
  31. package/package.json +59 -0
  32. package/src/adapter.ts +160 -0
  33. package/src/components/ChatInput.vue +649 -0
  34. package/src/components/ChatPanel.vue +309 -0
  35. package/src/components/chat/SearchResultBlock.vue +155 -0
  36. package/src/components/chat/ThinkingBlock.vue +109 -0
  37. package/src/components/chat/ToolCallBlock.vue +213 -0
  38. package/src/components/chat/messages/ExecutionSteps.vue +281 -0
  39. package/src/components/chat/messages/MessageBubble.vue +272 -0
  40. package/src/components/chat/ui/ChatHeader.vue +535 -0
  41. package/src/components/chat/ui/WelcomeMessage.vue +135 -0
  42. package/src/composables/useChat.ts +423 -0
  43. package/src/index.ts +82 -0
  44. package/src/preload/preload.ts +79 -0
  45. package/src/types/index.ts +164 -0
package/dist/index.js ADDED
@@ -0,0 +1,1497 @@
1
+ import { ref as M, shallowRef as Ae, defineComponent as K, computed as H, onMounted as oe, onUnmounted as fe, createElementBlock as i, openBlock as n, createElementVNode as t, Fragment as B, renderList as q, normalizeClass as E, toDisplayString as z, withModifiers as X, createVNode as S, unref as l, createCommentVNode as p, markRaw as W, createBlock as k, resolveDynamicComponent as te, watch as ae, withDirectives as Ne, vModelText as Be, reactive as Le, toRef as Oe, provide as Ue, nextTick as _e } from "vue";
2
+ import { X as ne, Plus as de, Clock as He, Trash2 as ve, MoreHorizontal as We, XCircle as qe, Download as Ve, Copy as ke, MessageSquare as Pe, Settings as Je, Code as Fe, FileText as pe, Search as ye, MessageCircle as be, Sparkles as Ce, Zap as he, ChevronDown as j, Check as se, AtSign as Ge, Globe as ie, ImageIcon as Ke, Square as Qe, ArrowUp as Xe, Mic as je, Loader2 as ee, Lightbulb as $e, RefreshCw as Ze, Video as Ye, Image as ge, Terminal as et } from "lucide-vue-next";
3
+ function tt() {
4
+ return {
5
+ async getSessions() {
6
+ return [];
7
+ },
8
+ async createSession(e) {
9
+ return {
10
+ id: Date.now().toString(),
11
+ title: e.title,
12
+ model: e.model,
13
+ mode: e.mode,
14
+ createdAt: /* @__PURE__ */ new Date(),
15
+ updatedAt: /* @__PURE__ */ new Date()
16
+ };
17
+ },
18
+ async updateSession() {
19
+ },
20
+ async deleteSession() {
21
+ },
22
+ async getMessages() {
23
+ return [];
24
+ },
25
+ async saveMessage(e) {
26
+ return {
27
+ id: Date.now().toString(),
28
+ sessionId: e.sessionId,
29
+ role: e.role,
30
+ content: e.content,
31
+ thinking: e.thinking,
32
+ toolCalls: e.toolCalls,
33
+ searchResults: e.searchResults,
34
+ timestamp: /* @__PURE__ */ new Date()
35
+ };
36
+ },
37
+ async *sendMessage() {
38
+ yield { type: "text", data: "无可用的 Adapter" }, yield { type: "done", data: "" };
39
+ },
40
+ cancel() {
41
+ }
42
+ };
43
+ }
44
+ function me() {
45
+ return Date.now().toString(36) + Math.random().toString(36).substr(2);
46
+ }
47
+ function nt(e) {
48
+ return {
49
+ id: e.id,
50
+ role: e.role,
51
+ content: e.content,
52
+ thinking: e.thinking || void 0,
53
+ thinkingComplete: !0,
54
+ toolCalls: e.toolCalls ? JSON.parse(e.toolCalls) : void 0,
55
+ searchResults: e.searchResults ? JSON.parse(e.searchResults) : void 0,
56
+ searching: !1,
57
+ timestamp: e.timestamp
58
+ };
59
+ }
60
+ function st(e = {}) {
61
+ const {
62
+ adapter: h = tt(),
63
+ defaultModel: g = "anthropic/claude-opus-4.5",
64
+ defaultMode: a = "agent"
65
+ } = e, c = M([]), f = M(null), s = M([]), m = M(a), D = M(g), y = M(!0), x = M(!0), A = M(!1), N = Ae(null);
66
+ async function P() {
67
+ try {
68
+ const d = await h.getSessions();
69
+ c.value = d, d.length > 0 && !f.value && await O(d[0].id);
70
+ } catch (d) {
71
+ console.error("加载会话失败:", d);
72
+ }
73
+ }
74
+ async function O(d) {
75
+ if (f.value !== d) {
76
+ f.value = d;
77
+ try {
78
+ const w = await h.getMessages(d);
79
+ s.value = w.map(nt);
80
+ const r = c.value.find((R) => R.id === d);
81
+ r && (m.value = r.mode, D.value = r.model);
82
+ } catch (w) {
83
+ console.error("加载消息失败:", w), s.value = [];
84
+ }
85
+ }
86
+ }
87
+ async function J() {
88
+ try {
89
+ const d = await h.createSession({
90
+ title: "新对话",
91
+ model: D.value,
92
+ mode: m.value
93
+ });
94
+ c.value = [d, ...c.value], f.value = d.id, s.value = [];
95
+ } catch (d) {
96
+ console.error("创建会话失败:", d);
97
+ }
98
+ }
99
+ async function I(d) {
100
+ try {
101
+ await h.deleteSession(d), c.value = c.value.filter((w) => w.id !== d), f.value === d && (c.value.length > 0 ? await O(c.value[0].id) : (f.value = null, s.value = []));
102
+ } catch (w) {
103
+ console.error("删除会话失败:", w);
104
+ }
105
+ }
106
+ async function T() {
107
+ f.value && await I(f.value);
108
+ }
109
+ function F(d, w) {
110
+ const r = s.value[d];
111
+ if (r) {
112
+ switch (w.type) {
113
+ case "thinking": {
114
+ const R = w.data;
115
+ R.content && (r.thinking = (r.thinking || "") + R.content), r.thinkingComplete = R.isComplete;
116
+ break;
117
+ }
118
+ case "search_start":
119
+ r.searching = !0;
120
+ break;
121
+ case "search_result": {
122
+ r.searching = !1;
123
+ const R = w.data;
124
+ r.searchResults = R.results || [];
125
+ break;
126
+ }
127
+ case "tool_call": {
128
+ const R = w.data;
129
+ r.toolCalls || (r.toolCalls = []), r.toolCalls.push({
130
+ name: R.name,
131
+ args: R.args,
132
+ status: "running"
133
+ });
134
+ break;
135
+ }
136
+ case "tool_result": {
137
+ const R = w.data;
138
+ r.toolCalls && (r.toolCalls = r.toolCalls.map((U) => U.name === R.name && U.status === "running" ? { ...U, result: R.result, status: "success" } : U));
139
+ break;
140
+ }
141
+ case "text_delta":
142
+ r.content = (r.content || "") + w.data;
143
+ break;
144
+ case "text":
145
+ r.content || (r.content = w.data);
146
+ break;
147
+ case "error":
148
+ r.content = (r.content || "") + `
149
+
150
+ ❌ 错误: ${w.data}`;
151
+ break;
152
+ }
153
+ s.value = [...s.value];
154
+ }
155
+ }
156
+ async function C(d, w) {
157
+ var u;
158
+ if (!d.trim() || A.value) return;
159
+ let r = f.value;
160
+ if (!r)
161
+ try {
162
+ const o = await h.createSession({
163
+ title: "新对话",
164
+ model: D.value,
165
+ mode: m.value
166
+ });
167
+ c.value = [o, ...c.value], f.value = o.id, r = o.id;
168
+ } catch (o) {
169
+ console.error("创建会话失败:", o);
170
+ return;
171
+ }
172
+ const R = {
173
+ id: me(),
174
+ role: "user",
175
+ content: d,
176
+ images: w,
177
+ timestamp: /* @__PURE__ */ new Date()
178
+ };
179
+ s.value = [...s.value, R];
180
+ try {
181
+ if (await h.saveMessage({
182
+ sessionId: r,
183
+ role: "user",
184
+ content: d
185
+ }), s.value.length === 1) {
186
+ const o = d.slice(0, 20) + (d.length > 20 ? "..." : "");
187
+ await h.updateSession(r, { title: o }), c.value = c.value.map(
188
+ ($) => $.id === r ? { ...$, title: o } : $
189
+ );
190
+ }
191
+ } catch (o) {
192
+ console.error("保存消息失败:", o);
193
+ }
194
+ const U = s.value.length, Y = {
195
+ id: me(),
196
+ role: "assistant",
197
+ content: "",
198
+ toolCalls: [],
199
+ thinkingComplete: !1,
200
+ searching: !1,
201
+ loading: !0,
202
+ timestamp: /* @__PURE__ */ new Date()
203
+ };
204
+ s.value = [...s.value, Y], A.value = !0, N.value = new AbortController();
205
+ try {
206
+ for await (const o of h.sendMessage(
207
+ d,
208
+ {
209
+ mode: m.value,
210
+ model: D.value,
211
+ enableWebSearch: y.value,
212
+ thinkingMode: x.value ? "enabled" : "disabled"
213
+ },
214
+ w
215
+ ))
216
+ if ((u = N.value) != null && u.signal.aborted || (F(U, o), o.type === "done" || o.type === "error"))
217
+ break;
218
+ } catch (o) {
219
+ console.error("发送消息失败:", o), F(U, {
220
+ type: "error",
221
+ data: o instanceof Error ? o.message : String(o)
222
+ });
223
+ } finally {
224
+ A.value = !1;
225
+ const o = s.value[U];
226
+ o && (o.loading = !1, s.value = [...s.value], r && h.saveMessage({
227
+ sessionId: r,
228
+ role: "assistant",
229
+ content: o.content,
230
+ thinking: o.thinking,
231
+ toolCalls: o.toolCalls ? JSON.stringify(o.toolCalls) : void 0,
232
+ searchResults: o.searchResults ? JSON.stringify(o.searchResults) : void 0
233
+ }).catch(($) => console.error("保存助手消息失败:", $))), N.value = null;
234
+ }
235
+ }
236
+ function v() {
237
+ var d;
238
+ h.cancel(), (d = N.value) == null || d.abort(), A.value = !1;
239
+ }
240
+ async function b(d) {
241
+ const w = s.value.find((r) => r.id === d);
242
+ if (w)
243
+ try {
244
+ await navigator.clipboard.writeText(w.content), s.value = s.value.map(
245
+ (r) => r.id === d ? { ...r, copied: !0 } : r
246
+ ), setTimeout(() => {
247
+ s.value = s.value.map(
248
+ (r) => r.id === d ? { ...r, copied: !1 } : r
249
+ );
250
+ }, 2e3);
251
+ } catch (r) {
252
+ console.error("复制失败:", r);
253
+ }
254
+ }
255
+ function V(d) {
256
+ var w;
257
+ if (d > 0 && ((w = s.value[d - 1]) == null ? void 0 : w.role) === "user") {
258
+ const r = s.value[d - 1];
259
+ s.value = s.value.slice(0, d - 1), C(r.content, r.images);
260
+ }
261
+ }
262
+ function G(d) {
263
+ h.setWorkingDir && h.setWorkingDir(d);
264
+ }
265
+ return {
266
+ // 状态
267
+ sessions: c,
268
+ currentSessionId: f,
269
+ messages: s,
270
+ isLoading: A,
271
+ mode: m,
272
+ model: D,
273
+ webSearch: y,
274
+ thinking: x,
275
+ // 会话方法
276
+ loadSessions: P,
277
+ switchSession: O,
278
+ createNewSession: J,
279
+ deleteSession: I,
280
+ deleteCurrentSession: T,
281
+ // 消息方法
282
+ sendMessage: C,
283
+ cancelRequest: v,
284
+ copyMessage: b,
285
+ regenerateMessage: V,
286
+ // 配置方法
287
+ setMode: (d) => {
288
+ m.value = d;
289
+ },
290
+ setModel: (d) => {
291
+ D.value = d;
292
+ },
293
+ setWebSearch: (d) => {
294
+ y.value = d;
295
+ },
296
+ setThinking: (d) => {
297
+ x.value = d;
298
+ },
299
+ // 工具方法
300
+ setWorkingDirectory: G
301
+ };
302
+ }
303
+ const we = [
304
+ {
305
+ provider: "openrouter",
306
+ model: "anthropic/claude-opus-4.5",
307
+ displayName: "Claude Opus 4.5",
308
+ supportsTools: !0,
309
+ supportsWebSearch: !0,
310
+ supportedThinkingModes: ["enabled", "disabled"]
311
+ },
312
+ {
313
+ provider: "doubao",
314
+ model: "doubao-seed-1-6-251015",
315
+ displayName: "Doubao Seed",
316
+ supportsTools: !0,
317
+ supportsWebSearch: !0,
318
+ supportedThinkingModes: ["enabled", "disabled"]
319
+ },
320
+ {
321
+ provider: "deepseek",
322
+ model: "deepseek-v3-1-terminus",
323
+ displayName: "DeepSeek V3",
324
+ supportsTools: !0,
325
+ supportsWebSearch: !0,
326
+ supportedThinkingModes: ["enabled", "disabled"]
327
+ },
328
+ {
329
+ provider: "qwen",
330
+ model: "qwen3-max-preview",
331
+ displayName: "Qwen Max",
332
+ supportsTools: !0,
333
+ supportsWebSearch: !0,
334
+ supportedThinkingModes: ["enabled", "disabled"]
335
+ },
336
+ {
337
+ provider: "gemini",
338
+ model: "gemini-3-pro-preview",
339
+ displayName: "Gemini 3 Pro",
340
+ supportsTools: !0,
341
+ supportsWebSearch: !0,
342
+ supportedThinkingModes: ["enabled", "disabled"]
343
+ }
344
+ ];
345
+ var lt = /* @__PURE__ */ ((e) => (e.FOLDER = "folder", e.IMAGE = "image", e.VIDEO = "video", e.AUDIO = "audio", e.TEXT = "text", e.PDF = "pdf", e.CODE = "code", e.ARCHIVE = "archive", e.OTHER = "other", e))(lt || {});
346
+ const at = { class: "chat-header" }, ot = { class: "tabs-container" }, it = {
347
+ key: 0,
348
+ class: "tab-item active"
349
+ }, ct = ["title", "onClick"], rt = { class: "tab-title" }, ut = ["onClick"], dt = { class: "header-actions" }, vt = {
350
+ key: 0,
351
+ class: "dropdown-panel history-panel"
352
+ }, ht = { class: "panel-header" }, gt = { class: "panel-content" }, mt = ["onClick"], ft = { class: "history-title" }, kt = { class: "history-date" }, pt = ["onClick"], yt = {
353
+ key: 0,
354
+ class: "empty-state"
355
+ }, bt = {
356
+ key: 0,
357
+ class: "dropdown-panel more-panel"
358
+ }, Ct = /* @__PURE__ */ K({
359
+ __name: "ChatHeader",
360
+ props: {
361
+ sessions: {},
362
+ currentSessionId: {},
363
+ showClose: { type: Boolean }
364
+ },
365
+ emits: ["new-session", "switch-session", "delete-session", "close", "clear-all", "close-others", "export", "copy-id", "feedback", "settings"],
366
+ setup(e, { emit: h }) {
367
+ const g = e, a = h, c = M(/* @__PURE__ */ new Set()), f = H(
368
+ () => g.sessions.filter((C) => !c.value.has(C.id))
369
+ ), s = M(!1), m = M(!1), D = M(null), y = M(null);
370
+ function x(C) {
371
+ return C === "新对话" ? "New Chat" : C;
372
+ }
373
+ function A(C) {
374
+ const v = new Date(C), V = (/* @__PURE__ */ new Date()).getTime() - v.getTime(), G = Math.floor(V / (1e3 * 60 * 60 * 24));
375
+ return G === 0 ? "今天" : G === 1 ? "昨天" : G < 7 ? `${G}天前` : v.toLocaleDateString();
376
+ }
377
+ function N(C) {
378
+ if (c.value = /* @__PURE__ */ new Set([...c.value, C]), C === g.currentSessionId) {
379
+ const v = g.sessions.filter(
380
+ (b) => b.id !== C && !c.value.has(b.id)
381
+ );
382
+ v.length > 0 && a("switch-session", v[0].id);
383
+ }
384
+ }
385
+ function P() {
386
+ s.value = !s.value, m.value = !1;
387
+ }
388
+ function O() {
389
+ m.value = !m.value, s.value = !1;
390
+ }
391
+ function J() {
392
+ a("new-session"), s.value = !1;
393
+ }
394
+ function I(C) {
395
+ if (a("switch-session", C), c.value.has(C)) {
396
+ const v = new Set(c.value);
397
+ v.delete(C), c.value = v;
398
+ }
399
+ s.value = !1;
400
+ }
401
+ function T(C) {
402
+ switch (m.value = !1, C) {
403
+ case "clear-all":
404
+ a("clear-all");
405
+ break;
406
+ case "close-others":
407
+ a("close-others");
408
+ break;
409
+ case "export":
410
+ a("export");
411
+ break;
412
+ case "copy-id":
413
+ a("copy-id");
414
+ break;
415
+ case "feedback":
416
+ a("feedback");
417
+ break;
418
+ case "settings":
419
+ a("settings");
420
+ break;
421
+ }
422
+ }
423
+ function F(C) {
424
+ const v = C.target;
425
+ D.value && !D.value.contains(v) && (s.value = !1), y.value && !y.value.contains(v) && (m.value = !1);
426
+ }
427
+ return oe(() => {
428
+ document.addEventListener("click", F);
429
+ }), fe(() => {
430
+ document.removeEventListener("click", F);
431
+ }), (C, v) => (n(), i("div", at, [
432
+ t("div", ot, [
433
+ f.value.length === 0 ? (n(), i("span", it, " New Chat ")) : (n(!0), i(B, { key: 1 }, q(f.value, (b) => (n(), i("div", {
434
+ key: b.id,
435
+ class: E(["tab-item", { active: b.id === e.currentSessionId }]),
436
+ title: b.title,
437
+ onClick: (V) => C.$emit("switch-session", b.id)
438
+ }, [
439
+ t("span", rt, z(x(b.title)), 1),
440
+ t("button", {
441
+ class: "tab-close",
442
+ onClick: X((V) => N(b.id), ["stop"]),
443
+ title: "关闭标签"
444
+ }, [
445
+ S(l(ne), { size: 12 })
446
+ ], 8, ut)
447
+ ], 10, ct))), 128))
448
+ ]),
449
+ t("div", dt, [
450
+ t("button", {
451
+ class: "icon-btn",
452
+ title: "新建对话",
453
+ onClick: v[0] || (v[0] = (b) => C.$emit("new-session"))
454
+ }, [
455
+ S(l(de), { size: 14 })
456
+ ]),
457
+ t("div", {
458
+ ref_key: "historyRef",
459
+ ref: D,
460
+ class: "dropdown-container"
461
+ }, [
462
+ t("button", {
463
+ class: E(["icon-btn", { active: s.value }]),
464
+ title: "历史记录",
465
+ onClick: X(P, ["stop"])
466
+ }, [
467
+ S(l(He), { size: 14 })
468
+ ], 2),
469
+ s.value ? (n(), i("div", vt, [
470
+ t("div", ht, [
471
+ v[8] || (v[8] = t("span", null, "历史记录", -1)),
472
+ t("button", {
473
+ class: "icon-btn small",
474
+ title: "新建对话",
475
+ onClick: J
476
+ }, [
477
+ S(l(de), { size: 12 })
478
+ ])
479
+ ]),
480
+ t("div", gt, [
481
+ (n(!0), i(B, null, q(e.sessions, (b) => (n(), i("div", {
482
+ key: b.id,
483
+ class: E(["history-item", { active: b.id === e.currentSessionId }]),
484
+ onClick: (V) => I(b.id)
485
+ }, [
486
+ t("span", ft, z(b.title), 1),
487
+ t("span", kt, z(A(b.updatedAt)), 1),
488
+ t("button", {
489
+ class: "history-delete",
490
+ title: "删除",
491
+ onClick: X((V) => C.$emit("delete-session", b.id), ["stop"])
492
+ }, [
493
+ S(l(ve), { size: 12 })
494
+ ], 8, pt)
495
+ ], 10, mt))), 128)),
496
+ e.sessions.length === 0 ? (n(), i("div", yt, " 暂无历史对话 ")) : p("", !0)
497
+ ])
498
+ ])) : p("", !0)
499
+ ], 512),
500
+ t("div", {
501
+ ref_key: "moreRef",
502
+ ref: y,
503
+ class: "dropdown-container"
504
+ }, [
505
+ t("button", {
506
+ class: E(["icon-btn", { active: m.value }]),
507
+ title: "更多选项",
508
+ onClick: X(O, ["stop"])
509
+ }, [
510
+ S(l(We), { size: 14 })
511
+ ], 2),
512
+ m.value ? (n(), i("div", bt, [
513
+ t("button", {
514
+ class: "menu-item",
515
+ onClick: v[1] || (v[1] = (b) => T("clear-all"))
516
+ }, [
517
+ S(l(ve), { size: 14 }),
518
+ v[9] || (v[9] = t("span", null, "清空所有对话", -1))
519
+ ]),
520
+ t("button", {
521
+ class: "menu-item",
522
+ onClick: v[2] || (v[2] = (b) => T("close-others"))
523
+ }, [
524
+ S(l(qe), { size: 14 }),
525
+ v[10] || (v[10] = t("span", null, "关闭其他对话", -1))
526
+ ]),
527
+ v[15] || (v[15] = t("div", { class: "menu-divider" }, null, -1)),
528
+ t("button", {
529
+ class: "menu-item",
530
+ onClick: v[3] || (v[3] = (b) => T("export"))
531
+ }, [
532
+ S(l(Ve), { size: 14 }),
533
+ v[11] || (v[11] = t("span", null, "导出对话", -1))
534
+ ]),
535
+ t("button", {
536
+ class: "menu-item",
537
+ onClick: v[4] || (v[4] = (b) => T("copy-id"))
538
+ }, [
539
+ S(l(ke), { size: 14 }),
540
+ v[12] || (v[12] = t("span", null, "复制请求 ID", -1))
541
+ ]),
542
+ v[16] || (v[16] = t("div", { class: "menu-divider" }, null, -1)),
543
+ t("button", {
544
+ class: "menu-item",
545
+ onClick: v[5] || (v[5] = (b) => T("feedback"))
546
+ }, [
547
+ S(l(Pe), { size: 14 }),
548
+ v[13] || (v[13] = t("span", null, "反馈", -1))
549
+ ]),
550
+ t("button", {
551
+ class: "menu-item",
552
+ onClick: v[6] || (v[6] = (b) => T("settings"))
553
+ }, [
554
+ S(l(Je), { size: 14 }),
555
+ v[14] || (v[14] = t("span", null, "Agent 设置", -1))
556
+ ])
557
+ ])) : p("", !0)
558
+ ], 512),
559
+ e.showClose ? (n(), i("button", {
560
+ key: 0,
561
+ class: "icon-btn",
562
+ title: "关闭",
563
+ onClick: v[7] || (v[7] = (b) => C.$emit("close"))
564
+ }, [
565
+ S(l(ne), { size: 14 })
566
+ ])) : p("", !0)
567
+ ])
568
+ ]));
569
+ }
570
+ }), Q = (e, h) => {
571
+ const g = e.__vccOpts || e;
572
+ for (const [a, c] of h)
573
+ g[a] = c;
574
+ return g;
575
+ }, $t = /* @__PURE__ */ Q(Ct, [["__scopeId", "data-v-fd156e6a"]]), wt = { class: "welcome-message" }, St = { class: "welcome-icon" }, Mt = { class: "quick-actions" }, zt = ["onClick"], Rt = /* @__PURE__ */ K({
576
+ __name: "WelcomeMessage",
577
+ emits: ["quick-action"],
578
+ setup(e) {
579
+ const h = [
580
+ {
581
+ id: "code",
582
+ label: "写代码",
583
+ prompt: "帮我写一段代码",
584
+ icon: W(Fe)
585
+ },
586
+ {
587
+ id: "explain",
588
+ label: "解释代码",
589
+ prompt: "帮我解释这段代码",
590
+ icon: W(pe)
591
+ },
592
+ {
593
+ id: "search",
594
+ label: "搜索信息",
595
+ prompt: "帮我搜索一下",
596
+ icon: W(ye)
597
+ },
598
+ {
599
+ id: "chat",
600
+ label: "聊聊天",
601
+ prompt: "我们聊聊天吧",
602
+ icon: W(be)
603
+ }
604
+ ];
605
+ return (g, a) => (n(), i("div", wt, [
606
+ t("div", St, [
607
+ S(l(Ce), { size: 48 })
608
+ ]),
609
+ a[0] || (a[0] = t("h3", { class: "welcome-title" }, "AI Assistant", -1)),
610
+ a[1] || (a[1] = t("p", { class: "welcome-desc" }, "我可以帮你完成各种任务,试试下面的快捷操作:", -1)),
611
+ t("div", Mt, [
612
+ (n(), i(B, null, q(h, (c) => t("button", {
613
+ key: c.id,
614
+ class: "quick-btn",
615
+ onClick: (f) => g.$emit("quick-action", c.prompt)
616
+ }, [
617
+ (n(), k(te(c.icon), {
618
+ size: 14,
619
+ class: "quick-icon"
620
+ })),
621
+ t("span", null, z(c.label), 1)
622
+ ], 8, zt)), 64))
623
+ ])
624
+ ]));
625
+ }
626
+ }), Dt = /* @__PURE__ */ Q(Rt, [["__scopeId", "data-v-f478d3aa"]]), It = {
627
+ key: 0,
628
+ class: "attachment-preview"
629
+ }, Tt = { class: "preview-images" }, xt = ["src"], Et = ["title", "onClick"], At = {
630
+ key: 0,
631
+ class: "preview-more"
632
+ }, Nt = { class: "input-field-wrapper" }, Bt = ["placeholder"], Lt = {
633
+ key: 1,
634
+ class: "input-controls"
635
+ }, Ot = { class: "input-left" }, Ut = ["onClick"], _t = ["onClick"], Ht = { class: "input-right" }, Wt = ["title"], qt = {
636
+ key: 1,
637
+ class: "icon-btn",
638
+ title: "语音输入"
639
+ }, Vt = /* @__PURE__ */ K({
640
+ __name: "ChatInput",
641
+ props: {
642
+ variant: { default: "input" },
643
+ value: { default: "" },
644
+ selectedImages: { default: () => [] },
645
+ isLoading: { type: Boolean, default: !1 },
646
+ mode: { default: "agent" },
647
+ model: { default: "" },
648
+ models: { default: () => we },
649
+ webSearchEnabled: { type: Boolean, default: !1 },
650
+ thinkingEnabled: { type: Boolean, default: !1 }
651
+ },
652
+ emits: ["send", "remove-image", "cancel", "upload-image", "at-context", "update:mode", "update:model", "update:webSearch", "update:thinking"],
653
+ setup(e, { expose: h, emit: g }) {
654
+ const a = e, c = g, f = H(() => a.variant === "message"), s = M(a.value), m = M(null), D = M(null), y = M(!1);
655
+ ae(
656
+ () => a.value,
657
+ (u) => {
658
+ s.value = u;
659
+ }
660
+ );
661
+ const x = [
662
+ { value: "agent", label: "Agent", icon: W(he) },
663
+ { value: "ask", label: "Ask", icon: W(be) }
664
+ ], A = M(!1), N = M(!1), P = H(() => !f.value || y.value), O = H(() => a.selectedImages.slice(0, 3)), J = H(() => a.selectedImages.length > 0 ? "描述你想要的效果..." : a.mode === "ask" ? "有什么问题想问我?" : "描述任务,@ 添加上下文"), I = H(() => {
665
+ const u = x.find((o) => o.value === a.mode);
666
+ return (u == null ? void 0 : u.label) || "Agent";
667
+ }), T = H(() => {
668
+ const u = x.find((o) => o.value === a.mode);
669
+ return (u == null ? void 0 : u.icon) || he;
670
+ }), F = H(() => {
671
+ const u = a.models.find((o) => o.model === a.model);
672
+ return (u == null ? void 0 : u.displayName) || "Auto";
673
+ });
674
+ function C() {
675
+ A.value = !A.value, N.value = !1;
676
+ }
677
+ function v() {
678
+ N.value = !N.value, A.value = !1;
679
+ }
680
+ function b(u) {
681
+ c("update:mode", u), A.value = !1;
682
+ }
683
+ function V(u) {
684
+ c("update:model", u.model), N.value = !1;
685
+ }
686
+ function G(u) {
687
+ return u.startsWith("app://") || u.startsWith("file://") || u.startsWith("data:") || u.startsWith("http") ? u : u.match(/^[A-Z]:\\/i) ? `app://file${encodeURIComponent(u.replace(/\\/g, "/"))}` : `app://file${encodeURIComponent(u)}`;
688
+ }
689
+ function d(u) {
690
+ const o = u.target;
691
+ o.style.display = "none";
692
+ }
693
+ function w(u) {
694
+ c("remove-image", u);
695
+ }
696
+ function r() {
697
+ if (m.value) {
698
+ m.value.style.height = "auto";
699
+ const u = m.value.scrollHeight;
700
+ m.value.style.height = `${Math.min(u, 150)}px`;
701
+ }
702
+ }
703
+ function R() {
704
+ var o;
705
+ if (a.isLoading) {
706
+ c("cancel");
707
+ return;
708
+ }
709
+ const u = s.value.trim();
710
+ u && (c("send", u), f.value ? y.value = !1 : (s.value = "", m.value && (m.value.style.height = "auto"), (o = m.value) == null || o.focus()));
711
+ }
712
+ function U(u) {
713
+ u.key === "Enter" && !u.shiftKey ? (u.preventDefault(), R()) : setTimeout(r, 0);
714
+ }
715
+ function Y(u) {
716
+ const o = u.target;
717
+ o.closest(".selector") || (A.value = !1, N.value = !1), f.value && D.value && !D.value.contains(o) && (y.value = !1);
718
+ }
719
+ return oe(() => {
720
+ document.addEventListener("click", Y);
721
+ }), fe(() => {
722
+ document.removeEventListener("click", Y);
723
+ }), h({
724
+ focus: () => {
725
+ var u;
726
+ return (u = m.value) == null ? void 0 : u.focus();
727
+ },
728
+ setText: (u) => {
729
+ s.value = u;
730
+ },
731
+ clear: () => {
732
+ s.value = "";
733
+ }
734
+ }), (u, o) => (n(), i("div", {
735
+ class: E(["chat-input", { "message-variant": f.value }])
736
+ }, [
737
+ t("div", {
738
+ ref_key: "containerRef",
739
+ ref: D,
740
+ class: E(["input-container", { focused: y.value }])
741
+ }, [
742
+ e.selectedImages.length > 0 ? (n(), i("div", It, [
743
+ t("div", Tt, [
744
+ (n(!0), i(B, null, q(O.value, ($, Z) => (n(), i("div", {
745
+ key: `${$}-${Z}`,
746
+ class: "preview-item"
747
+ }, [
748
+ t("img", {
749
+ src: G($),
750
+ class: "preview-thumb",
751
+ onError: d
752
+ }, null, 40, xt),
753
+ f.value ? p("", !0) : (n(), i("button", {
754
+ key: 0,
755
+ class: "remove-btn",
756
+ title: `移除图片 ${Z + 1}`,
757
+ onClick: (ce) => w(Z)
758
+ }, [
759
+ S(l(ne), { size: 10 })
760
+ ], 8, Et))
761
+ ]))), 128)),
762
+ e.selectedImages.length > 3 ? (n(), i("div", At, " +" + z(e.selectedImages.length - 3), 1)) : p("", !0)
763
+ ])
764
+ ])) : p("", !0),
765
+ t("div", Nt, [
766
+ Ne(t("textarea", {
767
+ ref_key: "inputRef",
768
+ ref: m,
769
+ "onUpdate:modelValue": o[0] || (o[0] = ($) => s.value = $),
770
+ placeholder: J.value,
771
+ rows: "1",
772
+ class: "input-field",
773
+ onKeydown: U,
774
+ onInput: r,
775
+ onFocus: o[1] || (o[1] = ($) => y.value = !0)
776
+ }, null, 40, Bt), [
777
+ [Be, s.value]
778
+ ])
779
+ ]),
780
+ P.value ? (n(), i("div", Lt, [
781
+ t("div", Ot, [
782
+ t("div", {
783
+ class: "selector mode-selector",
784
+ onClick: X(C, ["stop"])
785
+ }, [
786
+ (n(), k(te(T.value), { size: 12 })),
787
+ t("span", null, z(I.value), 1),
788
+ S(l(j), {
789
+ size: 10,
790
+ class: "chevron"
791
+ }),
792
+ A.value ? (n(), i("div", {
793
+ key: 0,
794
+ class: "dropdown-menu",
795
+ onClick: o[2] || (o[2] = X(() => {
796
+ }, ["stop"]))
797
+ }, [
798
+ (n(), i(B, null, q(x, ($) => t("button", {
799
+ key: $.value,
800
+ class: E(["dropdown-item", { active: e.mode === $.value }]),
801
+ onClick: (Z) => b($.value)
802
+ }, [
803
+ (n(), k(te($.icon), { size: 14 })),
804
+ t("span", null, z($.label), 1),
805
+ e.mode === $.value ? (n(), k(l(se), {
806
+ key: 0,
807
+ size: 14,
808
+ class: "check-icon"
809
+ })) : p("", !0)
810
+ ], 10, Ut)), 64))
811
+ ])) : p("", !0)
812
+ ]),
813
+ t("div", {
814
+ class: "selector model-selector",
815
+ onClick: X(v, ["stop"])
816
+ }, [
817
+ t("span", null, z(F.value), 1),
818
+ S(l(j), {
819
+ size: 10,
820
+ class: "chevron"
821
+ }),
822
+ N.value ? (n(), i("div", {
823
+ key: 0,
824
+ class: "dropdown-menu",
825
+ onClick: o[3] || (o[3] = X(() => {
826
+ }, ["stop"]))
827
+ }, [
828
+ (n(!0), i(B, null, q(e.models, ($) => (n(), i("button", {
829
+ key: $.model,
830
+ class: E(["dropdown-item", { active: e.model === $.model }]),
831
+ onClick: (Z) => V($)
832
+ }, [
833
+ t("span", null, z($.displayName), 1),
834
+ e.model === $.model ? (n(), k(l(se), {
835
+ key: 0,
836
+ size: 14,
837
+ class: "check-icon"
838
+ })) : p("", !0)
839
+ ], 10, _t))), 128))
840
+ ])) : p("", !0)
841
+ ])
842
+ ]),
843
+ t("div", Ht, [
844
+ t("button", {
845
+ class: "icon-btn",
846
+ title: "提及上下文 (@)",
847
+ onClick: o[4] || (o[4] = ($) => u.$emit("at-context"))
848
+ }, [
849
+ S(l(Ge), { size: 14 })
850
+ ]),
851
+ t("button", {
852
+ class: E(["toggle-btn", { active: e.thinkingEnabled }]),
853
+ title: "深度思考",
854
+ onClick: o[5] || (o[5] = ($) => u.$emit("update:thinking", !e.thinkingEnabled))
855
+ }, [
856
+ S(l(Ce), { size: 14 })
857
+ ], 2),
858
+ t("button", {
859
+ class: E(["toggle-btn", { active: e.webSearchEnabled }]),
860
+ title: "联网搜索",
861
+ onClick: o[6] || (o[6] = ($) => u.$emit("update:webSearch", !e.webSearchEnabled))
862
+ }, [
863
+ S(l(ie), { size: 14 })
864
+ ], 2),
865
+ t("button", {
866
+ class: "icon-btn",
867
+ title: "上传图片",
868
+ onClick: o[7] || (o[7] = ($) => u.$emit("upload-image"))
869
+ }, [
870
+ S(l(Ke), { size: 14 })
871
+ ]),
872
+ s.value.trim() || e.isLoading ? (n(), i("button", {
873
+ key: 0,
874
+ class: E(["send-btn", { loading: e.isLoading }]),
875
+ title: e.isLoading ? "停止" : f.value ? "重新发送" : "发送",
876
+ onClick: R
877
+ }, [
878
+ e.isLoading ? (n(), k(l(Qe), {
879
+ key: 0,
880
+ size: 14
881
+ })) : (n(), k(l(Xe), {
882
+ key: 1,
883
+ size: 14
884
+ }))
885
+ ], 10, Wt)) : (n(), i("button", qt, [
886
+ S(l(je), { size: 14 })
887
+ ]))
888
+ ])
889
+ ])) : p("", !0)
890
+ ], 2)
891
+ ], 2));
892
+ }
893
+ }), Se = /* @__PURE__ */ Q(Vt, [["__scopeId", "data-v-79ec50ab"]]), Pt = {
894
+ key: 0,
895
+ class: "execution-steps"
896
+ }, Jt = {
897
+ key: 0,
898
+ class: "step thinking-step"
899
+ }, Ft = { class: "step-icon" }, Gt = { class: "step-title" }, Kt = {
900
+ key: 0,
901
+ class: "step-content"
902
+ }, Qt = { class: "thinking-content" }, Xt = {
903
+ key: 1,
904
+ class: "step search-step"
905
+ }, jt = { class: "step-icon" }, Zt = { class: "step-title" }, Yt = {
906
+ key: 0,
907
+ class: "step-content"
908
+ }, en = { class: "search-results" }, tn = ["href"], nn = { class: "result-title" }, sn = { class: "result-url" }, ln = ["onClick"], an = { class: "step-icon" }, on = { class: "step-title" }, cn = {
909
+ key: 0,
910
+ class: "step-content"
911
+ }, rn = { class: "tool-result" }, un = /* @__PURE__ */ K({
912
+ __name: "ExecutionSteps",
913
+ props: {
914
+ loading: { type: Boolean },
915
+ hasContent: { type: Boolean },
916
+ thinking: {},
917
+ thinkingComplete: { type: Boolean },
918
+ searching: { type: Boolean },
919
+ searchResults: {},
920
+ toolCalls: {}
921
+ },
922
+ setup(e) {
923
+ const h = e, g = M(!1), a = M(!0), c = Le({}), f = H(() => {
924
+ var y, x;
925
+ return h.thinking || h.searching || ((y = h.searchResults) == null ? void 0 : y.length) || ((x = h.toolCalls) == null ? void 0 : x.length) || h.loading && !h.hasContent;
926
+ });
927
+ function s(y) {
928
+ c[y] = !c[y];
929
+ }
930
+ function m(y) {
931
+ try {
932
+ return new URL(y).hostname;
933
+ } catch {
934
+ return y;
935
+ }
936
+ }
937
+ function D(y) {
938
+ return {
939
+ web_search: "网页搜索",
940
+ read_file: "读取文件",
941
+ write_file: "写入文件",
942
+ execute_command: "执行命令",
943
+ list_directory: "列出目录",
944
+ create_directory: "创建目录",
945
+ delete_file: "删除文件",
946
+ move_file: "移动文件",
947
+ search_files: "搜索文件",
948
+ analyze_image: "分析图片"
949
+ }[y] || y;
950
+ }
951
+ return (y, x) => {
952
+ var A, N, P, O, J;
953
+ return f.value ? (n(), i("div", Pt, [
954
+ e.thinking || e.loading && !e.hasContent && !((A = e.toolCalls) != null && A.length) ? (n(), i("div", Jt, [
955
+ t("div", {
956
+ class: "step-header",
957
+ onClick: x[0] || (x[0] = (I) => g.value = !g.value)
958
+ }, [
959
+ t("div", Ft, [
960
+ e.thinkingComplete ? (n(), k(l($e), {
961
+ key: 1,
962
+ size: 14
963
+ })) : (n(), k(l(ee), {
964
+ key: 0,
965
+ size: 14,
966
+ class: "animate-spin"
967
+ }))
968
+ ]),
969
+ t("span", Gt, z(e.thinkingComplete ? "思考完成" : "正在思考..."), 1),
970
+ e.thinking ? (n(), k(l(j), {
971
+ key: 0,
972
+ size: 14,
973
+ class: E(["step-chevron", { expanded: g.value }])
974
+ }, null, 8, ["class"])) : p("", !0)
975
+ ]),
976
+ e.thinking && g.value ? (n(), i("div", Kt, [
977
+ t("div", Qt, z(e.thinking), 1)
978
+ ])) : p("", !0)
979
+ ])) : p("", !0),
980
+ e.searching || (N = e.searchResults) != null && N.length ? (n(), i("div", Xt, [
981
+ t("div", {
982
+ class: "step-header",
983
+ onClick: x[1] || (x[1] = (I) => a.value = !a.value)
984
+ }, [
985
+ t("div", jt, [
986
+ e.searching ? (n(), k(l(ee), {
987
+ key: 0,
988
+ size: 14,
989
+ class: "animate-spin"
990
+ })) : (n(), k(l(ie), {
991
+ key: 1,
992
+ size: 14
993
+ }))
994
+ ]),
995
+ t("span", Zt, z(e.searching ? "正在搜索..." : `找到 ${((P = e.searchResults) == null ? void 0 : P.length) || 0} 条结果`), 1),
996
+ (O = e.searchResults) != null && O.length ? (n(), k(l(j), {
997
+ key: 0,
998
+ size: 14,
999
+ class: E(["step-chevron", { expanded: a.value }])
1000
+ }, null, 8, ["class"])) : p("", !0)
1001
+ ]),
1002
+ (J = e.searchResults) != null && J.length && a.value ? (n(), i("div", Yt, [
1003
+ t("div", en, [
1004
+ (n(!0), i(B, null, q(e.searchResults, (I, T) => (n(), i("a", {
1005
+ key: T,
1006
+ href: I.url,
1007
+ target: "_blank",
1008
+ class: "search-result"
1009
+ }, [
1010
+ t("span", nn, z(I.title), 1),
1011
+ t("span", sn, z(m(I.url)), 1)
1012
+ ], 8, tn))), 128))
1013
+ ])
1014
+ ])) : p("", !0)
1015
+ ])) : p("", !0),
1016
+ (n(!0), i(B, null, q(e.toolCalls, (I, T) => (n(), i("div", {
1017
+ key: T,
1018
+ class: "step tool-step"
1019
+ }, [
1020
+ t("div", {
1021
+ class: "step-header",
1022
+ onClick: (F) => s(T)
1023
+ }, [
1024
+ t("div", an, [
1025
+ I.status === "running" ? (n(), k(l(ee), {
1026
+ key: 0,
1027
+ size: 14,
1028
+ class: "animate-spin"
1029
+ })) : I.status === "success" ? (n(), k(l(se), {
1030
+ key: 1,
1031
+ size: 14,
1032
+ class: "text-green"
1033
+ })) : (n(), k(l(ne), {
1034
+ key: 2,
1035
+ size: 14,
1036
+ class: "text-red"
1037
+ }))
1038
+ ]),
1039
+ t("span", on, z(D(I.name)), 1),
1040
+ I.result ? (n(), k(l(j), {
1041
+ key: 0,
1042
+ size: 14,
1043
+ class: E(["step-chevron", { expanded: c[T] }])
1044
+ }, null, 8, ["class"])) : p("", !0)
1045
+ ], 8, ln),
1046
+ I.result && c[T] ? (n(), i("div", cn, [
1047
+ t("pre", rn, z(I.result), 1)
1048
+ ])) : p("", !0)
1049
+ ]))), 128))
1050
+ ])) : p("", !0);
1051
+ };
1052
+ }
1053
+ }), dn = /* @__PURE__ */ Q(un, [["__scopeId", "data-v-5ad7fab1"]]), vn = {
1054
+ key: 1,
1055
+ class: "user-content"
1056
+ }, hn = { class: "user-text" }, gn = {
1057
+ key: 0,
1058
+ class: "user-images"
1059
+ }, mn = ["src", "onClick"], fn = { class: "assistant-content" }, kn = ["innerHTML"], pn = {
1060
+ key: 1,
1061
+ class: "loading-indicator"
1062
+ }, yn = {
1063
+ key: 0,
1064
+ class: "message-actions"
1065
+ }, bn = /* @__PURE__ */ K({
1066
+ __name: "MessageBubble",
1067
+ props: {
1068
+ role: {},
1069
+ content: {},
1070
+ images: {},
1071
+ thinking: {},
1072
+ thinkingComplete: { type: Boolean },
1073
+ searchResults: {},
1074
+ searching: { type: Boolean },
1075
+ toolCalls: {},
1076
+ loading: { type: Boolean },
1077
+ copied: { type: Boolean },
1078
+ onSend: { type: Function }
1079
+ },
1080
+ emits: ["copy", "regenerate", "view-image", "send"],
1081
+ setup(e) {
1082
+ const h = e, g = H(() => {
1083
+ let a = h.content;
1084
+ return a = a.replace(/```(\w*)\n([\s\S]*?)```/g, '<pre class="code-block"><code>$2</code></pre>'), a = a.replace(/`([^`]+)`/g, '<code class="inline-code">$1</code>'), a = a.replace(/\*\*([^*]+)\*\*/g, "<strong>$1</strong>"), a = a.replace(/\*([^*]+)\*/g, "<em>$1</em>"), a = a.replace(/\n/g, "<br>"), a;
1085
+ });
1086
+ return (a, c) => {
1087
+ var f;
1088
+ return n(), i("div", {
1089
+ class: E(["message-bubble", e.role])
1090
+ }, [
1091
+ e.role === "user" ? (n(), i(B, { key: 0 }, [
1092
+ e.onSend ? (n(), k(Se, {
1093
+ key: 0,
1094
+ variant: "message",
1095
+ value: e.content,
1096
+ "selected-images": e.images,
1097
+ onSend: c[0] || (c[0] = (s) => a.$emit("send", s))
1098
+ }, null, 8, ["value", "selected-images"])) : (n(), i("div", vn, [
1099
+ t("div", hn, z(e.content), 1),
1100
+ e.images && e.images.length > 0 ? (n(), i("div", gn, [
1101
+ (n(!0), i(B, null, q(e.images, (s, m) => (n(), i("img", {
1102
+ key: m,
1103
+ src: s,
1104
+ class: "user-image",
1105
+ onClick: (D) => a.$emit("view-image", s)
1106
+ }, null, 8, mn))), 128))
1107
+ ])) : p("", !0)
1108
+ ]))
1109
+ ], 64)) : (n(), i(B, { key: 1 }, [
1110
+ t("div", fn, [
1111
+ S(dn, {
1112
+ loading: e.loading,
1113
+ "has-content": !!e.content,
1114
+ thinking: e.thinking,
1115
+ "thinking-complete": e.thinkingComplete,
1116
+ searching: e.searching,
1117
+ "search-results": e.searchResults,
1118
+ "tool-calls": e.toolCalls
1119
+ }, null, 8, ["loading", "has-content", "thinking", "thinking-complete", "searching", "search-results", "tool-calls"]),
1120
+ e.content ? (n(), i("div", {
1121
+ key: 0,
1122
+ class: "assistant-text",
1123
+ innerHTML: g.value
1124
+ }, null, 8, kn)) : p("", !0),
1125
+ e.loading && !e.content && !e.thinking && !((f = e.toolCalls) != null && f.length) ? (n(), i("div", pn, [...c[3] || (c[3] = [
1126
+ t("span", { class: "loading-dot" }, null, -1),
1127
+ t("span", { class: "loading-dot" }, null, -1),
1128
+ t("span", { class: "loading-dot" }, null, -1)
1129
+ ])])) : p("", !0)
1130
+ ]),
1131
+ e.content && !e.loading ? (n(), i("div", yn, [
1132
+ t("button", {
1133
+ class: "action-btn",
1134
+ title: "复制",
1135
+ onClick: c[1] || (c[1] = (s) => a.$emit("copy"))
1136
+ }, [
1137
+ (n(), k(te(e.copied ? l(se) : l(ke)), { size: 14 }))
1138
+ ]),
1139
+ t("button", {
1140
+ class: "action-btn",
1141
+ title: "重新生成",
1142
+ onClick: c[2] || (c[2] = (s) => a.$emit("regenerate"))
1143
+ }, [
1144
+ S(l(Ze), { size: 14 })
1145
+ ])
1146
+ ])) : p("", !0)
1147
+ ], 64))
1148
+ ], 2);
1149
+ };
1150
+ }
1151
+ }), Cn = /* @__PURE__ */ Q(bn, [["__scopeId", "data-v-bb746e4b"]]), $n = { class: "chat-panel" }, wn = /* @__PURE__ */ K({
1152
+ __name: "ChatPanel",
1153
+ props: {
1154
+ adapter: { default: void 0 },
1155
+ workingDir: { default: void 0 },
1156
+ defaultModel: { default: "anthropic/claude-opus-4.5" },
1157
+ defaultMode: { default: "agent" },
1158
+ models: { default: () => we },
1159
+ hideHeader: { type: Boolean, default: !1 },
1160
+ onClose: { type: Function, default: void 0 },
1161
+ className: { default: "" }
1162
+ },
1163
+ emits: ["close"],
1164
+ setup(e, { emit: h }) {
1165
+ const g = e, a = h, c = st({
1166
+ adapter: g.adapter,
1167
+ defaultModel: g.defaultModel,
1168
+ defaultMode: g.defaultMode
1169
+ }), {
1170
+ sessions: f,
1171
+ currentSessionId: s,
1172
+ messages: m,
1173
+ isLoading: D,
1174
+ mode: y,
1175
+ model: x,
1176
+ webSearch: A,
1177
+ thinking: N,
1178
+ loadSessions: P,
1179
+ switchSession: O,
1180
+ createNewSession: J,
1181
+ deleteSession: I,
1182
+ sendMessage: T,
1183
+ cancelRequest: F,
1184
+ copyMessage: C,
1185
+ regenerateMessage: v,
1186
+ setMode: b,
1187
+ setModel: V,
1188
+ setWebSearch: G,
1189
+ setThinking: d,
1190
+ setWorkingDirectory: w
1191
+ } = c, r = M([]), R = M(null), U = Oe(g, "models");
1192
+ Ue("chatAdapter", g.adapter), oe(() => {
1193
+ P();
1194
+ }), ae(
1195
+ () => g.workingDir,
1196
+ (L) => {
1197
+ L && w(L);
1198
+ },
1199
+ { immediate: !0 }
1200
+ );
1201
+ async function Y() {
1202
+ await _e(), R.value && (R.value.scrollTop = R.value.scrollHeight);
1203
+ }
1204
+ ae(m, () => {
1205
+ Y();
1206
+ }, { flush: "post" });
1207
+ function u(L) {
1208
+ T(L, r.value.length > 0 ? r.value : void 0), r.value = [];
1209
+ }
1210
+ function o(L) {
1211
+ T(L);
1212
+ }
1213
+ function $(L, re) {
1214
+ m.value = m.value.slice(0, L), T(re);
1215
+ }
1216
+ function Z(L) {
1217
+ L >= 0 && L < r.value.length && r.value.splice(L, 1);
1218
+ }
1219
+ function ce() {
1220
+ console.log("上传图片");
1221
+ }
1222
+ function Me() {
1223
+ console.log("@ 上下文");
1224
+ }
1225
+ function ze() {
1226
+ g.onClose && g.onClose(), a("close");
1227
+ }
1228
+ function Re() {
1229
+ console.log("清空所有对话");
1230
+ }
1231
+ function De() {
1232
+ console.log("关闭其他对话");
1233
+ }
1234
+ function Ie() {
1235
+ console.log("导出对话");
1236
+ }
1237
+ function Te() {
1238
+ s.value && (navigator.clipboard.writeText(s.value), console.log("已复制请求 ID:", s.value));
1239
+ }
1240
+ function xe() {
1241
+ console.log("反馈");
1242
+ }
1243
+ function Ee() {
1244
+ console.log("Agent 设置");
1245
+ }
1246
+ return (L, re) => (n(), i("div", $n, [
1247
+ e.hideHeader ? p("", !0) : (n(), k($t, {
1248
+ key: 0,
1249
+ sessions: l(f),
1250
+ "current-session-id": l(s),
1251
+ "show-close": !!e.onClose,
1252
+ onNewSession: l(J),
1253
+ onSwitchSession: l(O),
1254
+ onDeleteSession: l(I),
1255
+ onClose: ze,
1256
+ onClearAll: Re,
1257
+ onCloseOthers: De,
1258
+ onExport: Ie,
1259
+ onCopyId: Te,
1260
+ onFeedback: xe,
1261
+ onSettings: Ee
1262
+ }, null, 8, ["sessions", "current-session-id", "show-close", "onNewSession", "onSwitchSession", "onDeleteSession"])),
1263
+ t("div", {
1264
+ ref_key: "messagesRef",
1265
+ ref: R,
1266
+ class: "messages-container"
1267
+ }, [
1268
+ l(m).length === 0 ? (n(), k(Dt, {
1269
+ key: 0,
1270
+ onQuickAction: o
1271
+ })) : (n(!0), i(B, { key: 1 }, q(l(m), (_, ue) => (n(), k(Cn, {
1272
+ key: _.id,
1273
+ role: _.role,
1274
+ content: _.content,
1275
+ images: _.images,
1276
+ thinking: _.thinking,
1277
+ "thinking-complete": _.thinkingComplete,
1278
+ "search-results": _.searchResults,
1279
+ searching: _.searching,
1280
+ "tool-calls": _.toolCalls,
1281
+ copied: _.copied,
1282
+ loading: _.loading,
1283
+ onCopy: (le) => l(C)(_.id),
1284
+ onRegenerate: (le) => l(v)(ue),
1285
+ onSend: (le) => $(ue, le)
1286
+ }, null, 8, ["role", "content", "images", "thinking", "thinking-complete", "search-results", "searching", "tool-calls", "copied", "loading", "onCopy", "onRegenerate", "onSend"]))), 128))
1287
+ ], 512),
1288
+ S(Se, {
1289
+ "selected-images": r.value,
1290
+ "is-loading": l(D),
1291
+ mode: l(y),
1292
+ model: l(x),
1293
+ models: U.value,
1294
+ "web-search-enabled": l(A),
1295
+ "thinking-enabled": l(N),
1296
+ onSend: u,
1297
+ onCancel: l(F),
1298
+ onRemoveImage: Z,
1299
+ onUploadImage: ce,
1300
+ onAtContext: Me,
1301
+ "onUpdate:mode": l(b),
1302
+ "onUpdate:model": l(V),
1303
+ "onUpdate:webSearch": l(G),
1304
+ "onUpdate:thinking": l(d)
1305
+ }, null, 8, ["selected-images", "is-loading", "mode", "model", "models", "web-search-enabled", "thinking-enabled", "onCancel", "onUpdate:mode", "onUpdate:model", "onUpdate:webSearch", "onUpdate:thinking"])
1306
+ ]));
1307
+ }
1308
+ }), Fn = /* @__PURE__ */ Q(wn, [["__scopeId", "data-v-2332ad8f"]]), Sn = { class: "thinking-icon" }, Mn = { class: "thinking-title" }, zn = {
1309
+ key: 0,
1310
+ class: "thinking-content"
1311
+ }, Rn = { class: "thinking-text" }, Dn = /* @__PURE__ */ K({
1312
+ __name: "ThinkingBlock",
1313
+ props: {
1314
+ content: {},
1315
+ isComplete: { type: Boolean }
1316
+ },
1317
+ setup(e) {
1318
+ const h = M(!1);
1319
+ return (g, a) => (n(), i("div", {
1320
+ class: E(["thinking-block", { expanded: h.value }])
1321
+ }, [
1322
+ t("button", {
1323
+ class: "thinking-header",
1324
+ onClick: a[0] || (a[0] = (c) => h.value = !h.value)
1325
+ }, [
1326
+ t("div", Sn, [
1327
+ e.isComplete ? (n(), k(l($e), {
1328
+ key: 1,
1329
+ size: 14
1330
+ })) : (n(), k(l(ee), {
1331
+ key: 0,
1332
+ size: 14,
1333
+ class: "spinning"
1334
+ }))
1335
+ ]),
1336
+ t("span", Mn, z(e.isComplete ? "思考完成" : "正在思考..."), 1),
1337
+ S(l(j), {
1338
+ size: 14,
1339
+ class: E(["chevron", { rotated: h.value }])
1340
+ }, null, 8, ["class"])
1341
+ ]),
1342
+ h.value && e.content ? (n(), i("div", zn, [
1343
+ t("div", Rn, z(e.content), 1)
1344
+ ])) : p("", !0)
1345
+ ], 2));
1346
+ }
1347
+ }), Gn = /* @__PURE__ */ Q(Dn, [["__scopeId", "data-v-318aa171"]]), In = { class: "tool-icon" }, Tn = { class: "tool-name" }, xn = {
1348
+ key: 0,
1349
+ class: "tool-args"
1350
+ }, En = { class: "arg-key" }, An = { class: "arg-value" }, Nn = {
1351
+ key: 1,
1352
+ class: "tool-result"
1353
+ }, Bn = /* @__PURE__ */ K({
1354
+ __name: "ToolCallBlock",
1355
+ props: {
1356
+ name: {},
1357
+ args: {},
1358
+ result: {},
1359
+ status: {}
1360
+ },
1361
+ setup(e) {
1362
+ const h = e, g = M(!1), a = H(() => ({
1363
+ execute_command: "执行命令",
1364
+ analyze_image: "分析图片",
1365
+ generate_image: "生成图片",
1366
+ analyze_video: "分析视频",
1367
+ web_search: "网络搜索",
1368
+ read_file: "读取文件",
1369
+ write_file: "写入文件",
1370
+ list_directory: "列出目录",
1371
+ create_directory: "创建目录",
1372
+ delete_file: "删除文件",
1373
+ move_file: "移动文件",
1374
+ search_files: "搜索文件"
1375
+ })[h.name] || h.name), c = H(() => ({
1376
+ execute_command: W(et),
1377
+ analyze_image: W(ge),
1378
+ generate_image: W(ge),
1379
+ analyze_video: W(Ye),
1380
+ web_search: W(ye)
1381
+ })[h.name] || W(pe));
1382
+ function f(s) {
1383
+ return typeof s == "string" ? s.length > 50 ? s.substring(0, 50) + "..." : s : JSON.stringify(s);
1384
+ }
1385
+ return (s, m) => (n(), i("div", {
1386
+ class: E(["tool-call-block", e.status])
1387
+ }, [
1388
+ t("div", {
1389
+ class: "tool-header",
1390
+ onClick: m[0] || (m[0] = (D) => g.value = !g.value)
1391
+ }, [
1392
+ t("div", In, [
1393
+ e.status === "running" ? (n(), k(l(ee), {
1394
+ key: 0,
1395
+ size: 14,
1396
+ class: "spinning"
1397
+ })) : e.status === "success" ? (n(), k(l(se), {
1398
+ key: 1,
1399
+ size: 14
1400
+ })) : e.status === "error" ? (n(), k(l(ne), {
1401
+ key: 2,
1402
+ size: 14
1403
+ })) : (n(), k(te(c.value), {
1404
+ key: 3,
1405
+ size: 14
1406
+ }))
1407
+ ]),
1408
+ t("span", Tn, z(a.value), 1),
1409
+ e.result ? (n(), k(l(j), {
1410
+ key: 0,
1411
+ size: 14,
1412
+ class: E(["chevron", { rotated: g.value }])
1413
+ }, null, 8, ["class"])) : p("", !0)
1414
+ ]),
1415
+ e.args && Object.keys(e.args).length > 0 && g.value ? (n(), i("div", xn, [
1416
+ (n(!0), i(B, null, q(e.args, (D, y) => (n(), i("div", {
1417
+ key: y,
1418
+ class: "arg-item"
1419
+ }, [
1420
+ t("span", En, z(y) + ":", 1),
1421
+ t("span", An, z(f(D)), 1)
1422
+ ]))), 128))
1423
+ ])) : p("", !0),
1424
+ e.result && g.value ? (n(), i("div", Nn, [
1425
+ t("pre", null, z(e.result), 1)
1426
+ ])) : p("", !0)
1427
+ ], 2));
1428
+ }
1429
+ }), Kn = /* @__PURE__ */ Q(Bn, [["__scopeId", "data-v-7098f4a3"]]), Ln = { class: "search-block" }, On = { class: "search-icon" }, Un = { class: "search-title" }, _n = {
1430
+ key: 0,
1431
+ class: "search-results"
1432
+ }, Hn = ["href"], Wn = { class: "result-title" }, qn = { class: "result-url" }, Vn = /* @__PURE__ */ K({
1433
+ __name: "SearchResultBlock",
1434
+ props: {
1435
+ results: {},
1436
+ searching: { type: Boolean }
1437
+ },
1438
+ setup(e) {
1439
+ const h = M(!0);
1440
+ function g(a) {
1441
+ try {
1442
+ return new URL(a).hostname;
1443
+ } catch {
1444
+ return a;
1445
+ }
1446
+ }
1447
+ return (a, c) => (n(), i("div", Ln, [
1448
+ t("div", {
1449
+ class: "search-header",
1450
+ onClick: c[0] || (c[0] = (f) => h.value = !h.value)
1451
+ }, [
1452
+ t("div", On, [
1453
+ e.searching ? (n(), k(l(ee), {
1454
+ key: 0,
1455
+ size: 14,
1456
+ class: "spinning"
1457
+ })) : (n(), k(l(ie), {
1458
+ key: 1,
1459
+ size: 14
1460
+ }))
1461
+ ]),
1462
+ t("span", Un, z(e.searching ? "正在搜索..." : `找到 ${e.results.length} 条结果`), 1),
1463
+ !e.searching && e.results.length > 0 ? (n(), k(l(j), {
1464
+ key: 0,
1465
+ size: 14,
1466
+ class: E(["chevron", { rotated: h.value }])
1467
+ }, null, 8, ["class"])) : p("", !0)
1468
+ ]),
1469
+ !e.searching && h.value && e.results.length > 0 ? (n(), i("div", _n, [
1470
+ (n(!0), i(B, null, q(e.results.slice(0, 5), (f, s) => (n(), i("a", {
1471
+ key: s,
1472
+ href: f.url,
1473
+ target: "_blank",
1474
+ class: "result-item"
1475
+ }, [
1476
+ t("span", Wn, z(f.title), 1),
1477
+ t("span", qn, z(g(f.url)), 1)
1478
+ ], 8, Hn))), 128))
1479
+ ])) : p("", !0)
1480
+ ]));
1481
+ }
1482
+ }), Qn = /* @__PURE__ */ Q(Vn, [["__scopeId", "data-v-f1490d29"]]);
1483
+ export {
1484
+ $t as ChatHeader,
1485
+ Se as ChatInput,
1486
+ Fn as ChatPanel,
1487
+ we as DEFAULT_MODELS,
1488
+ dn as ExecutionSteps,
1489
+ lt as FileType,
1490
+ Cn as MessageBubble,
1491
+ Qn as SearchResultBlock,
1492
+ Gn as ThinkingBlock,
1493
+ Kn as ToolCallBlock,
1494
+ Dt as WelcomeMessage,
1495
+ tt as createNullAdapter,
1496
+ st as useChat
1497
+ };