aicodeswitch 5.1.1 → 5.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server/coding-plan-headers.js +121 -0
- package/dist/server/config-managed-fields.js +1 -0
- package/dist/server/conversions/body-sanitizer.js +138 -0
- package/dist/server/conversions/index.js +46 -21
- package/dist/server/conversions/server-tool/mapper.js +49 -0
- package/dist/server/conversions/server-tool/providers.js +40 -0
- package/dist/server/conversions/thinking/mapper.js +21 -0
- package/dist/server/conversions/utils/tool-result.js +35 -0
- package/dist/server/fs-database.js +58 -0
- package/dist/server/main.js +308 -8
- package/dist/server/proxy-server.js +91 -14
- package/dist/server/rules-status-service.js +16 -0
- package/dist/server/session-launcher.js +282 -0
- package/dist/server/session-migration.js +419 -0
- package/dist/server/transformers/chunk-collector.js +28 -1
- package/dist/ui/assets/claude-XtpLmGtF.webp +0 -0
- package/dist/ui/assets/index-CMoQtBmK.css +1 -0
- package/dist/ui/assets/index-CXdNTFiX.js +532 -0
- package/dist/ui/assets/openai-CPEiZpaN.webp +0 -0
- package/dist/ui/index.html +2 -2
- package/package.json +1 -1
- package/dist/ui/assets/index-BHR12ImE.css +0 -1
- package/dist/ui/assets/index-CumAhpXg.js +0 -517
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.extractSessionContent = extractSessionContent;
|
|
13
|
+
exports.previewMigration = previewMigration;
|
|
14
|
+
exports.migrateSession = migrateSession;
|
|
15
|
+
function parseSSEChunks(sourceText) {
|
|
16
|
+
const chunks = sourceText.split('\n').map(item => item.trim()).join('\n')
|
|
17
|
+
.split('\n\n').filter(s => s.trim());
|
|
18
|
+
const events = [];
|
|
19
|
+
for (const chunk of chunks) {
|
|
20
|
+
let event = '';
|
|
21
|
+
let dataLines = [];
|
|
22
|
+
let dataInsert = 0;
|
|
23
|
+
const lines = chunk.split('\n');
|
|
24
|
+
lines.forEach((line) => {
|
|
25
|
+
if (/^[a-z]+:/.test(line)) {
|
|
26
|
+
const at = line.indexOf(':');
|
|
27
|
+
const type = line.slice(0, at).trim();
|
|
28
|
+
const content = line.slice(at + 1).trim();
|
|
29
|
+
if (type === 'event') {
|
|
30
|
+
event = content;
|
|
31
|
+
}
|
|
32
|
+
else if (type === 'data') {
|
|
33
|
+
dataLines.push(content);
|
|
34
|
+
dataInsert = 1;
|
|
35
|
+
}
|
|
36
|
+
else if (dataLines.length) {
|
|
37
|
+
dataInsert = -1;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else if (dataInsert === 1) {
|
|
41
|
+
dataLines.push(line);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
if (dataLines.length) {
|
|
45
|
+
const raw = dataLines.join('\n');
|
|
46
|
+
let parsed = raw;
|
|
47
|
+
try {
|
|
48
|
+
parsed = JSON.parse(raw);
|
|
49
|
+
}
|
|
50
|
+
catch ( /* keep raw string */_a) { /* keep raw string */ }
|
|
51
|
+
events.push({ event, data: parsed, raw });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return events;
|
|
55
|
+
}
|
|
56
|
+
function assembleStreamText(events) {
|
|
57
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
58
|
+
let text = '', thinking = '';
|
|
59
|
+
let inTextBlock = false, inThinkingBlock = false;
|
|
60
|
+
let reasoningAccumulated = false;
|
|
61
|
+
for (const ev of events) {
|
|
62
|
+
const data = ev.data;
|
|
63
|
+
if (!data)
|
|
64
|
+
continue;
|
|
65
|
+
// Claude format
|
|
66
|
+
if (typeof data === 'object' && data.type) {
|
|
67
|
+
if (data.type === 'content_block_start') {
|
|
68
|
+
if (((_a = data.content_block) === null || _a === void 0 ? void 0 : _a.type) === 'text')
|
|
69
|
+
inTextBlock = true;
|
|
70
|
+
else if (((_b = data.content_block) === null || _b === void 0 ? void 0 : _b.type) === 'thinking')
|
|
71
|
+
inThinkingBlock = true;
|
|
72
|
+
}
|
|
73
|
+
if (data.type === 'content_block_delta') {
|
|
74
|
+
if (((_c = data.delta) === null || _c === void 0 ? void 0 : _c.type) === 'text_delta' && inTextBlock)
|
|
75
|
+
text += data.delta.text || '';
|
|
76
|
+
if (((_d = data.delta) === null || _d === void 0 ? void 0 : _d.type) === 'thinking_delta' && inThinkingBlock)
|
|
77
|
+
thinking += data.delta.thinking || '';
|
|
78
|
+
}
|
|
79
|
+
if (data.type === 'content_block_stop') {
|
|
80
|
+
inTextBlock = false;
|
|
81
|
+
inThinkingBlock = false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// Responses API format
|
|
85
|
+
if (typeof data === 'object' && data.type) {
|
|
86
|
+
if (data.type === 'response.reasoning_text.delta') {
|
|
87
|
+
thinking += data.delta || '';
|
|
88
|
+
reasoningAccumulated = true;
|
|
89
|
+
}
|
|
90
|
+
if (data.type === 'response.content_part.done') {
|
|
91
|
+
if (((_e = data.part) === null || _e === void 0 ? void 0 : _e.type) === 'output_text' && ((_f = data.part) === null || _f === void 0 ? void 0 : _f.text)) {
|
|
92
|
+
text += data.part.text;
|
|
93
|
+
}
|
|
94
|
+
if (((_g = data.part) === null || _g === void 0 ? void 0 : _g.type) === 'reasoning_text' && ((_h = data.part) === null || _h === void 0 ? void 0 : _h.text) && !reasoningAccumulated) {
|
|
95
|
+
thinking += data.part.text;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// OpenAI Chat format
|
|
100
|
+
if (typeof data === 'object' && ((_k = (_j = data.choices) === null || _j === void 0 ? void 0 : _j[0]) === null || _k === void 0 ? void 0 : _k.delta)) {
|
|
101
|
+
const delta = data.choices[0].delta;
|
|
102
|
+
if (delta.content)
|
|
103
|
+
text += delta.content;
|
|
104
|
+
if ((_l = delta.thinking) === null || _l === void 0 ? void 0 : _l.content)
|
|
105
|
+
thinking += delta.thinking.content;
|
|
106
|
+
}
|
|
107
|
+
// DeepSeek direct format
|
|
108
|
+
if (typeof data === 'object' && (data.reasoning_content || data.thinking)) {
|
|
109
|
+
thinking += data.reasoning_content || data.thinking;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return { text, thinking };
|
|
113
|
+
}
|
|
114
|
+
// ─── 工具调用摘要化 ───
|
|
115
|
+
const TOOL_SUMMARIES = {
|
|
116
|
+
Bash: (i) => `🔧 执行命令: \`${i.command || i.cmd || ''}\``,
|
|
117
|
+
Read: (i) => `📖 读取文件: ${i.file_path || ''}`,
|
|
118
|
+
Write: (i) => `📝 写入文件: ${i.file_path || ''}`,
|
|
119
|
+
Edit: (i) => `✏️ 编辑文件: ${i.file_path || i.target_file || ''}`,
|
|
120
|
+
Glob: (i) => `🔍 搜索文件: ${i.pattern || ''}`,
|
|
121
|
+
Grep: (i) => `🔍 搜索内容: ${i.pattern || ''}`,
|
|
122
|
+
TodoWrite: () => `📋 更新任务列表`,
|
|
123
|
+
Agent: () => `🤖 启动子代理`,
|
|
124
|
+
TaskOutput: () => `📤 获取任务输出`,
|
|
125
|
+
SendMessage: () => `💬 发送消息`,
|
|
126
|
+
shell: (i) => `🔧 执行命令: \`${i.command || ''}\``,
|
|
127
|
+
apply_diff: (_i) => `✏️ 应用代码变更`,
|
|
128
|
+
create_file: (_i) => `📝 创建文件`,
|
|
129
|
+
};
|
|
130
|
+
function summarizeToolCall(toolName, input) {
|
|
131
|
+
const summarizer = TOOL_SUMMARIES[toolName];
|
|
132
|
+
if (summarizer) {
|
|
133
|
+
try {
|
|
134
|
+
return summarizer(input);
|
|
135
|
+
}
|
|
136
|
+
catch (_a) {
|
|
137
|
+
return `🔧 调用工具: ${toolName}`;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return `🔧 调用工具: ${toolName}`;
|
|
141
|
+
}
|
|
142
|
+
function extractUserTextFromClaudeMessages(messages) {
|
|
143
|
+
const userMsgs = messages.filter(m => m.role === 'user');
|
|
144
|
+
if (!userMsgs.length)
|
|
145
|
+
return '';
|
|
146
|
+
const lastMsg = userMsgs[userMsgs.length - 1];
|
|
147
|
+
if (typeof lastMsg.content === 'string')
|
|
148
|
+
return lastMsg.content;
|
|
149
|
+
if (Array.isArray(lastMsg.content)) {
|
|
150
|
+
return lastMsg.content
|
|
151
|
+
.filter(b => b.type === 'text' && b.text)
|
|
152
|
+
.map(b => b.text)
|
|
153
|
+
.join('\n');
|
|
154
|
+
}
|
|
155
|
+
return '';
|
|
156
|
+
}
|
|
157
|
+
function extractToolCallsFromClaudeMessage(msg) {
|
|
158
|
+
if (!Array.isArray(msg.content))
|
|
159
|
+
return [];
|
|
160
|
+
return msg.content
|
|
161
|
+
.filter(b => b.type === 'tool_use')
|
|
162
|
+
.map(b => summarizeToolCall(b.name || 'unknown', b.input || {}));
|
|
163
|
+
}
|
|
164
|
+
function extractUserTextFromCodexInput(inputArr) {
|
|
165
|
+
const userItems = inputArr.filter(i => i.type === 'message' && i.role === 'user');
|
|
166
|
+
if (!userItems.length)
|
|
167
|
+
return '';
|
|
168
|
+
const lastItem = userItems[userItems.length - 1];
|
|
169
|
+
if (typeof lastItem.content === 'string')
|
|
170
|
+
return lastItem.content;
|
|
171
|
+
if (Array.isArray(lastItem.content)) {
|
|
172
|
+
return lastItem.content
|
|
173
|
+
.filter((b) => b.type === 'input_text' && b.text)
|
|
174
|
+
.map((b) => b.text)
|
|
175
|
+
.join('\n');
|
|
176
|
+
}
|
|
177
|
+
return '';
|
|
178
|
+
}
|
|
179
|
+
function extractToolCallsFromCodexInput(inputArr) {
|
|
180
|
+
return inputArr
|
|
181
|
+
.filter(i => i.type === 'function_call')
|
|
182
|
+
.map(i => summarizeToolCall(i.name || 'unknown', typeof i.arguments === 'string' ? JSON.parse(i.arguments || '{}') : (i.arguments || {})));
|
|
183
|
+
}
|
|
184
|
+
function extractAssistantResponseFromLog(log) {
|
|
185
|
+
var _a, _b, _c;
|
|
186
|
+
let text = '', thinking = '';
|
|
187
|
+
// 1. Try downstreamResponseBody (SSE)
|
|
188
|
+
const sourceText = log.downstreamResponseBody;
|
|
189
|
+
if (typeof sourceText === 'string' && (sourceText.includes('event:') || sourceText.includes('data:'))) {
|
|
190
|
+
const events = parseSSEChunks(sourceText);
|
|
191
|
+
const assembled = assembleStreamText(events);
|
|
192
|
+
text = assembled.text;
|
|
193
|
+
thinking = assembled.thinking;
|
|
194
|
+
}
|
|
195
|
+
// 2. Try responseBody (JSON)
|
|
196
|
+
if (!text && !thinking && log.responseBody) {
|
|
197
|
+
try {
|
|
198
|
+
const parsed = typeof log.responseBody === 'string' ? JSON.parse(log.responseBody) : log.responseBody;
|
|
199
|
+
if (parsed.content) {
|
|
200
|
+
if (Array.isArray(parsed.content)) {
|
|
201
|
+
const parts = [];
|
|
202
|
+
for (const block of parsed.content) {
|
|
203
|
+
if (block.type === 'text' && block.text)
|
|
204
|
+
parts.push(block.text);
|
|
205
|
+
else if (block.type === 'thinking' && block.thinking)
|
|
206
|
+
thinking += block.thinking;
|
|
207
|
+
}
|
|
208
|
+
text = parts.join('\n\n');
|
|
209
|
+
}
|
|
210
|
+
else if (typeof parsed.content === 'string') {
|
|
211
|
+
text = parsed.content;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
if (!text && ((_c = (_b = (_a = parsed.choices) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.message) === null || _c === void 0 ? void 0 : _c.content)) {
|
|
215
|
+
text = parsed.choices[0].message.content;
|
|
216
|
+
}
|
|
217
|
+
if (!text && parsed.output) {
|
|
218
|
+
const parts = [];
|
|
219
|
+
for (const item of parsed.output) {
|
|
220
|
+
if (item.type === 'message') {
|
|
221
|
+
if (Array.isArray(item.content)) {
|
|
222
|
+
for (const c of item.content) {
|
|
223
|
+
if (c.type === 'output_text' && c.text)
|
|
224
|
+
parts.push(c.text);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
text = parts.join('\n\n');
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
catch ( /* ignore parse errors */_d) { /* ignore parse errors */ }
|
|
233
|
+
}
|
|
234
|
+
// 3. Try streamChunks
|
|
235
|
+
if (!text && Array.isArray(log.streamChunks)) {
|
|
236
|
+
const chunksText = log.streamChunks.join('');
|
|
237
|
+
if (chunksText.includes('event:') || chunksText.includes('data:')) {
|
|
238
|
+
const events = parseSSEChunks(chunksText);
|
|
239
|
+
const assembled = assembleStreamText(events);
|
|
240
|
+
text = assembled.text;
|
|
241
|
+
thinking = assembled.thinking;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return { text: text.trim(), thinking: thinking.trim() };
|
|
245
|
+
}
|
|
246
|
+
function isClaudeCodeBody(body) {
|
|
247
|
+
return (body === null || body === void 0 ? void 0 : body.messages) && Array.isArray(body.messages);
|
|
248
|
+
}
|
|
249
|
+
function isCodexBody(body) {
|
|
250
|
+
return (body === null || body === void 0 ? void 0 : body.input) && Array.isArray(body.input);
|
|
251
|
+
}
|
|
252
|
+
// ─── Token 估算 ───
|
|
253
|
+
function estimateTokens(text) {
|
|
254
|
+
let cjk = 0, other = 0;
|
|
255
|
+
for (const ch of text) {
|
|
256
|
+
const code = ch.charCodeAt(0);
|
|
257
|
+
if ((code >= 0x4E00 && code <= 0x9FFF) ||
|
|
258
|
+
(code >= 0x3400 && code <= 0x4DBF) ||
|
|
259
|
+
(code >= 0x20000 && code <= 0x2A6DF) ||
|
|
260
|
+
(code >= 0xF900 && code <= 0xFAFF)) {
|
|
261
|
+
cjk++;
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
other++;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return Math.ceil(cjk + other * 0.25);
|
|
268
|
+
}
|
|
269
|
+
// ─── 迁移 Prompt 生成 ───
|
|
270
|
+
function formatSessionTitle(title) {
|
|
271
|
+
if (!title)
|
|
272
|
+
return '(无标题)';
|
|
273
|
+
return title.replace(/<\/?session>/g, '').trim() || '(无标题)';
|
|
274
|
+
}
|
|
275
|
+
function generateMigrationPrompt(content, targetTool) {
|
|
276
|
+
const toolLabels = {
|
|
277
|
+
'claude-code': 'Claude Code',
|
|
278
|
+
'codex': 'Codex',
|
|
279
|
+
};
|
|
280
|
+
const sourceLabel = toolLabels[content.sourceTool];
|
|
281
|
+
const targetLabel = toolLabels[targetTool];
|
|
282
|
+
const lines = [];
|
|
283
|
+
lines.push(`# 会话迁移上下文`);
|
|
284
|
+
lines.push('');
|
|
285
|
+
lines.push(`> 以下内容从 ${sourceLabel} 会话「${formatSessionTitle(content.sessionTitle)}」迁移而来`);
|
|
286
|
+
lines.push(`> 目标工具:${targetLabel}`);
|
|
287
|
+
lines.push(`> 迁移时间:${new Date().toISOString()}`);
|
|
288
|
+
lines.push(`> 原始会话共 ${content.totalRounds} 轮对话,此处包含最近 ${content.extractedRounds} 轮`);
|
|
289
|
+
lines.push('');
|
|
290
|
+
lines.push('---');
|
|
291
|
+
lines.push('');
|
|
292
|
+
lines.push('## 对话历史');
|
|
293
|
+
lines.push('');
|
|
294
|
+
for (const round of content.rounds) {
|
|
295
|
+
lines.push(`### 👤 用户`);
|
|
296
|
+
lines.push(round.userMessage || '(无文本内容)');
|
|
297
|
+
lines.push('');
|
|
298
|
+
if (round.toolCallSummaries.length > 0) {
|
|
299
|
+
for (const summary of round.toolCallSummaries) {
|
|
300
|
+
lines.push(`> ${summary}`);
|
|
301
|
+
}
|
|
302
|
+
lines.push('');
|
|
303
|
+
}
|
|
304
|
+
lines.push(`### 🤖 助手`);
|
|
305
|
+
lines.push(round.assistantResponse || '(无文本内容)');
|
|
306
|
+
lines.push('');
|
|
307
|
+
if (round.thinking) {
|
|
308
|
+
lines.push('<details>');
|
|
309
|
+
lines.push('<summary>思考过程</summary>');
|
|
310
|
+
lines.push('');
|
|
311
|
+
lines.push(round.thinking);
|
|
312
|
+
lines.push('');
|
|
313
|
+
lines.push('</details>');
|
|
314
|
+
lines.push('');
|
|
315
|
+
}
|
|
316
|
+
lines.push('---');
|
|
317
|
+
lines.push('');
|
|
318
|
+
}
|
|
319
|
+
lines.push(`> ⚠️ 注意:以上对话历史和工具操作仅为上下文摘要,实际的文件修改和工具执行结果不会在目标工具中生效。`);
|
|
320
|
+
lines.push(`> 请基于以上上下文继续工作。`);
|
|
321
|
+
return lines.join('\n');
|
|
322
|
+
}
|
|
323
|
+
// ─── 主要导出 ───
|
|
324
|
+
function extractSessionContent(dbManager, sessionId, options) {
|
|
325
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
326
|
+
const logs = yield dbManager.getLogsBySessionId(sessionId, 10000);
|
|
327
|
+
const session = dbManager.getSession(sessionId);
|
|
328
|
+
if (!session) {
|
|
329
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
330
|
+
}
|
|
331
|
+
const sortedLogs = logs.sort((a, b) => a.timestamp - b.timestamp);
|
|
332
|
+
const rounds = [];
|
|
333
|
+
for (let i = 0; i < sortedLogs.length; i++) {
|
|
334
|
+
const log = sortedLogs[i];
|
|
335
|
+
const body = log.body
|
|
336
|
+
? (typeof log.body === 'string' ? JSON.parse(log.body) : log.body)
|
|
337
|
+
: null;
|
|
338
|
+
if (!body)
|
|
339
|
+
continue;
|
|
340
|
+
// Extract user message
|
|
341
|
+
let userMessage = '';
|
|
342
|
+
let toolCallSummaries = [];
|
|
343
|
+
if (isClaudeCodeBody(body)) {
|
|
344
|
+
userMessage = extractUserTextFromClaudeMessages(body.messages);
|
|
345
|
+
// Extract tool calls from assistant messages
|
|
346
|
+
if (options.includeToolCalls !== false && body.messages) {
|
|
347
|
+
for (const msg of body.messages) {
|
|
348
|
+
if (msg.role === 'assistant') {
|
|
349
|
+
toolCallSummaries.push(...extractToolCallsFromClaudeMessage(msg));
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
else if (isCodexBody(body)) {
|
|
355
|
+
userMessage = extractUserTextFromCodexInput(body.input);
|
|
356
|
+
if (options.includeToolCalls !== false) {
|
|
357
|
+
toolCallSummaries = extractToolCallsFromCodexInput(body.input);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
if (!userMessage && !toolCallSummaries.length)
|
|
361
|
+
continue;
|
|
362
|
+
// Extract assistant response
|
|
363
|
+
const { text, thinking } = extractAssistantResponseFromLog(log);
|
|
364
|
+
rounds.push({
|
|
365
|
+
index: rounds.length + 1,
|
|
366
|
+
userMessage,
|
|
367
|
+
assistantResponse: text,
|
|
368
|
+
toolCallSummaries,
|
|
369
|
+
thinking: options.includeThinking ? (thinking || undefined) : undefined,
|
|
370
|
+
timestamp: log.timestamp,
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
const maxRounds = options.maxRounds || 0;
|
|
374
|
+
const extractedRounds = maxRounds > 0 ? rounds.slice(-maxRounds) : rounds;
|
|
375
|
+
return {
|
|
376
|
+
sessionId,
|
|
377
|
+
sessionTitle: session.title || '',
|
|
378
|
+
sourceTool: session.targetType,
|
|
379
|
+
rounds: extractedRounds,
|
|
380
|
+
totalRounds: sortedLogs.length,
|
|
381
|
+
extractedRounds: extractedRounds.length,
|
|
382
|
+
};
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
function previewMigration(content, targetTool) {
|
|
386
|
+
const warnings = [];
|
|
387
|
+
const prompt = generateMigrationPrompt(content, targetTool);
|
|
388
|
+
const estimatedTokens = estimateTokens(prompt);
|
|
389
|
+
if (content.totalRounds > content.extractedRounds && content.extractedRounds > 0) {
|
|
390
|
+
warnings.push(`会话较长(${content.totalRounds} 轮),已截断到最近 ${content.extractedRounds} 轮对话`);
|
|
391
|
+
}
|
|
392
|
+
if (estimatedTokens > 100000) {
|
|
393
|
+
warnings.push(`迁移 Prompt 约 ${estimatedTokens.toLocaleString()} tokens,可能超过目标模型的上下文窗口`);
|
|
394
|
+
}
|
|
395
|
+
if (content.totalRounds === 0) {
|
|
396
|
+
warnings.push('该会话没有可提取的对话内容');
|
|
397
|
+
}
|
|
398
|
+
return {
|
|
399
|
+
content,
|
|
400
|
+
generatedPrompt: prompt,
|
|
401
|
+
estimatedTokens,
|
|
402
|
+
warnings,
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
function migrateSession(content, targetTool, editedPrompt) {
|
|
406
|
+
const prompt = editedPrompt || generateMigrationPrompt(content, targetTool);
|
|
407
|
+
const estimatedTokens = estimateTokens(prompt);
|
|
408
|
+
const warnings = [];
|
|
409
|
+
if (estimatedTokens > 100000) {
|
|
410
|
+
warnings.push(`迁移 Prompt 约 ${estimatedTokens.toLocaleString()} tokens,可能超过目标模型的上下文窗口`);
|
|
411
|
+
}
|
|
412
|
+
return {
|
|
413
|
+
success: true,
|
|
414
|
+
prompt,
|
|
415
|
+
format: 'markdown',
|
|
416
|
+
estimatedTokens,
|
|
417
|
+
warnings,
|
|
418
|
+
};
|
|
419
|
+
}
|
|
@@ -23,7 +23,7 @@ function isClientDisconnectError(error) {
|
|
|
23
23
|
* 这个Transform会记录所有经过它的数据块,同时将数据原封不动地传递给下一个stream
|
|
24
24
|
*/
|
|
25
25
|
class ChunkCollectorTransform extends stream_1.Transform {
|
|
26
|
-
constructor() {
|
|
26
|
+
constructor(refreshCallback) {
|
|
27
27
|
super({ writableObjectMode: true, readableObjectMode: true });
|
|
28
28
|
Object.defineProperty(this, "chunks", {
|
|
29
29
|
enumerable: true,
|
|
@@ -43,6 +43,25 @@ class ChunkCollectorTransform extends stream_1.Transform {
|
|
|
43
43
|
writable: true,
|
|
44
44
|
value: new string_decoder_1.StringDecoder('utf8')
|
|
45
45
|
});
|
|
46
|
+
Object.defineProperty(this, "lastRefreshTime", {
|
|
47
|
+
enumerable: true,
|
|
48
|
+
configurable: true,
|
|
49
|
+
writable: true,
|
|
50
|
+
value: 0
|
|
51
|
+
});
|
|
52
|
+
Object.defineProperty(this, "refreshCallback", {
|
|
53
|
+
enumerable: true,
|
|
54
|
+
configurable: true,
|
|
55
|
+
writable: true,
|
|
56
|
+
value: void 0
|
|
57
|
+
});
|
|
58
|
+
Object.defineProperty(this, "REFRESH_INTERVAL", {
|
|
59
|
+
enumerable: true,
|
|
60
|
+
configurable: true,
|
|
61
|
+
writable: true,
|
|
62
|
+
value: 5000
|
|
63
|
+
}); // 每5秒最多刷新一次
|
|
64
|
+
this.refreshCallback = refreshCallback;
|
|
46
65
|
this.on('error', (err) => {
|
|
47
66
|
if (isClientDisconnectError(err)) {
|
|
48
67
|
console.warn('[ChunkCollectorTransform] Stream closed (client disconnected)');
|
|
@@ -69,6 +88,14 @@ class ChunkCollectorTransform extends stream_1.Transform {
|
|
|
69
88
|
}
|
|
70
89
|
// 将chunk传递给下一个stream
|
|
71
90
|
this.push(chunk);
|
|
91
|
+
// 节流刷新规则使用状态(仅在有数据流过时触发)
|
|
92
|
+
if (this.refreshCallback) {
|
|
93
|
+
const now = Date.now();
|
|
94
|
+
if (now - this.lastRefreshTime >= this.REFRESH_INTERVAL) {
|
|
95
|
+
this.lastRefreshTime = now;
|
|
96
|
+
this.refreshCallback();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
72
99
|
callback();
|
|
73
100
|
}
|
|
74
101
|
catch (error) {
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.nav-item-with-tooltip{position:relative;display:block}.nav-tooltip{position:absolute;left:calc(100% + 12px);top:50%;transform:translateY(-50%);background:var(--bg-card);color:var(--text-primary);padding:8px 12px;border-radius:8px;font-size:14px;font-weight:500;white-space:nowrap;z-index:999999;pointer-events:none;box-shadow:0 4px 12px #00000026;border:1px solid var(--border-primary);animation:tooltipFadeIn .2s ease-out}.nav-tooltip:before{content:"";position:absolute;right:100%;top:50%;transform:translateY(-50%);border:6px solid transparent;border-right-color:var(--border-primary)}.nav-tooltip:after{content:"";position:absolute;right:100%;top:50%;transform:translateY(-50%);border:5px solid transparent;border-right-color:var(--bg-card);margin-right:-1px}@keyframes tooltipFadeIn{0%{opacity:0;transform:translateY(-50%) translate(-8px)}to{opacity:1;transform:translateY(-50%) translate(0)}}.app{display:flex;width:100%;height:100%;overflow:hidden}.sidebar{width:260px;background:var(--bg-sidebar);color:var(--text-primary);display:flex;flex-direction:column;padding:0 0 80px;border-radius:12px;box-shadow:0 4px 12px #00000026;margin:8px;position:relative;z-index:999999;border:1px solid rgba(255,255,255,.15);transition:width .1s ease,margin .1s ease}.sidebar.collapsed{width:80px;margin-right:8px;overflow:visible}.sidebar.collapsed .logo h2,.sidebar.collapsed .nav-menu .nav-text,.sidebar.collapsed .github-link,.sidebar.collapsed .version-info{display:none;opacity:0}.sidebar.collapsed .logo{padding:20px 10px}.sidebar.collapsed .nav-menu a{padding:14px;justify-content:center}.sidebar.collapsed .theme-toggle{flex-direction:column;gap:8px;align-items:center}.logo{padding:16px 20px;border-bottom:2px solid rgba(255,255,255,.2);text-align:center;position:relative;overflow:hidden;transition:padding .3s ease;display:flex;flex-direction:row;align-items:center;justify-content:center;gap:12px}.logo h2{font-size:18px;font-weight:800;background:linear-gradient(135deg,#fff,#f8f8ff,#e6e6fa);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;text-shadow:0 2px 4px rgba(0,0,0,.1);position:relative;z-index:1;letter-spacing:1px;text-transform:uppercase;transition:all .3s ease;margin:0}.logo-image{width:36px;height:36px;object-fit:contain;transition:all .3s ease;filter:drop-shadow(0 2px 8px rgba(0,0,0,.2));flex-shrink:0}.sidebar.collapsed .logo{justify-content:center;padding:12px 10px}.sidebar.collapsed .logo-image{width:32px;height:32px}.nav-menu{list-style:none;padding:16px 0;margin:0;overflow:visible}.nav-menu li{margin:8px 12px;overflow:visible}.nav-menu a{display:flex;align-items:center;gap:12px;padding:14px 20px;color:var(--text-sidebar);text-decoration:none;border-radius:12px;transition:all .3s ease-out;font-weight:500;position:relative;overflow:hidden}.nav-menu .nav-icon{font-size:20px;flex-shrink:0;transition:all .3s ease}.nav-menu .nav-text{transition:opacity .3s ease,width .3s ease;white-space:nowrap}.nav-menu a:before{content:"";position:absolute;top:0;left:-100%;width:100%;height:100%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.15),transparent);transition:left .5s ease-out}.nav-menu a:hover:before{left:100%}.nav-menu a:hover{background-color:#ffffff1a}.nav-menu a.active{background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary))}.main-content{flex:1;padding:24px;overflow:auto;background:var(--bg-primary);position:relative;margin:16px 16px 16px 0;border-radius:20px;transition:margin .3s ease}.main-content>.routes-page,.main-content>.vendors-page,.main-content>.logs-page{min-width:1000px}.page-header{margin-bottom:24px;position:relative;z-index:1}.page-header-content{display:flex;justify-content:space-between;align-items:center;gap:20px}.page-header-text h1{font-family:Fredoka,sans-serif;font-size:28px;font-weight:700;color:var(--accent-primary);margin-bottom:8px;text-shadow:0 2px 4px var(--shadow-primary)}.page-header-text p{color:var(--text-muted);font-size:16px;font-weight:400}.card{background:var(--bg-card);border-radius:20px;padding:24px;box-shadow:0 2px 8px #00000014;margin-bottom:24px;border:1px solid var(--border-primary);position:relative;overflow:hidden;transition:all .3s ease-out}.card:before{content:"";position:absolute;top:0;left:0;right:0;height:4px;background:linear-gradient(90deg,var(--accent-primary),var(--accent-secondary));border-radius:20px 20px 0 0}.card:hover{box-shadow:0 4px 12px #0000001f}.btn{padding:10px 20px;border:none;border-radius:12px;cursor:pointer;font-size:14px;font-weight:600;transition:all .3s ease-out;position:relative;overflow:hidden;white-space:nowrap}.btn:before{content:"";position:absolute;top:50%;left:50%;width:0;height:0;background:#ffffff4d;border-radius:50%;transform:translate(-50%,-50%);transition:width .6s,height .6s}.btn:hover:before{width:300px;height:300px}.btn:active{transform:translateY(0)}.btn:disabled{opacity:.4;cursor:not-allowed}.btn-primary{background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary));color:#fff;position:relative;overflow:hidden}.btn-primary:before{content:"";position:absolute;top:0;left:-100%;width:100%;height:100%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.3),transparent);transition:left .5s ease}.btn-primary:hover:before{left:100%}.btn-danger{background:var(--accent-danger);color:#fff}.btn-danger:hover{background:#ea580c}.btn-success{background:var(--accent-success);color:#fff}.btn-success:hover{background:#059669}.btn-secondary{background:var(--accent-secondary);color:#fff}.btn-secondary:hover{background:var(--accent-primary)}.btn-sm{padding:4px 8px}table{width:100%;border-collapse:collapse;margin-top:16px;border-radius:12px;overflow:hidden}table th,table td{padding:16px;text-align:left;border-bottom:1px solid var(--border-secondary);color:var(--text-primary)}table th{background:var(--bg-table-header);font-weight:700;color:var(--text-secondary);font-family:Fredoka,sans-serif;font-size:14px;white-space:nowrap}@media (max-width: 1200px){.rules-table .col-priority{display:none}.rules-table .action-buttons{flex-wrap:wrap;justify-content:flex-end}}.col-priority-box{display:flex;align-items:center;gap:4px}.priority-arrow-btn{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;background-color:var(--bg-card);border:1px solid var(--border-primary);border-radius:4px;color:var(--text-primary);font-size:12px;line-height:1;cursor:pointer;transition:all .2s ease;vertical-align:middle}.priority-arrow-btn:hover{background-color:var(--primary-color);border-color:var(--primary-color);color:#fff}.priority-arrow-btn:active{transform:scale(.95)}.form-group{margin-bottom:20px}.form-group label{display:block;margin-bottom:8px;color:var(--text-primary);font-size:14px;font-weight:600;font-family:Nunito,sans-serif}.form-group input,.form-group select,.form-group textarea{width:100%;padding:12px 16px;border:2px solid var(--border-primary);border-radius:12px;font-size:14px;font-family:Nunito,sans-serif;background:var(--bg-secondary);color:var(--text-primary);transition:all .3s ease-out}.form-group input:focus,.form-group select:focus,.form-group textarea:focus{outline:none;border-color:var(--accent-primary);box-shadow:0 0 0 3px var(--shadow-secondary);background:var(--bg-secondary)}.form-group input:disabled,.form-group select:disabled,.form-group textarea:disabled{background:var(--bg-input-disabled);cursor:not-allowed;color:var(--text-input-disabled);opacity:.7}.form-group label small{font-size:.8em;color:var(--text-light)}@keyframes modalFadeIn{0%{opacity:0}to{opacity:1}}.modal{background:var(--bg-secondary);border-radius:24px;padding:32px 28px 32px 32px;min-width:500px;width:800px;max-width:90%;max-height:90vh;box-shadow:0 8px 24px #0003;border:1px solid var(--border-secondary);animation:modalSlideIn .4s ease-out;overflow:hidden;display:flex;flex-direction:column}.modal-container{overflow-y:auto;overflow-x:hidden;margin-right:-8px;padding-right:8px;scrollbar-gutter:stable;scrollbar-width:thin;scrollbar-color:var(--border-secondary) transparent}.modal-container::-webkit-scrollbar{width:8px}.modal-container::-webkit-scrollbar-track{background:transparent;border-radius:4px;margin:4px}.modal-container::-webkit-scrollbar-thumb{background:var(--border-secondary);border-radius:4px;border:2px solid transparent}.modal-container::-webkit-scrollbar-thumb:hover{background:var(--text-muted)}.modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:#0009;display:flex;justify-content:center;align-items:center;z-index:1000000;animation:modalFadeIn .3s ease-out}.modal-close-btn{position:absolute;top:20px;right:20px;width:48px;height:48px;border:none;background:var(--accent-light);color:var(--text-primary);font-size:32px;line-height:1;cursor:pointer;border-radius:50%;transition:all .2s ease;display:flex;align-items:center;justify-content:center;padding:0;border:1px solid rgba(255,255,255,.3);z-index:1001}.modal-close-btn:hover{background:var(--accent-danger);color:#fff;transform:scale(1.05)}.modal-close-btn:active{transform:scale(.95)}@keyframes modalSlideIn{0%{opacity:0;transform:translateY(-20px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}.modal-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px;position:relative}.modal-header h2{font-size:20px;color:var(--text-primary);flex:1}.modal-footer{display:flex;justify-content:flex-end;gap:10px;margin-top:20px}.modal--sticky-layout .modal-header{flex-shrink:0;margin-bottom:16px;padding-bottom:12px;border-bottom:1px solid var(--border-color)}.modal--sticky-layout .modal-body-scrollable{flex:1;overflow-y:auto;overflow-x:hidden;min-height:0;scrollbar-gutter:stable;scrollbar-width:thin;scrollbar-color:var(--border-secondary) transparent;padding-right:8px;margin-right:-8px}.modal--sticky-layout .modal-body-scrollable::-webkit-scrollbar{width:8px}.modal--sticky-layout .modal-body-scrollable::-webkit-scrollbar-track{background:transparent}.modal--sticky-layout .modal-body-scrollable::-webkit-scrollbar-thumb{background-color:var(--border-secondary);border-radius:4px}.modal--sticky-layout .modal-footer{flex-shrink:0;margin-top:0;padding-top:16px;border-top:1px solid var(--border-color)}.session-refresh-btn{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;border:1px solid var(--border-color);border-radius:8px;background:var(--bg-primary-solid);color:var(--text-secondary);cursor:pointer;transition:all .2s ease}.session-refresh-btn:hover:not(:disabled){background:var(--bg-hover);color:var(--text-primary)}.session-refresh-btn:disabled{opacity:.5;cursor:not-allowed}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.spin-icon{animation:spin 1s linear infinite}.session-view-toggle{display:inline-flex;gap:0;border:1px solid var(--border-color);border-radius:8px;overflow:hidden;margin-left:12px}.session-view-toggle button{padding:4px 14px;font-size:13px;border:none;background:var(--bg-primary);color:var(--text-secondary);cursor:pointer;transition:all .2s ease;white-space:nowrap}.session-view-toggle button:not(:last-child){border-right:1px solid var(--border-color)}.session-view-toggle button.active{background:var(--accent-light);color:var(--text-primary);font-weight:600}.session-view-toggle button:hover:not(.active){background:var(--bg-hover)}.chat-view-container{display:flex;flex-direction:column;gap:16px;padding:4px 0;position:relative}.chat-scroll-bottom{position:sticky;bottom:0;left:50%;display:flex;justify-content:center;padding:8px 0;pointer-events:none}.chat-scroll-bottom-btn{pointer-events:auto;width:36px;height:36px;border-radius:50%;border:1px solid var(--border-color);background:var(--bg-secondary);color:var(--text-secondary);cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s ease;box-shadow:0 2px 8px #00000026}.chat-scroll-bottom-btn:hover{background:var(--bg-hover);color:var(--text-primary)}.chat-message{display:flex;flex-direction:column}.chat-message--user{align-items:flex-end}.chat-message--assistant{align-items:flex-start}.chat-bubble{max-width:85%;padding:10px 14px;border-radius:12px;font-size:14px;line-height:1.6;word-break:break-word;white-space:pre-wrap}.chat-tool-header{font-size:12px;color:var(--text-tertiary);font-style:italic;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;opacity:.55}.chat-collapse-top-bar{display:flex;align-items:center;justify-content:flex-end;gap:8px;position:sticky;top:0;z-index:1;margin-bottom:8px}.chat-message--user .chat-bubble{background:var(--accent-light);color:var(--text-primary);border-bottom-right-radius:4px}.chat-message--assistant .chat-bubble{background:var(--bg-primary-solid);color:var(--text-primary);border:1px solid var(--border-color);border-bottom-left-radius:4px}[data-theme=dark] .chat-message--user .chat-bubble{background:#003d22}[data-theme=dark] .chat-message--assistant .chat-bubble{background:#132d1c}[data-theme=dark] .chat-message--tool_result .chat-bubble,[data-theme=dark] .chat-message--tool_use .chat-bubble{background:#fff3}.chat-message--tool_result .chat-bubble,.chat-message--tool_use .chat-bubble{background:var(--bg-card);border:1px solid var(--border-color);opacity:.85}.chat-message--tool_result .chat-bubble{border-bottom-right-radius:4px}.chat-message--tool_use .chat-bubble{border-bottom-left-radius:4px}.chat-meta{font-size:12px;color:var(--text-tertiary);margin-top:4px;padding:0 4px}.chat-thinking{margin-bottom:8px;border:1px solid var(--border-thinking-box);border-radius:8px;padding:8px 10px;background-color:var(--bg-thinking-box)}.chat-thinking summary{cursor:pointer;font-weight:600;font-size:13px;color:var(--text-thinking-title);-webkit-user-select:none;user-select:none}.chat-thinking pre{margin-top:8px;white-space:pre-wrap;word-break:break-word;font-family:monospace;font-size:13px;color:var(--text-thinking-content);background-color:var(--bg-thinking-content);padding:8px;border-radius:4px;border:1px solid var(--border-thinking-content)}.chat-content-text{font-size:14px;line-height:1.6;white-space:pre-wrap;word-break:break-word}.chat-collapsible-wrapper{position:relative}.chat-collapse-btn-sticky{display:flex;justify-content:flex-end;flex-shrink:0;position:absolute;top:0;right:0}.chat-collapse-fade{position:relative;margin-top:-60px;height:60px;display:flex;align-items:center;justify-content:center;cursor:pointer}.chat-message--user .chat-collapse-fade{background:linear-gradient(to bottom,transparent,var(--accent-light))}.chat-message--assistant .chat-collapse-fade{background:linear-gradient(to bottom,transparent,var(--bg-primary-solid))}.chat-message--tool_result .chat-collapse-fade,.chat-message--tool_use .chat-collapse-fade{background:linear-gradient(to bottom,transparent,var(--bg-card))}[data-theme=dark] .chat-message--tool_result .chat-collapse-fade,[data-theme=dark] .chat-message--tool_use .chat-collapse-fade{background:linear-gradient(to bottom,transparent,rgba(255,255,255,.2))}.chat-collapse-fade-btn{font-size:12px;color:var(--text-secondary);background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:4px;padding:1px 10px;cursor:pointer;transition:all .2s ease;margin-top:40px}.chat-collapse-fade-btn:hover{background:var(--bg-secondary)}.chat-collapse-btn{display:inline-block;padding:2px 10px;font-size:12px;color:var(--text-secondary);background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:4px;cursor:pointer;transition:all .2s ease}.chat-collapse-btn:hover{background:var(--bg-secondary)}.chat-separator{text-align:center;color:var(--text-tertiary);font-size:12px;padding:4px 0;position:relative}.chat-separator:before,.chat-separator:after{content:"";position:absolute;top:50%;width:calc(50% - 40px);height:1px;background:var(--border-color)}.chat-separator:before{left:0}.chat-separator:after{right:0}.action-buttons{display:flex;gap:8px}.badge{display:inline-block;padding:6px 12px;border-radius:20px;font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;white-space:nowrap}.badge-success{background:var(--accent-success);color:#fff}.badge-warning{background:var(--accent-warning);color:#fff}.badge-danger{background:var(--accent-danger);color:#fff}.badge-claude-code{background:#ce653c;color:#fff}.badge-codex{background:#1f2937;color:#fff}.empty-state{text-align:center;padding:60px 20px;color:var(--text-muted);font-family:Nunito,sans-serif}.empty-state p{margin-bottom:20px;font-size:16px;font-weight:500}.pagination{display:flex;justify-content:space-between;align-items:center;margin-top:20px;padding:16px;background:var(--bg-secondary);border-radius:12px;border:1px solid var(--border-primary);gap:20px;flex-wrap:wrap}.pagination-info{color:var(--text-muted);font-size:14px;font-weight:500}.pagination-controls{display:flex;align-items:center;gap:10px}.pagination-btn{padding:6px 14px;border:1px solid var(--border-primary);background:var(--bg-card);color:var(--text-primary);border-radius:8px;cursor:pointer;font-size:14px;font-weight:500;transition:all .2s ease}.pagination-btn:hover:not(:disabled){background:var(--accent-primary);color:#fff;border-color:var(--accent-primary)}.pagination-btn:disabled{opacity:.4;cursor:not-allowed;background:var(--bg-secondary)}.pagination-size{display:flex;align-items:center;gap:8px;color:var(--text-primary);font-size:14px;font-weight:500}.pagination-select{padding:6px 10px;border:1px solid var(--border-primary);background:var(--bg-card);color:var(--text-primary);border-radius:8px;cursor:pointer;font-size:14px;outline:none;transition:all .2s ease}.pagination-select:hover{border-color:var(--accent-primary)}.pagination-select:focus{border-color:var(--accent-primary);box-shadow:0 0 0 2px #3498db1a}.toolbar{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px}.theme-toggle{position:absolute;bottom:20px;left:20px;right:20px;display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.sidebar-toggle-btn{background:none;border:none;color:var(--text-sidebar);cursor:pointer;padding:8px;border-radius:8px;transition:all .3s ease-out;display:flex;align-items:center;justify-content:center;font-size:18px;font-weight:700}.sidebar-toggle-btn:hover{background:#ffffff26;opacity:1}.github-link{background:none;border:none;color:var(--text-sidebar);cursor:pointer;padding:8px;border-radius:8px;transition:all .3s ease-out;display:flex;align-items:center;justify-content:center;opacity:.8;margin-left:auto}.github-link:hover{background:#ffffff26;opacity:1}.theme-toggle button{background:none;border:none;color:var(--text-sidebar);cursor:pointer;padding:8px;border-radius:8px;transition:all .3s ease-out;display:flex;align-items:center;justify-content:center}.version-info{font-size:12px;color:var(--text-sidebar);opacity:.7;font-family:Monaco,Menlo,monospace;font-weight:500;-webkit-user-select:none;user-select:none;transition:opacity .3s ease}.theme-toggle button:hover{background:#ffffff26}.theme-toggle button.active{background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary));color:#fff;animation:pulse 2s ease-in-out infinite}@keyframes pulse{0%,to{transform:scale(1)}50%{transform:scale(1.05)}}.version-info-wrapper{position:relative;display:flex;align-items:center}.version-info{font-size:12px;color:var(--text-sidebar);opacity:.7;font-family:Monaco,Menlo,monospace;font-weight:500;-webkit-user-select:none;user-select:none;transition:opacity .3s ease;position:relative}.version-info:hover{opacity:1}.version-badge{position:absolute;top:-2px;right:-6px;width:8px;height:8px;background:linear-gradient(135deg,#ef4444,#dc2626);border-radius:50%;border:2px solid var(--bg-sidebar);animation:pulse-badge 2s ease-in-out infinite;box-shadow:0 0 8px #ef444499}@keyframes pulse-badge{0%,to{transform:scale(1);opacity:1}50%{transform:scale(1.2);opacity:.8}}.version-update-popup{position:absolute;bottom:calc(100% + 12px);left:50%;transform:translate(-50%);background:#10b98126;border:1px solid rgba(16,185,129,.4);border-radius:12px;padding:12px;min-width:220px;box-shadow:0 4px 12px #0003;opacity:0;visibility:hidden;transition:all .3s ease-out;pointer-events:none;z-index:10000;text-decoration:none;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.version-info-wrapper:hover .version-update-popup,.version-update-popup:hover{opacity:1;visibility:visible;pointer-events:auto;transform:translate(-50%) translateY(12px)}.version-update-popup:after{content:"";position:absolute;top:100%;left:50%;transform:translate(-50%);border:6px solid transparent;border-top-color:#10b98166}.update-popup-content{display:flex;align-items:flex-start;gap:10px}.update-icon{font-size:18px;animation:bounce 1s ease-in-out infinite;flex-shrink:0}@keyframes bounce{0%,to{transform:translateY(0)}50%{transform:translateY(-3px)}}.update-text{flex:1}.update-title{font-size:13px;font-weight:600;color:var(--text-sidebar);margin-bottom:4px}.update-versions{font-size:11px;color:#fffc;font-family:Monaco,Menlo,monospace;margin-bottom:6px}.update-message{font-size:10px;color:var(--text-sidebar);line-height:1.4}.update-message code{background:#ffffff26;padding:2px 4px;border-radius:4px;font-family:Monaco,Menlo,monospace;margin-top:2px;display:inline-block;color:#ffffffe6}@media (prefers-reduced-motion: reduce){.nav-menu a,.card,.btn,.form-group input,.form-group select,.form-group textarea,.modal-overlay,.modal,table tr{transition:none;animation:none}.nav-menu a:hover,.card:hover,.btn:hover,table tr:hover{transform:none}.btn:before{display:none}}.markdown-content{line-height:1.7;color:var(--text-primary);max-width:100%;overflow-x:auto}.markdown-content h1{font-size:2em;font-weight:700;margin-top:0;margin-bottom:.8em;color:var(--text-primary);border-bottom:2px solid var(--border-color);padding-bottom:.3em}.markdown-content h2{font-size:1.6em;font-weight:600;margin-top:1.5em;margin-bottom:.6em;color:var(--text-primary);border-bottom:1px solid var(--border-color);padding-bottom:.25em}.markdown-content h3{font-size:1.3em;font-weight:600;margin-top:1.2em;margin-bottom:.5em;color:var(--text-primary)}.markdown-content h4{font-size:1.1em;font-weight:600;margin-top:1em;margin-bottom:.4em;color:var(--text-primary)}.markdown-content p{margin-bottom:1em;line-height:1.8}.markdown-content ul,.markdown-content ol{margin-bottom:1em;padding-left:2em}.markdown-content li{margin-bottom:.5em;line-height:1.7}.markdown-content code{background:var(--bg-secondary);padding:.2em .4em;border-radius:4px;font-size:.9em;font-family:Monaco,Menlo,Ubuntu Mono,Consolas,monospace;color:var(--accent-secondary);border:1px solid var(--border-color)}.markdown-content pre{background:var(--bg-secondary);padding:1em;border-radius:8px;overflow-x:auto;margin-bottom:1em;border:1px solid var(--border-color)}.markdown-content pre code{background:none;padding:0;border:none;color:var(--text-primary);font-size:.95em}.markdown-content blockquote{border-left:4px solid var(--accent-primary);padding-left:1em;margin-left:0;margin-bottom:1em;color:var(--text-secondary);font-style:italic}.markdown-content a{color:var(--accent-primary);text-decoration:none;border-bottom:1px solid var(--accent-secondary);transition:all .2s ease}.markdown-content a:hover{color:var(--accent-secondary)}.markdown-content table{width:100%;border-collapse:collapse;margin-bottom:1em}.markdown-content table th,.markdown-content table td{padding:.75em;text-align:left;border:1px solid var(--border-color)}.markdown-content table th{background:var(--bg-secondary);font-weight:600}.markdown-content hr{border:none;border-top:2px solid var(--border-color);margin:2em 0}.markdown-content strong{font-weight:600;color:var(--text-primary)}.markdown-content em{font-style:italic}.markdown-content img{max-width:100%;height:auto;border-radius:8px;margin:1em 0}.config-status-indicator{display:inline-block}.status-badge{display:inline-block;padding:4px 10px;border-radius:12px;font-size:11px;font-weight:600}.status-active{background:linear-gradient(135deg,#4caf50,#45a049);color:#fff}.status-backup{background:linear-gradient(135deg,#ff9800,#f57c00);color:#fff}.status-inactive{background:linear-gradient(135deg,#9e9e9e,#757575);color:#fff}.skills-header-row{display:flex;justify-content:space-between;align-items:flex-start;gap:16px;flex-wrap:wrap}.skills-header-actions{margin-top:8px}.skills-discover-btn{padding:18px 36px;font-size:16px;font-weight:700;border-radius:14px;box-shadow:0 4px 12px #00000026;position:relative}.skills-discover-btn:after{content:"";position:absolute;top:-6px;right:-6px;bottom:-6px;left:-6px;border-radius:18px;border:2px solid rgba(16,185,129,.35);opacity:.6}.skills-section-header{display:flex;flex-direction:column;gap:6px;margin-bottom:20px}.skills-section-header h2{margin:0;font-size:22px;color:var(--text-primary)}.skills-section-header span{color:var(--text-muted);font-size:14px}.skills-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(360px,1fr));gap:16px}.skill-card{display:flex;flex-direction:column;gap:16px;min-height:180px}.skill-title{font-size:18px;font-weight:700;color:var(--text-primary);margin-bottom:8px}.skill-description{color:var(--text-muted);font-size:14px;line-height:1.6;flex:1}.skill-tags{display:flex;flex-wrap:wrap;gap:8px}.skills-discover{display:flex;flex-direction:column;gap:20px}.skills-search-card{display:flex;flex-direction:column;gap:16px}.skills-search-header h3{margin:0 0 6px;font-size:18px;color:var(--text-primary)}.skills-search-header p{margin:0;color:var(--text-muted);font-size:14px}.skills-search-input{width:100%;padding:12px 14px;border-radius:12px;border:1px solid var(--border-primary);background:var(--bg-secondary);color:var(--text-primary);resize:vertical;min-height:120px;font-size:14px;line-height:1.6}.skills-search-actions{display:flex;justify-content:flex-end}.skills-results{display:flex;flex-direction:column;gap:16px}.skills-result-actions{display:flex;justify-content:flex-end;gap:8px}.badge-secondary{background:#0f513226;color:var(--text-primary)}.switch{position:relative;width:44px;height:24px;border-radius:12px;border:none;cursor:pointer;background-color:#4b5563;transition:background-color .2s}.switch.active{background-color:var(--primary-color)}.switch:disabled{cursor:not-allowed;opacity:.6}.switch:focus{outline:none;box-shadow:0 0 0 2px var(--primary-color)}.switch::-moz-focus-inner{border:0}.rules-table .vendor-sevices-col>div{white-space:nowrap}.api-binding-card{padding:20px 24px!important}.api-binding-header{display:flex;align-items:center;gap:10px;margin-bottom:6px}.api-binding-header-icon{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:10px;background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary));color:#fff;font-size:16px;flex-shrink:0}.api-binding-header h3{margin:0!important;font-size:18px!important;font-weight:700;letter-spacing:.2px}.api-binding-desc{margin:0 0 18px!important;font-size:13px!important;color:var(--text-muted)!important;line-height:1.6}.api-binding-baseurl-row{display:flex;align-items:center;margin:20px;border:1px solid var(--border-primary);border-radius:6px;overflow:hidden;background:var(--bg-secondary)}.api-binding-baseurl-prefix{flex-shrink:0;padding:6px 12px;font-size:12px;font-weight:600;color:var(--text-muted);background:var(--border-primary);letter-spacing:.3px}.api-binding-baseurl-value{flex:1;padding:6px 12px;font-family:monospace;font-size:13px;color:var(--text-secondary);-webkit-user-select:all;user-select:all}.api-binding-list{display:flex;flex-direction:column;gap:10px;margin:20px}.api-binding-row{display:flex;align-items:center;gap:12px;padding:10px 14px;border-radius:12px;background:var(--bg-secondary);border:1px solid var(--border-primary);transition:all .25s ease}.api-binding-row:hover{border-color:var(--accent-secondary);box-shadow:0 2px 8px var(--shadow-secondary)}.api-binding-path{flex:0 0 300px;padding:6px 12px;border-radius:8px;font-family:Monaco,Menlo,Consolas,monospace;font-size:13px;font-weight:600;letter-spacing:.3px;background:var(--bg-code);color:var(--accent-secondary);border:1px solid var(--border-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-webkit-user-select:all;user-select:all;transition:all .2s ease}.api-binding-path:hover{border-color:var(--accent-secondary)}.api-binding-path--disabled{background:var(--bg-route-item);color:var(--text-route-muted);opacity:.7}.api-binding-arrow{flex-shrink:0;color:var(--border-primary);font-size:16px;transition:color .2s ease}.api-binding-row:hover .api-binding-arrow{color:var(--accent-secondary)}.api-binding-control{flex:1;min-width:0;position:relative}.api-binding-control select,.api-binding-control input{width:100%;padding:8px 12px;border:1.5px solid var(--border-primary);border-radius:10px;font-size:13px;font-family:Nunito,sans-serif;background:var(--bg-card);color:var(--text-primary);transition:all .25s ease;-moz-appearance:none;appearance:none;-webkit-appearance:none;cursor:pointer}.api-binding-control input{cursor:text}.api-binding-control select{padding-right:32px;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23065F46' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 10px center;background-size:14px}[data-theme=dark] .api-binding-control select{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236EE7B7' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E")}.api-binding-control select:focus,.api-binding-control input:focus{outline:none;border-color:var(--accent-primary);box-shadow:0 0 0 3px var(--shadow-secondary)}.api-binding-control select:hover,.api-binding-control input:hover{border-color:var(--accent-secondary)}.api-binding-status{flex-shrink:0;width:8px;height:8px;border-radius:50%;background:var(--border-primary);transition:all .3s ease}.api-binding-status--bound{background:var(--accent-success);box-shadow:0 0 6px var(--shadow-secondary)}.api-binding-footer{margin-top:18px;display:flex;align-items:center;justify-content:flex-end;gap:12px}.api-binding-save-btn{padding:14px 36px!important;font-size:16px!important;border-radius:14px!important;font-weight:700;letter-spacing:.3px;display:inline-flex;align-items:center;gap:8px}@media (max-width: 900px){.api-binding-row{flex-wrap:wrap}.api-binding-path{flex:1 1 100%}.api-binding-arrow{display:none}.api-binding-control{flex:1 1 100%}}.tool-binding-block{margin-bottom:20px;padding:16px 18px;border-radius:12px;background:var(--bg-secondary);border:1px solid var(--border-primary);transition:all .25s ease}.tool-binding-block:hover{border-color:var(--accent-secondary);box-shadow:0 2px 8px var(--shadow-secondary)}.tool-binding-label{display:flex;align-items:center;gap:8px;font-weight:600;font-size:14px;margin-bottom:12px;color:var(--text-primary)}.tool-binding-label-icon{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:6px;background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary));color:#fff;font-size:13px;flex-shrink:0}.tool-binding-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap}.tool-binding-row select{flex:1;min-width:200px;padding:9px 32px 9px 12px;border:1.5px solid var(--border-primary);border-radius:10px;font-size:13px;font-family:Nunito,sans-serif;background-color:var(--bg-card);background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23065F46' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 10px center;background-size:14px;color:var(--text-primary);-moz-appearance:none;appearance:none;-webkit-appearance:none;cursor:pointer;transition:all .25s ease}[data-theme=dark] .tool-binding-row select{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236EE7B7' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E")}.tool-binding-row select:hover{border-color:var(--accent-secondary)}.tool-binding-row select:focus{outline:none;border-color:var(--accent-primary);box-shadow:0 0 0 3px var(--shadow-secondary)}.tool-binding-row select:disabled{opacity:.5;cursor:not-allowed}.tool-binding-deactivate-btn{padding:8px 18px!important;font-size:13px!important;border-radius:10px!important;font-weight:600;white-space:nowrap}.tool-binding-desc{font-size:12px;color:var(--text-muted);margin-top:10px;line-height:1.6}.migration-source-info{background:var(--bg-secondary, #f5f6fa);border-radius:8px;padding:14px 18px;border:1px solid var(--border-primary)}.migration-source-title{font-size:16px;font-weight:600;color:var(--text-primary);margin-bottom:8px}.migration-source-meta{display:flex;gap:12px;align-items:center;font-size:13px;color:var(--text-tertiary);flex-wrap:wrap}.migration-source-meta .badge{padding:2px 10px;border-radius:12px;font-size:12px;font-weight:500}.migration-source-badge{padding:3px 12px!important;border-radius:20px!important;font-size:11px!important;font-weight:600!important;text-transform:uppercase;letter-spacing:.5px}.migration-badge-claude{background:#e67e22!important;color:#fff!important}.migration-badge-codex{background:#2d3436!important;color:#fff!important}.migration-tool-cards{display:flex;align-items:stretch;justify-content:flex-start;gap:12px}.migration-tool-card{position:relative;flex:1;display:flex;flex-direction:column;align-items:center;gap:8px;padding:18px 20px 14px;border:2px solid var(--border-primary);border-radius:12px;background:var(--bg-primary);cursor:pointer;transition:all .15s ease;font-family:inherit;color:var(--text-primary)}.migration-tool-card:hover{border-color:var(--accent-color, #6c5ce7);background:var(--bg-secondary, #f5f6fa);transform:translateY(-1px);box-shadow:0 2px 8px #0000000a}.migration-tool-card.active{border-color:var(--accent-color, #6c5ce7);background:linear-gradient(135deg,#6c5ce70a,#00b8940a);box-shadow:0 0 0 3px #6c5ce71a}.migration-tool-card.is-source{cursor:default;border-style:dashed;border-color:var(--border-primary);background:var(--bg-secondary, #f5f6fa)}.migration-tool-card.is-source:hover{transform:none;box-shadow:none;border-color:var(--border-primary);background:var(--bg-secondary, #f5f6fa)}.migration-tool-card-icon{width:52px;height:52px;border-radius:14px;display:flex;align-items:center;justify-content:center;background:var(--bg-secondary, #f5f6fa);color:var(--accent-color, #6c5ce7);transition:all .15s ease}.migration-tool-card.active .migration-tool-card-icon{background:#6c5ce71a}.migration-tool-card.is-source .migration-tool-card-icon{opacity:.7}.migration-tool-card-name{font-size:16px;font-weight:600;white-space:nowrap}.migration-tool-card-desc{font-size:12px;color:var(--text-tertiary);text-align:center}.migration-tool-card-badge{position:absolute;top:-8px;right:-8px;padding:2px 8px;border-radius:10px;font-size:11px;font-weight:600;color:#fff;background:#8e44ad;box-shadow:0 2px 4px #8e44ad4d}.migration-arrow{flex-shrink:0;display:flex;align-items:center;color:var(--accent-color, #6c5ce7);opacity:.5}.migration-empty-hint{margin-top:16px;padding:20px 24px;border:1px dashed var(--border-primary);border-radius:10px;background:var(--bg-secondary, #f5f6fa);display:flex;align-items:center;gap:16px;color:var(--text-tertiary)}.migration-empty-hint svg{flex-shrink:0;opacity:.4}.migration-options label{color:var(--text-secondary)}.migration-options input[type=checkbox]{accent-color:var(--accent-color, #6c5ce7)}.migration-prompt-textarea{width:100%;min-height:400px;padding:12px;border:1px solid var(--border-primary);border-radius:8px;font-size:13px;font-family:SF Mono,Menlo,Monaco,Consolas,monospace;background-color:var(--input-bg);color:var(--text-primary);resize:vertical;line-height:1.5}.migration-prompt-textarea:focus{outline:none;border-color:var(--accent-color, #6c5ce7);box-shadow:0 0 0 2px #6c5ce71a}.migration-preview-footer{font-size:13px;color:var(--text-tertiary)}.migration-launch-result{animation:fadeIn .3s ease}@keyframes fadeIn{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}[data-theme=dark] .migration-source-info{background:var(--bg-secondary, #1e1e2e)}[data-theme=dark] .migration-tool-card{border-color:var(--border-primary, #3a3a5c);background:var(--bg-primary, #1a1a2e)}[data-theme=dark] .migration-tool-card:hover{border-color:var(--accent-color, #a29bfe);background:var(--bg-secondary, #1e1e2e)}[data-theme=dark] .migration-tool-card.active{border-color:var(--accent-color, #a29bfe);background:linear-gradient(135deg,#a29bfe0f,#00cec90f)}[data-theme=dark] .migration-tool-card.is-source,[data-theme=dark] .migration-tool-card.is-source:hover{border-color:var(--border-primary, #3a3a5c);background:var(--bg-secondary, #1e1e2e)}[data-theme=dark] .migration-tool-card-icon{background:var(--bg-secondary, #1e1e2e);color:var(--accent-color, #a29bfe)}[data-theme=dark] .migration-tool-card.active .migration-tool-card-icon{background:#a29bfe1a}[data-theme=dark] .migration-arrow{color:var(--accent-color, #a29bfe)}[data-theme=dark] .migration-prompt-textarea{background:var(--input-bg, #1e1e2e);color:var(--text-primary, #e0e0e0);border-color:var(--border-primary, #3a3a5c)}[data-theme=dark] .migration-options label,[data-theme=dark] .migration-source-meta{color:var(--text-secondary, #a0a0b8)}.route-icon-popover{position:absolute;bottom:calc(100% + 6px);right:0;background:var(--bg-tooltip, #333);color:#fff;font-size:11px;padding:4px 8px;border-radius:4px;white-space:nowrap;pointer-events:none;opacity:0;transition:opacity .15s ease;z-index:100;box-shadow:0 2px 8px #00000026}.route-icon-popover:after{content:"";position:absolute;top:100%;right:4px;border:4px solid transparent;border-top-color:var(--bg-tooltip, #333)}div:hover>.route-icon-popover{opacity:1}*{margin:0;padding:0;box-sizing:border-box}:root{--primary-color: #14532D;--error-color: #DC2626;--bg-primary: linear-gradient(135deg, #F7FEE7 0%, #F0FDF4 100%);--bg-primary-solid: #F3FCEF;--bg-secondary: rgba(255, 255, 255, .95);--bg-sidebar: linear-gradient(135deg, #0F5132 0%, #065F46 100%);--bg-card: rgba(255, 255, 255, .98);--bg-code: #f4fff7;--bg-table-header: linear-gradient(135deg, #A7F3D0 0%, #6EE7B7 100%);--text-primary: #14532D;--text-secondary: #064E3B;--text-muted: #065F46;--text-sidebar: #FFFFFF;--text-on-dark: #FFFFFF;--border-primary: rgba(15, 81, 50, .2);--border-secondary: rgba(6, 95, 70, .2);--accent-primary: #0F5132;--accent-secondary: #047857;--accent-light: #a1e9c7;--accent-success: #047857;--accent-warning: #D97706;--accent-danger: #DC2626;--shadow-primary: rgba(15, 81, 50, .3);--shadow-secondary: rgba(15, 81, 50, .15);--bg-route-item: rgba(248, 249, 250, .9);--bg-route-item-hover: rgba(230, 244, 234, .95);--bg-route-item-selected: rgba(161, 233, 199, .25);--text-route-muted: #6c757d;--text-info: #2faeee;--text-light: #018038;--bg-info-box: #f8f9fa;--border-info-box: #e0e0e0;--text-info-box: #666;--bg-info-blue: #e3f2fd;--border-info-blue: #2196f3;--bg-info-green: #f1f8e9;--border-info-green: #8bc34a;--bg-info-orange: #fff3e0;--border-info-orange: #ff9800;--bg-info-yellow: #fff8e1;--border-info-yellow: #ffc107;--bg-assembled-text: #f8f9fa;--bg-thinking-box: #fff9e6;--border-thinking-box: #e0e0e0;--text-thinking-title: #f39c12;--bg-thinking-content: #fff;--border-thinking-content: #f0e6d3;--text-thinking-content: #555;--text-reply-title: #333;--bg-reply-content: #fff;--border-reply-content: #ddd;--text-reply-content: #333;--bg-input-disabled: #e5e7eb;--text-input-disabled: #9ca3af}[data-theme=dark]{--bg-primary: linear-gradient(135deg, #0A1A0F 0%, #0F2415 100%);--bg-primary-solid: #0C1F12;--bg-secondary: rgba(15, 36, 21, .9);--bg-sidebar: linear-gradient(135deg, #0F5132 0%, #065F46 100%);--bg-card: rgba(25, 51, 31, .95);--bg-code: #0f172a;--bg-table-header: linear-gradient(135deg, #0F5132 0%, #047857 100%);--text-primary: #ECFEF5;--text-secondary: #A7F3D0;--text-muted: #6EE7B7;--text-sidebar: #FFFFFF;--text-on-dark: #ECFEF5;--border-primary: rgba(15, 81, 50, .5);--border-secondary: rgba(6, 95, 70, .5);--accent-primary: #0F5132;--accent-secondary: #047857;--accent-light: #002d18;--accent-success: #10B981;--accent-warning: #F59E0B;--accent-danger: #EF4444;--shadow-primary: rgba(15, 81, 50, .4);--shadow-secondary: rgba(6, 95, 70, .3);--bg-route-item: rgba(20, 46, 28, .7);--bg-route-item-hover: rgba(30, 60, 38, .85);--bg-route-item-selected: rgba(16, 185, 129, .15);--text-route-muted: #A7F3D0;--text-light: #999999;--bg-info-box: rgba(20, 46, 28, .6);--border-info-box: rgba(161, 233, 199, .2);--text-info-box: #A7F3D0;--bg-info-blue: rgba(13, 71, 161, .25);--border-info-blue: #1976d2;--bg-info-green: rgba(27, 94, 32, .25);--border-info-green: #689f38;--bg-info-orange: rgba(230, 81, 0, .2);--border-info-orange: #f57c00;--bg-info-yellow: rgba(255, 193, 7, .15);--border-info-yellow: #ffb300;--bg-assembled-text: rgba(15, 23, 42, .5);--bg-thinking-box: rgba(230, 81, 0, .15);--border-thinking-box: rgba(245, 158, 11, .3);--text-thinking-title: #fbbf24;--bg-thinking-content: rgba(15, 23, 42, .4);--border-thinking-content: rgba(245, 158, 11, .2);--text-thinking-content: #d1d5db;--text-reply-title: #e5e7eb;--bg-reply-content: rgba(15, 23, 42, .4);--border-reply-content: rgba(161, 233, 199, .2);--text-reply-content: #e5e7eb;--bg-input-disabled: #2d3748;--text-input-disabled: #718096}body{font-family:Nunito,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background:var(--bg-primary);color:var(--text-primary);transition:all .3s ease;min-height:100vh}code{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}#root{width:100vw;height:100vh;overflow:visible}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-track{background:var(--bg-secondary);border-radius:6px}::-webkit-scrollbar-thumb{background:var(--accent-secondary);border-radius:6px;border:2px solid var(--bg-secondary)}::-webkit-scrollbar-thumb:hover{background:var(--accent-primary)}::-webkit-scrollbar-corner{background:var(--bg-secondary)}*{scrollbar-width:thin;scrollbar-color:var(--accent-primary) var(--bg-secondary)}::-webkit-scrollbar-button{display:none}html{scroll-behavior:smooth}.datetime-picker-input{cursor:pointer}.datetime-picker-input::-webkit-calendar-picker-indicator{cursor:pointer;opacity:1;filter:brightness(0);padding:2px 4px}.datetime-picker-input::-webkit-calendar-picker-indicator:hover{filter:brightness(.3)}.datetime-picker-input::-moz-calendar-picker-indicator{cursor:pointer;opacity:1;filter:brightness(0);padding:2px 4px}.datetime-picker-input::-moz-calendar-picker-indicator:hover{filter:brightness(.3)}[data-theme=dark] .datetime-picker-input::-webkit-calendar-picker-indicator{filter:brightness(0) invert(1)}[data-theme=dark] .datetime-picker-input::-webkit-calendar-picker-indicator:hover{filter:brightness(.2) invert(1)}[data-theme=dark] .datetime-picker-input::-moz-calendar-picker-indicator{filter:brightness(0) invert(1)}[data-theme=dark] .datetime-picker-input::-moz-calendar-picker-indicator:hover{filter:brightness(.2) invert(1)}
|