coding-tool-x 3.6.13 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/README.md +46 -33
  2. package/dist/web/assets/{Analytics-CnA75GxO.js → Analytics-Dma_j2Rq.js} +1 -1
  3. package/dist/web/assets/{ConfigTemplates-D8XEscQY.js → ConfigTemplates-C49Y1PLH.js} +1 -1
  4. package/dist/web/assets/Home-DGGC8H4g.js +1 -0
  5. package/dist/web/assets/Home-ewgeIhF7.css +1 -0
  6. package/dist/web/assets/{PluginManager-BzKZ8TYu.js → PluginManager-B1ECTHyY.js} +1 -1
  7. package/dist/web/assets/{ProjectList-DL4JK6ci.css → ProjectList-B_L55-l9.css} +1 -1
  8. package/dist/web/assets/ProjectList-DyiGyT-H.js +1 -0
  9. package/dist/web/assets/SessionList-CH5GwwiJ.js +1 -0
  10. package/dist/web/assets/{SkillManager-fxOvFTYD.js → SkillManager-CRyVhjYQ.js} +1 -1
  11. package/dist/web/assets/{WorkspaceManager-Ch2mM8jm.js → WorkspaceManager-CO9tclVt.js} +1 -1
  12. package/dist/web/assets/{icons-QFXzEgqM.js → icons-Dop5j7Bf.js} +1 -1
  13. package/dist/web/assets/index-CM26UrnJ.css +1 -0
  14. package/dist/web/assets/index-EQq56pRa.js +2 -0
  15. package/dist/web/assets/{naive-ui-kcWDeJwl.js → naive-ui-CVyvdmg1.js} +1 -1
  16. package/dist/web/index.html +4 -4
  17. package/package.json +2 -1
  18. package/src/commands/channels.js +85 -24
  19. package/src/commands/daemon.js +7 -4
  20. package/src/commands/doctor.js +17 -8
  21. package/src/commands/logs.js +48 -6
  22. package/src/commands/port-config.js +83 -75
  23. package/src/commands/proxy-control.js +52 -19
  24. package/src/commands/stats.js +37 -19
  25. package/src/commands/switch.js +5 -1
  26. package/src/commands/toggle-proxy.js +131 -53
  27. package/src/commands/ui.js +3 -4
  28. package/src/commands/workspace.js +3 -35
  29. package/src/config/default.js +19 -2
  30. package/src/config/loader.js +5 -76
  31. package/src/config/paths.js +99 -11
  32. package/src/index.js +11 -16
  33. package/src/server/api/commands.js +1 -1
  34. package/src/server/api/config-export.js +4 -2
  35. package/src/server/api/config-registry.js +40 -34
  36. package/src/server/api/config.js +5 -1
  37. package/src/server/api/dashboard.js +22 -6
  38. package/src/server/api/mcp.js +5 -3
  39. package/src/server/api/pi-channels.js +349 -0
  40. package/src/server/api/pi-config.js +164 -0
  41. package/src/server/api/pi-projects.js +76 -0
  42. package/src/server/api/pi-proxy.js +154 -0
  43. package/src/server/api/pi-sessions.js +334 -0
  44. package/src/server/api/pi-statistics.js +40 -0
  45. package/src/server/api/plugins.js +1 -1
  46. package/src/server/api/prompts.js +3 -2
  47. package/src/server/api/settings.js +2 -0
  48. package/src/server/api/skills.js +1 -1
  49. package/src/server/api/workspaces.js +3 -41
  50. package/src/server/index.js +41 -0
  51. package/src/server/pi-proxy-server.js +66 -0
  52. package/src/server/services/agents-service.js +2 -1
  53. package/src/server/services/base/proxy-utils.js +1 -0
  54. package/src/server/services/channel-balance.js +151 -1
  55. package/src/server/services/channel-scheduler.js +7 -1
  56. package/src/server/services/commands-service.js +11 -2
  57. package/src/server/services/config-export-service.js +275 -18
  58. package/src/server/services/config-registry-service.js +20 -18
  59. package/src/server/services/config-sync-manager.js +115 -6
  60. package/src/server/services/config-sync-service.js +4 -2
  61. package/src/server/services/config-templates-service.js +183 -45
  62. package/src/server/services/mcp-service.js +217 -33
  63. package/src/server/services/pi-auth-providers.js +294 -0
  64. package/src/server/services/pi-channels.js +94 -0
  65. package/src/server/services/pi-config.js +287 -0
  66. package/src/server/services/pi-sessions.js +490 -0
  67. package/src/server/services/pi-settings-manager.js +571 -0
  68. package/src/server/services/pi-statistics-service.js +317 -0
  69. package/src/server/services/plugins-service.js +673 -11
  70. package/src/server/services/prompts-service.js +112 -7
  71. package/src/server/services/proxy-log-helper.js +1 -0
  72. package/src/server/services/proxy-runtime.js +5 -1
  73. package/src/server/services/sessions.js +19 -35
  74. package/src/server/services/skill-service.js +13 -3
  75. package/src/server/services/speed-test.js +9 -3
  76. package/src/server/services/ui-config.js +50 -12
  77. package/src/server/services/workspace-service.js +117 -225
  78. package/src/server/websocket-server.js +7 -1
  79. package/src/utils/session.js +4 -10
  80. package/dist/web/assets/Home-BiaKZMah.js +0 -1
  81. package/dist/web/assets/Home-CIua-b-o.css +0 -1
  82. package/dist/web/assets/ProjectList-BPfG_92X.js +0 -1
  83. package/dist/web/assets/SessionList-BIVtw00v.js +0 -1
  84. package/dist/web/assets/index-BpBFF3b2.js +0 -2
  85. package/dist/web/assets/index-Dsh4Q5Cg.css +0 -1
  86. package/src/utils/cli-flags.js +0 -7
@@ -1,6 +1,5 @@
1
1
  // 多项目工作区服务
2
2
  const fs = require('fs');
3
- const os = require('os');
4
3
  const path = require('path');
5
4
  const { execFileSync } = require('child_process');
6
5
  const { PATHS } = require('../../config/paths');
@@ -47,206 +46,6 @@ function resolveCurrentBranch(repoPath) {
47
46
  }
48
47
  }
49
48
 
