coding-tool-x 3.3.1 → 3.3.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/web/assets/{Analytics-BskCbia_.js → Analytics-DtR00OYP.js} +1 -1
- package/dist/web/assets/{ConfigTemplates-B4X3rgfY.js → ConfigTemplates-DWiSFOp5.js} +1 -1
- package/dist/web/assets/Home-BsSioaaB.css +1 -0
- package/dist/web/assets/Home-DUu2mGb6.js +1 -0
- package/dist/web/assets/{PluginManager-D_LoULGH.js → PluginManager-DsJ1KtNr.js} +1 -1
- package/dist/web/assets/{ProjectList-DiV4Qwa1.js → ProjectList-CzTJaBJb.js} +1 -1
- package/dist/web/assets/{SessionList-B24o0wiX.js → SessionList-D1ovPZ0I.js} +1 -1
- package/dist/web/assets/{SkillManager-B9Rnuaig.js → SkillManager-DqpDTc2c.js} +1 -1
- package/dist/web/assets/{WorkspaceManager-BkL2l5J9.js → WorkspaceManager-Dj28-3G5.js} +1 -1
- package/dist/web/assets/index-CaKktouI.js +2 -0
- package/dist/web/assets/{index-C5j22icm.css → index-DZjDFGqR.css} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/src/server/api/codex-proxy.js +81 -38
- package/src/server/api/config-export.js +4 -4
- package/src/server/api/gemini-proxy.js +81 -36
- package/src/server/api/opencode-proxy.js +60 -13
- package/src/server/api/proxy.js +37 -4
- package/src/server/services/channels.js +6 -6
- package/src/server/services/codex-channels.js +18 -9
- package/src/server/services/codex-settings-manager.js +18 -0
- package/src/server/services/config-export-service.js +8 -4
- package/src/server/services/gemini-channels.js +19 -11
- package/src/server/services/gemini-settings-manager.js +14 -0
- package/src/server/services/mcp-service.js +40 -15
- package/src/server/services/opencode-channels.js +18 -0
- package/src/server/services/opencode-sessions.js +25 -1
- package/src/server/services/opencode-settings-manager.js +16 -0
- package/dist/web/assets/Home-DHYMMKOU.js +0 -1
- package/dist/web/assets/Home-DuPOICVF.css +0 -1
- package/dist/web/assets/index-ZttxvTKw.js +0 -2
|
@@ -252,9 +252,9 @@ function updateChannel(channelId, updates) {
|
|
|
252
252
|
const proxyStatus = getCodexProxyStatus();
|
|
253
253
|
const isProxyRunning = proxyStatus.running;
|
|
254
254
|
|
|
255
|
-
// Single-channel enforcement: enabling a channel disables all others
|
|
256
|
-
//
|
|
257
|
-
if (newChannel.enabled && !oldChannel.enabled) {
|
|
255
|
+
// Single-channel enforcement: enabling a channel disables all others ONLY when proxy is OFF
|
|
256
|
+
// When proxy is ON (dynamic switching), multiple channels can be enabled simultaneously
|
|
257
|
+
if (!isProxyRunning && newChannel.enabled && !oldChannel.enabled) {
|
|
258
258
|
data.channels.forEach((ch, i) => {
|
|
259
259
|
if (i !== index && ch.enabled) {
|
|
260
260
|
ch.enabled = false;
|
|
@@ -273,9 +273,9 @@ function updateChannel(channelId, updates) {
|
|
|
273
273
|
|
|
274
274
|
saveChannels(data);
|
|
275
275
|
|
|
276
|
-
// Sync config.toml
|
|
277
|
-
//
|
|
278
|
-
if (newChannel.enabled) {
|
|
276
|
+
// Sync config.toml only when proxy is OFF.
|
|
277
|
+
// In dynamic switching mode, defer local config writes until proxy stop.
|
|
278
|
+
if (!isProxyRunning && newChannel.enabled) {
|
|
279
279
|
console.log(`[Codex Settings-sync] Channel "${newChannel.name}" enabled, syncing config.toml...`);
|
|
280
280
|
applyChannelToSettings(channelId);
|
|
281
281
|
}
|
|
@@ -564,9 +564,11 @@ function syncAllChannelEnvVars() {
|
|
|
564
564
|
* 类似 Claude 的"写入配置"功能,将渠道设置为当前激活的 provider
|
|
565
565
|
*
|
|
566
566
|
* @param {string} channelId - 渠道 ID
|
|
567
|
+
* @param {Object} options - 可选参数
|
|
568
|
+
* @param {boolean} options.pruneProviders - 是否清理 model_providers 仅保留当前渠道
|
|
567
569
|
* @returns {Object} 应用结果
|
|
568
570
|
*/
|
|
569
|
-
function applyChannelToSettings(channelId) {
|
|
571
|
+
function applyChannelToSettings(channelId, options = {}) {
|
|
570
572
|
const data = loadChannels();
|
|
571
573
|
const channel = data.channels.find(c => c.id === channelId);
|
|
572
574
|
|
|
@@ -613,8 +615,11 @@ function applyChannelToSettings(channelId) {
|
|
|
613
615
|
// 设置当前渠道为 model_provider
|
|
614
616
|
config.model_provider = channel.providerKey;
|
|
615
617
|
|
|
616
|
-
//
|
|
617
|
-
if (
|
|
618
|
+
// 可选:清理 provider,关闭动态切换后只保留当前渠道配置
|
|
619
|
+
if (options.pruneProviders === true) {
|
|
620
|
+
config.model_providers = {};
|
|
621
|
+
} else if (!config.model_providers) {
|
|
622
|
+
// 默认兼容历史行为:保留已有 provider
|
|
618
623
|
config.model_providers = {};
|
|
619
624
|
}
|
|
620
625
|
|
|
@@ -664,6 +669,10 @@ ${tomlContent}`;
|
|
|
664
669
|
delete auth[channel.envKey];
|
|
665
670
|
}
|
|
666
671
|
|
|
672
|
+
// 清除 chatgpt token 认证字段,避免 Codex 优先用过期 token 而报 usage limit
|
|
673
|
+
delete auth.tokens;
|
|
674
|
+
delete auth.auth_mode;
|
|
675
|
+
|
|
667
676
|
fs.writeFileSync(authPath, JSON.stringify(auth, null, 2), 'utf8');
|
|
668
677
|
|
|
669
678
|
if (channel.apiKey && channel.envKey) {
|
|
@@ -312,6 +312,23 @@ function backupSettings() {
|
|
|
312
312
|
}
|
|
313
313
|
}
|
|
314
314
|
|
|
315
|
+
// 只删除备份文件,不恢复(保留当前配置)
|
|
316
|
+
function deleteBackup() {
|
|
317
|
+
try {
|
|
318
|
+
if (fs.existsSync(getConfigBackupPath())) {
|
|
319
|
+
fs.unlinkSync(getConfigBackupPath());
|
|
320
|
+
}
|
|
321
|
+
if (fs.existsSync(getAuthBackupPath())) {
|
|
322
|
+
fs.unlinkSync(getAuthBackupPath());
|
|
323
|
+
}
|
|
324
|
+
console.log('Codex backup files deleted');
|
|
325
|
+
return { success: true };
|
|
326
|
+
} catch (err) {
|
|
327
|
+
console.warn('Failed to delete backup files:', err.message);
|
|
328
|
+
return { success: false, error: err.message };
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
315
332
|
// 恢复配置
|
|
316
333
|
function restoreSettings() {
|
|
317
334
|
try {
|
|
@@ -622,6 +639,7 @@ module.exports = {
|
|
|
622
639
|
writeAuth,
|
|
623
640
|
backupSettings,
|
|
624
641
|
restoreSettings,
|
|
642
|
+
deleteBackup,
|
|
625
643
|
setProxyConfig,
|
|
626
644
|
isProxyConfig,
|
|
627
645
|
getCurrentProxyPort,
|
|
@@ -572,7 +572,7 @@ function exportAllConfigsZip() {
|
|
|
572
572
|
* @param {Object} options - 导入选项 { overwrite: boolean }
|
|
573
573
|
* @returns {Object} 导入结果
|
|
574
574
|
*/
|
|
575
|
-
function importConfigs(importData, options = {}) {
|
|
575
|
+
async function importConfigs(importData, options = {}) {
|
|
576
576
|
const { overwrite = true } = options; // 默认覆盖模式
|
|
577
577
|
const results = {
|
|
578
578
|
configTemplates: { success: 0, failed: 0, skipped: 0 },
|
|
@@ -941,12 +941,16 @@ function importConfigs(importData, options = {}) {
|
|
|
941
941
|
}
|
|
942
942
|
|
|
943
943
|
// 导入 MCP Servers
|
|
944
|
-
|
|
944
|
+
const mcpServerList = Array.isArray(mcpServers)
|
|
945
|
+
? mcpServers
|
|
946
|
+
: Object.values(mcpServers || {});
|
|
947
|
+
|
|
948
|
+
if (mcpServerList.length > 0 && overwrite) {
|
|
945
949
|
try {
|
|
946
950
|
const mcpService = require('./mcp-service');
|
|
947
|
-
for (const server of
|
|
951
|
+
for (const server of mcpServerList) {
|
|
948
952
|
try {
|
|
949
|
-
mcpService.saveServer(server);
|
|
953
|
+
await mcpService.saveServer(server, { syncPlatforms: false });
|
|
950
954
|
results.mcpServers.success++;
|
|
951
955
|
} catch (err) {
|
|
952
956
|
console.error(`[ConfigImport] 导入 MCP Server 失败: ${server.name}`, err);
|
|
@@ -195,8 +195,12 @@ function createChannel(name, baseUrl, apiKey, model = 'gemini-2.5-pro', extraCon
|
|
|
195
195
|
data.channels.push(newChannel);
|
|
196
196
|
saveChannels(data);
|
|
197
197
|
|
|
198
|
-
//
|
|
199
|
-
|
|
198
|
+
// 仅在非动态切换模式下写入 Gemini 配置文件
|
|
199
|
+
const { getGeminiProxyStatus } = require('../gemini-proxy-server');
|
|
200
|
+
const proxyStatus = getGeminiProxyStatus();
|
|
201
|
+
if (!proxyStatus.running) {
|
|
202
|
+
writeGeminiConfigForMultiChannel(data.channels);
|
|
203
|
+
}
|
|
200
204
|
|
|
201
205
|
return newChannel;
|
|
202
206
|
}
|
|
@@ -237,9 +241,9 @@ function updateChannel(channelId, updates) {
|
|
|
237
241
|
const proxyStatus = getGeminiProxyStatus();
|
|
238
242
|
const isProxyRunning = proxyStatus.running;
|
|
239
243
|
|
|
240
|
-
// Single-channel enforcement: enabling a channel disables all others
|
|
241
|
-
//
|
|
242
|
-
if (nextChannel.enabled && !oldChannel.enabled) {
|
|
244
|
+
// Single-channel enforcement: enabling a channel disables all others ONLY when proxy is OFF
|
|
245
|
+
// When proxy is ON (dynamic switching), multiple channels can be enabled simultaneously
|
|
246
|
+
if (!isProxyRunning && nextChannel.enabled && !oldChannel.enabled) {
|
|
243
247
|
data.channels.forEach((ch, i) => {
|
|
244
248
|
if (i !== index && ch.enabled) {
|
|
245
249
|
ch.enabled = false;
|
|
@@ -258,12 +262,12 @@ function updateChannel(channelId, updates) {
|
|
|
258
262
|
|
|
259
263
|
saveChannels(data);
|
|
260
264
|
|
|
261
|
-
//
|
|
262
|
-
//
|
|
263
|
-
if (nextChannel.enabled) {
|
|
265
|
+
// Only sync .env when proxy is OFF.
|
|
266
|
+
// In dynamic switching mode, defer local config writes until proxy stop.
|
|
267
|
+
if (!isProxyRunning && nextChannel.enabled) {
|
|
264
268
|
console.log(`[Gemini Settings-sync] Channel "${nextChannel.name}" enabled, syncing .env...`);
|
|
265
269
|
applyChannelToSettings(channelId, data.channels);
|
|
266
|
-
} else {
|
|
270
|
+
} else if (!isProxyRunning) {
|
|
267
271
|
// 更新 Gemini 配置文件 (full rewrite for non-active-channel changes)
|
|
268
272
|
writeGeminiConfigForMultiChannel(data.channels);
|
|
269
273
|
}
|
|
@@ -352,8 +356,12 @@ async function deleteChannel(channelId) {
|
|
|
352
356
|
data.channels.splice(index, 1);
|
|
353
357
|
saveChannels(data);
|
|
354
358
|
|
|
355
|
-
//
|
|
356
|
-
|
|
359
|
+
// 仅在非动态切换模式下更新 Gemini 配置文件
|
|
360
|
+
const { getGeminiProxyStatus } = require('../gemini-proxy-server');
|
|
361
|
+
const proxyStatus = getGeminiProxyStatus();
|
|
362
|
+
if (!proxyStatus.running) {
|
|
363
|
+
writeGeminiConfigForMultiChannel(data.channels);
|
|
364
|
+
}
|
|
357
365
|
|
|
358
366
|
return { success: true };
|
|
359
367
|
}
|
|
@@ -138,6 +138,19 @@ function backupSettings() {
|
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
+
// 只删除备份文件,不恢复(保留当前配置中用户对 MCP 等的修改)
|
|
142
|
+
function deleteBackup() {
|
|
143
|
+
try {
|
|
144
|
+
if (fs.existsSync(getEnvBackupPath())) fs.unlinkSync(getEnvBackupPath());
|
|
145
|
+
if (fs.existsSync(getSettingsBackupPath())) fs.unlinkSync(getSettingsBackupPath());
|
|
146
|
+
console.log('Gemini backup files deleted');
|
|
147
|
+
return { success: true };
|
|
148
|
+
} catch (err) {
|
|
149
|
+
console.warn('Failed to delete Gemini backup files:', err.message);
|
|
150
|
+
return { success: false, error: err.message };
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
141
154
|
// 恢复配置
|
|
142
155
|
function restoreSettings() {
|
|
143
156
|
try {
|
|
@@ -257,6 +270,7 @@ module.exports = {
|
|
|
257
270
|
writeSettings,
|
|
258
271
|
backupSettings,
|
|
259
272
|
restoreSettings,
|
|
273
|
+
deleteBackup,
|
|
260
274
|
setProxyConfig,
|
|
261
275
|
isProxyConfig,
|
|
262
276
|
getCurrentProxyPort
|
|
@@ -419,12 +419,19 @@ function writeOpenCodeConfig(filePath, data) {
|
|
|
419
419
|
// MCP 数据管理
|
|
420
420
|
// ============================================================================
|
|
421
421
|
|
|
422
|
-
|
|
422
|
+
const DEFAULT_SERVER_APPS = {
|
|
423
|
+
claude: true,
|
|
424
|
+
codex: false,
|
|
425
|
+
gemini: false,
|
|
426
|
+
opencode: false
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
function normalizeServerApps(apps = {}, fallbackApps = DEFAULT_SERVER_APPS) {
|
|
423
430
|
return {
|
|
424
|
-
claude: apps.claude !== undefined ? !!apps.claude :
|
|
425
|
-
codex: !!apps.codex,
|
|
426
|
-
gemini: !!apps.gemini,
|
|
427
|
-
opencode: !!apps.opencode
|
|
431
|
+
claude: apps.claude !== undefined ? !!apps.claude : !!fallbackApps.claude,
|
|
432
|
+
codex: apps.codex !== undefined ? !!apps.codex : !!fallbackApps.codex,
|
|
433
|
+
gemini: apps.gemini !== undefined ? !!apps.gemini : !!fallbackApps.gemini,
|
|
434
|
+
opencode: apps.opencode !== undefined ? !!apps.opencode : !!fallbackApps.opencode
|
|
428
435
|
};
|
|
429
436
|
}
|
|
430
437
|
|
|
@@ -455,7 +462,9 @@ function getServer(id) {
|
|
|
455
462
|
/**
|
|
456
463
|
* 保存 MCP 服务器(添加或更新)
|
|
457
464
|
*/
|
|
458
|
-
async function saveServer(server) {
|
|
465
|
+
async function saveServer(server, options = {}) {
|
|
466
|
+
const { syncPlatforms = true } = options;
|
|
467
|
+
|
|
459
468
|
if (!server.id || !server.id.trim()) {
|
|
460
469
|
throw new Error('MCP 服务器 ID 不能为空');
|
|
461
470
|
}
|
|
@@ -464,25 +473,34 @@ async function saveServer(server) {
|
|
|
464
473
|
validateServerSpec(server.server);
|
|
465
474
|
|
|
466
475
|
const servers = getAllServers();
|
|
476
|
+
const existingServer = servers[server.id];
|
|
477
|
+
const previousApps = existingServer ? normalizeServerApps(existingServer.apps) : null;
|
|
467
478
|
|
|
468
479
|
// 如果是新服务器,设置默认值
|
|
469
|
-
if (!
|
|
480
|
+
if (!existingServer) {
|
|
470
481
|
server.createdAt = Date.now();
|
|
482
|
+
} else {
|
|
483
|
+
server.createdAt = existingServer.createdAt || server.createdAt || Date.now();
|
|
471
484
|
}
|
|
472
485
|
server.updatedAt = Date.now();
|
|
473
486
|
|
|
474
487
|
// 确保 apps 字段存在
|
|
475
488
|
if (!server.apps) {
|
|
476
|
-
|
|
489
|
+
// Updating a server without explicit app flags should preserve existing platform toggles.
|
|
490
|
+
server.apps = previousApps
|
|
491
|
+
? normalizeServerApps(previousApps)
|
|
492
|
+
: normalizeServerApps(DEFAULT_SERVER_APPS);
|
|
477
493
|
} else {
|
|
478
|
-
server.apps = normalizeServerApps(server.apps);
|
|
494
|
+
server.apps = normalizeServerApps(server.apps, previousApps || DEFAULT_SERVER_APPS);
|
|
479
495
|
}
|
|
480
496
|
|
|
481
497
|
servers[server.id] = server;
|
|
482
498
|
writeJsonFile(MCP_SERVERS_FILE, servers);
|
|
483
499
|
|
|
484
500
|
// 同步到各平台配置
|
|
485
|
-
|
|
501
|
+
if (syncPlatforms) {
|
|
502
|
+
await syncServerToAllPlatforms(server, previousApps);
|
|
503
|
+
}
|
|
486
504
|
|
|
487
505
|
return server;
|
|
488
506
|
}
|
|
@@ -580,30 +598,37 @@ function validateServerSpec(spec) {
|
|
|
580
598
|
/**
|
|
581
599
|
* 同步服务器到所有已启用的平台
|
|
582
600
|
*/
|
|
583
|
-
async function syncServerToAllPlatforms(server) {
|
|
601
|
+
async function syncServerToAllPlatforms(server, previousApps = null) {
|
|
584
602
|
const { apps } = server;
|
|
603
|
+
const previous = previousApps ? normalizeServerApps(previousApps) : null;
|
|
604
|
+
|
|
605
|
+
const shouldRemoveFromPlatform = (platform) => {
|
|
606
|
+
// For new servers we should not delete existing platform config implicitly.
|
|
607
|
+
if (!previous) return false;
|
|
608
|
+
return previous[platform] && !apps[platform];
|
|
609
|
+
};
|
|
585
610
|
|
|
586
611
|
if (apps.claude) {
|
|
587
612
|
await syncServerToPlatform(server, 'claude');
|
|
588
|
-
} else {
|
|
613
|
+
} else if (shouldRemoveFromPlatform('claude')) {
|
|
589
614
|
await removeServerFromPlatform(server.id, 'claude');
|
|
590
615
|
}
|
|
591
616
|
|
|
592
617
|
if (apps.codex) {
|
|
593
618
|
await syncServerToPlatform(server, 'codex');
|
|
594
|
-
} else {
|
|
619
|
+
} else if (shouldRemoveFromPlatform('codex')) {
|
|
595
620
|
await removeServerFromPlatform(server.id, 'codex');
|
|
596
621
|
}
|
|
597
622
|
|
|
598
623
|
if (apps.gemini) {
|
|
599
624
|
await syncServerToPlatform(server, 'gemini');
|
|
600
|
-
} else {
|
|
625
|
+
} else if (shouldRemoveFromPlatform('gemini')) {
|
|
601
626
|
await removeServerFromPlatform(server.id, 'gemini');
|
|
602
627
|
}
|
|
603
628
|
|
|
604
629
|
if (apps.opencode) {
|
|
605
630
|
await syncServerToPlatform(server, 'opencode');
|
|
606
|
-
} else {
|
|
631
|
+
} else if (shouldRemoveFromPlatform('opencode')) {
|
|
607
632
|
await removeServerFromPlatform(server.id, 'opencode');
|
|
608
633
|
}
|
|
609
634
|
}
|
|
@@ -245,6 +245,23 @@ function saveChannelOrder(order) {
|
|
|
245
245
|
saveChannels(data);
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
+
function applyChannelToSettings(channelId) {
|
|
249
|
+
const data = loadChannels();
|
|
250
|
+
const channel = data.channels.find(c => c.id === channelId);
|
|
251
|
+
|
|
252
|
+
if (!channel) {
|
|
253
|
+
throw new Error('Channel not found');
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// In single-channel mode, only this channel should be enabled
|
|
257
|
+
data.channels.forEach(ch => {
|
|
258
|
+
ch.enabled = ch.id === channelId;
|
|
259
|
+
});
|
|
260
|
+
saveChannels(data);
|
|
261
|
+
|
|
262
|
+
return channel;
|
|
263
|
+
}
|
|
264
|
+
|
|
248
265
|
function loadCodexChannels() {
|
|
249
266
|
const filePath = getCodexChannelsFilePath();
|
|
250
267
|
if (!fs.existsSync(filePath)) {
|
|
@@ -361,6 +378,7 @@ module.exports = {
|
|
|
361
378
|
deleteChannel,
|
|
362
379
|
getEnabledChannels,
|
|
363
380
|
saveChannelOrder,
|
|
381
|
+
applyChannelToSettings,
|
|
364
382
|
getEffectiveApiKey,
|
|
365
383
|
getEffectiveApiKeyCandidates
|
|
366
384
|
};
|
|
@@ -441,11 +441,35 @@ function normalizeSession(session, projectId = null) {
|
|
|
441
441
|
};
|
|
442
442
|
}
|
|
443
443
|
|
|
444
|
+
function isSessionLikeName(name) {
|
|
445
|
+
return /^ses_[a-z0-9_-]+$/i.test(name);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
function getProjectDisplayName(project) {
|
|
449
|
+
const rawName = typeof project?.name === 'string' ? project.name.trim() : '';
|
|
450
|
+
const rawId = typeof project?.id === 'string' ? project.id.trim() : '';
|
|
451
|
+
const worktree = typeof project?.worktree === 'string' ? project.worktree.trim() : '';
|
|
452
|
+
|
|
453
|
+
// OpenCode 的 project.name 可能为空或异常写成会话ID,优先回退为目录名。
|
|
454
|
+
if (rawName && rawName !== rawId && !isSessionLikeName(rawName)) {
|
|
455
|
+
return rawName;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
if (worktree) {
|
|
459
|
+
const dirName = path.basename(worktree);
|
|
460
|
+
if (dirName && dirName !== path.sep && dirName !== '.' && dirName !== '..') {
|
|
461
|
+
return dirName;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
return rawName || rawId;
|
|
466
|
+
}
|
|
467
|
+
|
|
444
468
|
// 获取所有项目
|
|
445
469
|
function getProjects() {
|
|
446
470
|
const projects = getProjectRows().map((project) => ({
|
|
447
471
|
name: project.id,
|
|
448
|
-
displayName: project
|
|
472
|
+
displayName: getProjectDisplayName(project),
|
|
449
473
|
fullPath: project.worktree || '/',
|
|
450
474
|
path: project.worktree || '/',
|
|
451
475
|
sessionCount: Number(project.session_count) || 0,
|
|
@@ -442,6 +442,21 @@ function restoreSettings() {
|
|
|
442
442
|
return { success: restored };
|
|
443
443
|
}
|
|
444
444
|
|
|
445
|
+
// 只删除备份文件,不恢复(保留当前配置中用户对 MCP 等的修改)
|
|
446
|
+
function deleteBackup() {
|
|
447
|
+
try {
|
|
448
|
+
[CONFIG_PATHS.opencodec, CONFIG_PATHS.opencode, CONFIG_PATHS.config].forEach(p => {
|
|
449
|
+
const bp = getBackupPath(p);
|
|
450
|
+
if (fs.existsSync(bp)) fs.unlinkSync(bp);
|
|
451
|
+
});
|
|
452
|
+
console.log('[OpenCode] Backup files deleted');
|
|
453
|
+
return { success: true };
|
|
454
|
+
} catch (err) {
|
|
455
|
+
console.warn('[OpenCode] Failed to delete backup files:', err.message);
|
|
456
|
+
return { success: false, error: err.message };
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
445
460
|
function isProxyConfig() {
|
|
446
461
|
try {
|
|
447
462
|
const filePath = selectConfigPath();
|
|
@@ -472,6 +487,7 @@ module.exports = {
|
|
|
472
487
|
hasBackup,
|
|
473
488
|
setProxyConfig,
|
|
474
489
|
restoreSettings,
|
|
490
|
+
deleteBackup,
|
|
475
491
|
isProxyConfig,
|
|
476
492
|
getCurrentProxyPort,
|
|
477
493
|
CONFIG_PATHS
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{d as e}from"./vendors-DMjSfzlv.js";import{a8 as a,f as l,r as n,w as s,h as c,K as t,a7 as o,c as i,o as u,a as d,W as r,X as v,a0 as p,Y as h,N as y,a3 as g,_ as m,p as f,F as k,$ as T,L as b,Z as x,v as C}from"./vue-vendor-DET08QYg.js";import{_,u as w,a as $,R as z,g as q,b as S,c as L,d as I,e as O,f as j,t as M,h as N,i as A,j as F,k as P,l as U,m as D,n as E,o as V,s as J}from"./index-ZttxvTKw.js";import{E as G,o as K,n as R,m as Z,ar as B,R as H,as as W,at as X,au as Y,av as Q,aa as ee,i as ae,A as le,aw as ne,ax as se,T as ce,a as te}from"./icons-B29onFfZ.js";import{L as oe,N as ie,c as ue,b as de,a as re,Z as ve,B as pe,s as he}from"./naive-ui-CxpuzdjU.js";import"./markdown-C9MYpaSi.js";const ye={class:"channel-column"},ge={class:"drag-handle",title:"拖拽排序"},me={class:"header-icon"},fe={class:"channel-title"},ke={class:"mcp-quick-panel"},Te={class:"panel-title"},be={key:0,class:"no-items"},xe={key:1,class:"mcp-quick-list"},Ce={class:"mcp-item-icon"},_e={class:"mcp-item-info"},we={class:"mcp-item-name"},$e={class:"mcp-item-type"},ze={key:1,class:"claude-extra-area"},qe={class:"skills-quick-panel"},Se={class:"panel-title"},Le={key:0,class:"no-items"},Ie={key:1,class:"skills-quick-list"},Oe={class:"skill-item-icon"},je={class:"skill-item-info"},Me={class:"skill-item-name"},Ne={class:"skill-item-desc"},Ae={key:0,class:"channel-content"},Fe={class:"card"},Pe={class:"card-header"},Ue={key:0,class:"runtime-badge"},De={class:"card-body",style:{padding:"6px 10px"}},Ee={class:"proxy-info-row"},Ve={class:"proxy-status"},Je={class:"proxy-port"},Ge={class:"channel-name"},Ke={class:"channel-quick-panel"},Re={class:"panel-title"},Ze={key:0,class:"no-channels"},Be={key:1,class:"channel-quick-list"},He={class:"channel-quick-info"},We={class:"channel-quick-name"},Xe={key:0,class:"channel-switching-tip"},Ye={class:"channel-metrics"},Qe={class:"metric-item"},ea={class:"metric-value"},aa={class:"metric-item"},la={class:"metric-value"},na={class:"metric-item"},sa={class:"metric-value"},ca={class:"metric-item"},ta={class:"card"},oa={class:"card-header compact"},ia={class:"card-body",style:{padding:"8px 10px"}},ua={class:"quick-access-list"},da={class:"access-icon"},ra={class:"access-content"},va={class:"access-value"},pa={class:"access-icon"},ha={class:"access-content"},ya={class:"access-value"},ga={class:"access-icon"},ma={class:"access-content"},fa={class:"access-goto"},ka={class:"card-header compact"},Ta={class:"card-body",style:{padding:"8px 10px"}},ba={class:"stats-inline stats-3col"},xa={class:"stat-inline-item stat-requests"},Ca={class:"stat-info"},_a={class:"stat-inline-item stat-input"},wa={class:"stat-info"},$a={class:"stat-inline-item stat-output"},za={class:"stat-info"},qa={key:1,class:"card logs-card"},Sa={class:"card-header compact"},La={class:"card-body logs-card-body"},Ia={class:"logs-table-wrapper"},Oa={key:0,class:"empty-logs"},ja={key:0,class:"action-content"},Ma={class:"action-msg"},Na={class:"action-time"},Aa={class:"locked-content"},Fa={class:"lock-icon"},Pa="channelLocks",Ua=_({__name:"ChannelColumn",props:{channelType:{type:String,required:!0,validator:e=>["claude","codex","gemini","opencode"].includes(e)}},setup(e){let _=null,V=null;const J=e,Ua=a(),Da=oe(),{claudeProxy:Ea,codexProxy:Va,geminiProxy:Ja,opencodeProxy:Ga,claudeChannels:Ka,codexChannels:Ra,geminiChannels:Za,opencodeChannels:Ba,schedulerState:Ha,getProxyState:Wa,startProxy:Xa,stopProxy:Ya,getLogs:Qa,clearLogsForSource:el,loadChannels:al,logLimit:ll,statsInterval:nl}=w(),{dashboardData:sl,loadDashboard:cl}=$(),tl={claude:{title:"ClaudeCode",subtitle:"智能编程助手",icon:Z},codex:{title:"Codex-CLI",subtitle:"高效代码生成",icon:R},gemini:{title:"Gemini-CLI",subtitle:"多模态AI助手",icon:K},opencode:{title:"OpenCode",subtitle:"AI 代码助手",icon:G}},ol=l(()=>tl[J.channelType].title);l(()=>tl[J.channelType].subtitle);const il=l(()=>tl[J.channelType].icon),ul=l(()=>"claude"===J.channelType?Ea.value:"codex"===J.channelType?Va.value:"gemini"===J.channelType?Ja.value:"opencode"===J.channelType?Ga.value:{}),dl=l(()=>"claude"===J.channelType?"Claude":"codex"===J.channelType?"Codex":"gemini"===J.channelType?"Gemini":"opencode"===J.channelType?"OpenCode":""),rl=n({projects:0,sessions:0}),vl=n({requests:0,tokens:0,cost:0}),pl=n({requests:0,tokens:0,cost:0}),hl={requests:0,tokens:0,cost:3};let yl={requests:null,tokens:null,cost:null};const gl=n({requests:!1,tokens:!1,cost:!1}),ml=l(()=>{var e,a,l;const n="claude"===J.channelType?"claude":"codex"===J.channelType?"codex":"opencode"===J.channelType?"opencode":"gemini";return(null==(l=null==(a=null==(e=sl.value)?void 0:e.todayStats)?void 0:a[n])?void 0:l.byModel)||{}});function fl(e,a,l,n=600){yl[e]&&cancelAnimationFrame(yl[e]),gl.value[e]=!0;const s=Date.now(),c=()=>{const t=Date.now()-s,o=Math.min(t/n,1),i=1-Math.pow(1-o,2),u=a+(l-a)*i,d=hl[e]??0,r=Math.pow(10,d),v=d>0?Math.round(u*r)/r:Math.round(u);pl.value[e]=v,o<1?yl[e]=requestAnimationFrame(c):gl.value[e]=!1};yl[e]=requestAnimationFrame(c)}const kl=n(!1),Tl=n(0),bl=n([]),xl=n(0),Cl=n([]),_l=l(()=>({claude:"Claude",codex:"Codex",gemini:"Gemini",opencode:"OpenCode"}[J.channelType]||""));async function wl(){if(["claude","codex","gemini","opencode"].includes(J.channelType))try{const e=await O(!1,J.channelType);if(e.success&&e.skills){const a=e.skills.filter(e=>e.installed);Tl.value=a.length,bl.value=a.slice(0,10).map(e=>({...e,_uninstalling:!1}))}}catch(e){}}async function $l(e=!1){try{const a=await async function(e=!1){if(!e&&_)return _;if(!e&&V)return V;const a=D().then(e=>(_=(null==e?void 0:e.success)&&e.servers?Object.values(e.servers):[],_)).finally(()=>{V=null});return V=a,a}(e),l=a.filter(e=>{var a;return!0===(null==(a=e.apps)?void 0:a[J.channelType])});xl.value=l.length,Cl.value=l.slice(0,10).map(e=>({...e,_toggling:!1}))}catch(a){}}function zl(e){try{const a=localStorage.getItem(Pa),l=a?JSON.parse(a):{};l[J.channelType]=e,localStorage.setItem(Pa,JSON.stringify(l))}catch(a){}}const ql=n(function(){try{const e=localStorage.getItem(Pa);if(e){return JSON.parse(e)[J.channelType]||!1}}catch(e){}return!1}());async function Sl(){ql.value=!ql.value,zl(ql.value);try{if(await E("channelLocks",J.channelType,ql.value),sl.value){const e=sl.value.uiConfig||{},a={...e.channelLocks||{}};a[J.channelType]=ql.value,sl.value={...sl.value,uiConfig:{...e,channelLocks:a}}}}catch(e){}}const Ll=n(!0);function Il(e){e.detail&&void 0!==e.detail.showLogs&&(Ll.value=e.detail.showLogs)}const Ol=n(Date.now()),jl=l(()=>{if(!ul.value.running)return"";const e=ul.value.startTime;if(!e)return"";const a=Ol.value-e;if(a<=0)return"";const l=Math.floor(a/1e3),n=Math.floor(l/3600),s=Math.floor(l%3600/60),c=l%60;let t="已运行 ";return n>0&&(t+=`${n}小时`),s>0&&(t+=`${s}分`),(c>0||0===n&&0===s)&&(t+=`${c}秒`),t}),Ml=n(null),Nl=l(()=>ll.value),Al={claude:Qa("claude"),codex:Qa("codex"),gemini:Qa("gemini"),opencode:Qa("opencode")},Fl=l(()=>((Al[J.channelType]||Al.claude).value||[]).slice(0,Nl.value));let Pl=null,Ul=null,Dl=null,El=!1,Vl=null;const Jl=l(()=>{let e=[];"claude"===J.channelType?e=Ka.value||[]:"codex"===J.channelType?e=Ra.value||[]:"gemini"===J.channelType?e=Za.value||[]:"opencode"===J.channelType&&(e=Ba.value||[]);return[...e.filter(e=>!1!==e.enabled),...e.filter(e=>!1===e.enabled)]});function Gl(e){const a=Ha[J.channelType];if(!a||!a.channels)return 0;const l=a.channels.find(a=>a.id===e);return l?l.inflight:0}const Kl=l(()=>{var e;const a=Jl.value.filter(e=>!1!==e.enabled).length;return(null==(e=ul.value.proxy)?void 0:e.running)?`${a}个渠道调度中`:Jl.value.length>0?`${a}个渠道已启用`:"无渠道"}),Rl=n({});function Zl(e){return Rl.value[e]||{requests:0,tokens:0,cost:0}}async function Bl(){var e;try{let a;if("claude"===J.channelType?a=await q():"codex"===J.channelType?a=await S():"gemini"===J.channelType?a=await L():"opencode"===J.channelType&&(a=await I()),a&&a.byChannel){const l={};for(const[n,s]of Object.entries(a.byChannel))l[n]={requests:s.requests||0,tokens:(null==(e=s.tokens)?void 0:e.total)||0,cost:s.cost||0};Rl.value=l}}catch(a){}}async function Hl(e){var a,l;const n=Wa(J.channelType);n.value.loading=!0;try{let a;a=e?await Xa(J.channelType):await Ya(J.channelType),!1!==a.success?Da.success(e?`${ol.value} 代理已启动`:`${ol.value} 代理已停止`):(Da.error(a.error||"操作失败"),n.value.running=!e)}catch(s){Da.error((null==(l=null==(a=s.response)?void 0:a.data)?void 0:l.error)||s.message||"操作失败"),n.value.running=!e}finally{n.value.loading=!1}}function Wl(){Ua.push({name:`${J.channelType}-projects`})}function Xl(){Ua.push({name:`${J.channelType}-projects`})}s(Fl,e=>{var a;const l=(null==(a=e[0])?void 0:a.id)||null;if(!l||l===Pl)return void(Pl=l);Pl=l,Vl&&clearTimeout(Vl),Vl=setTimeout(()=>{Bl()},5e3);(!Ml.value||Ml.value.scrollTop<20)&&C(()=>{Ml.value&&(Ml.value.scrollTop=0)})}),s(()=>vl.value.requests,e=>{fl("requests",pl.value.requests,e,600)}),s(()=>vl.value.tokens,e=>{fl("tokens",pl.value.tokens,e,600)}),s(()=>vl.value.cost,e=>{fl("cost",pl.value.cost,e,600)}),s(()=>J.channelType,()=>{var e;Pl=(null==(e=Fl.value[0])?void 0:e.id)||null}),s(()=>{var e,a;return null==(a=null==(e=sl.value)?void 0:e.counts)?void 0:a[J.channelType]},()=>{an()}),s(nl,()=>{El&&function(){Ul&&(clearInterval(Ul),Ul=null);const e=nl.value||30,a=Math.max(1e3*e,1e4);Ul=setInterval(()=>{ln(),Bl()},a)}()});const Yl=n({});function Ql(e){return!!Yl.value[e]}function en(e,a){e&&(Yl.value={...Yl.value,[e]:!!a})}function an(){var e,a;const l=null==(a=null==(e=sl.value)?void 0:e.counts)?void 0:a[J.channelType];rl.value.projects=(null==l?void 0:l.projectCount)||0,rl.value.sessions=(null==l?void 0:l.sessionCount)||0}async function ln(){if(sl.value&&sl.value.todayStats){const e=sl.value.todayStats[J.channelType];e&&(vl.value.requests=e.requests||0,vl.value.tokens=e.tokens||0,vl.value.cost=e.cost||0)}an()}function nn(){el(J.channelType)}function sn(){window.dispatchEvent(new CustomEvent("open-skills-drawer",{detail:{platform:J.channelType}}))}return c(async()=>{await Promise.all([cl().then(()=>ln()),Bl()]),wl(),$l(),async function(){var e,a;try{if(sl.value&&sl.value.uiConfig)Ll.value=!1!==(null==(e=sl.value.uiConfig.panelVisibility)?void 0:e.showLogs);else{const e=await j();e.success&&e.config&&(Ll.value=!1!==(null==(a=e.config.panelVisibility)?void 0:a.showLogs))}}catch(l){}}(),async function(){var e,a;try{let l=!1;if(sl.value&&sl.value.uiConfig)l=(null==(e=sl.value.uiConfig.channelLocks)?void 0:e[J.channelType])||!1;else{const e=await j();e.success&&e.config&&(l=(null==(a=e.config.channelLocks)?void 0:a[J.channelType])||!1)}ql.value=l,zl(l)}catch(l){}}(),window.addEventListener("panel-visibility-change",Il),pl.value={...vl.value},El=!0,Dl=setInterval(()=>{Ol.value=Date.now()},1e3)}),t(()=>{El=!1,Ul&&clearInterval(Ul),Dl&&clearInterval(Dl),Vl&&clearTimeout(Vl),window.removeEventListener("panel-visibility-change",Il),Object.values(yl).forEach(e=>{e&&cancelAnimationFrame(e)})}),(a,l)=>{const n=o("n-collapse");return u(),i("div",ye,[d("div",{class:b(["channel-header",e.channelType])},[d("div",ge,[v(y(ie),{size:16},{default:h(()=>[v(y(B))]),_:1})]),d("div",me,[v(y(ie),{size:20},{default:h(()=>[(u(),p(g(il.value)))]),_:1})]),d("h2",fe,m(ol.value),1),xl.value>0?(u(),p(y(ve),{key:0,trigger:"click",placement:"bottom",width:340,class:"mcp-popover"},{trigger:h(()=>[v(y(re),{type:"info",size:"small",bordered:!1,class:"mcp-count-tag clickable"},{default:h(()=>[f(" 已启用 "+m(xl.value)+" 个 MCP ",1)]),_:1})]),default:h(()=>[d("div",ke,[d("div",Te,[l[3]||(l[3]=d("span",null,"已启用的 MCP 服务",-1)),v(y(ue),{depth:"3",style:{"font-size":"11px"}},{default:h(()=>[f(m(_l.value)+" 平台",1)]),_:1})]),0===Cl.value.length?(u(),i("div",be,[v(y(ue),{depth:"3"},{default:h(()=>[...l[4]||(l[4]=[f("暂无启用的 MCP 服务",-1)])]),_:1})])):(u(),i("div",xe,[(u(!0),i(k,null,T(Cl.value,e=>(u(),i("div",{key:e.id,class:"mcp-quick-item"},[d("div",Ce,[v(y(ie),{size:14},{default:h(()=>[v(y(H))]),_:1})]),d("div",_e,[d("span",we,m(e.name),1),d("span",$e,m(e.transportType||"stdio"),1)]),v(y(de),{size:"small",value:!0,"onUpdate:value":a=>async function(e,a){e._toggling=!0;try{await M(e.id,J.channelType,a),Da.success(a?`已启用 ${e.name}`:`已禁用 ${e.name}`),await $l(!0)}catch(l){Da.error("操作失败: "+(l.message||"未知错误"))}finally{e._toggling=!1}}(e,a),loading:e._toggling},null,8,["onUpdate:value","loading"])]))),128))]))])]),_:1})):r("",!0),["claude","codex","gemini","opencode"].includes(e.channelType)?(u(),i("div",ze,[Tl.value>0?(u(),p(y(ve),{key:0,trigger:"click",placement:"bottom",width:340,class:"skills-popover"},{trigger:h(()=>[v(y(re),{type:"success",size:"small",bordered:!1,class:"skills-count-tag clickable"},{default:h(()=>[f(m(Tl.value)+" 个技能 ",1)]),_:1})]),default:h(()=>[d("div",qe,[d("div",Se,[l[6]||(l[6]=d("span",null,"已安装的技能",-1)),v(y(pe),{text:"",size:"tiny",onClick:sn},{default:h(()=>[...l[5]||(l[5]=[f(" 管理全部 ",-1)])]),_:1})]),0===bl.value.length?(u(),i("div",Le,[v(y(ue),{depth:"3"},{default:h(()=>[...l[7]||(l[7]=[f("暂无已安装的技能",-1)])]),_:1})])):(u(),i("div",Ie,[(u(!0),i(k,null,T(bl.value,e=>(u(),i("div",{key:e.id,class:"skill-quick-item"},[d("div",Oe,[v(y(ie),{size:14},{default:h(()=>[v(y(G))]),_:1})]),d("div",je,[d("span",Me,m(e.name),1),d("span",Ne,m(e.description||"无描述"),1)]),v(y(pe),{size:"tiny",tertiary:"",type:"error",onClick:a=>async function(e){e._uninstalling=!0;try{const a=await N(e.directory,J.channelType);a.success?(Da.success(`已卸载 ${e.name}`),await wl()):Da.error(a.error||"卸载失败")}catch(a){Da.error("卸载失败: "+(a.message||"未知错误"))}finally{e._uninstalling=!1}}(e),loading:e._uninstalling},{default:h(()=>[...l[8]||(l[8]=[f(" 卸载 ",-1)])]),_:1},8,["onClick","loading"])]))),128))]))])]),_:1})):r("",!0),v(y(he),{trigger:"hover"},{trigger:h(()=>[v(y(pe),{text:"",class:"skills-button",onClick:sn,title:"Skills 技能管理"},{icon:h(()=>[v(y(ie),{size:18},{default:h(()=>[v(y(G))]),_:1})]),_:1})]),default:h(()=>[l[9]||(l[9]=f(" Skills 技能管理 ",-1))]),_:1})])):r("",!0),v(y(pe),{text:"",class:"lock-button",onClick:Sl,title:ql.value?"解锁此列":"锁定此列"},{icon:h(()=>[v(y(ie),{size:18},{default:h(()=>[ql.value?(u(),p(y(W),{key:0})):(u(),p(y(X),{key:1}))]),_:1})]),_:1},8,["title"])],2),ql.value?r("",!0):(u(),i("div",Ae,[d("div",Fe,[d("div",Pe,[v(y(ie),{size:16},{default:h(()=>[v(y(Y))]),_:1}),l[10]||(l[10]=d("h3",{class:"card-title"},"代理控制",-1)),ul.value.running&&jl.value?(u(),i("span",Ue,m(jl.value),1)):r("",!0),v(y(de),{value:ul.value.running,"onUpdate:value":[l[0]||(l[0]=e=>ul.value.running=e),Hl],loading:ul.value.loading,size:"small",style:{"margin-left":"auto"}},null,8,["value","loading"])]),d("div",De,[d("div",Ee,[d("div",Ve,[d("div",{class:b(["status-dot",{active:ul.value.running}])},null,2),v(y(ue),{type:ul.value.running?"success":"default",style:{"font-size":"12px"}},{default:h(()=>[f(m(ul.value.running?"运行中":"已停止"),1)]),_:1},8,["type"]),d("span",Je,"端口: "+m(ul.value.port),1)]),v(y(ve),{trigger:"click",placement:"bottom",width:320,class:"channel-popover"},{trigger:h(()=>[v(y(pe),{text:"",size:"tiny",class:"channel-status"},{default:h(()=>[d("span",Ge,m(Kl.value),1)]),_:1})]),default:h(()=>[d("div",Ke,[d("div",Re,[l[12]||(l[12]=d("span",null,"渠道快捷管理",-1)),v(y(ue),{depth:"3",style:{"font-size":"11px"}},{default:h(()=>[...l[11]||(l[11]=[f("点击开关切换状态",-1)])]),_:1})]),0===Jl.value.length?(u(),i("div",Ze,[v(y(ue),{depth:"3"},{default:h(()=>[...l[13]||(l[13]=[f("暂无配置渠道",-1)])]),_:1})])):(u(),i("div",Be,[(u(!0),i(k,null,T(Jl.value,e=>{var a,n;return u(),i("div",{key:e.id,class:b(["channel-quick-item",{disabled:!1===e.enabled}])},[d("div",He,[d("span",We,m(e.name),1),"frozen"===(null==(a=e.health)?void 0:a.status)?(u(),p(y(re),{key:0,size:"tiny",type:"error",bordered:!1},{default:h(()=>[...l[14]||(l[14]=[f(" 冻结 ",-1)])]),_:1})):r("",!0),v(y(de),{size:"small",value:!1!==e.enabled,"onUpdate:value":a=>async function(e,a){if(e&&!Ql(e.id)){en(e.id,!0);try{let l;"claude"===J.channelType?l=A:"codex"===J.channelType?l=F:"gemini"===J.channelType?l=P:"opencode"===J.channelType&&(l=U),l&&(await l(e.id,{enabled:a}),Da.success(a?`渠道「${e.name}」已启用`:`渠道「${e.name}」已停用`),await al())}catch(l){Da.error("操作失败: "+l.message)}finally{en(e.id,!1)}}}(e,a),loading:Ql(e.id),disabled:Ql(e.id),style:{"margin-left":"auto"}},null,8,["value","onUpdate:value","loading","disabled"])]),Ql(e.id)?(u(),i("div",Xe," 正在切换渠道状态... ")):r("",!0),d("div",Ye,[d("span",Qe,[l[15]||(l[15]=d("span",{class:"metric-label"},"请求",-1)),d("span",ea,m(Zl(e.id).requests),1)]),d("span",aa,[l[16]||(l[16]=d("span",{class:"metric-label"},"Tokens",-1)),d("span",la,m((n=Zl(e.id).tokens,n>=1e6?(n/1e6).toFixed(1)+"M":n>=1e3?(n/1e3).toFixed(1)+"K":n.toString())),1)]),d("span",na,[l[17]||(l[17]=d("span",{class:"metric-label"},"权重",-1)),d("span",sa,m(e.weight||1),1)]),d("span",ca,[l[18]||(l[18]=d("span",{class:"metric-label"},"并发",-1)),d("span",{class:b(["metric-value",{active:Gl(e.id)>0}])},m(Gl(e.id))+m(e.maxConcurrency?`/${e.maxConcurrency}`:""),3)])])],2)}),128))]))])]),_:1})])])]),d("div",ta,[d("div",oa,[v(y(ie),{size:14},{default:h(()=>[v(y(Q))]),_:1}),l[19]||(l[19]=d("h3",{class:"card-title"},"快速访问",-1))]),d("div",ia,[d("div",ua,[d("div",{class:"access-card access-card-projects clickable",onClick:Wl},[d("div",da,[v(y(ie),{size:16},{default:h(()=>[v(y(ee))]),_:1})]),d("div",ra,[l[20]||(l[20]=d("span",{class:"access-label"},"项目",-1)),d("span",va,m(rl.value.projects),1)])]),d("div",{class:"access-card access-card-sessions clickable",onClick:l[1]||(l[1]=e=>kl.value=!0)},[d("div",pa,[v(y(ie),{size:16},{default:h(()=>[v(y(ae))]),_:1})]),d("div",ha,[l[21]||(l[21]=d("span",{class:"access-label"},"最新对话",-1)),d("span",ya,m(rl.value.sessions),1)])]),d("div",{class:"access-card access-card-goto clickable",onClick:Xl},[d("div",ga,[v(y(ie),{size:16},{default:h(()=>[v(y(le))]),_:1})]),d("div",ma,[l[22]||(l[22]=d("span",{class:"access-label"},"前往",-1)),d("span",fa,m(dl.value),1)])])])])]),d("div",{class:b(["card stats-card",`stats-card-${e.channelType}`])},[d("div",ka,[v(y(ie),{size:14},{default:h(()=>[v(y(ne))]),_:1}),l[23]||(l[23]=d("h3",{class:"card-title"},"今日数据",-1))]),d("div",Ta,[d("div",ba,[d("div",xa,[l[25]||(l[25]=d("div",{class:"stat-icon-dot requests"},null,-1)),d("div",Ca,[l[24]||(l[24]=d("span",{class:"stat-label"},"请求",-1)),d("span",{class:b(["stat-value",{animating:gl.value.requests}])},m(pl.value.requests),3)])]),d("div",_a,[l[27]||(l[27]=d("div",{class:"stat-icon-dot tokens"},null,-1)),d("div",wa,[l[26]||(l[26]=d("span",{class:"stat-label"},"总 Tokens",-1)),d("span",{class:b(["stat-value",{animating:gl.value.tokens}])},m((c=pl.value.tokens,c>=1e6?(c/1e6).toFixed(1)+"M":c>=1e3?(c/1e3).toFixed(1)+"K":c.toString())),3)])]),d("div",$a,[l[29]||(l[29]=d("div",{class:"stat-icon-dot cost"},null,-1)),d("div",za,[l[28]||(l[28]=d("span",{class:"stat-label"},"成本 / USD",-1)),d("span",{class:b(["stat-value",{animating:gl.value.cost}])},m((s=pl.value.cost,!s||Number.isNaN(s)?"$0":"$"+Number(s).toFixed(3))),3)])])])])],2),Object.keys(ml.value).length>0?(u(),i("div",{key:0,class:b(["card chart-card",`chart-card-${e.channelType}`])},[v(n,{"default-expanded-names":[],accordion:""})],2)):r("",!0),Ll.value?(u(),i("div",qa,[d("div",Sa,[v(y(ie),{size:14},{default:h(()=>[v(y(se))]),_:1}),l[30]||(l[30]=d("h3",{class:"card-title"},"实时日志",-1)),v(y(pe),{text:"",size:"tiny",onClick:x(nn,["stop"]),style:{"margin-left":"auto"},title:"清空日志"},{icon:h(()=>[v(y(ie),{size:14},{default:h(()=>[v(y(ce))]),_:1})]),_:1})]),d("div",La,[d("div",Ia,[d("div",{class:b(["logs-table-header",`logs-header-${e.channelType}`])},[d("div",{class:b(["log-col col-channel",`col-channel-${e.channelType}`])},"渠道",2),d("div",{class:b(["log-col col-token",`col-token-${e.channelType}`])},"请求",2),d("div",{class:b(["log-col col-token",`col-token-${e.channelType}`])},"回复",2),"claude"===e.channelType?(u(),i(k,{key:0},[d("div",{class:b(["log-col col-token",`col-token-${e.channelType}`])},"写入",2),d("div",{class:b(["log-col col-token",`col-token-${e.channelType}`])},"命中",2)],64)):"codex"===e.channelType?(u(),i(k,{key:1},[d("div",{class:b(["log-col col-token",`col-token-${e.channelType}`])},"推理",2),d("div",{class:b(["log-col col-token",`col-token-${e.channelType}`])},"缓存",2)],64)):"gemini"===e.channelType?(u(),i(k,{key:2},[d("div",{class:b(["log-col col-token",`col-token-${e.channelType}`])},"缓存",2),d("div",{class:b(["log-col col-token",`col-token-${e.channelType}`])},"总计",2)],64)):"opencode"===e.channelType?(u(),i(k,{key:3},[d("div",{class:b(["log-col col-token",`col-token-${e.channelType}`])},"缓存",2),d("div",{class:b(["log-col col-token",`col-token-${e.channelType}`])},"总计",2)],64)):r("",!0),d("div",{class:b(["log-col col-time",`col-time-${e.channelType}`])},"时间",2)],2),d("div",{class:"logs-container",ref_key:"logsContainer",ref:Ml},[0===Fl.value.length?(u(),i("div",Oa,[v(y(ie),{size:32,depth:"3",style:{"margin-bottom":"8px"}},{default:h(()=>[v(y(se))]),_:1}),v(y(ue),{depth:"3",style:{"font-size":"12px","font-weight":"500"}},{default:h(()=>[...l[31]||(l[31]=[f("暂无实时日志",-1)])]),_:1}),v(y(ue),{depth:"3",style:{"font-size":"11px","margin-top":"4px"}},{default:h(()=>[...l[32]||(l[32]=[f("开启代理后将显示请求记录",-1)])]),_:1})])):r("",!0),(u(!0),i(k,null,T(Fl.value,a=>{var l,n,s,c,t,o,p,g,T,x;return u(),i("div",{key:a.id,class:b(["log-row",{"action-row":"action"===a.type,"new-log":a.isNew}])},["action"===a.type?(u(),i("div",ja,[v(y(ie),{size:12,color:"#18a058"},{default:h(()=>[v(y(te))]),_:1}),d("span",Ma,m(a.message),1),d("span",Na,m(a.time),1)])):(u(),i(k,{key:1},[d("div",{class:b(["log-col col-channel",`col-channel-${e.channelType}`])},[v(y(re),{size:"tiny",type:"success"},{default:h(()=>[f(m(a.channel),1)]),_:2},1024)],2),d("div",{class:b(["log-col col-token",`col-token-${e.channelType}`])},m((null==(l=a.tokens)?void 0:l.input)||0),3),d("div",{class:b(["log-col col-token",`col-token-${e.channelType}`])},m((null==(n=a.tokens)?void 0:n.output)||0),3),"claude"===e.channelType?(u(),i(k,{key:0},[d("div",{class:b(["log-col col-token",`col-token-${e.channelType}`])},m((null==(s=a.tokens)?void 0:s.cacheCreation)||0),3),d("div",{class:b(["log-col col-token",`col-token-${e.channelType}`])},m((null==(c=a.tokens)?void 0:c.cacheRead)||0),3)],64)):"codex"===e.channelType?(u(),i(k,{key:1},[d("div",{class:b(["log-col col-token",`col-token-${e.channelType}`])},m((null==(t=a.tokens)?void 0:t.reasoning)||0),3),d("div",{class:b(["log-col col-token",`col-token-${e.channelType}`])},m((null==(o=a.tokens)?void 0:o.cached)||0),3)],64)):"gemini"===e.channelType?(u(),i(k,{key:2},[d("div",{class:b(["log-col col-token",`col-token-${e.channelType}`])},m((null==(p=a.tokens)?void 0:p.cached)||0),3),d("div",{class:b(["log-col col-token",`col-token-${e.channelType}`])},m((null==(g=a.tokens)?void 0:g.total)||0),3)],64)):"opencode"===e.channelType?(u(),i(k,{key:3},[d("div",{class:b(["log-col col-token",`col-token-${e.channelType}`])},m((null==(T=a.tokens)?void 0:T.cached)||0),3),d("div",{class:b(["log-col col-token",`col-token-${e.channelType}`])},m((null==(x=a.tokens)?void 0:x.total)||0),3)],64)):r("",!0),d("div",{class:b(["log-col col-time",`col-time-${e.channelType}`])},m(a.time),3)],64))],2)}),128))],512)])])])):r("",!0)])),ql.value?(u(),i("div",{key:1,class:b(["locked-overlay",`locked-${e.channelType}`])},[d("div",Aa,[d("div",Fa,[v(y(ie),{size:48},{default:h(()=>[v(y(W))]),_:1})]),l[34]||(l[34]=d("h3",{class:"locked-title"},"该渠道已锁定",-1)),v(y(ue),{depth:"3",class:"locked-hint"},{default:h(()=>[...l[33]||(l[33]=[f(" 点击上方按钮解锁以查看内容 ",-1)])]),_:1})])],2)):r("",!0),v(z,{visible:kl.value,"onUpdate:visible":l[2]||(l[2]=e=>kl.value=e),channel:e.channelType},null,8,["visible","channel"])]);var s,c}}},[["__scopeId","data-v-dbbe466d"]]),Da=n({theme:"light",panelVisibility:{showChannels:!0,showLogs:!0},channelLocks:{claude:!1,codex:!1,gemini:!1},channelCollapse:{claude:[],codex:[],gemini:[]},channelOrder:{claude:[],codex:[],gemini:[]}});let Ea=!1,Va=null;async function Ja(){return Ea?Da.value:Va||(Va=(async()=>{try{const e=await j();e.success&&e.config&&(Da.value=e.config,Ea=!0)}catch(e){}finally{Va=null}return Da.value})(),Va)}const Ga={class:"dashboard-container"},Ka="dashboardChannelOrder",Ra=_({__name:"Home",setup(a){const l=["claude","codex","gemini","opencode"],{uiConfig:s,updateConfig:t,loadUIConfig:o}=(Ea||Ja(),{uiConfig:Da,loadUIConfig:Ja,saveConfig:async function(e){try{const a=await J(e);return!!a.success&&(Da.value=a.config,!0)}catch(a){return!1}},updateConfig:async function(e,a){try{const l=await V(e,a);return!!l.success&&(Da.value=l.config,!0)}catch(l){return!1}},updateNestedConfig:async function(e,a,l){try{const n=await E(e,a,l);return!!n.success&&(Da.value=n.config,!0)}catch(n){return!1}}});function d(e){try{localStorage.setItem(Ka,JSON.stringify(e))}catch(a){}}const r=n(function(){try{const e=localStorage.getItem(Ka);if(e){const a=JSON.parse(e);if(Array.isArray(a)&&4===a.length)return a}}catch(e){}return l}().map(e=>({type:e})));async function g(){const e=r.value.map(e=>e.type);d(e),await t("dashboardChannelOrder",e)}return c(async()=>{if(await o(),s.value.dashboardChannelOrder&&Array.isArray(s.value.dashboardChannelOrder)&&4===s.value.dashboardChannelOrder.length){const e=s.value.dashboardChannelOrder;r.value=e.map(e=>({type:e})),d(e)}}),(a,l)=>(u(),i("div",Ga,[v(y(e),{modelValue:r.value,"onUpdate:modelValue":l[0]||(l[0]=e=>r.value=e),class:"dashboard-grid","item-key":"type",animation:200,handle:".drag-handle",onEnd:g},{item:h(({element:e})=>[(u(),p(Ua,{"channel-type":e.type,key:e.type},null,8,["channel-type"]))]),_:1},8,["modelValue"])]))}},[["__scopeId","data-v-06100f0f"]]);export{Ra as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.channel-column[data-v-dbbe466d]{display:flex;flex-direction:column;height:100%;min-height:0;background:var(--gradient-card);border:1px solid var(--border-primary);border-radius:8px;overflow:hidden;box-shadow:var(--shadow-sm)}.channel-header[data-v-dbbe466d]{display:flex;align-items:center;gap:10px;padding:12px 14px;background:var(--bg-primary);position:relative}.drag-handle[data-v-dbbe466d]{cursor:grab;color:var(--text-tertiary);display:flex;align-items:center;padding:4px;margin:-4px 0 -4px -4px;border-radius:4px;transition:all .2s}.drag-handle[data-v-dbbe466d]:hover{color:var(--text-secondary);background:var(--bg-tertiary)}.drag-handle[data-v-dbbe466d]:active{cursor:grabbing}.channel-header[data-v-dbbe466d]:after{content:"";position:absolute;bottom:0;left:14px;right:14px;height:2px;border-radius:1px}.channel-header.claude[data-v-dbbe466d]{background:linear-gradient(135deg,rgba(24,160,88,.08) 0%,transparent 100%)}.channel-header.claude[data-v-dbbe466d]:after{background:linear-gradient(90deg,#18a058,#18a0584d)}.channel-header.codex[data-v-dbbe466d]{background:linear-gradient(135deg,rgba(59,130,246,.08) 0%,transparent 100%)}.channel-header.codex[data-v-dbbe466d]:after{background:linear-gradient(90deg,#3b82f6,#3b82f64d)}.channel-header.gemini[data-v-dbbe466d]{background:linear-gradient(135deg,rgba(168,85,247,.08) 0%,transparent 100%)}.channel-header.gemini[data-v-dbbe466d]:after{background:linear-gradient(90deg,#a855f7,#a855f74d)}.channel-header.opencode[data-v-dbbe466d]{background:linear-gradient(135deg,rgba(234,88,12,.08) 0%,transparent 100%)}.channel-header.opencode[data-v-dbbe466d]:after{background:linear-gradient(90deg,#ea580c,#ea580c4d)}.header-icon[data-v-dbbe466d]{width:32px;height:32px;border-radius:6px;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 8px #0000001a}.channel-header.claude .header-icon[data-v-dbbe466d]{background:linear-gradient(135deg,#18a058,#15803d);color:#fff}.channel-header.codex .header-icon[data-v-dbbe466d]{background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff}.channel-header.gemini .header-icon[data-v-dbbe466d]{background:linear-gradient(135deg,#a855f7,#9333ea);color:#fff}.channel-header.opencode .header-icon[data-v-dbbe466d]{background:linear-gradient(135deg,#ea580c,#c2410c);color:#fff}.channel-title[data-v-dbbe466d]{font-size:15px;font-weight:700;margin:0;color:var(--text-primary);letter-spacing:.3px}.channel-content[data-v-dbbe466d]{flex:1;min-height:0;overflow:hidden;padding:10px;display:flex;flex-direction:column;gap:8px}.card[data-v-dbbe466d]{background:var(--bg-primary);border:1px solid var(--border-primary);border-radius:8px;overflow:hidden;transition:all .3s cubic-bezier(.4,0,.2,1);box-shadow:0 2px 12px #0000000d;position:relative}.card[data-v-dbbe466d]:before{content:"";position:absolute;top:0;left:0;right:0;height:1px;background:linear-gradient(90deg,transparent,rgba(255,255,255,.1),transparent);opacity:0;transition:opacity .3s ease}.card[data-v-dbbe466d]:hover{box-shadow:0 6px 20px #0000001a;border-color:var(--border-secondary)}.card[data-v-dbbe466d]:hover:before{opacity:1}.card.clickable[data-v-dbbe466d]{cursor:pointer}.card.clickable[data-v-dbbe466d]:hover{border-color:#18a058;transform:translateY(-2px);box-shadow:0 8px 24px #18a0582e}.card.clickable[data-v-dbbe466d]:after{content:"";position:absolute;top:0;right:0;bottom:0;left:0;background:linear-gradient(135deg,rgba(24,160,88,.02) 0%,transparent 100%);opacity:0;transition:opacity .3s ease;pointer-events:none}.card.clickable[data-v-dbbe466d]:hover:after{opacity:1}.card-header[data-v-dbbe466d]{display:flex;align-items:center;gap:8px;padding:10px 12px;background:linear-gradient(180deg,var(--bg-secondary) 0%,var(--bg-primary) 100%);border-bottom:1px solid var(--border-primary);position:relative;min-height:24px}.card-header.compact[data-v-dbbe466d]{padding:8px 12px}.card-header .n-icon[data-v-dbbe466d]{color:var(--text-tertiary);transition:color .2s ease}.card:hover .card-header .n-icon[data-v-dbbe466d]{color:var(--text-secondary)}.card-title[data-v-dbbe466d]{font-size:11px;font-weight:700;margin:0;color:var(--text-secondary);text-transform:uppercase;letter-spacing:.8px}.runtime-badge[data-v-dbbe466d]{display:inline-flex;align-items:center;padding:3px 8px;margin-left:8px;font-size:10px;font-weight:600;color:#10b981;background:linear-gradient(135deg,#10b9811a,#34d3991a);border:1px solid rgba(16,185,129,.2);border-radius:4px;white-space:nowrap;animation:pulse-runtime-dbbe466d 2s ease-in-out infinite}@keyframes pulse-runtime-dbbe466d{0%,to{opacity:1;transform:scale(1)}50%{opacity:.8;transform:scale(.98)}}.card-body[data-v-dbbe466d]{padding:12px;background:var(--bg-primary)}.card-body.compact[data-v-dbbe466d]{padding:10px 12px}.proxy-control[data-v-dbbe466d]{display:flex;justify-content:space-between;align-items:center;gap:16px}.proxy-info[data-v-dbbe466d]{display:flex;flex-direction:column;gap:4px}.proxy-info-row[data-v-dbbe466d]{display:flex;align-items:center;justify-content:space-between}.proxy-status[data-v-dbbe466d]{display:flex;align-items:center;gap:6px}.proxy-port[data-v-dbbe466d]{font-size:11px;color:var(--text-secondary);margin-left:6px}.channel-selector[data-v-dbbe466d]{display:flex;align-items:center;padding:4px 8px;background:linear-gradient(135deg,var(--bg-secondary) 0%,var(--bg-tertiary) 100%);border:1px solid var(--border-primary);border-radius:4px;color:var(--text-secondary);transition:all .2s ease}.channel-selector[data-v-dbbe466d]:hover{background:var(--hover-bg);border-color:var(--border-secondary);color:var(--text-primary)}.channel-selector[data-v-dbbe466d]:disabled{opacity:.5;cursor:not-allowed}.channel-name[data-v-dbbe466d]{font-size:11px;font-weight:500;max-width:90px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.status-dot[data-v-dbbe466d]{width:8px;height:8px;border-radius:50%;background:var(--border-secondary);transition:all .3s ease}.status-dot.active[data-v-dbbe466d]{background:#18a058;box-shadow:0 0 8px #18a05880}.quick-stats[data-v-dbbe466d]{display:flex;gap:16px;padding:4px 0}.stat-item[data-v-dbbe466d]{flex:1;display:flex;flex-direction:column;align-items:center;gap:2px;padding:4px 0}.stat-divider[data-v-dbbe466d]{width:1px;background:linear-gradient(180deg,transparent 0%,var(--border-primary) 50%,transparent 100%)}.quick-access-list[data-v-dbbe466d]{display:grid;grid-template-columns:repeat(3,1fr);gap:6px}.access-card[data-v-dbbe466d]{display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:6px;background:var(--bg-secondary);border:1px solid var(--border-color);transition:all .3s cubic-bezier(.4,0,.2,1);position:relative;min-height:52px;overflow:hidden}.access-card[data-v-dbbe466d]:before{content:"";position:absolute;top:0;right:0;bottom:0;left:0;opacity:0;transition:opacity .3s ease;pointer-events:none}.access-icon[data-v-dbbe466d]{width:32px;height:32px;border-radius:5px;display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:all .3s ease}.access-content[data-v-dbbe466d]{display:flex;flex-direction:column;gap:4px;flex:1}.access-card-projects .access-icon[data-v-dbbe466d]{background:linear-gradient(135deg,#6366f126,#8b5cf626);color:#6366f1}.access-card-projects[data-v-dbbe466d]:before{background:linear-gradient(135deg,#6366f114,#8b5cf614)}.access-card-projects:hover .access-icon[data-v-dbbe466d]{background:linear-gradient(135deg,#6366f140,#8b5cf640);transform:scale(1.1) rotate(-5deg)}.access-card-sessions .access-icon[data-v-dbbe466d]{background:linear-gradient(135deg,#10b98126,#05966926);color:#10b981}.access-card-sessions[data-v-dbbe466d]:before{background:linear-gradient(135deg,#10b98114,#05966914)}.access-card-sessions:hover .access-icon[data-v-dbbe466d]{background:linear-gradient(135deg,#10b98140,#05966940);transform:scale(1.1) rotate(5deg)}.access-card-goto .access-icon[data-v-dbbe466d]{background:linear-gradient(135deg,#f59e0b26,#fb923c26);color:#f59e0b}.access-card-goto[data-v-dbbe466d]:before{background:linear-gradient(135deg,#f59e0b14,#fb923c14)}.access-card-goto:hover .access-icon[data-v-dbbe466d]{background:linear-gradient(135deg,#f59e0b40,#fb923c40);transform:scale(1.1) translate(3px)}.access-card.clickable[data-v-dbbe466d]:hover{transform:translateY(-2px);box-shadow:0 8px 20px #0000001a;border-color:var(--border-secondary)}.access-card.clickable[data-v-dbbe466d]:hover:before{opacity:1}.access-card.clickable[data-v-dbbe466d]:active{transform:translateY(0)}.access-label[data-v-dbbe466d]{display:block;font-size:10px;font-weight:600;color:var(--text-secondary);text-transform:uppercase;letter-spacing:.3px}.access-value[data-v-dbbe466d]{display:block;font-size:18px;font-weight:800;color:var(--text-primary);line-height:1}.access-goto[data-v-dbbe466d]{display:block;font-size:12px;font-weight:700;color:var(--text-primary);line-height:1.2;white-space:nowrap}.stats-inline[data-v-dbbe466d]{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}.stats-inline.stats-3col[data-v-dbbe466d]{grid-template-columns:repeat(3,1fr)}.stat-inline-item[data-v-dbbe466d]{display:flex;align-items:center;gap:8px;padding:10px;background:var(--bg-secondary);border-radius:6px;border:1px solid var(--border-primary);transition:all .2s ease}.stat-inline-item[data-v-dbbe466d]:hover{border-color:var(--border-secondary);background:var(--hover-bg)}.stat-icon-dot[data-v-dbbe466d]{width:8px;height:8px;border-radius:50%;flex-shrink:0}.stat-icon-dot.requests[data-v-dbbe466d]{background:#3b82f6;box-shadow:0 0 6px #3b82f680}.stat-icon-dot.tokens[data-v-dbbe466d]{background:#18a058;box-shadow:0 0 6px #18a05880}.stat-icon-dot.cost[data-v-dbbe466d]{background:#f59e0b;box-shadow:0 0 6px #f59e0b80}.stat-info[data-v-dbbe466d]{display:flex;flex-direction:column;gap:1px;min-width:0}.stat-label[data-v-dbbe466d]{font-size:10px;color:var(--text-tertiary);font-weight:500;text-transform:uppercase;letter-spacing:.2px}.stat-value[data-v-dbbe466d]{font-size:16px;font-weight:700;color:var(--text-primary);line-height:1.2;transition:all .3s ease}.stat-value.animating[data-v-dbbe466d]{animation:numberChange-dbbe466d .6s ease}@keyframes numberChange-dbbe466d{0%{transform:translateY(-6px);opacity:.5}50%{transform:translateY(0);opacity:1;color:var(--primary-color)}to{transform:translateY(0);opacity:1}}.stats-card[data-v-dbbe466d],.chart-card[data-v-dbbe466d]{border-left:2px solid transparent}.stats-card-claude[data-v-dbbe466d],.chart-card[data-v-dbbe466d]:has(+.stats-card-claude),.card[data-v-dbbe466d]:has(.panel-card):nth-child(4){border-left-color:#18a058}.chart-card.chart-card-claude[data-v-dbbe466d]{border-left-color:#18a058}.stats-card-codex[data-v-dbbe466d],.chart-card[data-v-dbbe466d]:has(+.stats-card-codex),.card[data-v-dbbe466d]:has(.panel-card):nth-child(4){border-left-color:#3b82f6}.chart-card.chart-card-codex[data-v-dbbe466d]{border-left-color:#3b82f6}.stats-card-gemini[data-v-dbbe466d],.chart-card[data-v-dbbe466d]:has(+.stats-card-gemini),.card[data-v-dbbe466d]:has(.panel-card):nth-child(4){border-left-color:#a855f7}.chart-card.chart-card-gemini[data-v-dbbe466d]{border-left-color:#a855f7}.stats-card-opencode[data-v-dbbe466d],.chart-card[data-v-dbbe466d]:has(+.stats-card-opencode),.card[data-v-dbbe466d]:has(.panel-card):nth-child(4){border-left-color:#ea580c}.chart-card.chart-card-opencode[data-v-dbbe466d]{border-left-color:#ea580c}.chart-card[data-v-dbbe466d]{padding:0;overflow:hidden}.chart-card[data-v-dbbe466d] .panel-card{border:none;border-radius:0;box-shadow:none;background:transparent}.stat-requests .stat-value[data-v-dbbe466d]{color:#3b82f6}.stat-input .stat-value[data-v-dbbe466d]{color:#18a058}.stat-output .stat-value[data-v-dbbe466d]{color:#f59e0b}.token-label[data-v-dbbe466d]{display:flex;align-items:center;gap:8px}.token-dot[data-v-dbbe466d]{width:8px;height:8px;border-radius:50%}.logs-card[data-v-dbbe466d]{flex:1;min-height:0;display:flex;flex-direction:column;overflow:hidden;border:1px solid var(--border-primary);border-radius:6px}.logs-card-body[data-v-dbbe466d]{flex:1;min-height:0;display:flex;flex-direction:column;padding:0}.logs-card .card-header[data-v-dbbe466d]{background:linear-gradient(135deg,var(--bg-secondary) 0%,var(--bg-tertiary) 100%)}.logs-table-wrapper[data-v-dbbe466d]{flex:1;min-height:0;display:flex;flex-direction:column;overflow:hidden;background:var(--bg-primary)}.logs-table-header[data-v-dbbe466d]{display:flex;padding:10px 12px;background:linear-gradient(180deg,var(--bg-tertiary) 0%,var(--bg-secondary) 100%);border-bottom:2px solid var(--border-primary);font-size:11px;font-weight:700;color:var(--text-tertiary);text-transform:uppercase;letter-spacing:.6px;flex-shrink:0}.logs-header-claude .log-col[data-v-dbbe466d]{color:#18a058b3;font-weight:600}.logs-header-codex .log-col[data-v-dbbe466d]{color:#3b82f6b3;font-weight:600}.logs-header-gemini .log-col[data-v-dbbe466d]{color:#a855f7b3;font-weight:600}.logs-header-opencode .log-col[data-v-dbbe466d]{color:#ea580cb3;font-weight:600}[data-theme=dark] .logs-header-claude .log-col[data-v-dbbe466d]{color:#34d399a6}[data-theme=dark] .logs-header-codex .log-col[data-v-dbbe466d]{color:#60a5faa6}[data-theme=dark] .logs-header-gemini .log-col[data-v-dbbe466d]{color:#c084fca6}[data-theme=dark] .logs-header-opencode .log-col[data-v-dbbe466d]{color:#fb923ca6}.logs-container[data-v-dbbe466d]{flex:1;min-height:0;overflow-y:auto;overflow-x:hidden}.logs-container[data-v-dbbe466d]::-webkit-scrollbar{width:4px}.logs-container[data-v-dbbe466d]::-webkit-scrollbar-thumb{background:#18a0584d;border-radius:2px}.logs-container[data-v-dbbe466d]::-webkit-scrollbar-thumb:hover{background:#18a05880}.empty-logs[data-v-dbbe466d]{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:40px 20px;color:var(--text-tertiary);min-height:200px;text-align:center}.log-row[data-v-dbbe466d]{display:flex;align-items:center;padding:10px 12px;min-height:40px;border-bottom:1px solid var(--border-primary);font-size:12px;transition:all .2s ease;background:var(--bg-primary);position:relative}.log-row[data-v-dbbe466d]:nth-child(2n){background:var(--bg-secondary)}.log-row[data-v-dbbe466d]:hover{background:var(--hover-bg);transform:translate(2px)}.log-row.new-log[data-v-dbbe466d]{animation:newLogPulse-dbbe466d 4.5s cubic-bezier(.25,.46,.45,.94) forwards;border-left:3px solid #18a058}@keyframes newLogPulse-dbbe466d{0%{background:linear-gradient(90deg,#18a05826,#18a0580f);box-shadow:0 0 8px #18a05833}5%{background:linear-gradient(90deg,#18a0582e,#18a05814);box-shadow:0 0 12px 1px #18a05840}15%{background:linear-gradient(90deg,#18a05829,#18a05812);box-shadow:0 0 10px 1px #18a05833}30%{background:linear-gradient(90deg,#18a0581f,#18a0580d);box-shadow:0 0 6px #18a05826}50%{background:linear-gradient(90deg,#18a05814,#18a05808);box-shadow:0 0 4px #18a0581a}70%{background:linear-gradient(90deg,#18a0580a,#18a05804);box-shadow:0 0 2px #18a0580f}85%{background:linear-gradient(90deg,#18a05805,#18a05802);box-shadow:0 0 1px #18a05808}to{background:transparent;box-shadow:0 0 #18a05800;border-left-color:transparent}}[data-theme=dark] .log-row.new-log[data-v-dbbe466d]{animation:newLogPulseDark-dbbe466d 4.5s cubic-bezier(.25,.46,.45,.94) forwards}@keyframes newLogPulseDark-dbbe466d{0%{background:linear-gradient(90deg,#18a05833,#18a05814);box-shadow:0 0 10px #18a05840}5%{background:linear-gradient(90deg,#18a0583d,#18a0581a);box-shadow:0 0 14px 2px #18a0584d}15%{background:linear-gradient(90deg,#18a05836,#18a05817);box-shadow:0 0 12px 1px #18a05840}30%{background:linear-gradient(90deg,#18a05829,#18a05812);box-shadow:0 0 8px 1px #18a0582e}50%{background:linear-gradient(90deg,#18a0581c,#18a0580b);box-shadow:0 0 5px #18a0581f}70%{background:linear-gradient(90deg,#18a0580f,#18a05806);box-shadow:0 0 3px #18a05814}85%{background:linear-gradient(90deg,#18a05808,#18a05803);box-shadow:0 0 1px #18a0580a}to{background:transparent;box-shadow:0 0 #18a05800;border-left-color:transparent}}.log-row.new-log.action-row[data-v-dbbe466d]{border-left:3px solid #18a058}.log-row.action-row[data-v-dbbe466d]{background:linear-gradient(90deg,#18a0581f,#18a0580a);border-left:3px solid #18a058;padding-left:8px}.log-row.action-row[data-v-dbbe466d]:hover{background:linear-gradient(90deg,#18a0582e,#18a05814)}.action-content[data-v-dbbe466d]{display:flex;align-items:center;gap:8px;width:100%}.action-msg[data-v-dbbe466d]{flex:1;font-size:11px;color:#18a058;font-weight:600;letter-spacing:.2px}.action-time[data-v-dbbe466d]{font-size:10px;font-family:SF Mono,Monaco,monospace;color:var(--text-tertiary);background:#18a0581a;padding:2px 6px;border-radius:4px}.log-col[data-v-dbbe466d]{display:flex;align-items:center;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.col-channel[data-v-dbbe466d]{min-width:0}.col-channel .n-tag[data-v-dbbe466d]{max-width:100%;font-size:11px;font-weight:600;border-radius:4px;padding:3px 10px}.col-token[data-v-dbbe466d]{justify-content:center;font-family:SF Mono,Monaco,Consolas,monospace;font-size:12px;font-weight:600;color:var(--text-secondary);background:#00000008;padding:4px 8px;border-radius:4px;margin:0 3px}[data-theme=dark] .col-token[data-v-dbbe466d]{background:#ffffff0f}.col-time[data-v-dbbe466d]{justify-content:flex-end;font-family:SF Mono,Monaco,Consolas,monospace;font-size:11px;font-weight:500;color:var(--text-tertiary);padding-right:2px;opacity:.85}.log-row:hover .col-time[data-v-dbbe466d]{opacity:1;color:var(--text-secondary)}.col-channel-claude[data-v-dbbe466d]{flex:2 1 60px;min-width:50px}.col-token-claude[data-v-dbbe466d]{flex:1 1 40px;min-width:35px}.col-time-claude[data-v-dbbe466d]{flex:1.5 1 55px;min-width:50px}.col-channel-codex[data-v-dbbe466d]{flex:2 1 60px;min-width:50px}.col-token-codex[data-v-dbbe466d]{flex:1 1 40px;min-width:35px}.col-time-codex[data-v-dbbe466d]{flex:1.5 1 55px;min-width:50px}.col-channel-gemini[data-v-dbbe466d]{flex:2.5 1 70px;min-width:55px}.col-token-gemini[data-v-dbbe466d]{flex:1.2 1 45px;min-width:40px}.col-time-gemini[data-v-dbbe466d]{flex:1.8 1 60px;min-width:55px}.col-channel-opencode[data-v-dbbe466d]{flex:2.5 1 70px;min-width:55px}.col-token-opencode[data-v-dbbe466d]{flex:1.2 1 45px;min-width:40px}.col-time-opencode[data-v-dbbe466d]{flex:1.8 1 60px;min-width:55px}.claude-extra-area[data-v-dbbe466d]{display:flex;align-items:center;gap:6px;margin-left:auto}.mcp-count-tag[data-v-dbbe466d],.skills-count-tag[data-v-dbbe466d]{font-size:10px;font-weight:500;padding:0 8px;height:22px;line-height:22px;border-radius:4px;cursor:pointer;transition:all .2s ease}.mcp-count-tag.clickable[data-v-dbbe466d]:hover,.skills-count-tag.clickable[data-v-dbbe466d]:hover{transform:scale(1.03);filter:brightness(1.1)}.mcp-quick-panel[data-v-dbbe466d],.skills-quick-panel[data-v-dbbe466d]{padding:2px 0}.mcp-quick-panel .panel-title[data-v-dbbe466d],.skills-quick-panel .panel-title[data-v-dbbe466d]{display:flex;justify-content:space-between;align-items:center;padding:6px 10px 8px;border-bottom:1px solid var(--border-primary);margin-bottom:4px}.mcp-quick-panel .panel-title span[data-v-dbbe466d]:first-child,.skills-quick-panel .panel-title span[data-v-dbbe466d]:first-child{font-size:13px;font-weight:600;color:var(--text-primary)}.no-items[data-v-dbbe466d]{padding:16px 10px;text-align:center}.mcp-quick-list[data-v-dbbe466d],.skills-quick-list[data-v-dbbe466d]{max-height:300px;overflow-y:auto;padding:0 4px 4px}.mcp-quick-item[data-v-dbbe466d],.skill-quick-item[data-v-dbbe466d]{display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:5px;margin-bottom:4px;background:var(--bg-secondary);transition:all .2s ease}.mcp-quick-item[data-v-dbbe466d]:hover,.skill-quick-item[data-v-dbbe466d]:hover{background:var(--hover-bg)}.mcp-item-icon[data-v-dbbe466d],.skill-item-icon[data-v-dbbe466d]{width:24px;height:24px;border-radius:5px;display:flex;align-items:center;justify-content:center;flex-shrink:0}.mcp-item-icon[data-v-dbbe466d]{background:linear-gradient(135deg,#3b82f626,#3b82f60d);color:#3b82f6}.skill-item-icon[data-v-dbbe466d]{background:linear-gradient(135deg,#18a05826,#18a0580d);color:#18a058}.mcp-item-info[data-v-dbbe466d],.skill-item-info[data-v-dbbe466d]{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}.mcp-item-name[data-v-dbbe466d],.skill-item-name[data-v-dbbe466d]{font-size:12px;font-weight:600;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mcp-item-type[data-v-dbbe466d]{font-size:10px;color:var(--text-tertiary);text-transform:uppercase}.skill-item-desc[data-v-dbbe466d]{font-size:10px;color:var(--text-tertiary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mcp-item-status[data-v-dbbe466d]{flex-shrink:0}.mcp-item-status .status-dot[data-v-dbbe466d]{width:8px;height:8px;border-radius:50%;background:var(--border-secondary)}.mcp-item-status.online .status-dot[data-v-dbbe466d]{background:#18a058;box-shadow:0 0 6px #18a05880}.mcp-item-status.error .status-dot[data-v-dbbe466d]{background:#d03050;box-shadow:0 0 6px #d0305080}.mcp-quick-list[data-v-dbbe466d]::-webkit-scrollbar,.skills-quick-list[data-v-dbbe466d]::-webkit-scrollbar{width:4px}.mcp-quick-list[data-v-dbbe466d]::-webkit-scrollbar-thumb,.skills-quick-list[data-v-dbbe466d]::-webkit-scrollbar-thumb{background:#00000026;border-radius:2px}[data-theme=dark] .mcp-quick-list[data-v-dbbe466d]::-webkit-scrollbar-thumb,[data-theme=dark] .skills-quick-list[data-v-dbbe466d]::-webkit-scrollbar-thumb{background:#ffffff26}.skills-button[data-v-dbbe466d]{padding:6px!important;width:30px;height:30px;display:flex;align-items:center;justify-content:center;border-radius:5px;background:var(--bg-secondary);border:1px solid var(--border-primary);transition:all .25s cubic-bezier(.4,0,.2,1);box-shadow:0 2px 4px #0000000d}.skills-button .n-icon[data-v-dbbe466d]{color:var(--text-color-3);transition:all .25s ease}.skills-button[data-v-dbbe466d]:hover{background:linear-gradient(135deg,#18a0581a,#18a0580d);border-color:#18a0584d;box-shadow:0 4px 12px #18a05826;transform:translateY(-1px)}.skills-button:hover .n-icon[data-v-dbbe466d]{color:#18a058;transform:scale(1.1)}.skills-button[data-v-dbbe466d]:active{transform:translateY(0);box-shadow:0 2px 4px #0000000d}.lock-button[data-v-dbbe466d]{margin-left:6px;padding:6px!important;width:30px;height:30px;display:flex;align-items:center;justify-content:center;border-radius:5px;background:var(--bg-secondary);border:1px solid var(--border-primary);transition:all .25s cubic-bezier(.4,0,.2,1);box-shadow:0 2px 4px #0000000d}.lock-button .n-icon[data-v-dbbe466d]{color:var(--text-color-3);transition:all .25s ease}.lock-button[data-v-dbbe466d]:hover{background:linear-gradient(135deg,#6b72801a,#6b72800d);border-color:#6b72804d;box-shadow:0 4px 12px #0000001a;transform:translateY(-1px)}.lock-button:hover .n-icon[data-v-dbbe466d]{color:var(--text-color-1);transform:scale(1.1)}.lock-button[data-v-dbbe466d]:active{transform:translateY(0);box-shadow:0 2px 4px #0000000d}.locked-overlay[data-v-dbbe466d]{flex:1;display:flex;align-items:center;justify-content:center;border-radius:6px;margin:10px;position:relative;overflow:hidden;background:var(--bg-secondary);border:1px solid var(--border-primary);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.locked-overlay[data-v-dbbe466d]:before{content:"";position:absolute;width:400px;height:400px;border-radius:50%;top:50%;left:50%;transform:translate(-50%,-50%);opacity:.4;filter:blur(60px);pointer-events:none}.locked-claude[data-v-dbbe466d]{background:linear-gradient(135deg,rgba(24,160,88,.03) 0%,var(--bg-secondary) 50%,rgba(24,160,88,.02) 100%)}.locked-claude[data-v-dbbe466d]:before{background:radial-gradient(circle,rgba(24,160,88,.15) 0%,transparent 70%)}.locked-codex[data-v-dbbe466d]{background:linear-gradient(135deg,rgba(59,130,246,.03) 0%,var(--bg-secondary) 50%,rgba(59,130,246,.02) 100%)}.locked-codex[data-v-dbbe466d]:before{background:radial-gradient(circle,rgba(59,130,246,.15) 0%,transparent 70%)}.locked-gemini[data-v-dbbe466d]{background:linear-gradient(135deg,rgba(168,85,247,.03) 0%,var(--bg-secondary) 50%,rgba(168,85,247,.02) 100%)}.locked-gemini[data-v-dbbe466d]:before{background:radial-gradient(circle,rgba(168,85,247,.15) 0%,transparent 70%)}.locked-opencode[data-v-dbbe466d]{background:linear-gradient(135deg,rgba(234,88,12,.03) 0%,var(--bg-secondary) 50%,rgba(234,88,12,.02) 100%)}.locked-opencode[data-v-dbbe466d]:before{background:radial-gradient(circle,rgba(234,88,12,.15) 0%,transparent 70%)}.locked-content[data-v-dbbe466d]{display:flex;flex-direction:column;align-items:center;gap:20px;padding:60px 40px;text-align:center;position:relative;z-index:1}.lock-icon[data-v-dbbe466d]{width:96px;height:96px;display:flex;align-items:center;justify-content:center;border-radius:10px;background:var(--bg-primary);border:2px solid var(--border-primary);margin-bottom:8px;position:relative;box-shadow:0 8px 24px #0000001f;animation:lock-float-dbbe466d 3s ease-in-out infinite}@keyframes lock-float-dbbe466d{0%,to{transform:translateY(0)}50%{transform:translateY(-6px)}}.lock-icon[data-v-dbbe466d]:before{content:"";position:absolute;top:-8px;right:-8px;bottom:-8px;left:-8px;border-radius:20px;opacity:.6;filter:blur(12px)}.locked-claude .lock-icon[data-v-dbbe466d]{background:linear-gradient(135deg,rgba(24,160,88,.12) 0%,var(--bg-primary) 100%);border-color:#18a05840;box-shadow:0 8px 24px #18a05826,0 0 0 1px #18a0581a inset}.locked-claude .lock-icon[data-v-dbbe466d]:before{background:radial-gradient(circle,rgba(24,160,88,.3) 0%,transparent 60%)}.locked-claude .lock-icon .n-icon[data-v-dbbe466d]{color:#18a058;filter:drop-shadow(0 2px 4px rgba(24,160,88,.3))}.locked-codex .lock-icon[data-v-dbbe466d]{background:linear-gradient(135deg,rgba(59,130,246,.12) 0%,var(--bg-primary) 100%);border-color:#3b82f640;box-shadow:0 8px 24px #3b82f626,0 0 0 1px #3b82f61a inset}.locked-codex .lock-icon[data-v-dbbe466d]:before{background:radial-gradient(circle,rgba(59,130,246,.3) 0%,transparent 60%)}.locked-codex .lock-icon .n-icon[data-v-dbbe466d]{color:#3b82f6;filter:drop-shadow(0 2px 4px rgba(59,130,246,.3))}.locked-gemini .lock-icon[data-v-dbbe466d]{background:linear-gradient(135deg,rgba(168,85,247,.12) 0%,var(--bg-primary) 100%);border-color:#a855f740;box-shadow:0 8px 24px #a855f726,0 0 0 1px #a855f71a inset}.locked-gemini .lock-icon[data-v-dbbe466d]:before{background:radial-gradient(circle,rgba(168,85,247,.3) 0%,transparent 60%)}.locked-gemini .lock-icon .n-icon[data-v-dbbe466d]{color:#a855f7;filter:drop-shadow(0 2px 4px rgba(168,85,247,.3))}.locked-opencode .lock-icon[data-v-dbbe466d]{background:linear-gradient(135deg,rgba(234,88,12,.12) 0%,var(--bg-primary) 100%);border-color:#ea580c40;box-shadow:0 8px 24px #ea580c26,0 0 0 1px #ea580c1a inset}.locked-opencode .lock-icon[data-v-dbbe466d]:before{background:radial-gradient(circle,rgba(234,88,12,.3) 0%,transparent 60%)}.locked-opencode .lock-icon .n-icon[data-v-dbbe466d]{color:#ea580c;filter:drop-shadow(0 2px 4px rgba(234,88,12,.3))}.lock-icon .n-icon[data-v-dbbe466d]{opacity:.85;position:relative;z-index:1}.locked-title[data-v-dbbe466d]{font-size:17px;font-weight:600;color:var(--text-color-1);margin:0;letter-spacing:.3px}.locked-hint[data-v-dbbe466d]{font-size:13px;color:var(--text-color-3);max-width:220px;line-height:1.7;opacity:.9}.channel-status[data-v-dbbe466d]{cursor:pointer;padding:4px 8px!important;border-radius:4px;transition:all .2s ease}.channel-status[data-v-dbbe466d]:hover{background:var(--hover-bg)}.channel-quick-panel[data-v-dbbe466d]{padding:4px 0}.panel-title[data-v-dbbe466d]{display:flex;justify-content:space-between;align-items:center;padding:8px 12px 12px;border-bottom:1px solid var(--border-primary);margin-bottom:8px}.panel-title span[data-v-dbbe466d]:first-child{font-size:13px;font-weight:600;color:var(--text-primary)}.no-channels[data-v-dbbe466d]{padding:24px 12px;text-align:center}.channel-quick-list[data-v-dbbe466d]{max-height:360px;overflow-y:auto}.channel-quick-item[data-v-dbbe466d]{display:flex;flex-direction:column;gap:8px;padding:10px 12px;border-radius:6px;margin:0 4px 6px;background:var(--bg-secondary);transition:all .2s ease}.channel-quick-item[data-v-dbbe466d]:hover{background:var(--hover-bg)}.channel-quick-item.disabled[data-v-dbbe466d]{opacity:.6}.channel-quick-info[data-v-dbbe466d]{display:flex;align-items:center;gap:8px;width:100%}.channel-quick-name[data-v-dbbe466d]{font-size:13px;font-weight:600;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.channel-metrics[data-v-dbbe466d]{display:flex;gap:6px;width:100%}.channel-metrics .metric-item[data-v-dbbe466d]{flex:1;display:flex;flex-direction:column;align-items:center;gap:2px;padding:6px 4px;background:var(--bg-primary);border-radius:4px;border:1px solid var(--border-primary)}.channel-metrics .metric-label[data-v-dbbe466d]{font-size:10px;color:var(--text-tertiary);font-weight:500}.channel-metrics .metric-value[data-v-dbbe466d]{font-size:12px;font-weight:700;color:var(--text-primary);font-family:SF Mono,Monaco,monospace}.channel-metrics .metric-value.active[data-v-dbbe466d]{color:#f59e0b}.channel-switching-tip[data-v-dbbe466d]{font-size:11px;color:var(--text-tertiary);padding:0 2px}.channel-quick-item.disabled .channel-metrics .metric-value[data-v-dbbe466d]{color:var(--text-tertiary)}.channel-quick-list[data-v-dbbe466d]::-webkit-scrollbar{width:4px}.channel-quick-list[data-v-dbbe466d]::-webkit-scrollbar-thumb{background:#00000026;border-radius:2px}[data-theme=dark] .channel-quick-list[data-v-dbbe466d]::-webkit-scrollbar-thumb{background:#ffffff26}@media (max-width: 1024px){.channel-column[data-v-dbbe466d]{border-radius:6px}.card-header[data-v-dbbe466d]{padding:8px 10px}.card-title[data-v-dbbe466d]{font-size:13px}.stats-inline[data-v-dbbe466d]{gap:6px}.stat-inline-item[data-v-dbbe466d]{padding:8px}.stat-value[data-v-dbbe466d]{font-size:14px}.stat-label[data-v-dbbe466d]{font-size:9px}.logs-table-header[data-v-dbbe466d]{padding:8px 10px;font-size:10px}.log-row[data-v-dbbe466d]{padding:8px 10px;font-size:11px}}@media (max-width: 768px){.channel-column[data-v-dbbe466d]{border-radius:6px;min-height:300px;height:auto;max-height:400px}.card-header[data-v-dbbe466d]{padding:8px;gap:6px}.card-title[data-v-dbbe466d]{font-size:12px}.stats-inline[data-v-dbbe466d]{gap:4px}.stat-inline-item[data-v-dbbe466d]{padding:6px;gap:6px}.stat-icon-dot[data-v-dbbe466d]{width:6px;height:6px}.stat-value[data-v-dbbe466d]{font-size:13px}.stat-label[data-v-dbbe466d]{font-size:8px}.logs-card[data-v-dbbe466d]{min-height:150px}.logs-table-header[data-v-dbbe466d]{padding:6px 8px;font-size:9px}.log-row[data-v-dbbe466d]{padding:6px 8px;font-size:10px;min-height:32px}.col-token[data-v-dbbe466d]{font-size:10px;padding:2px 4px}.col-time[data-v-dbbe466d]{font-size:9px}.mcp-count-tag[data-v-dbbe466d],.skills-count-tag[data-v-dbbe466d]{font-size:9px;padding:0 6px;height:18px;line-height:18px}.skills-button[data-v-dbbe466d]{padding:4px 8px;font-size:10px;gap:4px}.lock-button[data-v-dbbe466d]{width:26px;height:26px}}@media (max-width: 640px){.channel-column[data-v-dbbe466d]{min-height:250px;max-height:350px}.card-header[data-v-dbbe466d]{padding:6px;gap:4px;flex-wrap:wrap}.card-title[data-v-dbbe466d]{font-size:11px}.stats-card .card-content[data-v-dbbe466d]{padding:6px}.stats-inline[data-v-dbbe466d]{gap:3px;flex-wrap:wrap}.stat-inline-item[data-v-dbbe466d]{padding:5px;gap:4px;min-width:calc(33% - 3px);flex:1 1 auto}.stat-icon-dot[data-v-dbbe466d]{width:5px;height:5px}.stat-value[data-v-dbbe466d]{font-size:12px}.stat-label[data-v-dbbe466d]{font-size:7px}.logs-card[data-v-dbbe466d]{min-height:120px}.logs-table-header[data-v-dbbe466d]{padding:5px 6px;font-size:8px;letter-spacing:.3px}.log-row[data-v-dbbe466d]{padding:5px 6px;font-size:9px;min-height:28px}.col-channel .n-tag[data-v-dbbe466d]{font-size:9px;padding:2px 6px}.col-token[data-v-dbbe466d]{font-size:9px;padding:2px 3px;margin:0 1px}.col-time[data-v-dbbe466d]{font-size:8px}.claude-extra-area[data-v-dbbe466d]{gap:4px}.mcp-count-tag[data-v-dbbe466d],.skills-count-tag[data-v-dbbe466d]{font-size:8px;padding:0 4px;height:16px;line-height:16px}.skills-button[data-v-dbbe466d]{padding:3px 6px;font-size:9px;gap:3px}.skills-button .n-icon[data-v-dbbe466d]{font-size:12px!important}.lock-button[data-v-dbbe466d]{width:24px;height:24px;margin-left:4px}.lock-button .n-icon[data-v-dbbe466d]{font-size:12px!important}.locked-content[data-v-dbbe466d]{padding:30px 20px;gap:12px}.lock-icon[data-v-dbbe466d]{width:64px;height:64px}.lock-icon .n-icon[data-v-dbbe466d]{font-size:28px!important}.lock-title[data-v-dbbe466d]{font-size:14px}.lock-subtitle[data-v-dbbe466d]{font-size:10px}.unlock-btn[data-v-dbbe466d]{padding:8px 16px;font-size:11px}}@media (max-width: 480px){.channel-column[data-v-dbbe466d]{min-height:220px;max-height:300px}.card-header[data-v-dbbe466d]{padding:5px}.card-title[data-v-dbbe466d]{font-size:10px}.stats-inline[data-v-dbbe466d]{gap:2px}.stat-inline-item[data-v-dbbe466d]{padding:4px;gap:3px}.stat-value[data-v-dbbe466d]{font-size:11px}.stat-label[data-v-dbbe466d]{font-size:6px}.logs-table-header[data-v-dbbe466d]{padding:4px 5px;font-size:7px}.log-row[data-v-dbbe466d]{padding:4px 5px;font-size:8px;min-height:24px}.col-token[data-v-dbbe466d]{font-size:8px}.col-time[data-v-dbbe466d]{font-size:7px}}.card[data-v-dbbe466d]:not(.logs-card) .n-collapse{background:transparent}.card[data-v-dbbe466d]:not(.logs-card) .n-collapse-item{background:transparent}.card[data-v-dbbe466d] .n-collapse-item__header{padding:12px 16px;background:transparent;transition:all .3s ease}.card[data-v-dbbe466d] .n-collapse-item__header:hover{background:#00000005}.card[data-v-dbbe466d] .n-collapse-item__header-main{width:100%}.card[data-v-dbbe466d]:not(.logs-card) .n-collapse-item__content-wrapper{padding:0 16px 12px}.card[data-v-dbbe466d]:not(.logs-card) .n-collapse-item__content-inner{padding-top:0}.chart-card[data-v-dbbe466d]:has(.n-collapse){padding:0}.dashboard-container[data-v-06100f0f]{height:100%;background:var(--bg-primary);overflow:hidden;padding:12px;box-sizing:border-box;display:flex;flex-direction:column}.dashboard-toolbar[data-v-06100f0f]{display:flex;justify-content:flex-end;margin-bottom:8px;flex-shrink:0}.analytics-link[data-v-06100f0f]{display:inline-flex;align-items:center;gap:5px;font-size:12px;color:var(--primary-color, #18a058);text-decoration:none;padding:4px 10px;border-radius:4px;background:#18a05814;transition:background .2s}.analytics-link[data-v-06100f0f]:hover{background:#18a05826}.analytics-link-icon[data-v-06100f0f]{font-size:14px}.dashboard-grid[data-v-06100f0f]{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;flex:1;min-height:0;overflow:hidden;box-sizing:border-box}.dashboard-grid[data-v-06100f0f] .sortable-ghost{opacity:.4}.dashboard-grid[data-v-06100f0f] .sortable-chosen{box-shadow:0 8px 24px #00000026}@media (max-width: 1600px){.dashboard-grid[data-v-06100f0f]{grid-template-columns:repeat(3,1fr)}}@media (max-width: 1200px){.dashboard-grid[data-v-06100f0f]{grid-template-columns:repeat(2,1fr)}}@media (max-width: 1024px){.dashboard-container[data-v-06100f0f]{padding:10px}.dashboard-grid[data-v-06100f0f]{gap:10px}}@media (max-width: 900px){.dashboard-grid[data-v-06100f0f]{grid-template-columns:1fr}}@media (max-width: 768px){.dashboard-container[data-v-06100f0f]{padding:8px;overflow-y:auto}.dashboard-grid[data-v-06100f0f]{gap:8px;overflow:visible;min-height:auto}}@media (max-width: 640px){.dashboard-container[data-v-06100f0f]{padding:6px}.dashboard-grid[data-v-06100f0f]{gap:6px}}@media (max-width: 480px){.dashboard-container[data-v-06100f0f]{padding:4px}.dashboard-grid[data-v-06100f0f]{gap:4px}}
|