agent-tool-chat 1.1.6 → 1.6.0
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 +127 -5
- package/dist/agent-core/agent.d.ts +8 -0
- package/dist/agent-core/index.d.ts +2 -1
- package/dist/agent-core/storage.d.ts +4 -0
- package/dist/agent-core/truncate.d.ts +8 -0
- package/dist/agent-core/types.d.ts +16 -0
- package/dist/agent-tool-chat.css +1 -1
- package/dist/api/openai-compatible.d.ts +11 -0
- package/dist/api/openai.d.ts +2 -0
- package/dist/api/provider-registry.d.ts +8 -0
- package/dist/components/ChatMessage.vue.d.ts +3 -7
- package/dist/components/ChatPanel.vue.d.ts +42 -1
- package/dist/components/SelectionSend.vue.d.ts +25 -0
- package/dist/components/SessionDrawer.vue.d.ts +22 -0
- package/dist/composables/useAgentChat.d.ts +48 -17
- package/dist/config.d.ts +11 -4
- package/dist/core/context-builder.d.ts +1 -0
- package/dist/core/session-store.d.ts +21 -0
- package/dist/core/tool-requirements.d.ts +44 -0
- package/dist/index.cjs +46 -37
- package/dist/index.d.ts +11 -3
- package/dist/index.js +4303 -3166
- package/dist/types.d.ts +122 -10
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
基于 **ToolPackage** 架构的 AI 对话插件,工具由宿主控制执行。基于 Vue 3 + Element Plus。
|
|
4
4
|
|
|
5
|
-
**版本:** 1.0
|
|
5
|
+
**版本:** 1.5.0
|
|
6
6
|
|
|
7
7
|
## 安装
|
|
8
8
|
|
|
@@ -140,7 +140,7 @@ const myToolPackage: ToolPackage = {
|
|
|
140
140
|
|
|
141
141
|
| 字段 | 作用 |
|
|
142
142
|
|---|---|
|
|
143
|
-
| `suggestComponent` | 建议使用组件名(`ToolPackage.components`
|
|
143
|
+
| `suggestComponent` | 建议使用组件名(`ToolPackage.components` 中注册)渲染;组件在本轮消息末尾显示(最终文字之后、建议条之前) |
|
|
144
144
|
| `resultFormat` | `table` / `card` / `list` / `text` / `map`,无组件时按此降级渲染 |
|
|
145
145
|
| `previewFields` | 表格列字段(→ `RenderBlock.fields`),空数组/缺省时全量显示 |
|
|
146
146
|
| `summaryTemplate` | 渲染块标题模板,`{key}` 从工具 `args` 插值 |
|
|
@@ -149,6 +149,42 @@ const myToolPackage: ToolPackage = {
|
|
|
149
149
|
| `suggestedNext` | 后续建议文本 |
|
|
150
150
|
| `suggestedNextEvent` | 延迟建议:等待该业务事件到达后再显示 |
|
|
151
151
|
|
|
152
|
+
### 工具前置条件(`requires`)
|
|
153
|
+
|
|
154
|
+
有些工具必须在满足业务条件后才能执行(如"设置河段模型"需要已选中方案、"创建水文方案"需要先确认出口站)。用 `requires` 声明条件:插件把条件写进系统提示词,并在执行前通过 `onCheckToolRequirement` 交给宿主校验;未满足时**不调用工具**,而是返回结构化结果给模型。
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
const tool: ToolDefinition = {
|
|
158
|
+
name: 'handle_set_edge_model',
|
|
159
|
+
// ...
|
|
160
|
+
requires: {
|
|
161
|
+
description: '需要已选中/打开一个方案',
|
|
162
|
+
check: 'scheme:selected', // 宿主校验项 id(硬拦截)
|
|
163
|
+
hint: '当前没有选中的方案,请先打开方案或询问用户',
|
|
164
|
+
action: 'ask-user', // call-tool | ask-user | block
|
|
165
|
+
// tools: ['handle_get_current_scheme_id'], // 可选:仅提示词建议
|
|
166
|
+
},
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const chat = useAgentChat({
|
|
170
|
+
toolPackages: [pkg],
|
|
171
|
+
onToolCall,
|
|
172
|
+
onCheckToolRequirement: async ({ check, toolName, args, sessionId }) => {
|
|
173
|
+
if (check === 'scheme:selected') {
|
|
174
|
+
return getCurrentSchemeId()
|
|
175
|
+
? { ok: true }
|
|
176
|
+
: { ok: false, message: '当前没有选中的方案' }
|
|
177
|
+
}
|
|
178
|
+
return { ok: true }
|
|
179
|
+
},
|
|
180
|
+
})
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
- `tools` 只是提示词建议("建议先调用"),插件**不做**"是否调用过前置工具"的硬校验(历史调用 ≠ 当前状态);需要硬拦截时用 `check`。
|
|
184
|
+
- 未满足时工具结果是结构化 JSON:`{ ok:false, code:'REQUIREMENT_UNMET', tool, requirements:[…], hint, suggestedTool, action, retryable:true }`,模型据此补齐条件后重试;UI 上该工具显示为「缺少前置条件」告警态,悬浮可见原因。
|
|
185
|
+
- 宿主未提供 `onCheckToolRequirement` 时 `check` 型条件放行(控制台告警一次),保持旧行为;校验钩子抛异常按"未满足"处理,避免半状态产生副作用。
|
|
186
|
+
- 未声明 `requires` 的工具行为完全不变。
|
|
187
|
+
|
|
152
188
|
### 表格行选择
|
|
153
189
|
|
|
154
190
|
当工具结果渲染为表格且 `selectable: true` 时,多行结果每行出现"选择"按钮,点击后向对话发送:
|
|
@@ -233,14 +269,90 @@ interface FileAttachment {
|
|
|
233
269
|
3. **渲染 `ChatPanel`** — 将返回的 `AgentChatAPI` 绑定到 `chat` prop;也可不传 `chat`,仅传可选 `options`(或不传,直接开箱即用内置工具)。
|
|
234
270
|
4. **文件上传** — `ChatInput` 支持文件选择,工具通过 `fileId` 引用。
|
|
235
271
|
5. **业务联动** — 页面操作完成后 `eventBus.dispatch` 回灌,驱动 LLM 回复或延迟建议。
|
|
236
|
-
6.
|
|
272
|
+
6. **选中文字发送** — 在消息区选中文字后,选区旁浮出「发送」按钮,点击即把选中文本作为一条用户消息发出。
|
|
273
|
+
7. **持久化** — 消息与设置自动保存(direct 模式 localStorage 按会话分键;proxy 模式写服务端 `/api/sessions`,按 device_id 区分)。
|
|
274
|
+
|
|
275
|
+
## 模型提供方
|
|
276
|
+
|
|
277
|
+
插件内置 DeepSeek、上善、自定义(OpenAI 兼容)三种提供方,可在设置面板切换,每个提供方独立保存 `apiKey / baseUrl / model / temperature / thinking`(`openai` 预设目前处于注释状态,需要时在 `config.ts` 中取消注释即可启用)。
|
|
278
|
+
|
|
279
|
+
```ts
|
|
280
|
+
const chat = useAgentChat({
|
|
281
|
+
toolPackages: [],
|
|
282
|
+
// 可选:扩展自定义 OpenAI 兼容提供方
|
|
283
|
+
providerPresets: [
|
|
284
|
+
{
|
|
285
|
+
id: 'my-gateway',
|
|
286
|
+
name: '内部网关',
|
|
287
|
+
protocol: 'openai-compatible',
|
|
288
|
+
defaultBaseUrl: 'https://gateway.example.com/v1',
|
|
289
|
+
defaultModel: 'my-model',
|
|
290
|
+
models: [],
|
|
291
|
+
capabilities: {},
|
|
292
|
+
},
|
|
293
|
+
],
|
|
294
|
+
})
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
- `settings.providerId` 标识当前提供方,默认 `deepseek`;旧版设置会自动迁移到当前提供方,无 `providerId` 时迁移到 `providers.deepseek`。
|
|
298
|
+
- localStorage 中已保存的设置按字段覆盖 `options.settings`;未保存的字段沿用 `options.settings` / 默认值。
|
|
299
|
+
- 旧字段 `settings.apiKey/baseUrl/model` 仍可读取,会始终镜像当前提供方的值。
|
|
300
|
+
- 前端直连使用 `POST {baseUrl}/chat/completions`;后端代理使用 `POST {proxyUrl}/api/chat`,并在请求体携带 `providerId`。
|
|
301
|
+
- 代理服务按 `<PROVIDER_ID>_API_KEY` / `<PROVIDER_ID>_BASE_URL` 环境变量路由,详见 `server/.env.example`。
|
|
302
|
+
- **上善**:前端设置面板选「上善」即可;代理模式下地址与 Key 都由服务端决定——只需配置 `SHANGSHAN_API_KEY`。地址默认使用内置上善地址(可用 `SHANGSHAN_BASE_URL` 覆盖),`SHANGSHAN_MODEL` 可在客户端未传模型时兜底。
|
|
303
|
+
- 服务端内置默认地址的提供方:`deepseek` / `openai` / `shangshan`;`openai-compatible`、`openai-compatible-custom` 没有默认地址,必须显式配置 `*_BASE_URL`。
|
|
304
|
+
- 非 OpenAI 兼容协议(如 Claude/Gemini)可通过 `registerProvider(id, factory)` 或 `options.provider` 接入。
|
|
305
|
+
|
|
306
|
+
## 会话管理(新开会话 / 历史会话)
|
|
307
|
+
|
|
308
|
+
面板头部提供 **新对话**(➕)与 **历史对话**(🕘)两个入口:
|
|
309
|
+
|
|
310
|
+
- **新对话**:清空当前上下文、回到草稿;草稿在发出首条消息时才落库,历史列表里不会出现空会话;
|
|
311
|
+
- **历史对话**:右侧抽屉列出全部会话(标题、更新时间、消息数),点击切换、垃圾桶图标删除(二次确认);当前会话高亮;
|
|
312
|
+
- 标题自动取**首条用户消息前 24 字**(无文字时退化为文件名);
|
|
313
|
+
- 刷新后自动打开上次打开的会话(`{storagePrefix}current_session` 记录)。
|
|
314
|
+
|
|
315
|
+
```ts
|
|
316
|
+
const chat = useAgentChat({ toolPackages: [], onToolCall })
|
|
317
|
+
|
|
318
|
+
await chat.newSession() // 新对话(当前会话先落盘)
|
|
319
|
+
await chat.switchSession(id) // 切换历史会话
|
|
320
|
+
await chat.deleteSession(id) // 删除会话
|
|
321
|
+
chat.sessions // Ref<SessionMeta[]>,按 updatedAt 倒序
|
|
322
|
+
chat.currentSessionId // Ref<string>,'' 表示草稿
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### 存储位置
|
|
326
|
+
|
|
327
|
+
| providerMode | 会话 / 消息存储 | 说明 |
|
|
328
|
+
|---|---|---|
|
|
329
|
+
| `direct` | `localStorage` | 索引 `{storagePrefix}sessions`;每个会话 `{storagePrefix}session_{id}`;防抖 400ms 批量写入 |
|
|
330
|
+
| `proxy` | 服务端 `packages/agent-chat/server`(SQLite `data.db`) | `GET/POST /api/sessions`、`GET/PUT /api/sessions/:id/messages`、`PATCH/DELETE /api/sessions/:id`,按 `device_id` 归属 |
|
|
331
|
+
|
|
332
|
+
- 旧版单会话数据自动迁移:直连模式下 `{storagePrefix}messages` → 一条历史会话(迁移后删除旧键);服务端旧表 `messages/sessions` → `legacy_{device_id}` 会话,旧表重命名为 `*_legacy` 保留。
|
|
333
|
+
- 服务端旧接口 `/api/messages` 仍可用(映射到该设备最近一条会话),仅用于兼容老前端,建议新代码使用 `/api/sessions`。
|
|
237
334
|
|
|
238
335
|
## 数据持久化
|
|
239
336
|
|
|
240
337
|
| providerMode | 消息存储 | 说明 |
|
|
241
338
|
|---|---|---|
|
|
242
|
-
| `direct` | `localStorage` |
|
|
243
|
-
| `proxy` | 服务端 `/api/messages` | 按 `device_id` 标识,防抖 400ms 批量提交 |
|
|
339
|
+
| `direct` | `localStorage` | 按会话分键,见上表 |
|
|
340
|
+
| `proxy` | 服务端 `/api/sessions/:id/messages` | 按 `device_id` 标识,防抖 400ms 批量提交 |
|
|
341
|
+
|
|
342
|
+
## 会话上限与生命周期
|
|
343
|
+
|
|
344
|
+
```ts
|
|
345
|
+
const chat = useAgentChat({
|
|
346
|
+
maxContextTokens: 48000, // 历史 token 预算(估算值),超出从前往后裁剪
|
|
347
|
+
maxHistoryMessages: 60, // 历史消息硬上限
|
|
348
|
+
maxToolResultChars: 30000, // 单次工具结果写入模型的字符上限;0 = 不限制
|
|
349
|
+
disposeOnUnmount: false, // 组件卸载时是否自动 dispose,默认 false
|
|
350
|
+
})
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
- **工具结果截断**:仅截断写入模型上下文的部分(保留首尾 + 截断标记),UI 中工具结果始终完整。默认 30000 字符,正常工具返回不受影响;设 `0` 完全关闭。
|
|
354
|
+
- **生命周期**:业务事件(`EventEngine`)按应用级常驻,组件卸载默认**不会**停止它——这样宿主缓存 chat 实例(例如跨路由复用)时,路由往返后事件依然有效。需要"卸载即清理"的旧行为时传 `disposeOnUnmount: true`;也可随时手动调用 `chat.dispose()` 停止事件引擎、待定监听与持久化定时器。
|
|
355
|
+
- **同步失败可见**:`chat.syncError` 记录 proxy/本地存储的同步失败原因,`ChatPanel` 会与 `errorMsg` 合并展示,不再静默丢数据。
|
|
244
356
|
|
|
245
357
|
## API 概览
|
|
246
358
|
|
|
@@ -249,11 +361,21 @@ useAgentChat(options) // 核心组合式函数,返回 AgentChatAP
|
|
|
249
361
|
ChatPanel // 对话面板(chat / options prop,chat 可选)
|
|
250
362
|
buildSystemPrompt(packages) // 构建系统提示词
|
|
251
363
|
createDeepSeekProvider() // 直连 DeepSeek LLM 提供者
|
|
364
|
+
createOpenAIProvider() // 直连 OpenAI LLM 提供者
|
|
365
|
+
createOpenAICompatibleProvider() // 通用 OpenAI 兼容提供者
|
|
252
366
|
createProxyProvider() // 代理模式 LLM 提供者
|
|
367
|
+
createProvider(id, mode) // 按 providerId + 模式路由
|
|
368
|
+
registerProvider(id, factory) // 注册非 OpenAI 兼容协议提供方
|
|
253
369
|
createEventBus() // 创建独立 EventBus
|
|
254
370
|
Agent, ToolRegistry // 底层 Agent 多轮循环器 / 工具注册表
|
|
371
|
+
clampText(text, limit) // 工具结果截断工具函数
|
|
372
|
+
createLocalSessionStore(prefix) // 直连模式会话存储(localStorage)
|
|
373
|
+
createProxySessionStore(base, id) // 代理模式会话存储(/api/sessions)
|
|
374
|
+
deriveSessionTitle(text, files) // 会话标题生成(首条消息前 24 字)
|
|
255
375
|
```
|
|
256
376
|
|
|
377
|
+
`AgentChatAPI` 除 `messages / settings / loading / errorMsg / sendMessage / stopGeneration / clearMessages / saveSettings` 外,还提供 `sessions / currentSessionId / sessionsLoading / newSession / switchSession / deleteSession`(多会话)、`syncError`(同步失败提示)与 `dispose()`(主动释放)。
|
|
378
|
+
|
|
257
379
|
## 详细文档
|
|
258
380
|
|
|
259
381
|
- [DESIGN.md](./DESIGN.md) — 完整架构设计(事件系统、渲染流程、SuggestedNext 延迟显示逻辑等)
|
|
@@ -6,8 +6,14 @@ export interface AgentConfig {
|
|
|
6
6
|
provider: LLMProvider;
|
|
7
7
|
providerConfig: LLMProviderConfig;
|
|
8
8
|
tools: ToolRegistry;
|
|
9
|
+
/**
|
|
10
|
+
* @deprecated 消息持久化由上层(useAgentChat 的防抖持久化)负责,
|
|
11
|
+
* 这里仅保留接口兼容;不传时 agent 不做任何落盘。
|
|
12
|
+
*/
|
|
9
13
|
storage?: StorageAdapter;
|
|
10
14
|
maxToolRounds?: number;
|
|
15
|
+
/** 单次工具结果写入模型的字符上限;0 表示不限制。默认 30000 */
|
|
16
|
+
maxToolResultChars?: number;
|
|
11
17
|
systemPrompt?: string;
|
|
12
18
|
maxContextTokens?: number;
|
|
13
19
|
maxHistoryMessages?: number;
|
|
@@ -27,5 +33,7 @@ export declare class Agent {
|
|
|
27
33
|
private emit;
|
|
28
34
|
sendMessage(text: string): Promise<void>;
|
|
29
35
|
stop(): void;
|
|
36
|
+
/** 移除末尾的空 assistant 占位(请求失败后调用) */
|
|
37
|
+
private dropTrailingEmptyAssistant;
|
|
30
38
|
private buildApiMessages;
|
|
31
39
|
}
|
|
@@ -2,6 +2,7 @@ export { Agent } from './agent';
|
|
|
2
2
|
export type { AgentConfig } from './agent';
|
|
3
3
|
export { ToolRegistry } from './tool-registry';
|
|
4
4
|
export { createLocalStorageAdapter } from './storage';
|
|
5
|
+
export { clampText } from './truncate';
|
|
5
6
|
export type { StorageAdapter } from './storage';
|
|
6
7
|
export type { LLMProvider, StreamChatParams } from './provider';
|
|
7
|
-
export type { CoreMessage, ToolCall, ToolOutput, ToolDefinition, ToolHandler, StreamResult, LLMProviderConfig, AgentEvent, AgentEventListener, MessageRole, } from './types';
|
|
8
|
+
export type { CoreMessage, ToolCall, ToolOutput, ToolDefinition, ToolHandler, StreamResult, LLMProviderConfig, AgentEvent, AgentEventListener, MessageRole, TokenUsage, } from './types';
|
|
@@ -3,4 +3,8 @@ export interface StorageAdapter {
|
|
|
3
3
|
load(): CoreMessage[] | Promise<CoreMessage[]>;
|
|
4
4
|
save(messages: CoreMessage[]): void | Promise<void>;
|
|
5
5
|
}
|
|
6
|
+
/**
|
|
7
|
+
* @deprecated 消息持久化由 useAgentChat 的防抖持久化负责(direct → localStorage,
|
|
8
|
+
* proxy → POST /api/messages)。此适配器仅为兼容旧的 Agent 用法保留。
|
|
9
|
+
*/
|
|
6
10
|
export declare function createLocalStorageAdapter(key: string): StorageAdapter;
|
|
@@ -17,6 +17,8 @@ export interface CoreMessage {
|
|
|
17
17
|
export interface ToolOutput {
|
|
18
18
|
success: boolean;
|
|
19
19
|
result: string;
|
|
20
|
+
/** 结构化错误码,例如 REQUIREMENT_UNMET(前置条件未满足) */
|
|
21
|
+
code?: string;
|
|
20
22
|
}
|
|
21
23
|
export interface ToolDefinition {
|
|
22
24
|
type: 'function';
|
|
@@ -27,22 +29,35 @@ export interface ToolDefinition {
|
|
|
27
29
|
};
|
|
28
30
|
}
|
|
29
31
|
export type ToolHandler = (args: any) => Promise<ToolOutput> | ToolOutput;
|
|
32
|
+
/** 上游返回的 token 用量(部分提供方/网关不返回) */
|
|
33
|
+
export interface TokenUsage {
|
|
34
|
+
prompt_tokens?: number;
|
|
35
|
+
completion_tokens?: number;
|
|
36
|
+
total_tokens?: number;
|
|
37
|
+
}
|
|
30
38
|
export interface StreamResult {
|
|
31
39
|
content: string;
|
|
32
40
|
reasoning: string;
|
|
33
41
|
tool_calls: ToolCall[];
|
|
34
42
|
finish_reason: string;
|
|
43
|
+
usage?: TokenUsage;
|
|
35
44
|
}
|
|
36
45
|
export interface ThinkingConfig {
|
|
37
46
|
type: 'enabled' | 'disabled';
|
|
38
47
|
effort?: 'low' | 'high' | 'max';
|
|
39
48
|
}
|
|
40
49
|
export interface LLMProviderConfig {
|
|
50
|
+
/** 当前模型提供方 ID(用于 registry 路由) */
|
|
51
|
+
providerId?: string;
|
|
52
|
+
/** 直连 / 代理模式 */
|
|
53
|
+
mode?: 'direct' | 'proxy';
|
|
41
54
|
baseUrl: string;
|
|
42
55
|
apiKey: string;
|
|
43
56
|
model: string;
|
|
44
57
|
temperature?: number;
|
|
45
58
|
thinking?: ThinkingConfig;
|
|
59
|
+
/** 提供方专用扩展请求字段 */
|
|
60
|
+
extraBody?: Record<string, unknown>;
|
|
46
61
|
}
|
|
47
62
|
export type AgentEvent = {
|
|
48
63
|
type: 'message';
|
|
@@ -57,6 +72,7 @@ export type AgentEvent = {
|
|
|
57
72
|
type: 'stream:end';
|
|
58
73
|
content: string;
|
|
59
74
|
reasoning: string;
|
|
75
|
+
finishReason?: string;
|
|
60
76
|
} | {
|
|
61
77
|
type: 'tool:start';
|
|
62
78
|
call: ToolCall;
|
package/dist/agent-tool-chat.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.render-block[data-v-ea599d5b]{margin:8px 0;padding:8px 0;width:100%}.render-block__component[data-v-ea599d5b]{border-radius:8px;background:var(--el-fill-color-lighter);box-shadow:0 0 10px #0000001a}.render-block__title[data-v-ea599d5b]{font-weight:600;font-size:14px;margin-bottom:6px;color:var(--el-text-color-primary)}.render-block__table[data-v-ea599d5b]{width:100%;max-width:900px;border-radius:8px;overflow:hidden;box-shadow:0 2px 8px #0000000f}.render-block__cards[data-v-ea599d5b]{display:flex;flex-direction:column;gap:8px}.card-item[data-v-ea599d5b]{border:1px solid var(--el-border-color);border-radius:8px;padding:10px 14px;background:var(--el-fill-color-lighter);box-shadow:0 2px 6px #0000000d}.card-field[data-v-ea599d5b]{display:flex;gap:6px;font-size:13px;line-height:1.8}.card-label[data-v-ea599d5b]{font-weight:600;color:var(--el-text-color-secondary);min-width:80px}.card-value[data-v-ea599d5b]{color:var(--el-text-color-primary)}.render-block__list[data-v-ea599d5b]{display:flex;flex-direction:column;gap:4px}.list-item[data-v-ea599d5b]{padding:6px 10px;font-size:13px;border-left:3px solid var(--el-color-primary);background:var(--el-fill-color-lighter);border-radius:0 4px 4px 0;box-shadow:0 1px 4px #0000000a}.suggested-next[data-v-0e0e9b65]{display:flex;align-items:center;gap:8px;padding:8px 12px;margin:6px 0;background:var(--el-color-primary-light-9);border:1px solid var(--el-color-primary-light-7);border-radius:8px;font-size:13px}.suggested-next__icon[data-v-0e0e9b65]{font-size:15px;flex-shrink:0}.suggested-next__text[data-v-0e0e9b65]{flex:1;color:var(--el-text-color-regular)}.chat-message[data-v-7317da3a]{display:flex;gap:10px;padding:12px 0;animation:msg-in-7317da3a .25s ease both}@keyframes msg-in-7317da3a{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}.chat-message.role-user[data-v-7317da3a]{flex-direction:row-reverse}.chat-message.role-user .message-time[data-v-7317da3a]{text-align:right}.message-avatar[data-v-7317da3a]{width:32px;height:32px;border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0;font-size:16px;color:#fff;box-shadow:0 0 0 2px var(--el-bg-color),0 2px 6px #0000001f}.role-user .message-avatar[data-v-7317da3a]{background:linear-gradient(135deg,var(--el-color-primary),var(--el-color-primary-light-3))}.role-assistant .message-avatar[data-v-7317da3a]{background:linear-gradient(135deg,#009688,#2d8cf0)}.message-time[data-v-7317da3a]{display:block;font-size:11px;line-height:1;color:var(--el-text-color-placeholder);margin-bottom:4px}.message-body[data-v-7317da3a]{max-width:80%;min-width:0}.role-user .message-body[data-v-7317da3a]{background:linear-gradient(135deg,var(--el-color-primary-light-9),var(--el-color-primary-light-8));padding:8px 14px;border-radius:12px 4px 12px 12px;box-shadow:0 2px 8px #0000000f,0 1px 2px #0000000a}.role-assistant .message-body[data-v-7317da3a]{position:relative;background:var(--el-fill-color-lighter);padding:8px 14px;border-radius:4px 12px 12px;display:flex;flex-direction:column;box-shadow:0 2px 8px #0000000f,0 1px 2px #0000000a}.message-actions[data-v-7317da3a]{position:absolute;top:0;right:0;opacity:0;transition:opacity .2s;z-index:1}.role-assistant .message-body:hover .message-actions[data-v-7317da3a]{opacity:1}.role-assistant .message-body .message-time[data-v-7317da3a]{float:left;width:10px}.message-action-btn[data-v-7317da3a]{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border:none;background:transparent;border-radius:4px;color:var(--el-text-color-secondary);cursor:pointer;font-size:15px}.message-action-btn[data-v-7317da3a]:hover{background:var(--el-fill-color);color:var(--el-color-primary)}.message-user-text[data-v-7317da3a]{font-size:14px;line-height:1.5;color:var(--el-text-color-primary);white-space:pre-wrap;word-break:break-word}.message-content[data-v-7317da3a]{font-size:14px;line-height:1.6;color:var(--el-text-color-primary);word-break:break-word;background:transparent;border:none;outline:none;box-shadow:none;height:auto;overflow-wrap:break-word}.message-content[data-v-7317da3a] p{margin:0 0 8px}.message-content[data-v-7317da3a] p:last-child{margin-bottom:0}.message-content[data-v-7317da3a] h1,.message-content[data-v-7317da3a] h2,.message-content[data-v-7317da3a] h3,.message-content[data-v-7317da3a] h4,.message-content[data-v-7317da3a] h5,.message-content[data-v-7317da3a] h6{margin:12px 0 8px;font-weight:600;line-height:1.4;color:var(--el-text-color-primary);cursor:pointer;-webkit-user-select:none;user-select:none}.message-content[data-v-7317da3a] h1[data-collapsed]:after,.message-content[data-v-7317da3a] h2[data-collapsed]:after,.message-content[data-v-7317da3a] h3[data-collapsed]:after,.message-content[data-v-7317da3a] h4[data-collapsed]:after,.message-content[data-v-7317da3a] h5[data-collapsed]:after,.message-content[data-v-7317da3a] h6[data-collapsed]:after{content:" ▸";font-size:.8em;color:var(--el-text-color-secondary)}.message-content[data-v-7317da3a] h1{font-size:20px}.message-content[data-v-7317da3a] h2{font-size:18px;padding-bottom:4px;border-bottom:1px solid var(--el-border-color-lighter)}.message-content[data-v-7317da3a] h3{font-size:16px}.message-content[data-v-7317da3a] h4{font-size:15px}.message-content[data-v-7317da3a] h5,.message-content[data-v-7317da3a] h6{font-size:14px}.message-content[data-v-7317da3a] strong{font-weight:600}.message-content[data-v-7317da3a] em{font-style:italic}.message-content[data-v-7317da3a] ul,.message-content[data-v-7317da3a] ol{margin:0 0 8px;padding-left:20px}.message-content[data-v-7317da3a] ul:last-child,.message-content[data-v-7317da3a] ol:last-child{margin-bottom:0}.message-content[data-v-7317da3a] li{margin:2px 0}.message-content[data-v-7317da3a] li>ul,.message-content[data-v-7317da3a] li>ol{margin:0}.message-content[data-v-7317da3a] code{padding:1px 5px;margin:0 2px;font-size:12px;font-family:Consolas,Monaco,Courier New,monospace;background:var(--el-fill-color);color:var(--el-color-primary);border-radius:4px}.message-content[data-v-7317da3a] pre{margin:8px 0;padding:10px 12px;background:var(--el-bg-color);border:1px solid var(--el-border-color-lighter);border-radius:6px;overflow-x:auto}.message-content[data-v-7317da3a] .md-code-block{margin:8px 0}.message-content[data-v-7317da3a] .md-code-block__head{display:flex;align-items:center;justify-content:space-between;padding:6px 12px;background:var(--el-fill-color);border:1px solid var(--el-border-color-lighter);border-bottom:none;border-radius:6px 6px 0 0;font-size:12px}.message-content[data-v-7317da3a] .md-code-block__lang{color:var(--el-text-color-secondary);font-family:Consolas,Monaco,Courier New,monospace}.message-content[data-v-7317da3a] .md-code-block__copy{color:var(--el-color-primary);cursor:pointer;-webkit-user-select:none;user-select:none;transition:opacity .2s}.message-content[data-v-7317da3a] .md-code-block__copy:hover{opacity:.7}.message-content[data-v-7317da3a] .md-code-block pre{margin:0;border-radius:0 0 6px 6px}.message-content[data-v-7317da3a] pre code{display:block;padding:0;margin:0;font-size:12px;line-height:1.6;background:transparent;color:var(--el-text-color-primary);border-radius:0;white-space:pre}.message-content[data-v-7317da3a] blockquote{margin:8px 0;padding:4px 12px;border-left:3px solid var(--el-color-primary-light-5);background:var(--el-fill-color-lighter);border-radius:0 6px 6px 0;color:var(--el-text-color-regular)}.message-content[data-v-7317da3a] blockquote p{margin:0}.message-content[data-v-7317da3a] table{width:100%;margin:8px 0;border-collapse:collapse;font-size:13px}.message-content[data-v-7317da3a] th,.message-content[data-v-7317da3a] td{padding:6px 10px;border:1px solid var(--el-border-color-lighter);text-align:left}.message-content[data-v-7317da3a] th{background:var(--el-fill-color);font-weight:600;color:var(--el-text-color-primary)}.message-content[data-v-7317da3a] tbody tr:nth-child(2n){background:var(--el-fill-color-lighter)}.message-content.is-table-clickable[data-v-7317da3a] tbody tr{cursor:pointer;transition:background .15s}.message-content.is-table-clickable[data-v-7317da3a] tbody tr:hover{background:var(--el-color-primary-light-9)}.message-content.is-list-clickable[data-v-7317da3a] li{cursor:pointer;border-radius:4px;transition:background .15s}.message-content.is-list-clickable[data-v-7317da3a] li:hover{background:var(--el-color-primary-light-9)}.message-content[data-v-7317da3a] a{color:var(--el-color-primary);text-decoration:none}.message-content[data-v-7317da3a] a:hover{text-decoration:underline}.message-content[data-v-7317da3a] img{max-width:100%;border-radius:6px}.message-content[data-v-7317da3a] hr{margin:12px 0;border:none;border-top:1px solid var(--el-border-color-lighter)}.typing-dots[data-v-7317da3a]{display:inline-flex;align-items:center;gap:4px;padding:2px 0}.typing-dots i[data-v-7317da3a]{width:6px;height:6px;border-radius:50%;background:var(--el-color-primary);animation:typing-bounce-7317da3a 1.2s ease-in-out infinite}.typing-dots i[data-v-7317da3a]:nth-child(2){animation-delay:.15s}.typing-dots i[data-v-7317da3a]:nth-child(3){animation-delay:.3s}@keyframes typing-bounce-7317da3a{0%,60%,to{transform:translateY(0);opacity:.4}30%{transform:translateY(-4px);opacity:1}}.message-error[data-v-7317da3a]{margin-top:4px;font-size:12px;color:var(--el-color-danger)}.message-reasoning[data-v-7317da3a]{margin-bottom:8px}.reasoning-toggle[data-v-7317da3a]{display:inline-flex;align-items:center;gap:4px;padding:4px 10px;border:1px solid var(--el-border-color);border-radius:999px;background:var(--el-fill-color);color:var(--el-text-color-regular);font-size:12px;line-height:1;cursor:pointer;transition:all .2s}.reasoning-toggle[data-v-7317da3a]:hover{background:var(--el-fill-color-light);color:var(--el-color-primary);border-color:var(--el-color-primary-light-5)}.reasoning-toggle__arrow[data-v-7317da3a]{display:inline-block;font-size:12px;transition:transform .2s}.reasoning-toggle__arrow.open[data-v-7317da3a]{transform:rotate(180deg)}.reasoning-content[data-v-7317da3a]{margin:6px 0 0;padding:8px;background:var(--el-fill-color);border-radius:6px;font-size:12px;white-space:pre-wrap;word-break:break-word;max-height:200px;overflow-y:auto}.message-files[data-v-7317da3a]{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:8px}.message-file[data-v-7317da3a]{display:flex;align-items:center;gap:8px;padding:6px 10px;border:1px solid var(--el-border-color);border-radius:8px;background:var(--el-bg-color);font-size:12px}.message-file.is-image[data-v-7317da3a]{padding:4px;flex-direction:column;align-items:flex-start}.file-image[data-v-7317da3a]{max-width:200px;max-height:200px;border-radius:6px;object-fit:contain;cursor:zoom-in;transition:box-shadow .2s}.file-image[data-v-7317da3a]:hover{box-shadow:0 0 0 2px var(--el-color-primary-light-5)}.file-info[data-v-7317da3a]{display:flex;flex-direction:column;gap:2px}.file-name[data-v-7317da3a]{color:var(--el-text-color-primary);font-weight:500;max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.file-size[data-v-7317da3a]{color:var(--el-text-color-secondary);font-size:11px}.chat-input[data-v-e7db63f0]{padding:12px 16px;border-top:1px solid var(--el-border-color-lighter);background:var(--el-bg-color);display:flex;flex-direction:column}.chat-input__files[data-v-e7db63f0]{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px}.chat-input__preview[data-v-e7db63f0]{margin-left:auto;height:24px;padding:0 8px}.chat-input__files[data-v-e7db63f0] .el-tag{border-radius:999px}.chat-input__send.el-button--primary[data-v-e7db63f0]{background:linear-gradient(135deg,#009688,#2d8cf0);border-color:transparent;color:#fff;transition:box-shadow .2s,transform .2s}.chat-input__send.el-button--primary[data-v-e7db63f0]:hover{background:linear-gradient(135deg,#00807a,#256fce);box-shadow:0 4px 12px #2d8cf059;transform:translateY(-1px)}.chat-input__wrap[data-v-e7db63f0]{display:flex;align-items:flex-end;gap:8px;background:var(--el-fill-color-light);border:1px solid var(--el-border-color);border-radius:12px;padding:6px 6px 6px 12px;transition:border-color .2s,box-shadow .2s}.chat-input__wrap[data-v-e7db63f0]:focus-within{border-color:var(--el-color-primary);box-shadow:0 0 0 2px var(--el-color-primary-light-8)}.chat-input__wrap[data-v-e7db63f0] .el-textarea__inner{border:none;background:transparent;box-shadow:none;padding:4px 0;line-height:1.6;font-size:14px}.chat-input__wrap[data-v-e7db63f0] .el-textarea__inner:focus{box-shadow:none}.chat-input__actions[data-v-e7db63f0]{flex-shrink:0;display:flex;align-items:center;gap:2px;padding-bottom:2px}.form-tip[data-v-2522ad20]{font-size:12px;color:var(--el-text-color-secondary);line-height:1.6;margin-top:4px}.form-tip-inline[data-v-2522ad20]{margin-left:8px;font-size:12px;color:var(--el-text-color-secondary)}.temp-row[data-v-2522ad20]{display:flex;align-items:center;gap:12px;width:100%}.temp-val[data-v-2522ad20]{width:28px;text-align:right;font-size:13px;color:var(--el-text-color-secondary)}.chat-panel-root[data-v-5dde3b27]{position:fixed;z-index:1999}.ai-fab[data-v-5dde3b27]{position:fixed;right:22px;bottom:25px;z-index:2000;display:flex;align-items:center;gap:8px;height:52px;padding:0 22px 0 18px;border-radius:26px;color:#fff;font-size:15px;font-weight:600;cursor:pointer;background:linear-gradient(135deg,#009688,#2d8cf0);box-shadow:0 6px 24px #2d8cf080;transition:transform .25s cubic-bezier(.34,1.56,.64,1),box-shadow .25s;-webkit-user-select:none;user-select:none;overflow:hidden;isolation:isolate;animation:ai-fab-float-5dde3b27 3.6s ease-in-out infinite}@keyframes ai-fab-float-5dde3b27{0%,to{transform:translateY(0)}50%{transform:translateY(-6px)}}.ai-fab[data-v-5dde3b27]:before{content:"";position:absolute;top:0;right:0;bottom:0;left:0;border-radius:inherit;background:linear-gradient(105deg,transparent 30%,rgba(255,255,255,.25) 50%,transparent 70%);background-size:200% 100%;background-position:100% 0;animation:ai-fab-shimmer-5dde3b27 4s ease-in-out infinite;z-index:-1;pointer-events:none}@keyframes ai-fab-shimmer-5dde3b27{0%,to{background-position:100% 0}50%{background-position:0 0}}.ai-fab[data-v-5dde3b27]:after{content:"";position:absolute;top:-4px;right:-4px;bottom:-4px;left:-4px;border-radius:inherit;border:2px solid rgba(45,140,240,.35);animation:ai-fab-pulse-5dde3b27 2.4s ease-in-out infinite;pointer-events:none;z-index:-2}@keyframes ai-fab-pulse-5dde3b27{0%,to{opacity:.6;transform:scale(1)}50%{opacity:0;transform:scale(1.12)}}.ai-fab__icon[data-v-5dde3b27]{font-size:22px;filter:drop-shadow(0 0 4px rgba(255,255,255,.4));transition:transform .3s cubic-bezier(.34,1.56,.64,1)}.ai-fab__label[data-v-5dde3b27]{line-height:1;text-shadow:0 1px 4px rgba(0,0,0,.15)}.ai-fab[data-v-5dde3b27]:hover{animation:none;transform:translateY(-4px) scale(1.04);box-shadow:0 12px 32px #2d8cf099}.ai-fab[data-v-5dde3b27]:hover:before{animation:none;background-position:0 0}.ai-fab--active[data-v-5dde3b27]{animation:none;box-shadow:0 4px 16px #2d8cf066}.ai-fab--active[data-v-5dde3b27]:after{animation:none;opacity:0}.ai-fab--active[data-v-5dde3b27]:before{animation:none}.ai-fab--active .ai-fab__icon[data-v-5dde3b27]{transform:rotate(45deg)}.ai-fab--dragged[data-v-5dde3b27]{animation:none}.ai-fab--dragged[data-v-5dde3b27]:before,.ai-fab--dragged[data-v-5dde3b27]:after{animation:none;opacity:0}.chat-panel[data-v-5dde3b27]{position:fixed;bottom:25px;right:22px;z-index:9999;display:flex;flex-direction:column;height:680px;width:560px;min-height:400px;background:var(--el-bg-color);box-shadow:0 20px 50px #0000002e,0 6px 18px #00000014;border-radius:16px;transform-origin:bottom right}.panel-enter-active[data-v-5dde3b27],.panel-leave-active[data-v-5dde3b27]{transition:opacity .3s ease,transform .3s cubic-bezier(.34,1.56,.64,1)}.panel-enter-from[data-v-5dde3b27],.panel-leave-to[data-v-5dde3b27]{opacity:0;transform:translateY(16px) scale(.96)}.chat-panel__header[data-v-5dde3b27]{display:flex;align-items:center;justify-content:space-between;padding:10px 16px;cursor:move;-webkit-user-select:none;user-select:none;border-bottom:1px solid var(--el-border-color-lighter);background:linear-gradient(135deg,var(--el-color-primary-light-7),var(--el-bg-color));border-radius:16px 16px 0 0;flex-shrink:0}.chat-panel__title[data-v-5dde3b27]{display:flex;align-items:center;gap:8px;font-size:15px;font-weight:600;color:var(--el-text-color-primary)}.title-icon[data-v-5dde3b27]{color:var(--el-color-primary);font-size:18px}.chat-panel__ops[data-v-5dde3b27]{display:flex;gap:4px}.chat-panel__scroll-wrap[data-v-5dde3b27]{position:relative;flex:1;min-height:0;display:flex}.chat-panel__body[data-v-5dde3b27]{flex:1;overflow-y:auto;padding:0 16px;min-height:0;scrollbar-width:thin;scrollbar-color:var(--el-border-color-darker) transparent}.chat-panel__nav[data-v-5dde3b27]{position:absolute;right:6px;top:50%;transform:translateY(-50%);display:flex;flex-direction:column;align-items:center;gap:6px;padding:6px 4px;background:var(--el-bg-color);border:1px solid var(--el-border-color-lighter);border-radius:10px;box-shadow:0 2px 10px #00000014;opacity:.35;transition:opacity .2s}.chat-panel__nav[data-v-5dde3b27]:hover,.chat-panel__nav.is-suppressed-scroll[data-v-5dde3b27]{opacity:1}.chat-panel__nav-count[data-v-5dde3b27]{font-size:10px;line-height:1;color:var(--el-text-color-secondary);font-variant-numeric:tabular-nums}.chat-panel__nav-btn[data-v-5dde3b27]{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;padding:0;border:none;border-radius:8px;background:transparent;color:var(--el-text-color-regular);cursor:pointer;font-size:14px;transition:background .15s,color .15s}.chat-panel__nav-btn[data-v-5dde3b27]:hover:not(:disabled){background:var(--el-color-primary-light-9);color:var(--el-color-primary)}.chat-panel__nav-btn[data-v-5dde3b27]:disabled{color:var(--el-text-color-placeholder);cursor:not-allowed;opacity:.5}.chat-panel__body[data-v-5dde3b27] [data-msg-id].is-locate{animation:locate-flash-5dde3b27 1.2s ease both}@keyframes locate-flash-5dde3b27{0%{outline:2px solid var(--el-color-primary);outline-offset:2px;border-radius:8px}to{outline:2px solid transparent;outline-offset:2px;border-radius:8px}}.chat-panel__body[data-v-5dde3b27]::-webkit-scrollbar{width:8px}.chat-panel__body[data-v-5dde3b27]::-webkit-scrollbar-track{background:var(--el-fill-color-lighter);border-radius:4px}.chat-panel__body[data-v-5dde3b27]::-webkit-scrollbar-thumb{background:var(--el-border-color-darker);border-radius:4px;border:2px solid transparent;background-clip:content-box}.chat-panel__body[data-v-5dde3b27]::-webkit-scrollbar-thumb:hover{background:var(--el-text-color-secondary);background-clip:content-box}.chat-empty[data-v-5dde3b27]{height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:14px}.chat-empty__logo[data-v-5dde3b27]{width:64px;height:64px;border-radius:18px;background:linear-gradient(135deg,#009688,#2d8cf0);color:#fff;display:flex;align-items:center;justify-content:center;font-size:32px;box-shadow:0 8px 24px #2d8cf04d}.chat-empty h3[data-v-5dde3b27]{margin:0;font-size:18px;color:var(--el-text-color-primary)}.chat-empty__desc[data-v-5dde3b27]{margin:0;font-size:13px;color:var(--el-text-color-secondary);line-height:1.6}.chat-empty__desc .hl[data-v-5dde3b27]{color:var(--el-color-primary);font-weight:600}.chat-empty__commands[data-v-5dde3b27]{display:flex;flex-wrap:wrap;justify-content:center;gap:8px}.chat-empty__commands .el-button[data-v-5dde3b27]{margin-left:0}.chat-panel__footer[data-v-5dde3b27]{flex-shrink:0}.chat-panel__stop[data-v-5dde3b27]{display:flex;justify-content:center;padding:6px 0 0}.chat-panel__error[data-v-5dde3b27]{padding:8px 16px 0}.fade-enter-active[data-v-5dde3b27],.fade-leave-active[data-v-5dde3b27]{transition:opacity .2s}.fade-enter-from[data-v-5dde3b27],.fade-leave-to[data-v-5dde3b27]{opacity:0}.chat-panel--fullscreen[data-v-5dde3b27]{position:fixed;top:5%;right:10%;bottom:5%;left:10%;z-index:9999;height:90vh!important;width:80%!important}
|
|
1
|
+
.render-block[data-v-d7f1b4ad]{margin:8px 0;padding:8px 0;width:100%}.render-block__component[data-v-d7f1b4ad]{border-radius:8px;background:var(--el-fill-color-lighter);box-shadow:0 0 10px #0000001a}.render-block__title[data-v-d7f1b4ad]{font-weight:600;font-size:14px;margin-bottom:6px;color:var(--el-text-color-primary)}.render-block__table[data-v-d7f1b4ad]{width:100%;max-width:900px;border-radius:8px;overflow:hidden;box-shadow:0 2px 8px #0000000f}.render-block__cards[data-v-d7f1b4ad]{display:flex;flex-direction:column;gap:8px}.card-item[data-v-d7f1b4ad]{border:1px solid var(--el-border-color);border-radius:8px;padding:10px 14px;background:var(--el-fill-color-lighter);box-shadow:0 2px 6px #0000000d}.card-field[data-v-d7f1b4ad]{display:flex;gap:6px;font-size:13px;line-height:1.8}.card-label[data-v-d7f1b4ad]{font-weight:600;color:var(--el-text-color-secondary);min-width:80px}.card-value[data-v-d7f1b4ad]{color:var(--el-text-color-primary)}.render-block__list[data-v-d7f1b4ad]{display:flex;flex-direction:column;gap:4px}.list-item[data-v-d7f1b4ad]{padding:6px 10px;font-size:13px;border-left:3px solid var(--el-color-primary);background:var(--el-fill-color-lighter);border-radius:0 4px 4px 0;box-shadow:0 1px 4px #0000000a}.suggested-next[data-v-0e0e9b65]{display:flex;align-items:center;gap:8px;padding:8px 12px;margin:6px 0;background:var(--el-color-primary-light-9);border:1px solid var(--el-color-primary-light-7);border-radius:8px;font-size:13px}.suggested-next__icon[data-v-0e0e9b65]{font-size:15px;flex-shrink:0}.suggested-next__text[data-v-0e0e9b65]{flex:1;color:var(--el-text-color-regular)}.chat-message[data-v-25c0f8d1]{display:flex;gap:10px;padding:12px 0;animation:msg-in-25c0f8d1 .25s ease both}@keyframes msg-in-25c0f8d1{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}.chat-message.role-user[data-v-25c0f8d1]{flex-direction:row-reverse}.chat-message.role-user .message-time[data-v-25c0f8d1]{text-align:right}.message-avatar[data-v-25c0f8d1]{width:32px;height:32px;border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0;font-size:16px;color:#fff;box-shadow:0 0 0 2px var(--el-bg-color),0 2px 6px #0000001f}.role-user .message-avatar[data-v-25c0f8d1]{background:linear-gradient(135deg,var(--el-color-primary),var(--el-color-primary-light-3))}.role-assistant .message-avatar[data-v-25c0f8d1]{background:linear-gradient(135deg,#009688,#2d8cf0)}.message-time[data-v-25c0f8d1]{display:block;font-size:11px;line-height:1;color:var(--el-text-color-placeholder);margin-bottom:4px}.message-body[data-v-25c0f8d1]{max-width:80%;min-width:0}.role-user .message-body[data-v-25c0f8d1]{background:linear-gradient(135deg,var(--el-color-primary-light-9),var(--el-color-primary-light-8));padding:8px 14px;border-radius:12px 4px 12px 12px;box-shadow:0 2px 8px #0000000f,0 1px 2px #0000000a}.role-assistant .message-body[data-v-25c0f8d1]{position:relative;background:var(--el-fill-color-lighter);padding:8px 14px;border-radius:4px 12px 12px;display:flex;flex-direction:column;box-shadow:0 2px 8px #0000000f,0 1px 2px #0000000a}.message-actions[data-v-25c0f8d1]{position:absolute;top:0;right:0;opacity:0;transition:opacity .2s;z-index:1}.role-assistant .message-body:hover .message-actions[data-v-25c0f8d1]{opacity:1}.role-assistant .message-body .message-time[data-v-25c0f8d1]{float:left;width:10px}.message-action-btn[data-v-25c0f8d1]{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border:none;background:transparent;border-radius:4px;color:var(--el-text-color-secondary);cursor:pointer;font-size:15px}.message-action-btn[data-v-25c0f8d1]:hover{background:var(--el-fill-color);color:var(--el-color-primary)}.message-user-text[data-v-25c0f8d1]{font-size:14px;line-height:1.5;color:var(--el-text-color-primary);white-space:pre-wrap;word-break:break-word}.message-content[data-v-25c0f8d1]{font-size:14px;line-height:1.6;color:var(--el-text-color-primary);word-break:break-word;background:transparent;border:none;outline:none;box-shadow:none;height:auto;overflow-wrap:break-word;min-height:8px!important}.message-content[data-v-25c0f8d1] p{margin:0 0 8px}.message-content[data-v-25c0f8d1] p:last-child{margin-bottom:0}.message-content[data-v-25c0f8d1] h1,.message-content[data-v-25c0f8d1] h2,.message-content[data-v-25c0f8d1] h3,.message-content[data-v-25c0f8d1] h4,.message-content[data-v-25c0f8d1] h5,.message-content[data-v-25c0f8d1] h6{margin:12px 0 8px;font-weight:600;line-height:1.4;color:var(--el-text-color-primary);cursor:pointer;-webkit-user-select:none;user-select:none}.message-content[data-v-25c0f8d1] h1[data-collapsed]:after,.message-content[data-v-25c0f8d1] h2[data-collapsed]:after,.message-content[data-v-25c0f8d1] h3[data-collapsed]:after,.message-content[data-v-25c0f8d1] h4[data-collapsed]:after,.message-content[data-v-25c0f8d1] h5[data-collapsed]:after,.message-content[data-v-25c0f8d1] h6[data-collapsed]:after{content:" ▸";font-size:.8em;color:var(--el-text-color-secondary)}.message-content[data-v-25c0f8d1] h1{font-size:20px}.message-content[data-v-25c0f8d1] h2{font-size:18px;padding-bottom:4px;border-bottom:1px solid var(--el-border-color-lighter)}.message-content[data-v-25c0f8d1] h3{font-size:16px}.message-content[data-v-25c0f8d1] h4{font-size:15px}.message-content[data-v-25c0f8d1] h5,.message-content[data-v-25c0f8d1] h6{font-size:14px}.message-content[data-v-25c0f8d1] strong{font-weight:600}.message-content[data-v-25c0f8d1] em{font-style:italic}.message-content[data-v-25c0f8d1] ul,.message-content[data-v-25c0f8d1] ol{margin:0 0 8px;padding-left:20px}.message-content[data-v-25c0f8d1] ul:last-child,.message-content[data-v-25c0f8d1] ol:last-child{margin-bottom:0}.message-content[data-v-25c0f8d1] li{margin:2px 0}.message-content[data-v-25c0f8d1] li>ul,.message-content[data-v-25c0f8d1] li>ol{margin:0}.message-content[data-v-25c0f8d1] code{padding:1px 5px;margin:0 2px;font-size:12px;font-family:Consolas,Monaco,Courier New,monospace;background:var(--el-fill-color);color:var(--el-color-primary);border-radius:4px}.message-content[data-v-25c0f8d1] pre{margin:8px 0;padding:10px 12px;background:var(--el-bg-color);border:1px solid var(--el-border-color-lighter);border-radius:6px;overflow-x:auto}.message-content[data-v-25c0f8d1] .md-code-block{margin:8px 0}.message-content[data-v-25c0f8d1] .md-code-block__head{display:flex;align-items:center;justify-content:space-between;padding:6px 12px;background:var(--el-fill-color);border:1px solid var(--el-border-color-lighter);border-bottom:none;border-radius:6px 6px 0 0;font-size:12px}.message-content[data-v-25c0f8d1] .md-code-block__lang{color:var(--el-text-color-secondary);font-family:Consolas,Monaco,Courier New,monospace}.message-content[data-v-25c0f8d1] .md-code-block__copy{color:var(--el-color-primary);cursor:pointer;-webkit-user-select:none;user-select:none;transition:opacity .2s}.message-content[data-v-25c0f8d1] .md-code-block__copy:hover{opacity:.7}.message-content[data-v-25c0f8d1] .md-code-block pre{margin:0;border-radius:0 0 6px 6px}.message-content[data-v-25c0f8d1] pre code{display:block;padding:0;margin:0;font-size:12px;line-height:1.6;background:transparent;color:var(--el-text-color-primary);border-radius:0;white-space:pre}.message-content[data-v-25c0f8d1] blockquote{margin:8px 0;padding:4px 12px;border-left:3px solid var(--el-color-primary-light-5);background:var(--el-fill-color-lighter);border-radius:0 6px 6px 0;color:var(--el-text-color-regular)}.message-content[data-v-25c0f8d1] blockquote p{margin:0}.message-content[data-v-25c0f8d1] table{width:100%;margin:8px 0;border-collapse:collapse;font-size:13px}.message-content[data-v-25c0f8d1] th,.message-content[data-v-25c0f8d1] td{padding:6px 10px;border:1px solid var(--el-border-color-lighter);text-align:left}.message-content[data-v-25c0f8d1] th{background:var(--el-fill-color);font-weight:600;color:var(--el-text-color-primary)}.message-content[data-v-25c0f8d1] tbody tr:nth-child(2n){background:var(--el-fill-color-lighter)}.message-content.is-table-clickable[data-v-25c0f8d1] tbody tr{cursor:pointer;transition:background .15s}.message-content.is-table-clickable[data-v-25c0f8d1] tbody tr:hover{background:var(--el-color-primary-light-9)}.message-content.is-list-clickable[data-v-25c0f8d1] li{cursor:pointer;border-radius:4px;transition:background .15s}.message-content.is-list-clickable[data-v-25c0f8d1] li:hover{background:var(--el-color-primary-light-9)}.message-content[data-v-25c0f8d1] a{color:var(--el-color-primary);text-decoration:none}.message-content[data-v-25c0f8d1] a:hover{text-decoration:underline}.message-content[data-v-25c0f8d1] img{max-width:100%;border-radius:6px}.message-content[data-v-25c0f8d1] hr{margin:12px 0;border:none;border-top:1px solid var(--el-border-color-lighter)}.typing-dots[data-v-25c0f8d1]{display:inline-flex;align-items:center;gap:4px;padding:2px 0}.typing-dots i[data-v-25c0f8d1]{width:6px;height:6px;border-radius:50%;background:var(--el-color-primary);animation:typing-bounce-25c0f8d1 1.2s ease-in-out infinite}.typing-dots i[data-v-25c0f8d1]:nth-child(2){animation-delay:.15s}.typing-dots i[data-v-25c0f8d1]:nth-child(3){animation-delay:.3s}@keyframes typing-bounce-25c0f8d1{0%,60%,to{transform:translateY(0);opacity:.4}30%{transform:translateY(-4px);opacity:1}}.message-error[data-v-25c0f8d1]{margin-top:4px;font-size:12px;color:var(--el-color-danger)}.message-reasoning[data-v-25c0f8d1]{margin-bottom:8px}.reasoning-toggle[data-v-25c0f8d1]{display:inline-flex;align-items:center;gap:4px;padding:4px 10px;border:1px solid var(--el-border-color);border-radius:999px;background:var(--el-fill-color);color:var(--el-text-color-regular);font-size:12px;line-height:1;cursor:pointer;transition:all .2s}.reasoning-toggle[data-v-25c0f8d1]:hover{background:var(--el-fill-color-light);color:var(--el-color-primary);border-color:var(--el-color-primary-light-5)}.reasoning-toggle__arrow[data-v-25c0f8d1]{display:inline-block;font-size:12px;transition:transform .2s}.reasoning-toggle__arrow.open[data-v-25c0f8d1]{transform:rotate(180deg)}.reasoning-content[data-v-25c0f8d1]{margin:6px 0 0;padding:8px;background:var(--el-fill-color);border-radius:6px;font-size:12px;white-space:pre-wrap;word-break:break-word;max-height:200px;overflow-y:auto}.message-tools[data-v-25c0f8d1]{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px}.message-tool[data-v-25c0f8d1]{display:inline-flex;align-items:center;gap:4px;padding:3px 8px;border:1px solid var(--el-border-color-lighter);border-radius:999px;background:var(--el-bg-color);color:var(--el-text-color-regular);font-size:12px;line-height:1.4}.message-tool.is-running[data-v-25c0f8d1]{border-color:var(--el-color-primary-light-5);color:var(--el-color-primary)}.message-tool.is-success[data-v-25c0f8d1]{border-color:var(--el-color-success-light-5);color:var(--el-color-success)}.message-tool.is-error[data-v-25c0f8d1]{border-color:var(--el-color-danger-light-5);color:var(--el-color-danger)}.message-tool.is-blocked[data-v-25c0f8d1]{border-color:var(--el-color-warning-light-5);color:var(--el-color-warning)}.message-tool__icon[data-v-25c0f8d1]{font-size:13px}.message-tool__status[data-v-25c0f8d1]{color:var(--el-text-color-secondary)}.message-tool.is-running .message-tool__status[data-v-25c0f8d1],.message-tool.is-success .message-tool__status[data-v-25c0f8d1],.message-tool.is-error .message-tool__status[data-v-25c0f8d1],.message-tool.is-blocked .message-tool__status[data-v-25c0f8d1]{color:inherit}.message-tool__icon.is-spinning[data-v-25c0f8d1]{animation:tool-spin-25c0f8d1 1s linear infinite}@keyframes tool-spin-25c0f8d1{to{transform:rotate(360deg)}}.message-files[data-v-25c0f8d1]{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:8px}.message-file[data-v-25c0f8d1]{display:flex;align-items:center;gap:8px;padding:6px 10px;border:1px solid var(--el-border-color);border-radius:8px;background:var(--el-bg-color);font-size:12px}.message-file.is-image[data-v-25c0f8d1]{padding:4px;flex-direction:column;align-items:flex-start}.file-image[data-v-25c0f8d1]{max-width:200px;max-height:200px;border-radius:6px;object-fit:contain;cursor:zoom-in;transition:box-shadow .2s}.file-image[data-v-25c0f8d1]:hover{box-shadow:0 0 0 2px var(--el-color-primary-light-5)}.file-info[data-v-25c0f8d1]{display:flex;flex-direction:column;gap:2px}.file-name[data-v-25c0f8d1]{color:var(--el-text-color-primary);font-weight:500;max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.file-size[data-v-25c0f8d1]{color:var(--el-text-color-secondary);font-size:11px}.chat-input[data-v-e7db63f0]{padding:12px 16px;border-top:1px solid var(--el-border-color-lighter);background:var(--el-bg-color);display:flex;flex-direction:column}.chat-input__files[data-v-e7db63f0]{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px}.chat-input__preview[data-v-e7db63f0]{margin-left:auto;height:24px;padding:0 8px}.chat-input__files[data-v-e7db63f0] .el-tag{border-radius:999px}.chat-input__send.el-button--primary[data-v-e7db63f0]{background:linear-gradient(135deg,#009688,#2d8cf0);border-color:transparent;color:#fff;transition:box-shadow .2s,transform .2s}.chat-input__send.el-button--primary[data-v-e7db63f0]:hover{background:linear-gradient(135deg,#00807a,#256fce);box-shadow:0 4px 12px #2d8cf059;transform:translateY(-1px)}.chat-input__wrap[data-v-e7db63f0]{display:flex;align-items:flex-end;gap:8px;background:var(--el-fill-color-light);border:1px solid var(--el-border-color);border-radius:12px;padding:6px 6px 6px 12px;transition:border-color .2s,box-shadow .2s}.chat-input__wrap[data-v-e7db63f0]:focus-within{border-color:var(--el-color-primary);box-shadow:0 0 0 2px var(--el-color-primary-light-8)}.chat-input__wrap[data-v-e7db63f0] .el-textarea__inner{border:none;background:transparent;box-shadow:none;padding:4px 0;line-height:1.6;font-size:14px}.chat-input__wrap[data-v-e7db63f0] .el-textarea__inner:focus{box-shadow:none}.chat-input__actions[data-v-e7db63f0]{flex-shrink:0;display:flex;align-items:center;gap:2px;padding-bottom:2px}.form-tip[data-v-6282664f]{font-size:12px;color:var(--el-text-color-secondary);line-height:1.6;margin-top:4px}.form-tip-inline[data-v-6282664f]{margin-left:8px;font-size:12px;color:var(--el-text-color-secondary)}.temp-row[data-v-6282664f]{display:flex;align-items:center;gap:12px;width:100%}.temp-val[data-v-6282664f]{width:28px;text-align:right;font-size:13px;color:var(--el-text-color-secondary)}.session-drawer[data-v-42d4ed19]{display:flex;flex-direction:column;gap:12px;height:100%}.session-drawer__new[data-v-42d4ed19]{width:100%}.session-drawer__loading[data-v-42d4ed19]{padding:24px 0;text-align:center;font-size:13px;color:var(--el-text-color-secondary)}.session-list[data-v-42d4ed19]{display:flex;flex-direction:column;gap:6px;overflow-y:auto;padding-right:2px}.session-item[data-v-42d4ed19]{display:flex;align-items:center;gap:6px;padding:8px 10px;border:1px solid var(--el-border-color-lighter);border-radius:8px;cursor:pointer;transition:background .15s,border-color .15s}.session-item[data-v-42d4ed19]:hover{background:var(--el-fill-color-light)}.session-item.is-active[data-v-42d4ed19]{border-color:var(--el-color-primary-light-5);background:var(--el-color-primary-light-9)}.session-item__body[data-v-42d4ed19]{flex:1;min-width:0}.session-item__title[data-v-42d4ed19]{font-size:13px;font-weight:600;color:var(--el-text-color-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.session-item__meta[data-v-42d4ed19]{display:flex;gap:8px;margin-top:2px;font-size:11px;color:var(--el-text-color-secondary)}.session-item__del[data-v-42d4ed19]{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;border:none;border-radius:6px;background:transparent;color:var(--el-text-color-secondary);cursor:pointer;opacity:.6;transition:background .15s,color .15s,opacity .15s}.session-item__del[data-v-42d4ed19]:hover{opacity:1;color:var(--el-color-danger);background:var(--el-color-danger-light-9)}.ai-selection-send[data-v-a4fae753]{position:fixed;z-index:10000;display:inline-flex;align-items:center;gap:4px;height:30px;padding:0 12px;border:none;border-radius:15px;background:linear-gradient(135deg,#009688,#2d8cf0);color:#fff;font-size:12px;font-weight:600;line-height:1;cursor:pointer;-webkit-user-select:none;user-select:none;box-shadow:0 4px 14px #2d8cf073;transition:transform .15s,box-shadow .15s,opacity .15s}.ai-selection-send[data-v-a4fae753]:hover:not(.is-disabled){transform:translateY(-1px);box-shadow:0 8px 20px #2d8cf08c}.ai-selection-send.is-disabled[data-v-a4fae753]{opacity:.55;cursor:not-allowed}.ai-selection-send__icon[data-v-a4fae753]{font-size:14px}.sel-send-fade-enter-active[data-v-a4fae753],.sel-send-fade-leave-active[data-v-a4fae753]{transition:opacity .12s ease}.sel-send-fade-enter-from[data-v-a4fae753],.sel-send-fade-leave-to[data-v-a4fae753]{opacity:0}.chat-panel-root[data-v-597f8f19]{position:fixed;z-index:1999}.ai-fab[data-v-597f8f19]{position:fixed;right:22px;bottom:25px;z-index:2000;display:flex;align-items:center;gap:8px;height:52px;padding:0 22px 0 18px;border-radius:26px;color:#fff;font-size:15px;font-weight:600;cursor:pointer;background:linear-gradient(135deg,#009688,#2d8cf0);box-shadow:0 6px 24px #2d8cf080;transition:transform .25s cubic-bezier(.34,1.56,.64,1),box-shadow .25s;-webkit-user-select:none;user-select:none;overflow:hidden;isolation:isolate;animation:ai-fab-float-597f8f19 3.6s ease-in-out infinite}@keyframes ai-fab-float-597f8f19{0%,to{transform:translateY(0)}50%{transform:translateY(-6px)}}.ai-fab[data-v-597f8f19]:before{content:"";position:absolute;top:0;right:0;bottom:0;left:0;border-radius:inherit;background:linear-gradient(105deg,transparent 30%,rgba(255,255,255,.25) 50%,transparent 70%);background-size:200% 100%;background-position:100% 0;animation:ai-fab-shimmer-597f8f19 4s ease-in-out infinite;z-index:-1;pointer-events:none}@keyframes ai-fab-shimmer-597f8f19{0%,to{background-position:100% 0}50%{background-position:0 0}}.ai-fab[data-v-597f8f19]:after{content:"";position:absolute;top:-4px;right:-4px;bottom:-4px;left:-4px;border-radius:inherit;border:2px solid rgba(45,140,240,.35);animation:ai-fab-pulse-597f8f19 2.4s ease-in-out infinite;pointer-events:none;z-index:-2}@keyframes ai-fab-pulse-597f8f19{0%,to{opacity:.6;transform:scale(1)}50%{opacity:0;transform:scale(1.12)}}.ai-fab__icon[data-v-597f8f19]{font-size:22px;filter:drop-shadow(0 0 4px rgba(255,255,255,.4));transition:transform .3s cubic-bezier(.34,1.56,.64,1)}.ai-fab__label[data-v-597f8f19]{line-height:1;text-shadow:0 1px 4px rgba(0,0,0,.15)}.ai-fab[data-v-597f8f19]:hover{animation:none;transform:translateY(-4px) scale(1.04);box-shadow:0 12px 32px #2d8cf099}.ai-fab[data-v-597f8f19]:hover:before{animation:none;background-position:0 0}.ai-fab--active[data-v-597f8f19]{animation:none;box-shadow:0 4px 16px #2d8cf066}.ai-fab--active[data-v-597f8f19]:after{animation:none;opacity:0}.ai-fab--active[data-v-597f8f19]:before{animation:none}.ai-fab--active .ai-fab__icon[data-v-597f8f19]{transform:rotate(45deg)}.ai-fab--dragged[data-v-597f8f19]{animation:none}.ai-fab--dragged[data-v-597f8f19]:before,.ai-fab--dragged[data-v-597f8f19]:after{animation:none;opacity:0}.chat-panel[data-v-597f8f19]{position:fixed;bottom:25px;right:22px;z-index:9999;display:flex;flex-direction:column;height:680px;width:560px;min-height:400px;background:var(--el-bg-color);box-shadow:0 20px 50px #0000002e,0 6px 18px #00000014;border-radius:16px;transform-origin:bottom right}.panel-enter-active[data-v-597f8f19],.panel-leave-active[data-v-597f8f19]{transition:opacity .3s ease,transform .3s cubic-bezier(.34,1.56,.64,1)}.panel-enter-from[data-v-597f8f19],.panel-leave-to[data-v-597f8f19]{opacity:0;transform:translateY(16px) scale(.96)}.chat-panel__header[data-v-597f8f19]{display:flex;align-items:center;justify-content:space-between;padding:10px 16px;cursor:move;-webkit-user-select:none;user-select:none;border-bottom:1px solid var(--el-border-color-lighter);background:linear-gradient(135deg,var(--el-color-primary-light-7),var(--el-bg-color));border-radius:16px 16px 0 0;flex-shrink:0}.chat-panel__title[data-v-597f8f19]{display:flex;align-items:center;gap:8px;font-size:15px;font-weight:600;color:var(--el-text-color-primary)}.title-icon[data-v-597f8f19]{color:var(--el-color-primary);font-size:18px}.chat-panel__ops[data-v-597f8f19]{display:flex;gap:4px}.chat-panel__scroll-wrap[data-v-597f8f19]{position:relative;flex:1;min-height:0;display:flex}.chat-panel__body[data-v-597f8f19]{flex:1;overflow-y:auto;padding:0 16px;min-height:0;scrollbar-width:thin;scrollbar-color:var(--el-border-color-darker) transparent}.chat-panel__nav[data-v-597f8f19]{position:absolute;right:6px;top:50%;transform:translateY(-50%);display:flex;flex-direction:column;align-items:center;gap:6px;padding:6px 4px;background:var(--el-bg-color);border:1px solid var(--el-border-color-lighter);border-radius:10px;box-shadow:0 2px 10px #00000014;opacity:.35;transition:opacity .2s}.chat-panel__nav[data-v-597f8f19]:hover,.chat-panel__nav.is-suppressed-scroll[data-v-597f8f19]{opacity:1}.chat-panel__nav-count[data-v-597f8f19]{font-size:10px;line-height:1;color:var(--el-text-color-secondary);font-variant-numeric:tabular-nums}.chat-panel__nav-btn[data-v-597f8f19]{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;padding:0;border:none;border-radius:8px;background:transparent;color:var(--el-text-color-regular);cursor:pointer;font-size:14px;transition:background .15s,color .15s}.chat-panel__nav-btn[data-v-597f8f19]:hover:not(:disabled){background:var(--el-color-primary-light-9);color:var(--el-color-primary)}.chat-panel__nav-btn[data-v-597f8f19]:disabled{color:var(--el-text-color-placeholder);cursor:not-allowed;opacity:.5}.chat-panel__body[data-v-597f8f19] [data-msg-id].is-locate{animation:locate-flash-597f8f19 1.2s ease both}@keyframes locate-flash-597f8f19{0%{outline:2px solid var(--el-color-primary);outline-offset:2px;border-radius:8px}to{outline:2px solid transparent;outline-offset:2px;border-radius:8px}}.chat-panel__body[data-v-597f8f19]::-webkit-scrollbar{width:8px}.chat-panel__body[data-v-597f8f19]::-webkit-scrollbar-track{background:var(--el-fill-color-lighter);border-radius:4px}.chat-panel__body[data-v-597f8f19]::-webkit-scrollbar-thumb{background:var(--el-border-color-darker);border-radius:4px;border:2px solid transparent;background-clip:content-box}.chat-panel__body[data-v-597f8f19]::-webkit-scrollbar-thumb:hover{background:var(--el-text-color-secondary);background-clip:content-box}.chat-empty[data-v-597f8f19]{height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:14px}.chat-empty__logo[data-v-597f8f19]{width:64px;height:64px;border-radius:18px;background:linear-gradient(135deg,#009688,#2d8cf0);color:#fff;display:flex;align-items:center;justify-content:center;font-size:32px;box-shadow:0 8px 24px #2d8cf04d}.chat-empty h3[data-v-597f8f19]{margin:0;font-size:18px;color:var(--el-text-color-primary)}.chat-empty__desc[data-v-597f8f19]{margin:0;font-size:13px;color:var(--el-text-color-secondary);line-height:1.6}.chat-empty__desc .hl[data-v-597f8f19]{color:var(--el-color-primary);font-weight:600}.chat-empty__commands[data-v-597f8f19]{display:flex;flex-wrap:wrap;justify-content:center;gap:8px}.chat-empty__commands .el-button[data-v-597f8f19]{margin-left:0}.chat-panel__footer[data-v-597f8f19]{flex-shrink:0}.chat-panel__stop[data-v-597f8f19]{display:flex;justify-content:center;padding:6px 0 0}.chat-panel__error[data-v-597f8f19]{padding:8px 16px 0}.fade-enter-active[data-v-597f8f19],.fade-leave-active[data-v-597f8f19]{transition:opacity .2s}.fade-enter-from[data-v-597f8f19],.fade-leave-to[data-v-597f8f19]{opacity:0}.chat-panel--fullscreen[data-v-597f8f19]{position:fixed;top:5%;right:10%;bottom:5%;left:10%;z-index:9999;height:90vh!important;width:80%!important}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { LLMProvider } from '../agent-core';
|
|
2
|
+
import { ProviderPreset } from '../types';
|
|
3
|
+
export interface OpenAICompatibleProviderOptions {
|
|
4
|
+
preset: ProviderPreset;
|
|
5
|
+
mode?: 'direct' | 'proxy';
|
|
6
|
+
}
|
|
7
|
+
/** 兼容传入 origin、/v1 或完整 /chat/completions 地址 */
|
|
8
|
+
export declare function resolveChatCompletionsUrl(baseUrl: string): string;
|
|
9
|
+
/** 代理地址兼容 http://host 与 http://host/api/chat 两种写法 */
|
|
10
|
+
export declare function getServerBase(proxyUrl: string): string;
|
|
11
|
+
export declare function createOpenAICompatibleProvider(options: OpenAICompatibleProviderOptions): LLMProvider;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { LLMProvider } from '../agent-core';
|
|
2
|
+
export interface ProviderFactoryContext {
|
|
3
|
+
id: string;
|
|
4
|
+
mode: 'direct' | 'proxy';
|
|
5
|
+
}
|
|
6
|
+
export type ProviderFactory = (context: ProviderFactoryContext) => LLMProvider;
|
|
7
|
+
export declare function registerProvider(id: string, factory: ProviderFactory): void;
|
|
8
|
+
export declare function createProvider(id: string, mode: 'direct' | 'proxy'): LLMProvider;
|
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ChatMessage } from '../types';
|
|
1
|
+
import { ChatMessage, ToolPackage } from '../types';
|
|
3
2
|
type __VLS_Props = {
|
|
4
3
|
message: ChatMessage;
|
|
5
|
-
toolPackages:
|
|
6
|
-
id: string;
|
|
7
|
-
components?: Record<string, Component>;
|
|
8
|
-
}[];
|
|
4
|
+
toolPackages: ToolPackage[];
|
|
9
5
|
mdTableClick?: boolean;
|
|
10
6
|
mdListClick?: boolean;
|
|
11
7
|
};
|
|
@@ -13,5 +9,5 @@ declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {
|
|
|
13
9
|
execute: (text: string) => any;
|
|
14
10
|
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
15
11
|
onExecute?: (text: string) => any;
|
|
16
|
-
}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {},
|
|
12
|
+
}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
17
13
|
export default _default;
|
|
@@ -1,20 +1,31 @@
|
|
|
1
|
-
import { ChatMessage as ChatMessageType, ChatSettings as ChatSettingsType, ToolPackage, ChatCommand, FileAttachment } from '../types';
|
|
1
|
+
import { ChatMessage as ChatMessageType, ChatSettings as ChatSettingsType, SessionMeta, ToolPackage, ChatCommand, FileAttachment } from '../types';
|
|
2
2
|
import { EventBus } from '../core/event-bus';
|
|
3
3
|
export interface AgentChatAPI {
|
|
4
4
|
messages: import('vue').Ref<ChatMessageType[]>;
|
|
5
5
|
settings: import('vue').Ref<ChatSettingsType>;
|
|
6
6
|
loading: import('vue').Ref<boolean>;
|
|
7
7
|
errorMsg: import('vue').Ref<string>;
|
|
8
|
+
/** 会话记录同步(proxy 上传 / 本地存储)失败时的提示 */
|
|
9
|
+
syncError?: import('vue').Ref<string>;
|
|
8
10
|
hasApiKey: import('vue').ComputedRef<boolean>;
|
|
9
11
|
toolPackages: ToolPackage[];
|
|
10
12
|
fileStore: Map<string, FileAttachment>;
|
|
11
13
|
visible: import('vue').Ref<boolean>;
|
|
12
14
|
eventBus: EventBus;
|
|
13
15
|
deviceId: string;
|
|
16
|
+
/** 多会话(宿主自建实例可缺省) */
|
|
17
|
+
sessions?: import('vue').Ref<SessionMeta[]>;
|
|
18
|
+
currentSessionId?: import('vue').Ref<string>;
|
|
19
|
+
sessionsLoading?: import('vue').Ref<boolean>;
|
|
20
|
+
newSession?: () => Promise<void>;
|
|
21
|
+
switchSession?: (id: string) => Promise<void>;
|
|
22
|
+
deleteSession?: (id: string) => Promise<void>;
|
|
14
23
|
sendMessage: (text: string, files?: FileAttachment[]) => Promise<void>;
|
|
15
24
|
stopGeneration: () => void;
|
|
16
25
|
clearMessages: () => void;
|
|
17
26
|
saveSettings: (s: ChatSettingsType) => void;
|
|
27
|
+
/** 主动释放:停止业务事件引擎、待定监听与持久化定时器 */
|
|
28
|
+
dispose?: () => void;
|
|
18
29
|
suggestedCommands: ChatCommand[];
|
|
19
30
|
}
|
|
20
31
|
type __VLS_Props = {
|
|
@@ -28,5 +39,35 @@ declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {
|
|
|
28
39
|
fabRef: HTMLDivElement;
|
|
29
40
|
panelRef: HTMLDivElement;
|
|
30
41
|
scrollRef: HTMLDivElement;
|
|
42
|
+
selectionSendRef: import('vue').CreateComponentPublicInstanceWithMixins<Readonly<{
|
|
43
|
+
container: HTMLElement | null;
|
|
44
|
+
disabled?: boolean;
|
|
45
|
+
}> & Readonly<{
|
|
46
|
+
onSend?: (text: string) => any;
|
|
47
|
+
}>, {
|
|
48
|
+
hide: () => void;
|
|
49
|
+
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
|
|
50
|
+
send: (text: string) => any;
|
|
51
|
+
}, import('vue').PublicProps, {
|
|
52
|
+
disabled: boolean;
|
|
53
|
+
}, false, {}, {}, import('vue').GlobalComponents, import('vue').GlobalDirectives, string, {
|
|
54
|
+
btnRef: HTMLButtonElement;
|
|
55
|
+
}, any, import('vue').ComponentProvideOptions, {
|
|
56
|
+
P: {};
|
|
57
|
+
B: {};
|
|
58
|
+
D: {};
|
|
59
|
+
C: {};
|
|
60
|
+
M: {};
|
|
61
|
+
Defaults: {};
|
|
62
|
+
}, Readonly<{
|
|
63
|
+
container: HTMLElement | null;
|
|
64
|
+
disabled?: boolean;
|
|
65
|
+
}> & Readonly<{
|
|
66
|
+
onSend?: (text: string) => any;
|
|
67
|
+
}>, {
|
|
68
|
+
hide: () => void;
|
|
69
|
+
}, {}, {}, {}, {
|
|
70
|
+
disabled: boolean;
|
|
71
|
+
}>;
|
|
31
72
|
}, HTMLDivElement>;
|
|
32
73
|
export default _default;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 选中文字后浮出「发送」按钮:
|
|
3
|
+
* - 只在 container(聊天面板消息区)内的选区才显示;
|
|
4
|
+
* - 点击发送把选中文本(trim)通过 send 事件交给宿主;
|
|
5
|
+
* - 滚动/点击别处/选区清空/面板关闭时自动隐藏。
|
|
6
|
+
*/
|
|
7
|
+
type __VLS_Props = {
|
|
8
|
+
/** 允许触发选区的容器(通常是 .chat-panel__body) */
|
|
9
|
+
container: HTMLElement | null;
|
|
10
|
+
/** 生成中禁用发送 */
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
};
|
|
13
|
+
declare function hide(): void;
|
|
14
|
+
declare const _default: import('vue').DefineComponent<__VLS_Props, {
|
|
15
|
+
hide: typeof hide;
|
|
16
|
+
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
|
|
17
|
+
send: (text: string) => any;
|
|
18
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
19
|
+
onSend?: (text: string) => any;
|
|
20
|
+
}>, {
|
|
21
|
+
disabled: boolean;
|
|
22
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
|
|
23
|
+
btnRef: HTMLButtonElement;
|
|
24
|
+
}, any>;
|
|
25
|
+
export default _default;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { SessionMeta } from '../types';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
modelValue: boolean;
|
|
4
|
+
sessions: SessionMeta[];
|
|
5
|
+
currentId?: string;
|
|
6
|
+
loading?: boolean;
|
|
7
|
+
};
|
|
8
|
+
declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
|
|
9
|
+
select: (id: string) => any;
|
|
10
|
+
"update:modelValue": (value: boolean) => any;
|
|
11
|
+
create: () => any;
|
|
12
|
+
remove: (id: string) => any;
|
|
13
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
14
|
+
onSelect?: (id: string) => any;
|
|
15
|
+
"onUpdate:modelValue"?: (value: boolean) => any;
|
|
16
|
+
onCreate?: () => any;
|
|
17
|
+
onRemove?: (id: string) => any;
|
|
18
|
+
}>, {
|
|
19
|
+
loading: boolean;
|
|
20
|
+
currentId: string;
|
|
21
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
22
|
+
export default _default;
|