50
- function getGitErrorMessage(error) {
51
- const stderr = error && error.stderr ? error.stderr.toString().trim() : '';
52
- return stderr || (error && error.message) || String(error);
53
- }
54
-
55
- function normalizeString(value) {
56
- return typeof value === 'string' ? value.trim() : '';
57
- }
58
-
59
- function normalizeBranchMode(projectConfig = {}) {
60
- const branchMode = normalizeString(projectConfig.branchMode);
61
- if (branchMode === 'new' || branchMode === 'existing') {
62
- return branchMode;
63
- }
64
- return normalizeString(projectConfig.baseBranch) ? 'new' : 'existing';
65
- }
66
-
67
- function normalizeGitBranchRef(branchName) {
68
- return normalizeString(branchName).replace(/^refs\/heads\//, '');
69
- }
70
-
71
- function parseGitWorktrees(output) {
72
- const worktrees = [];
73
- const lines = output.split('\n');
74
- let current = {};
75
-
76
- for (const line of lines) {
77
- if (line.startsWith('worktree ')) {
78
- if (current.path) {
79
- worktrees.push(current);
80
- }
81
- current = { path: line.substring(9) };
82
- } else if (line.startsWith('branch ')) {
83
- current.branch = line.substring(7);
84
- } else if (line.startsWith('HEAD ')) {
85
- current.head = line.substring(5);
86
- }
87
- }
88
-
89
- if (current.path) {
90
- worktrees.push(current);
91
- }
92
-
93
- return worktrees;
94
- }
95
-
96
- function listGitWorktrees(repoPath) {
97
- const output = runGitCommand(['worktree', 'list', '--porcelain'], {
98
- cwd: repoPath
99
- });
100
- return parseGitWorktrees(output);
101
- }
102
-
103
- function hasGitRef(repoPath, ref) {
104
- try {
105
- runGitCommand(['show-ref', '--verify', '--quiet', ref], {
106
- cwd: repoPath,
107
- stdio: 'ignore'
108
- });
109
- return true;
110
- } catch (_) {
111
- return false;
112
- }
113
- }
114
-
115
- function findWorktreeForBranch(repoPath, branchName) {
116
- const normalizedBranch = normalizeGitBranchRef(branchName);
117
- const refName = `refs/heads/${normalizedBranch}`;
118
- return listGitWorktrees(repoPath).find(wt => wt.branch === refName);
119
- }
120
-
121
- function pullBaseBranch(worktreePath, baseBranch) {
122
- try {
123
- runGitCommand(['pull', '--ff-only'], { cwd: worktreePath });
124
- } catch (error) {
125
- try {
126
- runGitCommand(['remote', 'get-url', 'origin'], { cwd: worktreePath });
127
- } catch (_) {
128
- return;
129
- }
130
- const normalizedBaseBranch = normalizeGitBranchRef(baseBranch);
131
- runGitCommand(['pull', '--ff-only', 'origin', normalizedBaseBranch], {
132
- cwd: worktreePath
133
- });
134
- }
135
- }
136
-
137
- function removeTemporaryWorktree(repoPath, tempWorktreePath) {
138
- try {
139
- runGitCommand(['worktree', 'remove', tempWorktreePath, '--force'], {
140
- cwd: repoPath
141
- });
142
- } catch (error) {
143
- console.warn(`移除临时 worktree 失败: ${tempWorktreePath}`, error.message);
144
- } finally {
145
- if (fs.existsSync(tempWorktreePath)) {
146
- fs.rmSync(tempWorktreePath, { recursive: true, force: true });
147
- }
148
- }
149
- }
150
-
151
- function updateBaseBranch(repoPath, baseBranch) {
152
- const normalizedBaseBranch = normalizeGitBranchRef(baseBranch);
153
- if (!normalizedBaseBranch) {
154
- return null;
155
- }
156
-
157
- runGitCommand(['fetch', '--all', '--prune'], { cwd: repoPath });
158
-
159
- const localRef = `refs/heads/${normalizedBaseBranch}`;
160
- const remoteRef = `refs/remotes/origin/${normalizedBaseBranch}`;
161
- const hasLocalBranch = hasGitRef(repoPath, localRef);
162
- const hasRemoteBranch = hasGitRef(repoPath, remoteRef);
163
- if (!hasLocalBranch && !hasRemoteBranch) {
164
- throw new Error(`基础分支不存在: ${normalizedBaseBranch}`);
165
- }
166
-
167
- const existingWorktree = hasLocalBranch ? findWorktreeForBranch(repoPath, normalizedBaseBranch) : null;
168
- if (existingWorktree) {
169
- pullBaseBranch(existingWorktree.path, normalizedBaseBranch);
170
- return normalizedBaseBranch;
171
- }
172
-
173
- const tempParent = fs.mkdtempSync(path.join(os.tmpdir(), 'ctx-base-'));
174
- const tempWorktreePath = path.join(tempParent, 'worktree');
175
- try {
176
- if (hasLocalBranch) {
177
- runGitCommand(['worktree', 'add', tempWorktreePath, normalizedBaseBranch], {
178
- cwd: repoPath
179
- });
180
- } else {
181
- runGitCommand(['worktree', 'add', tempWorktreePath, '-b', normalizedBaseBranch, `origin/${normalizedBaseBranch}`], {
182
- cwd: repoPath
183
- });
184
- }
185
- pullBaseBranch(tempWorktreePath, normalizedBaseBranch);
186
- return normalizedBaseBranch;
187
- } finally {
188
- removeTemporaryWorktree(repoPath, tempWorktreePath);
189
- if (fs.existsSync(tempParent)) {
190
- fs.rmSync(tempParent, { recursive: true, force: true });
191
- }
192
- }
193
- }
194
-
195
- function createGitWorktree({ sourcePath, worktreePath, branch, baseBranch, branchMode, actionLabel }) {
196
- let targetBranch = normalizeString(branch);
197
- if (!targetBranch) {
198
- try {
199
- targetBranch = resolveCurrentBranch(sourcePath);
200
- } catch (e) {
201
- targetBranch = 'main';
202
- }
203
- }
204
-
205
- const resolvedBranchMode = branchMode === 'new' ? 'new' : 'existing';
206
-
207
- if (resolvedBranchMode === 'new') {
208
- const worktreeArgs = ['worktree', 'add', worktreePath, '-b', targetBranch];
209
- const updatedBaseBranch = updateBaseBranch(sourcePath, baseBranch);
210
- if (updatedBaseBranch) {
211
- worktreeArgs.push(updatedBaseBranch);
212
- }
213
-
214
- try {
215
- runGitCommand(worktreeArgs, { cwd: sourcePath });
216
- return { branch: targetBranch, path: worktreePath };
217
- } catch (error) {
218
- throw new Error(`创建 worktree 失败: ${getGitErrorMessage(error)}`);
219
- }
220
- }
221
-
222
- try {
223
- runGitCommand(['worktree', 'add', worktreePath, targetBranch], {
224
- cwd: sourcePath
225
- });
226
- return { branch: targetBranch, path: worktreePath };
227
- } catch (error) {
228
- const message = getGitErrorMessage(error);
229
- if (/already (checked out|used by worktree)/i.test(message)) {
230
- try {
231
- runGitCommand(['worktree', 'add', '--force', worktreePath, targetBranch], {
232
- cwd: sourcePath
233
- });
234
- return { branch: targetBranch, path: worktreePath };
235
- } catch (forceError) {
236
- throw new Error(
237
- `无法${actionLabel}:分支 '${targetBranch}' 已在其他工作树中检出。\n` +
238
- `仓库路径: ${sourcePath}\n` +
239
- `错误详情: ${getGitErrorMessage(forceError)}\n\n` +
240
- `解决方案:\n` +
241
- `1. 指定不同的分支名\n` +
242
- `2. 或者禁用 worktree 模式(设置 createWorktree: false)`
243
- );
244
- }
245
- }
246
- throw new Error(`创建 worktree 失败: ${message}`);
247
- }
248
- }
249
-
250
49
  /**
251
50
  * 生成唯一工作区 ID
252
51
  */
@@ -348,7 +147,31 @@ function getGitWorktrees(repoPath) {
348
147
  if (!isGitRepo(repoPath)) {
349
148
  return [];
350
149
  }
351
- const worktrees = listGitWorktrees(repoPath);
150
+ const output = runGitCommand(['worktree', 'list', '--porcelain'], {
151
+ cwd: repoPath
152
+ });
153
+
154
+ const worktrees = [];
155
+ const lines = output.split('\n');
156
+ let current = {};
157
+
158
+ for (const line of lines) {
159
+ if (line.startsWith('worktree ')) {
160
+ if (current.path) {
161
+ worktrees.push(current);
162
+ }
163
+ current = { path: line.substring(9) };
164
+ } else if (line.startsWith('branch ')) {
165
+ current.branch = line.substring(7);
166
+ } else if (line.startsWith('HEAD ')) {
167
+ current.head = line.substring(5);
168
+ }
169
+ }
170
+
171
+ if (current.path) {
172
+ worktrees.push(current);
173
+ }
174
+
352
175
  return worktrees.filter(wt => wt.path !== repoPath); // 排除主仓库
353
176
  } catch (error) {
354
177
  console.error('获取 worktree 列表失败:', error.message);
@@ -485,19 +308,48 @@ function createWorkspace(options) {
485
308
 
486
309
  // Git 仓库且需要创建 worktree:直接在工作区目录内创建,无需额外 symlink
487
310
  if (isGit && useWorktree) {
311
+ // 获取当前分支作为默认分支
312
+ let targetBranch = branch;
313
+ if (!targetBranch) {
314
+ try {
315
+ targetBranch = resolveCurrentBranch(sourcePath);
316
+ } catch (e) {
317
+ targetBranch = 'main';
318
+ }
319
+ }
320
+
488
321
  // worktree 直接创建到工作区目录内的项目路径
489
322
  const worktreePath = symlinkPath;
490
- const createdWorktree = createGitWorktree({
491
- sourcePath,
492
- worktreePath,
493
- branch,
494
- baseBranch,
495
- branchMode: normalizeBranchMode(proj),
496
- actionLabel: '创建 worktree'
497
- });
323
+
324
+ try {
325
+ // 尝试检出已有分支
326
+ runGitCommand(['worktree', 'add', worktreePath, targetBranch], {
327
+ cwd: sourcePath
328
+ });
329
+ } catch (error) {
330
+ // 如果分支不存在,尝试创建新分支
331
+ try {
332
+ const worktreeArgs = ['worktree', 'add', worktreePath, '-b', targetBranch];
333
+ if (baseBranch && baseBranch.trim()) {
334
+ worktreeArgs.push(baseBranch.trim());
335
+ }
336
+ runGitCommand(worktreeArgs, {
337
+ cwd: sourcePath
338
+ });
339
+ } catch (err) {
340
+ if (err.message.includes('already checked out')) {
341
+ throw new Error(
342
+ `无法创建 worktree:分支 '${targetBranch}' 已在其他工作树中检出。\n` +
343
+ `错误详情: ${err.message}\n\n` +
344
+ `提示:请为此项目指定不同的分支名,或禁用 worktree 模式。`
345
+ );
346
+ }
347
+ throw new Error(`创建 worktree 失败: ${err.message}`);
348
+ }
349
+ }
498
350
 
499
351
  targetPath = worktreePath;
500
- worktrees.push(createdWorktree);
352
+ worktrees.push({ branch: targetBranch, path: worktreePath });
501
353
  } else if (isGit) {
502
354
  // Git 仓库但不创建 worktree:symlink 指向源路径,记录已有 worktrees
503
355
  worktrees = getGitWorktrees(sourcePath);
@@ -657,18 +509,44 @@ function addProjectToWorkspace(workspaceId, projectConfig) {
657
509
 
658
510
  // Git 仓库且需要创建 worktree:直接在工作区目录内创建,无需额外 symlink
659
511
  if (isGit && useWorktree) {
512
+ let targetBranch = branch;
513
+ if (!targetBranch) {
514
+ try {
515
+ targetBranch = resolveCurrentBranch(sourcePath);
516
+ } catch (e) {
517
+ targetBranch = 'main';
518
+ }
519
+ }
520
+
660
521
  const worktreePath = symlinkPath;
661
- const createdWorktree = createGitWorktree({
662
- sourcePath,
663
- worktreePath,
664
- branch,
665
- baseBranch,
666
- branchMode: normalizeBranchMode(projectConfig),
667
- actionLabel: '添加项目'
668
- });
522
+
523
+ try {
524
+ runGitCommand(['worktree', 'add', worktreePath, targetBranch], {
525
+ cwd: sourcePath
526
+ });
527
+ } catch (error) {
528
+ try {
529
+ const worktreeArgs = ['worktree', 'add', worktreePath, '-b', targetBranch];
530
+ if (baseBranch && baseBranch.trim()) {
531
+ worktreeArgs.push(baseBranch.trim());
532
+ }
533
+ runGitCommand(worktreeArgs, { cwd: sourcePath });
534
+ } catch (err) {
535
+ if (err.message && err.message.includes('already checked out')) {
536
+ throw new Error(
537
+ `无法添加项目:分支 '${targetBranch}' 已在其他工作树中检出。\n` +
538
+ `仓库路径: ${sourcePath}\n\n` +
539
+ `解决方案:\n` +
540
+ `1. 指定不同的分支名\n` +
541
+ `2. 或者禁用 worktree 模式(设置 createWorktree: false)`
542
+ );
543
+ }
544
+ throw new Error(`创建 worktree 失败: ${err.message}`);
545
+ }
546
+ }
669
547
 
670
548
  targetPath = worktreePath;
671
- worktrees.push(createdWorktree);
549
+ worktrees.push({ branch: targetBranch, path: worktreePath });
672
550
  } else if (isGit) {
673
551
  // Git 仓库但不创建 worktree:symlink 指向源路径
674
552
  worktrees = getGitWorktrees(sourcePath);
@@ -743,7 +621,7 @@ function removeProjectFromWorkspace(workspaceId, projectName) {
743
621
 
744
622
 
745
623
  /**
746
- * 获取所有渠道(Claude/Codex/Gemini)的项目并集
624
+ * 获取所有渠道(Claude/Codex/Gemini/OpenCode/OMP)的项目并集
747
625
  * @returns {Promise<Array>} 去重后的项目列表
748
626
  */
749
627
  async function getAllAvailableProjects() {
@@ -752,6 +630,7 @@ async function getAllAvailableProjects() {
752
630
  const codexSessionsService = require('./codex-sessions');
753
631
  const geminiSessionsService = require('./gemini-sessions');
754
632
  const opencodeSessionsService = require('./opencode-sessions');
633
+ const piSessionsService = require('./pi-sessions');
755
634
  const { isCodexInstalled } = require('./codex-config');
756
635
  const { isGeminiInstalled } = require('./gemini-config');
757
636
  const { isOpenCodeInstalled } = require('./opencode-sessions');
@@ -769,7 +648,7 @@ async function getAllAvailableProjects() {
769
648
  seenKeys.add(projectKey);
770
649
 
771
650
  const displayName = project.displayName || (projectPath ? path.basename(projectPath) : project.name);
772
- const lastUsedValue = project.lastUsed || project.lastUpdated || null;
651
+ const lastUsedValue = project.lastUsed || project.lastUpdated || project.mtimeMs || null;
773
652
  const lastUsed = typeof lastUsedValue === 'string'
774
653
  ? new Date(lastUsedValue).getTime()
775
654
  : (lastUsedValue || 0);
@@ -824,6 +703,16 @@ async function getAllAvailableProjects() {
824
703
  console.error('获取 opencode 项目失败:', error.message);
825
704
  }
826
705
 
706
+ try {
707
+ const piProjects = piSessionsService.getProjects();
708
+ const list = Array.isArray(piProjects) ? piProjects : [];
709
+ if (list.length > 0 || piSessionsService.isPiInstalled()) {
710
+ list.forEach(project => addProject('pi', project));
711
+ }
712
+ } catch (error) {
713
+ console.error('获取 OMP 项目失败:', error.message);
714
+ }
715
+
827
716
  // 按最后使用时间排序
828
717
  allProjects.sort((a, b) => (b.lastUsed || 0) - (a.lastUsed || 0));
829
718
 
@@ -833,7 +722,7 @@ async function getAllAvailableProjects() {
833
722
  /**
834
723
  * 在工作区中启动 CLI 工具
835
724
  * @param {string} workspaceId 工作区 ID
836
- * @param {string} tool 工具名称 (claude/codex/gemini/opencode)
725
+ * @param {string} tool 工具名称 (claude/codex/gemini/opencode/pi/omp)
837
726
  * @param {string} projectName 可选,工作区内的项目名
838
727
  * @returns {object} 启动信息
839
728
  */
@@ -860,15 +749,18 @@ function getLaunchCommand(workspaceId, tool, projectName = null) {
860
749
  }
861
750
  }
862
751
 
752
+ const normalizedTool = tool === 'omp' ? 'pi' : tool;
753
+
863
754
  // 根据工具类型生成启动命令
864
755
  const commands = {
865
756
  claude: 'claude',
866
757
  codex: 'codex',
867
758
  gemini: 'gemini',
868
- opencode: 'opencode'
759
+ opencode: 'opencode',
760
+ pi: 'omp'
869
761
  };
870
762
 
871
- const cmd = commands[tool];
763
+ const cmd = commands[normalizedTool];
872
764
  if (!cmd) {
873
765
  throw new Error(`不支持的工具: ${tool}`);
874
766
  }
@@ -182,18 +182,24 @@ function inferSource(log) {
182
182
  if (log.toolType) {
183
183
  if (log.toolType.includes('codex')) return 'codex';
184
184
  if (log.toolType.includes('gemini')) return 'gemini';
185
+ if (log.toolType.includes('opencode')) return 'opencode';
186
+ if (log.toolType.includes('pi')) return 'pi';
185
187
  }
186
188
  if (typeof log.model === 'string') {
187
189
  const model = log.model.toLowerCase();
188
190
  if (model.includes('gemini')) return 'gemini';
191
+ if (model.includes('opencode')) return 'opencode';
192
+ if (model.includes('pi')) return 'pi';
189
193
  if (model.includes('gpt') || model.includes('o1') || model.includes('o3')) return 'codex';
190
194
  if (model.includes('claude')) return 'claude';
191
195
  }
192
196
  if (typeof log.action === 'string') {
193
197
  if (log.action.includes('codex')) return 'codex';
194
198
  if (log.action.includes('gemini')) return 'gemini';
199
+ if (log.action.includes('opencode')) return 'opencode';
200
+ if (log.action.includes('pi')) return 'pi';
195
201
  }
196
- if (log.channelType === 'codex' || log.channelType === 'gemini') {
202
+ if (log.channelType === 'codex' || log.channelType === 'gemini' || log.channelType === 'opencode' || log.channelType === 'pi') {
197
203
  return log.channelType;
198
204
  }
199
205
  return 'claude';
@@ -2,17 +2,12 @@
2
2
  const fs = require('fs');
3
3
  const path = require('path');
4
4
  const chalk = require('chalk');
5
- const { NATIVE_PATHS } = require('../config/paths');
6
-
7
- function resolveProjectsDir(config = {}) {
8
- return config.projectsDir || NATIVE_PATHS.claude.projects;
9
- }
10
5
 
11
6
  /**
12
7
  * 获取会话目录
13
8
  */
14
9
  function getSessionsDir(config) {
15
- return path.join(resolveProjectsDir(config), config.currentProject);
10
+ return path.join(config.projectsDir, config.currentProject);
16
11
  }
17
12
 
18
13
  /**
@@ -201,7 +196,7 @@ function parseLinesWithTail(headLines, tailLines) {
201
196
  * 获取所有可用的项目
202
197
  */
203
198
  async function getAvailableProjects(config) {
204
- const projectsDir = resolveProjectsDir(config);
199
+ const projectsDir = config.projectsDir;
205
200
  if (!fs.existsSync(projectsDir)) {
206
201
  console.log(chalk.red(`项目目录不存在: ${projectsDir}`));
207
202
  return [];
@@ -209,9 +204,8 @@ async function getAvailableProjects(config) {
209
204
 
210
205
  // 获取项目列表和统计信息(包含解析后的名称)
211
206
  const { getProjectsWithStats, getProjectOrder } = require('../server/services/sessions');
212
- const resolvedConfig = { ...config, projectsDir };
213
- const projects = await getProjectsWithStats(resolvedConfig);
214
- const savedOrder = getProjectOrder(resolvedConfig);
207
+ const projects = await getProjectsWithStats(config);
208
+ const savedOrder = getProjectOrder(config);
215
209
  const projectList = Array.isArray(projects) ? projects : [];
216
210
 
217
211
  // 按保存的顺序排列
@@ -1 +0,0 @@
1
- import{d as e}from"./vendors-DQA4Hw9v.js";import{a8 as a,f as n,r as l,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,Y as p,N as h,a0 as y,a3 as g,_ as m,p as f,L as k,F as T,$ as b,Z as x,v as w}from"./vue-vendor-B5RqjEjQ.js";import{_ as C,u as $,a as _,R as z,g as q,b as S,c as L,d as I,e as j,f as M,h as O,i as A,j as N,k as E,l as F,s as P}from"./index-BpBFF3b2.js";import{E as D,o as U,n as V,m as J,aq as K,h as R,P as B,ar as G,as as Z,at as H,au as W,a9 as X,i as Y,A as Q,av as ee,aw as ae,T as ne,a as le,b as se}from"./icons-QFXzEgqM.js";import{L as ce,N as te,B as oe,s as ie,b as ue,c as de,a as re,Z as ve}from"./naive-ui-kcWDeJwl.js";import"./markdown-BNJfEgCA.js";const pe={class:"channel-column"},he={class:"drag-handle",title:"拖拽排序"},ye={class:"header-icon"},ge={class:"channel-title"},me={key:0,class:"claude-extra-area"},fe={key:0,class:"channel-content"},ke={class:"card"},Te={class:"card-header"},be={key:0,class:"runtime-badge"},xe={class:"card-body",style:{padding:"6px 10px"}},we={class:"proxy-info-row"},Ce={class:"proxy-status"},$e={class:"proxy-port"},_e={class:"channel-name"},ze={class:"channel-quick-panel"},qe={class:"panel-title"},Se={key:0,class:"no-channels"},Le={key:1,class:"channel-quick-list"},Ie={class:"channel-quick-info"},je={class:"channel-quick-name"},Me={key:0,class:"channel-switching-tip"},Oe={class:"channel-metrics"},Ae={class:"metric-item"},Ne={class:"metric-value"},Ee={class:"metric-item"},Fe={class:"metric-value"},Pe={class:"metric-item"},De={class:"metric-value"},Ue={class:"metric-item"},Ve={class:"card"},Je={class:"card-header compact"},Ke={class:"card-body",style:{padding:"8px 10px"}},Re={class:"quick-access-list"},Be={class:"access-icon"},Ge={class:"access-content"},Ze={class:"access-value"},He={class:"access-icon"},We={class:"access-content"},Xe={class:"access-value"},Ye={class:"access-icon"},Qe={class:"access-content"},ea={class:"access-goto"},aa={class:"card-header compact"},na={class:"card-body",style:{padding:"8px 10px"}},la={class:"stats-inline stats-3col"},sa={class:"stat-inline-item stat-requests"},ca={class:"stat-info"},ta={class:"stat-inline-item stat-input"},oa={class:"stat-info"},ia={class:"stat-inline-item stat-output"},ua={class:"stat-info"},da={key:1,class:"card logs-card"},ra={class:"card-header compact"},va={class:"card-body logs-card-body"},pa={class:"logs-table-wrapper"},ha={key:0,class:"empty-logs"},ya=["title"],ga={key:0,class:"action-content"},ma={class:"action-msg"},fa={class:"action-time"},ka={key:1,class:"action-content"},Ta={class:"action-msg error-msg"},ba={class:"action-time error-time"},xa={class:"locked-content"},wa={class:"lock-icon"},Ca="channelLocks",$a=C({__name:"ChannelColumn",props:{channelType:{type:String,required:!0,validator:e=>["claude","codex","gemini","opencode"].includes(e)}},setup(e){const C=e,F=a(),P=ce(),{claudeProxy:$a,codexProxy:_a,geminiProxy:za,opencodeProxy:qa,claudeChannels:Sa,codexChannels:La,geminiChannels:Ia,opencodeChannels:ja,schedulerState:Ma,getProxyState:Oa,startProxy:Aa,stopProxy:Na,getLogs:Ea,clearLogsForSource:Fa,loadChannels:Pa,logLimit:Da,statsInterval:Ua}=$(),{dashboardData:Va,loadDashboard:Ja}=_(),Ka={claude:{title:"ClaudeCode",subtitle:"智能编程助手",icon:J},codex:{title:"Codex-CLI",subtitle:"高效代码生成",icon:V},gemini:{title:"Gemini-CLI",subtitle:"多模态AI助手",icon:U},opencode:{title:"OpenCode",subtitle:"AI 代码助手",icon:D}},Ra=n(()=>Ka[C.channelType].title);n(()=>Ka[C.channelType].subtitle);const Ba=n(()=>Ka[C.channelType].icon),Ga=n(()=>"claude"===C.channelType?$a.value:"codex"===C.channelType?_a.value:"gemini"===C.channelType?za.value:"opencode"===C.channelType?qa.value:{}),Za=n(()=>"claude"===C.channelType?"Claude":"codex"===C.channelType?"Codex":"gemini"===C.channelType?"Gemini":"opencode"===C.channelType?"OpenCode":""),Ha=l({projects:0,sessions:0}),Wa=l({requests:0,tokens:0,cost:0}),Xa=l({requests:0,tokens:0,cost:0}),Ya={requests:0,tokens:0,cost:3};let Qa={requests:null,tokens:null,cost:null};const en=l({requests:!1,tokens:!1,cost:!1}),an=n(()=>{var e,a,n;const l="claude"===C.channelType?"claude":"codex"===C.channelType?"codex":"opencode"===C.channelType?"opencode":"gemini";return(null==(n=null==(a=null==(e=Va.value)?void 0:e.todayStats)?void 0:a[l])?void 0:n.byModel)||{}});function nn(e,a,n,l=600){Qa[e]&&cancelAnimationFrame(Qa[e]),en.value[e]=!0;const s=Date.now(),c=()=>{const t=Date.now()-s,o=Math.min(t/l,1),i=1-Math.pow(1-o,2),u=a+(n-a)*i,d=Ya[e]??0,r=Math.pow(10,d),v=d>0?Math.round(u*r)/r:Math.round(u);Xa.value[e]=v,o<1?Qa[e]=requestAnimationFrame(c):en.value[e]=!1};Qa[e]=requestAnimationFrame(c)}const ln=l(!1);function sn(e){try{const a=localStorage.getItem(Ca),n=a?JSON.parse(a):{};n[C.channelType]=e,localStorage.setItem(Ca,JSON.stringify(n))}catch(a){}}const cn=l(function(){try{const e=localStorage.getItem(Ca);if(e){return JSON.parse(e)[C.channelType]||!1}}catch(e){}return!1}());async function tn(){cn.value=!cn.value,sn(cn.value);try{if(await E("channelLocks",C.channelType,cn.value),Va.value){const e=Va.value.uiConfig||{},a={...e.channelLocks||{}};a[C.channelType]=cn.value,Va.value={...Va.value,uiConfig:{...e,channelLocks:a}}}}catch(e){}}const on=l(!0);function un(e){e.detail&&void 0!==e.detail.showLogs&&(on.value=e.detail.showLogs)}const dn=l(Date.now()),rn=n(()=>{if(!Ga.value.running)return"";const e=Ga.value.startTime;if(!e)return"";const a=dn.value-e;if(a<=0)return"";const n=Math.floor(a/1e3),l=Math.floor(n/3600),s=Math.floor(n%3600/60),c=n%60;let t="已运行 ";return l>0&&(t+=`${l}小时`),s>0&&(t+=`${s}分`),(c>0||0===l&&0===s)&&(t+=`${c}秒`),t}),vn=l(null),pn=n(()=>Da.value),hn={claude:Ea("claude"),codex:Ea("codex"),gemini:Ea("gemini"),opencode:Ea("opencode")},yn=n(()=>((hn[C.channelType]||hn.claude).value||[]).slice(0,pn.value));let gn=null,mn=null,fn=null,kn=!1,Tn=null;const bn=n(()=>{let e=[];"claude"===C.channelType?e=Sa.value||[]:"codex"===C.channelType?e=La.value||[]:"gemini"===C.channelType?e=Ia.value||[]:"opencode"===C.channelType&&(e=ja.value||[]);return[...e.filter(e=>!1!==e.enabled),...e.filter(e=>!1===e.enabled)]});function xn(e){const a=Ma[C.channelType];if(!a||!a.channels)return 0;const n=a.channels.find(a=>a.id===e);return n?n.inflight:0}const wn=n(()=>{var e;const a=bn.value.filter(e=>!1!==e.enabled).length;return(null==(e=Ga.value.proxy)?void 0:e.running)?`${a}个渠道调度中`:bn.value.length>0?`${a}个渠道已启用`:"无渠道"}),Cn=l({});function $n(e){return Cn.value[e]||{requests:0,tokens:0,cost:0}}async function _n(){var e;try{let a;if("claude"===C.channelType?a=await q():"codex"===C.channelType?a=await S():"gemini"===C.channelType?a=await L():"opencode"===C.channelType&&(a=await I()),a&&a.byChannel){const n={};for(const[l,s]of Object.entries(a.byChannel))n[l]={requests:s.requests||0,tokens:(null==(e=s.tokens)?void 0:e.total)||0,cost:s.cost||0};Cn.value=n}}catch(a){}}function zn(e,a){var n;return(null==e?void 0:e.usageMissing)?"--":(null==(n=null==e?void 0:e.tokens)?void 0:n[a])||0}function qn(e){if(!e||"action"===e.type||"error"===e.status)return"";const a=[];return e.model&&a.push(`模型: ${e.model}`),e.originalModel&&e.originalModel!==e.model&&a.push(`重定向: ${e.originalModel} -> ${e.model}`),e.usageMissing&&a.push("上游响应未返回 usage,当前无法计算 token。"),a.join("\n")}async function Sn(e){var a,n;const l=Oa(C.channelType);l.value.loading=!0;try{let a;a=e?await Aa(C.channelType):await Na(C.channelType,{refreshChannelsDrawer:!0}),!1!==a.success?P.success(e?`${Ra.value} 代理已启动`:`${Ra.value} 代理已停止`):(P.error(a.error||"操作失败"),l.value.running=!e)}catch(s){P.error((null==(n=null==(a=s.response)?void 0:a.data)?void 0:n.error)||s.message||"操作失败"),l.value.running=!e}finally{l.value.loading=!1}}function Ln(){F.push({name:`${C.channelType}-projects`})}function In(){F.push({name:`${C.channelType}-projects`})}s(yn,e=>{var a;const n=(null==(a=e[0])?void 0:a.id)||null;if(!n||n===gn)return void(gn=n);gn=n,Tn&&clearTimeout(Tn),Tn=setTimeout(()=>{_n()},5e3);(!vn.value||vn.value.scrollTop<20)&&w(()=>{vn.value&&(vn.value.scrollTop=0)})}),s(()=>Wa.value.requests,e=>{nn("requests",Xa.value.requests,e,600)}),s(()=>Wa.value.tokens,e=>{nn("tokens",Xa.value.tokens,e,600)}),s(()=>Wa.value.cost,e=>{nn("cost",Xa.value.cost,e,600)}),s(()=>C.channelType,()=>{var e;gn=(null==(e=yn.value[0])?void 0:e.id)||null}),s(()=>{var e,a;return null==(a=null==(e=Va.value)?void 0:e.counts)?void 0:a[C.channelType]},()=>{An()}),s(Ua,()=>{kn&&function(){mn&&(clearInterval(mn),mn=null);const e=Ua.value||30,a=Math.max(1e3*e,1e4);mn=setInterval(()=>{Nn(),_n()},a)}()});const jn=l({});function Mn(e){return!!jn.value[e]}function On(e,a){e&&(jn.value={...jn.value,[e]:!!a})}function An(){var e,a;const n=null==(a=null==(e=Va.value)?void 0:e.counts)?void 0:a[C.channelType];Ha.value.projects=(null==n?void 0:n.projectCount)||0,Ha.value.sessions=(null==n?void 0:n.sessionCount)||0}async function Nn(){if(Va.value&&Va.value.todayStats){const e=Va.value.todayStats[C.channelType];e&&(Wa.value.requests=e.requests||0,Wa.value.tokens=e.tokens||0,Wa.value.cost=e.cost||0)}An()}function En(){Fa(C.channelType)}function Fn(e){var a,n;null==(n=null==(a=null==e?void 0:e.currentTarget)?void 0:a.blur)||n.call(a)}function Pn(e){window.dispatchEvent(new CustomEvent("open-skills-drawer",{detail:{platform:C.channelType}})),Fn(e)}function Dn(e){window.dispatchEvent(new CustomEvent("open-commands-drawer",{detail:{platform:C.channelType}})),Fn(e)}function Un(e){window.dispatchEvent(new CustomEvent("open-agents-drawer",{detail:{platform:C.channelType}})),Fn(e)}return c(async()=>{await Promise.all([Ja().then(()=>Nn()),_n()]),async function(){var e,a;try{if(Va.value&&Va.value.uiConfig)on.value=!1!==(null==(e=Va.value.uiConfig.panelVisibility)?void 0:e.showLogs);else{const e=await j();e.success&&e.config&&(on.value=!1!==(null==(a=e.config.panelVisibility)?void 0:a.showLogs))}}catch(n){}}(),async function(){var e,a;try{let n=!1;if(Va.value&&Va.value.uiConfig)n=(null==(e=Va.value.uiConfig.channelLocks)?void 0:e[C.channelType])||!1;else{const e=await j();e.success&&e.config&&(n=(null==(a=e.config.channelLocks)?void 0:a[C.channelType])||!1)}cn.value=n,sn(n)}catch(n){}}(),window.addEventListener("panel-visibility-change",un),Xa.value={...Wa.value},kn=!0,fn=setInterval(()=>{dn.value=Date.now()},1e3)}),t(()=>{kn=!1,mn&&clearInterval(mn),fn&&clearInterval(fn),Tn&&clearTimeout(Tn),window.removeEventListener("panel-visibility-change",un),Object.values(Qa).forEach(e=>{e&&cancelAnimationFrame(e)})}),(a,n)=>{const l=o("n-collapse");return u(),i("div",pe,[d("div",{class:k(["channel-header",e.channelType])},[d("div",he,[v(h(te),{size:16},{default:p(()=>[v(h(K))]),_:1})]),d("div",ye,[v(h(te),{size:20},{default:p(()=>[(u(),y(g(Ba.value)))]),_:1})]),d("h2",ge,m(Ra.value),1),["claude","codex","gemini","opencode"].includes(e.channelType)?(u(),i("div",me,[v(h(ie),{trigger:"hover"},{trigger:p(()=>[v(h(oe),{text:"",class:"config-shortcut-button",onClick:Pn,title:"Skills 技能管理"},{icon:p(()=>[v(h(te),{size:18},{default:p(()=>[v(h(D))]),_:1})]),_:1})]),default:p(()=>[n[3]||(n[3]=f(" Skills 技能管理 ",-1))]),_:1}),v(h(ie),{trigger:"hover"},{trigger:p(()=>[v(h(oe),{text:"",class:"config-shortcut-button",onClick:Dn,title:"Commands 命令管理"},{icon:p(()=>[v(h(te),{size:18},{default:p(()=>[v(h(R))]),_:1})]),_:1})]),default:p(()=>[n[4]||(n[4]=f(" Commands 命令管理 ",-1))]),_:1}),v(h(ie),{trigger:"hover"},{trigger:p(()=>[v(h(oe),{text:"",class:"config-shortcut-button",onClick:Un,title:"Agents 代理管理"},{icon:p(()=>[v(h(te),{size:18},{default:p(()=>[v(h(B))]),_:1})]),_:1})]),default:p(()=>[n[5]||(n[5]=f(" Agents 代理管理 ",-1))]),_:1})])):r("",!0),v(h(oe),{text:"",class:"lock-button",onClick:tn,title:cn.value?"解锁此列":"锁定此列"},{icon:p(()=>[v(h(te),{size:18},{default:p(()=>[cn.value?(u(),y(h(G),{key:0})):(u(),y(h(Z),{key:1}))]),_:1})]),_:1},8,["title"])],2),cn.value?r("",!0):(u(),i("div",fe,[d("div",ke,[d("div",Te,[v(h(te),{size:16},{default:p(()=>[v(h(H))]),_:1}),n[6]||(n[6]=d("h3",{class:"card-title"},"代理控制",-1)),Ga.value.running&&rn.value?(u(),i("span",be,m(rn.value),1)):r("",!0),v(h(ue),{value:Ga.value.running,"onUpdate:value":[n[0]||(n[0]=e=>Ga.value.running=e),Sn],loading:Ga.value.loading,size:"small",style:{"margin-left":"auto"}},null,8,["value","loading"])]),d("div",xe,[d("div",we,[d("div",Ce,[d("div",{class:k(["status-dot",{active:Ga.value.running}])},null,2),v(h(de),{type:Ga.value.running?"success":"default",style:{"font-size":"12px"}},{default:p(()=>[f(m(Ga.value.running?"运行中":"已停止"),1)]),_:1},8,["type"]),d("span",$e,"端口: "+m(Ga.value.port),1)]),v(h(ve),{trigger:"click",placement:"bottom",width:320,class:"channel-popover"},{trigger:p(()=>[v(h(oe),{text:"",size:"tiny",class:"channel-status"},{default:p(()=>[d("span",_e,m(wn.value),1)]),_:1})]),default:p(()=>[d("div",ze,[d("div",qe,[n[8]||(n[8]=d("span",null,"渠道快捷管理",-1)),v(h(de),{depth:"3",style:{"font-size":"11px"}},{default:p(()=>[...n[7]||(n[7]=[f("点击开关切换状态",-1)])]),_:1})]),0===bn.value.length?(u(),i("div",Se,[v(h(de),{depth:"3"},{default:p(()=>[...n[9]||(n[9]=[f("暂无配置渠道",-1)])]),_:1})])):(u(),i("div",Le,[(u(!0),i(T,null,b(bn.value,e=>{var a,l;return u(),i("div",{key:e.id,class:k(["channel-quick-item",{disabled:!1===e.enabled}])},[d("div",Ie,[d("span",je,m(e.name),1),"frozen"===(null==(a=e.health)?void 0:a.status)?(u(),y(h(re),{key:0,size:"tiny",type:"error",bordered:!1},{default:p(()=>[...n[10]||(n[10]=[f(" 冻结 ",-1)])]),_:1})):r("",!0),v(h(ue),{size:"small",value:!1!==e.enabled,"onUpdate:value":a=>async function(e,a){if(e&&!Mn(e.id)){On(e.id,!0);try{let n;"claude"===C.channelType?n=M:"codex"===C.channelType?n=O:"gemini"===C.channelType?n=A:"opencode"===C.channelType&&(n=N),n&&(await n(e.id,{enabled:a}),P.success(a?`渠道「${e.name}」已启用`:`渠道「${e.name}」已停用`),await Pa())}catch(n){P.error("操作失败: "+n.message)}finally{On(e.id,!1)}}}(e,a),loading:Mn(e.id),disabled:Mn(e.id),style:{"margin-left":"auto"}},null,8,["value","onUpdate:value","loading","disabled"])]),Mn(e.id)?(u(),i("div",Me," 正在切换渠道状态... ")):r("",!0),d("div",Oe,[d("span",Ae,[n[11]||(n[11]=d("span",{class:"metric-label"},"请求",-1)),d("span",Ne,m($n(e.id).requests),1)]),d("span",Ee,[n[12]||(n[12]=d("span",{class:"metric-label"},"Tokens",-1)),d("span",Fe,m((l=$n(e.id).tokens,l>=1e6?(l/1e6).toFixed(1)+"M":l>=1e3?(l/1e3).toFixed(1)+"K":l.toString())),1)]),d("span",Pe,[n[13]||(n[13]=d("span",{class:"metric-label"},"权重",-1)),d("span",De,m(e.weight||1),1)]),d("span",Ue,[n[14]||(n[14]=d("span",{class:"metric-label"},"并发",-1)),d("span",{class:k(["metric-value",{active:xn(e.id)>0}])},m(xn(e.id))+m(e.maxConcurrency?`/${e.maxConcurrency}`:""),3)])])],2)}),128))]))])]),_:1})])])]),d("div",Ve,[d("div",Je,[v(h(te),{size:14},{default:p(()=>[v(h(W))]),_:1}),n[15]||(n[15]=d("h3",{class:"card-title"},"快速访问",-1))]),d("div",Ke,[d("div",Re,[d("div",{class:"access-card access-card-projects clickable",onClick:Ln},[d("div",Be,[v(h(te),{size:16},{default:p(()=>[v(h(X))]),_:1})]),d("div",Ge,[n[16]||(n[16]=d("span",{class:"access-label"},"项目",-1)),d("span",Ze,m(Ha.value.projects),1)])]),d("div",{class:"access-card access-card-sessions clickable",onClick:n[1]||(n[1]=e=>ln.value=!0)},[d("div",He,[v(h(te),{size:16},{default:p(()=>[v(h(Y))]),_:1})]),d("div",We,[n[17]||(n[17]=d("span",{class:"access-label"},"最新对话",-1)),d("span",Xe,m(Ha.value.sessions),1)])]),d("div",{class:"access-card access-card-goto clickable",onClick:In},[d("div",Ye,[v(h(te),{size:16},{default:p(()=>[v(h(Q))]),_:1})]),d("div",Qe,[n[18]||(n[18]=d("span",{class:"access-label"},"前往",-1)),d("span",ea,m(Za.value),1)])])])])]),d("div",{class:k(["card stats-card",`stats-card-${e.channelType}`])},[d("div",aa,[v(h(te),{size:14},{default:p(()=>[v(h(ee))]),_:1}),n[19]||(n[19]=d("h3",{class:"card-title"},"今日数据",-1))]),d("div",na,[d("div",la,[d("div",sa,[n[21]||(n[21]=d("div",{class:"stat-icon-dot requests"},null,-1)),d("div",ca,[n[20]||(n[20]=d("span",{class:"stat-label"},"请求",-1)),d("span",{class:k(["stat-value",{animating:en.value.requests}])},m(Xa.value.requests),3)])]),d("div",ta,[n[23]||(n[23]=d("div",{class:"stat-icon-dot tokens"},null,-1)),d("div",oa,[n[22]||(n[22]=d("span",{class:"stat-label"},"总 Tokens",-1)),d("span",{class:k(["stat-value",{animating:en.value.tokens}])},m((c=Xa.value.tokens,c>=1e6?(c/1e6).toFixed(1)+"M":c>=1e3?(c/1e3).toFixed(1)+"K":c.toString())),3)])]),d("div",ia,[n[25]||(n[25]=d("div",{class:"stat-icon-dot cost"},null,-1)),d("div",ua,[n[24]||(n[24]=d("span",{class:"stat-label"},"成本 / USD",-1)),d("span",{class:k(["stat-value",{animating:en.value.cost}])},m((s=Xa.value.cost,!s||Number.isNaN(s)?"$0":"$"+Number(s).toFixed(3))),3)])])])])],2),Object.keys(an.value).length>0?(u(),i("div",{key:0,class:k(["card chart-card",`chart-card-${e.channelType}`])},[v(l,{"default-expanded-names":[],accordion:""})],2)):r("",!0),on.value?(u(),i("div",da,[d("div",ra,[v(h(te),{size:14},{default:p(()=>[v(h(ae))]),_:1}),n[26]||(n[26]=d("h3",{class:"card-title"},"实时日志",-1)),v(h(oe),{text:"",size:"tiny",onClick:x(En,["stop"]),style:{"margin-left":"auto"},title:"清空日志"},{icon:p(()=>[v(h(te),{size:14},{default:p(()=>[v(h(ne))]),_:1})]),_:1})]),d("div",va,[d("div",pa,[d("div",{class:k(["logs-table-header",`logs-header-${e.channelType}`])},[d("div",{class:k(["log-col col-channel",`col-channel-${e.channelType}`])},"渠道",2),d("div",{class:k(["log-col col-token",`col-token-${e.channelType}`])},"请求",2),d("div",{class:k(["log-col col-token",`col-token-${e.channelType}`])},"回复",2),"claude"===e.channelType?(u(),i(T,{key:0},[d("div",{class:k(["log-col col-token",`col-token-${e.channelType}`])},"写入",2),d("div",{class:k(["log-col col-token",`col-token-${e.channelType}`])},"命中",2)],64)):"codex"===e.channelType?(u(),i(T,{key:1},[d("div",{class:k(["log-col col-token",`col-token-${e.channelType}`])},"推理",2),d("div",{class:k(["log-col col-token",`col-token-${e.channelType}`])},"缓存",2),d("div",{class:k(["log-col col-token",`col-token-${e.channelType}`])},"总计",2)],64)):"gemini"===e.channelType?(u(),i(T,{key:2},[d("div",{class:k(["log-col col-token",`col-token-${e.channelType}`])},"缓存",2),d("div",{class:k(["log-col col-token",`col-token-${e.channelType}`])},"总计",2)],64)):"opencode"===e.channelType?(u(),i(T,{key:3},[d("div",{class:k(["log-col col-token",`col-token-${e.channelType}`])},"推理",2),d("div",{class:k(["log-col col-token",`col-token-${e.channelType}`])},"缓存",2),d("div",{class:k(["log-col col-token",`col-token-${e.channelType}`])},"总计",2)],64)):r("",!0),d("div",{class:k(["log-col col-time",`col-time-${e.channelType}`])},"时间",2)],2),d("div",{class:"logs-container",ref_key:"logsContainer",ref:vn},[0===yn.value.length?(u(),i("div",ha,[v(h(te),{size:32,depth:"3",style:{"margin-bottom":"8px"}},{default:p(()=>[v(h(ae))]),_:1}),v(h(de),{depth:"3",style:{"font-size":"12px","font-weight":"500"}},{default:p(()=>[...n[27]||(n[27]=[f("暂无实时日志",-1)])]),_:1}),v(h(de),{depth:"3",style:{"font-size":"11px","margin-top":"4px"}},{default:p(()=>[...n[28]||(n[28]=[f("开启代理后将显示请求记录",-1)])]),_:1})])):r("",!0),(u(!0),i(T,null,b(yn.value,a=>(u(),i("div",{key:a.id,class:k(["log-row",{"action-row":"action"===a.type,"error-row":"error"===a.status,"new-log":a.isNew}]),title:qn(a)},["action"===a.type?(u(),i("div",ga,[v(h(te),{size:12,color:"#18a058"},{default:p(()=>[v(h(le))]),_:1}),d("span",ma,m(a.message),1),d("span",fa,m(a.time),1)])):"error"===a.status?(u(),i("div",ka,[v(h(te),{size:12,color:"#d03050"},{default:p(()=>[v(h(se))]),_:1}),d("span",Ta,m(a.channel)+": "+m(a.error||a.message||"请求失败"),1),d("span",ba,m(a.time),1)])):(u(),i(T,{key:2},[d("div",{class:k(["log-col col-channel",`col-channel-${e.channelType}`])},[v(h(re),{size:"tiny",type:"success"},{default:p(()=>[f(m(a.channel),1)]),_:2},1024)],2),d("div",{class:k(["log-col col-token",`col-token-${e.channelType}`])},m(zn(a,"input")),3),d("div",{class:k(["log-col col-token",`col-token-${e.channelType}`])},m(zn(a,"output")),3),"claude"===e.channelType?(u(),i(T,{key:0},[d("div",{class:k(["log-col col-token",`col-token-${e.channelType}`])},m(zn(a,"cacheCreation")),3),d("div",{class:k(["log-col col-token",`col-token-${e.channelType}`])},m(zn(a,"cacheRead")),3)],64)):"codex"===e.channelType?(u(),i(T,{key:1},[d("div",{class:k(["log-col col-token",`col-token-${e.channelType}`])},m(zn(a,"reasoning")),3),d("div",{class:k(["log-col col-token",`col-token-${e.channelType}`])},m(zn(a,"cached")),3),d("div",{class:k(["log-col col-token",`col-token-${e.channelType}`])},m(zn(a,"total")),3)],64)):"gemini"===e.channelType?(u(),i(T,{key:2},[d("div",{class:k(["log-col col-token",`col-token-${e.channelType}`])},m(zn(a,"cached")),3),d("div",{class:k(["log-col col-token",`col-token-${e.channelType}`])},m(zn(a,"total")),3)],64)):"opencode"===e.channelType?(u(),i(T,{key:3},[d("div",{class:k(["log-col col-token",`col-token-${e.channelType}`])},m(zn(a,"reasoning")),3),d("div",{class:k(["log-col col-token",`col-token-${e.channelType}`])},m(zn(a,"cached")),3),d("div",{class:k(["log-col col-token",`col-token-${e.channelType}`])},m(zn(a,"total")),3)],64)):r("",!0),d("div",{class:k(["log-col col-time",`col-time-${e.channelType}`])},m(a.time),3)],64))],10,ya))),128))],512)])])])):r("",!0)])),cn.value?(u(),i("div",{key:1,class:k(["locked-overlay",`locked-${e.channelType}`])},[d("div",xa,[d("div",wa,[v(h(te),{size:48},{default:p(()=>[v(h(G))]),_:1})]),n[30]||(n[30]=d("h3",{class:"locked-title"},"该渠道已锁定",-1)),v(h(de),{depth:"3",class:"locked-hint"},{default:p(()=>[...n[29]||(n[29]=[f(" 点击上方按钮解锁以查看内容 ",-1)])]),_:1})])],2)):r("",!0),v(z,{visible:ln.value,"onUpdate:visible":n[2]||(n[2]=e=>ln.value=e),channel:e.channelType},null,8,["visible","channel"])]);var s,c}}},[["__scopeId","data-v-3a91c627"]]),_a=l({theme:"light",panelVisibility:{showChannels:!0,showLogs:!0},channelBalance:{showRemaining:!1},channelLocks:{claude:!1,codex:!1,gemini:!1},channelCollapse:{claude:[],codex:[],gemini:[]},channelOrder:{claude:[],codex:[],gemini:[]}});let za=!1,qa=null;async function Sa(){return za?_a.value:qa||(qa=(async()=>{try{const e=await j();e.success&&e.config&&(_a.value=e.config,za=!0)}catch(e){}finally{qa=null}return _a.value})(),qa)}const La={class:"dashboard-container"},Ia="dashboardChannelOrder",ja=C({__name:"Home",setup(a){const n=["claude","codex","gemini","opencode"],{uiConfig:s,updateConfig:t,loadUIConfig:o}=(za||Sa(),{uiConfig:_a,loadUIConfig:Sa,saveConfig:async function(e){try{const a=await P(e);return!!a.success&&(_a.value=a.config,!0)}catch(a){return!1}},updateConfig:async function(e,a){try{const n=await F(e,a);return!!n.success&&(_a.value=n.config,!0)}catch(n){return!1}},updateNestedConfig:async function(e,a,n){try{const l=await E(e,a,n);return!!l.success&&(_a.value=l.config,!0)}catch(l){return!1}}});function d(e){try{localStorage.setItem(Ia,JSON.stringify(e))}catch(a){}}const r=l(function(){try{const e=localStorage.getItem(Ia);if(e){const a=JSON.parse(e);if(Array.isArray(a)&&4===a.length)return a}}catch(e){}return n}().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,n)=>(u(),i("div",La,[v(h(e),{modelValue:r.value,"onUpdate:modelValue":n[0]||(n[0]=e=>r.value=e),class:"dashboard-grid","item-key":"type",animation:200,handle:".drag-handle",onEnd:g},{item:p(({element:e})=>[(u(),y($a,{"channel-type":e.type,key:e.type},null,8,["channel-type"]))]),_:1},8,["modelValue"])]))}},[["__scopeId","data-v-a6410dd2"]]);export{ja as default};
@@ -1 +0,0 @@
1
- .channel-column[data-v-3a91c627]{display:flex;flex-direction:column;height:100%;min-height:0;background:linear-gradient(180deg,#ffffffeb,#f7faf8fa);border:1px solid rgba(216,225,222,.92);border-radius:22px;overflow:hidden;box-shadow:0 22px 52px #0f171d1a;-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px)}.channel-header[data-v-3a91c627]{display:flex;align-items:center;gap:10px;padding:12px 14px;background:linear-gradient(180deg,#ffffffd1,#ffffff8c);position:relative}.drag-handle[data-v-3a91c627]{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-3a91c627]:hover{color:var(--text-secondary);background:var(--bg-tertiary)}.drag-handle[data-v-3a91c627]:active{cursor:grabbing}.channel-header[data-v-3a91c627]:after{content:"";position:absolute;bottom:0;left:18px;right:18px;height:2px;border-radius:1px}.channel-header.claude[data-v-3a91c627]{background:linear-gradient(135deg,rgba(24,160,88,.08) 0%,transparent 100%)}.channel-header.claude[data-v-3a91c627]:after{background:linear-gradient(90deg,#18a058,#18a0584d)}.channel-header.codex[data-v-3a91c627]{background:linear-gradient(135deg,rgba(59,130,246,.08) 0%,transparent 100%)}.channel-header.codex[data-v-3a91c627]:after{background:linear-gradient(90deg,#3b82f6,#3b82f64d)}.channel-header.gemini[data-v-3a91c627]{background:linear-gradient(135deg,rgba(168,85,247,.08) 0%,transparent 100%)}.channel-header.gemini[data-v-3a91c627]:after{background:linear-gradient(90deg,#a855f7,#a855f74d)}.channel-header.opencode[data-v-3a91c627]{background:linear-gradient(135deg,rgba(234,88,12,.08) 0%,transparent 100%)}.channel-header.opencode[data-v-3a91c627]:after{background:linear-gradient(90deg,#ea580c,#ea580c4d)}.header-icon[data-v-3a91c627]{width:36px;height:36px;border-radius:12px;display:flex;align-items:center;justify-content:center;box-shadow:0 10px 24px #0f171d24}.channel-header.claude .header-icon[data-v-3a91c627]{background:linear-gradient(135deg,#18a058,#15803d);color:#fff}.channel-header.codex .header-icon[data-v-3a91c627]{background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff}.channel-header.gemini .header-icon[data-v-3a91c627]{background:linear-gradient(135deg,#a855f7,#9333ea);color:#fff}.channel-header.opencode .header-icon[data-v-3a91c627]{background:linear-gradient(135deg,#ea580c,#c2410c);color:#fff}.channel-title[data-v-3a91c627]{font-size:13px;font-weight:700;margin:0;color:var(--text-primary);letter-spacing:.3px;line-height:1.15;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;flex:1}.channel-content[data-v-3a91c627]{flex:1;min-height:0;overflow:hidden;padding:10px;display:flex;flex-direction:column;gap:6px}.card[data-v-3a91c627]{background:linear-gradient(180deg,#fffffff0,#f7faf8f5);border:1px solid rgba(216,225,222,.92);border-radius:18px;overflow:hidden;transition:all .3s cubic-bezier(.4,0,.2,1);box-shadow:0 10px 28px #0f171d0f;position:relative}.card[data-v-3a91c627]: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-3a91c627]:hover{box-shadow:0 18px 38px #0f171d1a;border-color:#c3d0cbf2}.card[data-v-3a91c627]:hover:before{opacity:1}.card.clickable[data-v-3a91c627]{cursor:pointer}.card.clickable[data-v-3a91c627]:hover{border-color:#18a058;transform:translateY(-2px);box-shadow:0 8px 24px #18a0582e}.card.clickable[data-v-3a91c627]: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-3a91c627]:hover:after{opacity:1}.card-header[data-v-3a91c627]{display:flex;align-items:center;gap:8px;padding:9px 12px;background:linear-gradient(180deg,#f4f7f8f5,#ffffffd6);border-bottom:1px solid rgba(216,225,222,.9);position:relative;min-height:24px}.card-header.compact[data-v-3a91c627]{padding:8px 12px}.card-header .n-icon[data-v-3a91c627]{color:var(--text-tertiary);transition:color .2s ease}.card:hover .card-header .n-icon[data-v-3a91c627]{color:var(--text-secondary)}.card-title[data-v-3a91c627]{font-size:11px;font-weight:700;margin:0;color:var(--text-secondary);text-transform:uppercase;letter-spacing:.8px}.runtime-badge[data-v-3a91c627]{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:999px;white-space:nowrap;animation:pulse-runtime-3a91c627 2s ease-in-out infinite}@keyframes pulse-runtime-3a91c627{0%,to{opacity:1;transform:scale(1)}50%{opacity:.8;transform:scale(.98)}}.card-body[data-v-3a91c627]{padding:8px 10px;background:transparent}.card-body.compact[data-v-3a91c627]{padding:7px 10px}.proxy-control[data-v-3a91c627]{display:flex;justify-content:space-between;align-items:center;gap:16px}.proxy-info[data-v-3a91c627]{display:flex;flex-direction:column;gap:4px}.proxy-info-row[data-v-3a91c627]{display:flex;align-items:center;justify-content:space-between}.proxy-status[data-v-3a91c627]{display:flex;align-items:center;gap:6px}.proxy-port[data-v-3a91c627]{font-size:11px;color:var(--text-secondary);margin-left:6px}.channel-selector[data-v-3a91c627]{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-3a91c627]:hover{background:var(--hover-bg);border-color:var(--border-secondary);color:var(--text-primary)}.channel-selector[data-v-3a91c627]:disabled{opacity:.5;cursor:not-allowed}.channel-name[data-v-3a91c627]{font-size:11px;font-weight:500;max-width:90px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.status-dot[data-v-3a91c627]{width:8px;height:8px;border-radius:50%;background:var(--border-secondary);transition:all .3s ease}.status-dot.active[data-v-3a91c627]{background:#18a058;box-shadow:0 0 8px #18a05880}.quick-stats[data-v-3a91c627]{display:flex;gap:16px;padding:4px 0}.stat-item[data-v-3a91c627]{flex:1;display:flex;flex-direction:column;align-items:center;gap:2px;padding:4px 0}.stat-divider[data-v-3a91c627]{width:1px;background:linear-gradient(180deg,transparent 0%,var(--border-primary) 50%,transparent 100%)}.quick-access-list[data-v-3a91c627]{display:grid;grid-template-columns:repeat(3,1fr);gap:4px}.access-card[data-v-3a91c627]{display:flex;align-items:center;gap:5px;padding:7px 8px;border-radius:14px;background:#f4f7f8e0;border:1px solid rgba(216,225,222,.9);transition:all .3s cubic-bezier(.4,0,.2,1);position:relative;min-height:44px;overflow:hidden}.access-card[data-v-3a91c627]: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-3a91c627]{width:28px;height:28px;border-radius:9px;display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:all .3s ease}.access-content[data-v-3a91c627]{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0;overflow:hidden}.access-card-projects .access-icon[data-v-3a91c627]{background:linear-gradient(135deg,#6366f126,#8b5cf626);color:#6366f1}.access-card-projects[data-v-3a91c627]:before{background:linear-gradient(135deg,#6366f114,#8b5cf614)}.access-card-projects:hover .access-icon[data-v-3a91c627]{background:linear-gradient(135deg,#6366f140,#8b5cf640);transform:scale(1.1) rotate(-5deg)}.access-card-sessions .access-icon[data-v-3a91c627]{background:linear-gradient(135deg,#10b98126,#05966926);color:#10b981}.access-card-sessions[data-v-3a91c627]:before{background:linear-gradient(135deg,#10b98114,#05966914)}.access-card-sessions:hover .access-icon[data-v-3a91c627]{background:linear-gradient(135deg,#10b98140,#05966940);transform:scale(1.1) rotate(5deg)}.access-card-goto .access-icon[data-v-3a91c627]{background:linear-gradient(135deg,#f59e0b26,#fb923c26);color:#f59e0b}.access-card-goto[data-v-3a91c627]:before{background:linear-gradient(135deg,#f59e0b14,#fb923c14)}.access-card-goto:hover .access-icon[data-v-3a91c627]{background:linear-gradient(135deg,#f59e0b40,#fb923c40);transform:scale(1.1) translate(3px)}.access-card.clickable[data-v-3a91c627]:hover{transform:translateY(-2px);box-shadow:0 8px 20px #0000001a;border-color:var(--border-secondary)}.access-card.clickable[data-v-3a91c627]:hover:before{opacity:1}.access-card.clickable[data-v-3a91c627]:active{transform:translateY(0)}.access-label[data-v-3a91c627]{display:block;font-size:8px;font-weight:600;color:var(--text-secondary);text-transform:uppercase;letter-spacing:.3px;white-space:nowrap;line-height:1.1}.access-value[data-v-3a91c627]{display:block;font-size:13px;font-weight:800;color:var(--text-primary);line-height:1;white-space:nowrap}.access-goto[data-v-3a91c627]{display:block;font-size:9px;font-weight:700;color:var(--text-primary);line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.stats-inline[data-v-3a91c627]{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}.stats-inline.stats-3col[data-v-3a91c627]{grid-template-columns:repeat(3,1fr)}.stat-inline-item[data-v-3a91c627]{display:flex;align-items:center;gap:8px;padding:10px;background:#f4f7f8e6;border-radius:14px;border:1px solid rgba(216,225,222,.88);transition:all .2s ease}.stat-inline-item[data-v-3a91c627]:hover{border-color:var(--border-secondary);background:var(--hover-bg)}.stat-icon-dot[data-v-3a91c627]{width:8px;height:8px;border-radius:50%;flex-shrink:0}.stat-icon-dot.requests[data-v-3a91c627]{background:#3b82f6;box-shadow:0 0 6px #3b82f680}.stat-icon-dot.tokens[data-v-3a91c627]{background:#18a058;box-shadow:0 0 6px #18a05880}.stat-icon-dot.cost[data-v-3a91c627]{background:#f59e0b;box-shadow:0 0 6px #f59e0b80}.stat-info[data-v-3a91c627]{display:flex;flex-direction:column;gap:1px;min-width:0}.stat-label[data-v-3a91c627]{font-size:10px;color:var(--text-tertiary);font-weight:500;text-transform:uppercase;letter-spacing:.2px}.stat-value[data-v-3a91c627]{font-size:16px;font-weight:700;color:var(--text-primary);line-height:1.2;transition:all .3s ease}.stat-value.animating[data-v-3a91c627]{animation:numberChange-3a91c627 .6s ease}@keyframes numberChange-3a91c627{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-3a91c627],.chart-card[data-v-3a91c627]{border-left:2px solid transparent}.stats-card-claude[data-v-3a91c627],.chart-card[data-v-3a91c627]:has(+.stats-card-claude),.card[data-v-3a91c627]:has(.panel-card):nth-child(4){border-left-color:#18a058}.chart-card.chart-card-claude[data-v-3a91c627]{border-left-color:#18a058}.stats-card-codex[data-v-3a91c627],.chart-card[data-v-3a91c627]:has(+.stats-card-codex),.card[data-v-3a91c627]:has(.panel-card):nth-child(4){border-left-color:#3b82f6}.chart-card.chart-card-codex[data-v-3a91c627]{border-left-color:#3b82f6}.stats-card-gemini[data-v-3a91c627],.chart-card[data-v-3a91c627]:has(+.stats-card-gemini),.card[data-v-3a91c627]:has(.panel-card):nth-child(4){border-left-color:#a855f7}.chart-card.chart-card-gemini[data-v-3a91c627]{border-left-color:#a855f7}.stats-card-opencode[data-v-3a91c627],.chart-card[data-v-3a91c627]:has(+.stats-card-opencode),.card[data-v-3a91c627]:has(.panel-card):nth-child(4){border-left-color:#ea580c}.chart-card.chart-card-opencode[data-v-3a91c627]{border-left-color:#ea580c}.chart-card[data-v-3a91c627]{padding:0;overflow:hidden}.chart-card[data-v-3a91c627] .panel-card{border:none;border-radius:0;box-shadow:none;background:transparent}.stat-requests .stat-value[data-v-3a91c627]{color:#3b82f6}.stat-input .stat-value[data-v-3a91c627]{color:#18a058}.stat-output .stat-value[data-v-3a91c627]{color:#f59e0b}.token-label[data-v-3a91c627]{display:flex;align-items:center;gap:8px}.token-dot[data-v-3a91c627]{width:8px;height:8px;border-radius:50%}.logs-card[data-v-3a91c627]{flex:1;min-height:0;display:flex;flex-direction:column;overflow:hidden;border:1px solid rgba(216,225,222,.88);border-radius:18px}.logs-card-body[data-v-3a91c627]{flex:1;min-height:0;display:flex;flex-direction:column;padding:0}.logs-card .card-header[data-v-3a91c627]{background:linear-gradient(135deg,var(--bg-secondary) 0%,var(--bg-tertiary) 100%)}.logs-table-wrapper[data-v-3a91c627]{flex:1;min-height:0;display:flex;flex-direction:column;overflow:hidden;background:var(--bg-primary)}.logs-table-header[data-v-3a91c627]{display:flex;padding:8px 12px;background:linear-gradient(180deg,#edf3f1f5,#f4f7f8eb);border-bottom:1px solid rgba(216,225,222,.92);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-3a91c627]{color:#18a058b3;font-weight:600}.logs-header-codex .log-col[data-v-3a91c627]{color:#3b82f6b3;font-weight:600}.logs-header-gemini .log-col[data-v-3a91c627]{color:#a855f7b3;font-weight:600}.logs-header-opencode .log-col[data-v-3a91c627]{color:#ea580cb3;font-weight:600}[data-theme=dark] .logs-header-claude .log-col[data-v-3a91c627]{color:#34d399a6}[data-theme=dark] .logs-header-codex .log-col[data-v-3a91c627]{color:#60a5faa6}[data-theme=dark] .logs-header-gemini .log-col[data-v-3a91c627]{color:#c084fca6}[data-theme=dark] .logs-header-opencode .log-col[data-v-3a91c627]{color:#fb923ca6}[data-theme=dark] .channel-column[data-v-3a91c627]{background:linear-gradient(180deg,#111b20f5,#0d161bfa);border-color:#2b424ae6;box-shadow:0 24px 56px #00000047}[data-theme=dark] .channel-header[data-v-3a91c627]{background:linear-gradient(180deg,#162329e6,#111b20c7)}[data-theme=dark] .card[data-v-3a91c627],[data-theme=dark] .access-card[data-v-3a91c627],[data-theme=dark] .stat-inline-item[data-v-3a91c627]{background:linear-gradient(180deg,#111b20f2,#0f1a1ffa);border-color:#2b424ae6}.logs-container[data-v-3a91c627]{flex:1;min-height:0;overflow-y:auto;overflow-x:hidden}.logs-container[data-v-3a91c627]::-webkit-scrollbar{width:4px}.logs-container[data-v-3a91c627]::-webkit-scrollbar-thumb{background:#18a0584d;border-radius:2px}.logs-container[data-v-3a91c627]::-webkit-scrollbar-thumb:hover{background:#18a05880}.empty-logs[data-v-3a91c627]{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-3a91c627]{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-3a91c627]:nth-child(2n){background:var(--bg-secondary)}.log-row[data-v-3a91c627]:hover{background:var(--hover-bg);transform:translate(2px)}.log-row.new-log[data-v-3a91c627]{animation:newLogPulse-3a91c627 4.5s cubic-bezier(.25,.46,.45,.94) forwards;border-left:3px solid #18a058}@keyframes newLogPulse-3a91c627{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-3a91c627]{animation:newLogPulseDark-3a91c627 4.5s cubic-bezier(.25,.46,.45,.94) forwards}@keyframes newLogPulseDark-3a91c627{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-3a91c627]{border-left:3px solid #18a058}.log-row.action-row[data-v-3a91c627]{background:linear-gradient(90deg,#18a0581f,#18a0580a);border-left:3px solid #18a058;padding-left:8px}.log-row.error-row[data-v-3a91c627]{background:linear-gradient(90deg,#d0305024,#d030500a);border-left:3px solid #d03050;padding-left:8px}.log-row.action-row[data-v-3a91c627]:hover{background:linear-gradient(90deg,#18a0582e,#18a05814)}.log-row.error-row[data-v-3a91c627]:hover{background:linear-gradient(90deg,#d0305033,#d0305014)}.action-content[data-v-3a91c627]{display:flex;align-items:center;gap:8px;width:100%}.action-msg[data-v-3a91c627]{flex:1;font-size:11px;color:#18a058;font-weight:600;letter-spacing:.2px}.action-msg.error-msg[data-v-3a91c627]{color:#d03050}.action-time[data-v-3a91c627]{font-size:10px;font-family:SF Mono,Monaco,monospace;color:var(--text-tertiary);background:#18a0581a;padding:2px 6px;border-radius:4px}.action-time.error-time[data-v-3a91c627]{background:#d030501f}.log-col[data-v-3a91c627]{display:flex;align-items:center;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.col-channel[data-v-3a91c627]{min-width:0}.col-channel .n-tag[data-v-3a91c627]{max-width:100%;font-size:11px;font-weight:600;border-radius:4px;padding:3px 10px}.col-token[data-v-3a91c627]{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-3a91c627]{background:#ffffff0f}.col-time[data-v-3a91c627]{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-3a91c627]{opacity:1;color:var(--text-secondary)}.col-channel-claude[data-v-3a91c627]{flex:2 1 60px;min-width:50px}.col-token-claude[data-v-3a91c627]{flex:1 1 40px;min-width:35px}.col-time-claude[data-v-3a91c627]{flex:1.5 1 55px;min-width:50px}.col-channel-codex[data-v-3a91c627]{flex:2 1 60px;min-width:50px}.col-token-codex[data-v-3a91c627]{flex:1 1 40px;min-width:35px}.col-time-codex[data-v-3a91c627]{flex:1.5 1 55px;min-width:50px}.col-channel-gemini[data-v-3a91c627]{flex:2.5 1 70px;min-width:55px}.col-token-gemini[data-v-3a91c627]{flex:1.2 1 45px;min-width:40px}.col-time-gemini[data-v-3a91c627]{flex:1.8 1 60px;min-width:55px}.col-channel-opencode[data-v-3a91c627]{flex:2.5 1 70px;min-width:55px}.col-token-opencode[data-v-3a91c627]{flex:1.2 1 45px;min-width:40px}.col-time-opencode[data-v-3a91c627]{flex:1.8 1 60px;min-width:55px}.claude-extra-area[data-v-3a91c627]{display:flex;align-items:center;gap:6px;margin-left:auto}.mcp-count-tag[data-v-3a91c627],.skills-count-tag[data-v-3a91c627]{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-3a91c627]:hover,.skills-count-tag.clickable[data-v-3a91c627]:hover{transform:scale(1.03);filter:brightness(1.1)}.mcp-quick-panel[data-v-3a91c627],.skills-quick-panel[data-v-3a91c627]{padding:2px 0}.mcp-quick-panel .panel-title[data-v-3a91c627],.skills-quick-panel .panel-title[data-v-3a91c627]{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-3a91c627]:first-child,.skills-quick-panel .panel-title span[data-v-3a91c627]:first-child{font-size:13px;font-weight:600;color:var(--text-primary)}.no-items[data-v-3a91c627]{padding:16px 10px;text-align:center}.mcp-quick-list[data-v-3a91c627],.skills-quick-list[data-v-3a91c627]{max-height:300px;overflow-y:auto;padding:0 4px 4px}.mcp-quick-item[data-v-3a91c627],.skill-quick-item[data-v-3a91c627]{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-3a91c627]:hover,.skill-quick-item[data-v-3a91c627]:hover{background:var(--hover-bg)}.mcp-item-icon[data-v-3a91c627],.skill-item-icon[data-v-3a91c627]{width:24px;height:24px;border-radius:5px;display:flex;align-items:center;justify-content:center;flex-shrink:0}.mcp-item-icon[data-v-3a91c627]{background:linear-gradient(135deg,#3b82f626,#3b82f60d);color:#3b82f6}.skill-item-icon[data-v-3a91c627]{background:linear-gradient(135deg,#18a05826,#18a0580d);color:#18a058}.mcp-item-info[data-v-3a91c627],.skill-item-info[data-v-3a91c627]{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}.mcp-item-name[data-v-3a91c627],.skill-item-name[data-v-3a91c627]{font-size:12px;font-weight:600;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mcp-item-type[data-v-3a91c627]{font-size:10px;color:var(--text-tertiary);text-transform:uppercase}.skill-item-desc[data-v-3a91c627]{font-size:10px;color:var(--text-tertiary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mcp-item-status[data-v-3a91c627]{flex-shrink:0}.mcp-item-status .status-dot[data-v-3a91c627]{width:8px;height:8px;border-radius:50%;background:var(--border-secondary)}.mcp-item-status.online .status-dot[data-v-3a91c627]{background:#18a058;box-shadow:0 0 6px #18a05880}.mcp-item-status.error .status-dot[data-v-3a91c627]{background:#d03050;box-shadow:0 0 6px #d0305080}.mcp-quick-list[data-v-3a91c627]::-webkit-scrollbar,.skills-quick-list[data-v-3a91c627]::-webkit-scrollbar{width:4px}.mcp-quick-list[data-v-3a91c627]::-webkit-scrollbar-thumb,.skills-quick-list[data-v-3a91c627]::-webkit-scrollbar-thumb{background:#00000026;border-radius:2px}[data-theme=dark] .mcp-quick-list[data-v-3a91c627]::-webkit-scrollbar-thumb,[data-theme=dark] .skills-quick-list[data-v-3a91c627]::-webkit-scrollbar-thumb{background:#ffffff26}.config-shortcut-button[data-v-3a91c627]{--asset-shortcut-text: var(--text-color-3);--n-text-color: var(--asset-shortcut-text) !important;--n-text-color-hover: var(--asset-shortcut-text) !important;--n-text-color-pressed: var(--asset-shortcut-text) !important;--n-text-color-focus: var(--asset-shortcut-text) !important;padding:6px!important;width:28px;height:28px;display:flex;align-items:center;justify-content:center;border-radius:5px;background:var(--bg-secondary);border:1px solid var(--border-primary);color:var(--asset-shortcut-text)!important;transition:transform .18s cubic-bezier(.4,0,.2,1),box-shadow .18s cubic-bezier(.4,0,.2,1);box-shadow:0 2px 4px #0000000d}.config-shortcut-button .n-icon[data-v-3a91c627]{color:var(--asset-shortcut-text)!important;transition:transform .18s ease}.config-shortcut-button[data-v-3a91c627] .n-button__content,.config-shortcut-button[data-v-3a91c627] .n-button__icon{color:var(--asset-shortcut-text)!important}.config-shortcut-button[data-v-3a91c627]:hover,.config-shortcut-button[data-v-3a91c627]:focus,.config-shortcut-button[data-v-3a91c627]:focus-visible{background:var(--bg-secondary);border-color:var(--border-primary);color:var(--asset-shortcut-text)!important;box-shadow:0 3px 8px #00000014;transform:translateY(-1px)}.config-shortcut-button:hover .n-icon[data-v-3a91c627],.config-shortcut-button:focus .n-icon[data-v-3a91c627],.config-shortcut-button:focus-visible .n-icon[data-v-3a91c627]{color:var(--asset-shortcut-text)!important;transform:scale(1.1)}.config-shortcut-button[data-v-3a91c627]:active{background:var(--bg-secondary);border-color:var(--border-primary);color:var(--asset-shortcut-text)!important;transform:translateY(0);box-shadow:0 2px 4px #0000000d}.lock-button[data-v-3a91c627]{margin-left:6px;padding:6px!important;width:28px;height:28px;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-3a91c627]{color:var(--text-color-3);transition:all .25s ease}.lock-button[data-v-3a91c627]: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-3a91c627]{color:var(--text-color-1);transform:scale(1.1)}.lock-button[data-v-3a91c627]:active{transform:translateY(0);box-shadow:0 2px 4px #0000000d}.locked-overlay[data-v-3a91c627]{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-3a91c627]: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-3a91c627]{background:linear-gradient(135deg,rgba(24,160,88,.03) 0%,var(--bg-secondary) 50%,rgba(24,160,88,.02) 100%)}.locked-claude[data-v-3a91c627]:before{background:radial-gradient(circle,rgba(24,160,88,.15) 0%,transparent 70%)}.locked-codex[data-v-3a91c627]{background:linear-gradient(135deg,rgba(59,130,246,.03) 0%,var(--bg-secondary) 50%,rgba(59,130,246,.02) 100%)}.locked-codex[data-v-3a91c627]:before{background:radial-gradient(circle,rgba(59,130,246,.15) 0%,transparent 70%)}.locked-gemini[data-v-3a91c627]{background:linear-gradient(135deg,rgba(168,85,247,.03) 0%,var(--bg-secondary) 50%,rgba(168,85,247,.02) 100%)}.locked-gemini[data-v-3a91c627]:before{background:radial-gradient(circle,rgba(168,85,247,.15) 0%,transparent 70%)}.locked-opencode[data-v-3a91c627]{background:linear-gradient(135deg,rgba(234,88,12,.03) 0%,var(--bg-secondary) 50%,rgba(234,88,12,.02) 100%)}.locked-opencode[data-v-3a91c627]:before{background:radial-gradient(circle,rgba(234,88,12,.15) 0%,transparent 70%)}.locked-content[data-v-3a91c627]{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-3a91c627]{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-3a91c627 3s ease-in-out infinite}@keyframes lock-float-3a91c627{0%,to{transform:translateY(0)}50%{transform:translateY(-6px)}}.lock-icon[data-v-3a91c627]: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-3a91c627]{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-3a91c627]:before{background:radial-gradient(circle,rgba(24,160,88,.3) 0%,transparent 60%)}.locked-claude .lock-icon .n-icon[data-v-3a91c627]{color:#18a058;filter:drop-shadow(0 2px 4px rgba(24,160,88,.3))}.locked-codex .lock-icon[data-v-3a91c627]{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-3a91c627]:before{background:radial-gradient(circle,rgba(59,130,246,.3) 0%,transparent 60%)}.locked-codex .lock-icon .n-icon[data-v-3a91c627]{color:#3b82f6;filter:drop-shadow(0 2px 4px rgba(59,130,246,.3))}.locked-gemini .lock-icon[data-v-3a91c627]{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-3a91c627]:before{background:radial-gradient(circle,rgba(168,85,247,.3) 0%,transparent 60%)}.locked-gemini .lock-icon .n-icon[data-v-3a91c627]{color:#a855f7;filter:drop-shadow(0 2px 4px rgba(168,85,247,.3))}.locked-opencode .lock-icon[data-v-3a91c627]{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-3a91c627]:before{background:radial-gradient(circle,rgba(234,88,12,.3) 0%,transparent 60%)}.locked-opencode .lock-icon .n-icon[data-v-3a91c627]{color:#ea580c;filter:drop-shadow(0 2px 4px rgba(234,88,12,.3))}.lock-icon .n-icon[data-v-3a91c627]{opacity:.85;position:relative;z-index:1}.locked-title[data-v-3a91c627]{font-size:17px;font-weight:600;color:var(--text-color-1);margin:0;letter-spacing:.3px}.locked-hint[data-v-3a91c627]{font-size:13px;color:var(--text-color-3);max-width:220px;line-height:1.7;opacity:.9}.channel-status[data-v-3a91c627]{cursor:pointer;padding:4px 8px!important;border-radius:4px;transition:all .2s ease}.channel-status[data-v-3a91c627]:hover{background:var(--hover-bg)}.channel-quick-panel[data-v-3a91c627]{padding:4px 0}.panel-title[data-v-3a91c627]{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-3a91c627]:first-child{font-size:13px;font-weight:600;color:var(--text-primary)}.no-channels[data-v-3a91c627]{padding:24px 12px;text-align:center}.channel-quick-list[data-v-3a91c627]{max-height:360px;overflow-y:auto}.channel-quick-item[data-v-3a91c627]{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-3a91c627]:hover{background:var(--hover-bg)}.channel-quick-item.disabled[data-v-3a91c627]{opacity:.6}.channel-quick-info[data-v-3a91c627]{display:flex;align-items:center;gap:8px;width:100%}.channel-quick-name[data-v-3a91c627]{font-size:13px;font-weight:600;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.channel-metrics[data-v-3a91c627]{display:flex;gap:6px;width:100%}.channel-metrics .metric-item[data-v-3a91c627]{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-3a91c627]{font-size:10px;color:var(--text-tertiary);font-weight:500}.channel-metrics .metric-value[data-v-3a91c627]{font-size:12px;font-weight:700;color:var(--text-primary);font-family:SF Mono,Monaco,monospace}.channel-metrics .metric-value.active[data-v-3a91c627]{color:#f59e0b}.channel-switching-tip[data-v-3a91c627]{font-size:11px;color:var(--text-tertiary);padding:0 2px}.channel-quick-item.disabled .channel-metrics .metric-value[data-v-3a91c627]{color:var(--text-tertiary)}.channel-quick-list[data-v-3a91c627]::-webkit-scrollbar{width:4px}.channel-quick-list[data-v-3a91c627]::-webkit-scrollbar-thumb{background:#00000026;border-radius:2px}[data-theme=dark] .channel-quick-list[data-v-3a91c627]::-webkit-scrollbar-thumb{background:#ffffff26}@media (max-width: 1024px){.channel-column[data-v-3a91c627]{border-radius:6px}.card-header[data-v-3a91c627]{padding:8px 10px}.card-title[data-v-3a91c627]{font-size:13px}.stats-inline[data-v-3a91c627]{gap:6px}.stat-inline-item[data-v-3a91c627]{padding:8px}.stat-value[data-v-3a91c627]{font-size:14px}.stat-label[data-v-3a91c627]{font-size:9px}.logs-table-header[data-v-3a91c627]{padding:8px 10px;font-size:10px}.log-row[data-v-3a91c627]{padding:8px 10px;font-size:11px}}@media (max-width: 768px){.channel-column[data-v-3a91c627]{border-radius:6px;min-height:300px;height:auto;max-height:400px}.card-header[data-v-3a91c627]{padding:8px;gap:6px}.card-title[data-v-3a91c627]{font-size:12px}.stats-inline[data-v-3a91c627]{gap:4px}.stat-inline-item[data-v-3a91c627]{padding:6px;gap:6px}.stat-icon-dot[data-v-3a91c627]{width:6px;height:6px}.stat-value[data-v-3a91c627]{font-size:13px}.stat-label[data-v-3a91c627]{font-size:8px}.logs-card[data-v-3a91c627]{min-height:150px}.logs-table-header[data-v-3a91c627]{padding:6px 8px;font-size:9px}.log-row[data-v-3a91c627]{padding:6px 8px;font-size:10px;min-height:32px}.col-token[data-v-3a91c627]{font-size:10px;padding:2px 4px}.col-time[data-v-3a91c627]{font-size:9px}.mcp-count-tag[data-v-3a91c627],.skills-count-tag[data-v-3a91c627]{font-size:9px;padding:0 6px;height:18px;line-height:18px}.config-shortcut-button[data-v-3a91c627]{padding:4px 8px;font-size:10px;gap:4px}.lock-button[data-v-3a91c627]{width:26px;height:26px}}@media (max-width: 640px){.channel-column[data-v-3a91c627]{min-height:250px;max-height:350px}.card-header[data-v-3a91c627]{padding:6px;gap:4px;flex-wrap:wrap}.card-title[data-v-3a91c627]{font-size:11px}.stats-card .card-content[data-v-3a91c627]{padding:6px}.stats-inline[data-v-3a91c627]{gap:3px;flex-wrap:wrap}.stat-inline-item[data-v-3a91c627]{padding:5px;gap:4px;min-width:calc(33% - 3px);flex:1 1 auto}.stat-icon-dot[data-v-3a91c627]{width:5px;height:5px}.stat-value[data-v-3a91c627]{font-size:12px}.stat-label[data-v-3a91c627]{font-size:7px}.logs-card[data-v-3a91c627]{min-height:120px}.logs-table-header[data-v-3a91c627]{padding:5px 6px;font-size:8px;letter-spacing:.3px}.log-row[data-v-3a91c627]{padding:5px 6px;font-size:9px;min-height:28px}.col-channel .n-tag[data-v-3a91c627]{font-size:9px;padding:2px 6px}.col-token[data-v-3a91c627]{font-size:9px;padding:2px 3px;margin:0 1px}.col-time[data-v-3a91c627]{font-size:8px}.claude-extra-area[data-v-3a91c627]{gap:4px}.mcp-count-tag[data-v-3a91c627],.skills-count-tag[data-v-3a91c627]{font-size:8px;padding:0 4px;height:16px;line-height:16px}.config-shortcut-button[data-v-3a91c627]{padding:3px 6px;font-size:9px;gap:3px}.config-shortcut-button .n-icon[data-v-3a91c627]{font-size:12px!important}.lock-button[data-v-3a91c627]{width:24px;height:24px;margin-left:4px}.lock-button .n-icon[data-v-3a91c627]{font-size:12px!important}.locked-content[data-v-3a91c627]{padding:30px 20px;gap:12px}.lock-icon[data-v-3a91c627]{width:64px;height:64px}.lock-icon .n-icon[data-v-3a91c627]{font-size:28px!important}.lock-title[data-v-3a91c627]{font-size:14px}.lock-subtitle[data-v-3a91c627]{font-size:10px}.unlock-btn[data-v-3a91c627]{padding:8px 16px;font-size:11px}}@media (max-width: 480px){.channel-column[data-v-3a91c627]{min-height:220px;max-height:300px}.card-header[data-v-3a91c627]{padding:5px}.card-title[data-v-3a91c627]{font-size:10px}.stats-inline[data-v-3a91c627]{gap:2px}.stat-inline-item[data-v-3a91c627]{padding:4px;gap:3px}.stat-value[data-v-3a91c627]{font-size:11px}.stat-label[data-v-3a91c627]{font-size:6px}.logs-table-header[data-v-3a91c627]{padding:4px 5px;font-size:7px}.log-row[data-v-3a91c627]{padding:4px 5px;font-size:8px;min-height:24px}.col-token[data-v-3a91c627]{font-size:8px}.col-time[data-v-3a91c627]{font-size:7px}}.card[data-v-3a91c627]:not(.logs-card) .n-collapse{background:transparent}.card[data-v-3a91c627]:not(.logs-card) .n-collapse-item{background:transparent}.card[data-v-3a91c627] .n-collapse-item__header{padding:12px 16px;background:transparent;transition:all .3s ease}.card[data-v-3a91c627] .n-collapse-item__header:hover{background:#00000005}.card[data-v-3a91c627] .n-collapse-item__header-main{width:100%}.card[data-v-3a91c627]:not(.logs-card) .n-collapse-item__content-wrapper{padding:0 16px 12px}.card[data-v-3a91c627]:not(.logs-card) .n-collapse-item__content-inner{padding-top:0}.chart-card[data-v-3a91c627]:has(.n-collapse){padding:0}.dashboard-container[data-v-a6410dd2]{height:100%;background:var(--gradient-bg);overflow:hidden;padding:18px;box-sizing:border-box;display:flex;flex-direction:column}.dashboard-toolbar[data-v-a6410dd2]{display:flex;justify-content:flex-end;margin-bottom:8px;flex-shrink:0}.analytics-link[data-v-a6410dd2]{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-a6410dd2]:hover{background:#18a05826}.analytics-link-icon[data-v-a6410dd2]{font-size:14px}.dashboard-grid[data-v-a6410dd2]{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;flex:1;min-height:0;overflow:hidden;box-sizing:border-box;align-items:stretch}.dashboard-grid[data-v-a6410dd2] .sortable-ghost{opacity:.4}.dashboard-grid[data-v-a6410dd2] .sortable-chosen{box-shadow:0 8px 24px #00000026}@media (max-width: 1240px){.dashboard-grid[data-v-a6410dd2]{grid-template-columns:repeat(3,1fr)}}@media (max-width: 960px){.dashboard-grid[data-v-a6410dd2]{grid-template-columns:repeat(2,1fr)}}@media (max-width: 1024px){.dashboard-container[data-v-a6410dd2]{padding:14px}.dashboard-grid[data-v-a6410dd2]{gap:12px}}@media (max-width: 900px){.dashboard-grid[data-v-a6410dd2]{grid-template-columns:1fr}}@media (max-width: 768px){.dashboard-container[data-v-a6410dd2]{padding:10px;overflow-y:auto}.dashboard-grid[data-v-a6410dd2]{gap:10px;overflow:visible;min-height:auto}}@media (max-width: 640px){.dashboard-container[data-v-a6410dd2]{padding:6px}.dashboard-grid[data-v-a6410dd2]{gap:6px}}@media (max-width: 480px){.dashboard-container[data-v-a6410dd2]{padding:4px}.dashboard-grid[data-v-a6410dd2]{gap:4px}}