cc-viewer 1.6.293 → 1.6.295

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 (110) hide show
  1. package/cli.js +7 -2
  2. package/dist/assets/App-Br-u2TKk.js +2 -0
  3. package/dist/assets/App-eFrjLzF_.css +1 -0
  4. package/dist/assets/{MdxEditorPanel-Cf01KF6Z.js → MdxEditorPanel-Cy4egsQx.js} +1 -1
  5. package/dist/assets/{Mobile-BJlGkvAP.js → Mobile-ZHF74GQs.js} +1 -1
  6. package/dist/assets/{_baseUniq-CPUnJ5bQ.js → _baseUniq-r3p3rodd.js} +1 -1
  7. package/dist/assets/{arc-WhuJ-oY5.js → arc-CjTV5gxc.js} +1 -1
  8. package/dist/assets/{architectureDiagram-Q4EWVU46-CWx77Yhd.js → architectureDiagram-Q4EWVU46-BqzjXpCq.js} +1 -1
  9. package/dist/assets/{blockDiagram-DXYQGD6D-D7AQLCoj.js → blockDiagram-DXYQGD6D-CLyFfeHh.js} +1 -1
  10. package/dist/assets/{c4Diagram-AHTNJAMY-BoPHNqCF.js → c4Diagram-AHTNJAMY-BaO-0tuc.js} +1 -1
  11. package/dist/assets/{channel-B9Ja6Xkc.js → channel-yOyhvOLV.js} +1 -1
  12. package/dist/assets/{chunk-4BX2VUAB-B-b0RYab.js → chunk-4BX2VUAB-CMTnvZkS.js} +1 -1
  13. package/dist/assets/{chunk-4TB4RGXK-BK_V34yf.js → chunk-4TB4RGXK-QI41m9WP.js} +1 -1
  14. package/dist/assets/{chunk-55IACEB6-D-kMbu-2.js → chunk-55IACEB6-C4ZO8bM3.js} +1 -1
  15. package/dist/assets/{chunk-EDXVE4YY-CEtSkZzd.js → chunk-EDXVE4YY-Bo8P4o65.js} +1 -1
  16. package/dist/assets/{chunk-FMBD7UC4-BXa_7Pn3.js → chunk-FMBD7UC4-CTHLGcHh.js} +1 -1
  17. package/dist/assets/{chunk-OYMX7WX6-tvM_OApS.js → chunk-OYMX7WX6-D0OHxKGd.js} +1 -1
  18. package/dist/assets/{chunk-QZHKN3VN-DrEmcVHf.js → chunk-QZHKN3VN-CoYnjUpS.js} +1 -1
  19. package/dist/assets/{chunk-YZCP3GAM-D2M9T_R5.js → chunk-YZCP3GAM-BY71mTXM.js} +1 -1
  20. package/dist/assets/classDiagram-6PBFFD2Q-C9o5ip5q.js +1 -0
  21. package/dist/assets/classDiagram-v2-HSJHXN6E-C9o5ip5q.js +1 -0
  22. package/dist/assets/clone-GDqN3kwT.js +1 -0
  23. package/dist/assets/{cose-bilkent-S5V4N54A-H7bkwu5F.js → cose-bilkent-S5V4N54A-DUNsA_MT.js} +1 -1
  24. package/dist/assets/{dagre-KV5264BT-DKXEGN18.js → dagre-KV5264BT-BzlT2Exr.js} +1 -1
  25. package/dist/assets/{diagram-5BDNPKRD-DZFhwpI3.js → diagram-5BDNPKRD-CiqQK3Ci.js} +1 -1
  26. package/dist/assets/{diagram-G4DWMVQ6-Crg9GlIk.js → diagram-G4DWMVQ6-BciK18tQ.js} +1 -1
  27. package/dist/assets/{diagram-MMDJMWI5-B8Qn1fKP.js → diagram-MMDJMWI5-C1WH1vfU.js} +1 -1
  28. package/dist/assets/{diagram-TYMM5635-BHE1LjtY.js → diagram-TYMM5635-CR5RzJ6u.js} +1 -1
  29. package/dist/assets/{erDiagram-SMLLAGMA-BaEqFWLd.js → erDiagram-SMLLAGMA-NJQKXu51.js} +1 -1
  30. package/dist/assets/{flowDiagram-DWJPFMVM-b2ukTawV.js → flowDiagram-DWJPFMVM-Cjx5t_1H.js} +1 -1
  31. package/dist/assets/{ganttDiagram-T4ZO3ILL-D5quyFgK.js → ganttDiagram-T4ZO3ILL-YFTDBBiU.js} +1 -1
  32. package/dist/assets/{gitGraphDiagram-UUTBAWPF-BE1H5_fN.js → gitGraphDiagram-UUTBAWPF-C2muKahz.js} +1 -1
  33. package/dist/assets/{graph-D_JLoOax.js → graph-I1olozIg.js} +1 -1
  34. package/dist/assets/{index-Cx8bk0Tp.js → index-7vxIrUNA.js} +1 -1
  35. package/dist/assets/{index-BDUs32pN.css → index-Be9T-kDq.css} +1 -1
  36. package/dist/assets/{index-CtrY6gFZ.js → index-C1RNAzAB.js} +1 -1
  37. package/dist/assets/{index-CQrdpZQb.js → index-Cf4FBg-V.js} +1 -1
  38. package/dist/assets/{index-B8UmlA4F.js → index-D-HPuqxB.js} +1 -1
  39. package/dist/assets/{index-k0AH8cvI.js → index-D2QUxu18.js} +1 -1
  40. package/dist/assets/index-DMuCrfTo.js +2 -0
  41. package/dist/assets/{index-DiZ9CErG.js → index-DhzoJ5wE.js} +1 -1
  42. package/dist/assets/{index-CWjqMDrs.js → index-fhI0i2p3.js} +1 -1
  43. package/dist/assets/{infoDiagram-42DDH7IO-DQKlrVkw.js → infoDiagram-42DDH7IO-C9bza97c.js} +1 -1
  44. package/dist/assets/{ishikawaDiagram-UXIWVN3A-BchFlpPc.js → ishikawaDiagram-UXIWVN3A-BtZGipfW.js} +1 -1
  45. package/dist/assets/{journeyDiagram-VCZTEJTY-Dg1mt4df.js → journeyDiagram-VCZTEJTY-CKTp590c.js} +1 -1
  46. package/dist/assets/{jszip.min-LIb2SFoK.js → jszip.min-DDU-_oA-.js} +1 -1
  47. package/dist/assets/{kanban-definition-6JOO6SKY-226va2PS.js → kanban-definition-6JOO6SKY-BHLNWfr5.js} +1 -1
  48. package/dist/assets/{layout-rSa8rcPi.js → layout-DBmqcl9N.js} +1 -1
  49. package/dist/assets/{linear-BeARi8nH.js → linear-Br9n7mCI.js} +1 -1
  50. package/dist/assets/{mermaid.core-CDgdx9l7.js → mermaid.core-BV3ugHFm.js} +2 -2
  51. package/dist/assets/{min-B9yebCuj.js → min-D-YA3MGY.js} +1 -1
  52. package/dist/assets/{mindmap-definition-QFDTVHPH-C3apVbdg.js → mindmap-definition-QFDTVHPH-CzrYj3cB.js} +1 -1
  53. package/dist/assets/{pieDiagram-DEJITSTG-xjOQoQeL.js → pieDiagram-DEJITSTG-BAvtfiT3.js} +1 -1
  54. package/dist/assets/{quadrantDiagram-34T5L4WZ-Dq8x_VN2.js → quadrantDiagram-34T5L4WZ-i4zhnBJq.js} +1 -1
  55. package/dist/assets/{requirementDiagram-MS252O5E-CLmO1Gai.js → requirementDiagram-MS252O5E-Cb2wX9Sk.js} +1 -1
  56. package/dist/assets/{sankeyDiagram-XADWPNL6-BuUP1Eqq.js → sankeyDiagram-XADWPNL6-CcpbP6z5.js} +1 -1
  57. package/dist/assets/seqResourceLoaders-C7X23dCJ.js +2 -0
  58. package/dist/assets/{seqResourceLoaders-DWKAvGtj.css → seqResourceLoaders-De_-fYhE.css} +2 -2
  59. package/dist/assets/{sequenceDiagram-FGHM5R23-B18koU20.js → sequenceDiagram-FGHM5R23-BcbUxMmI.js} +1 -1
  60. package/dist/assets/{stateDiagram-FHFEXIEX-Cj57OCcO.js → stateDiagram-FHFEXIEX-CpIa1qoO.js} +1 -1
  61. package/dist/assets/{stateDiagram-v2-QKLJ7IA2-C01a2p--.js → stateDiagram-v2-QKLJ7IA2-d3GoyW9S.js} +1 -1
  62. package/dist/assets/{timeline-definition-GMOUNBTQ-cOlsEN_F.js → timeline-definition-GMOUNBTQ-BfQPSOuT.js} +1 -1
  63. package/dist/assets/{vendor-antd-DqFS7Zj9.js → vendor-antd-Bur5ZxWE.js} +1 -1
  64. package/dist/assets/{vendor-codemirror-B_pF4DrA.js → vendor-codemirror-Si44UqBp.js} +1 -1
  65. package/dist/assets/{vendor-mdxeditor-B_IrHcWH.js → vendor-mdxeditor-Cco3AQJS.js} +2 -2
  66. package/dist/assets/{vendor-qrcode-C4PneAS5.js → vendor-qrcode-Dn3GYC4l.js} +1 -1
  67. package/dist/assets/{vendor-virtuoso-CEGeJyDP.js → vendor-virtuoso-CW9EqKMt.js} +1 -1
  68. package/dist/assets/{vennDiagram-DHZGUBPP-BCjdwiDk.js → vennDiagram-DHZGUBPP-hTgiYDQL.js} +1 -1
  69. package/dist/assets/{wardley-RL74JXVD-CRmLlBwn.js → wardley-RL74JXVD-ByDpAPp1.js} +1 -1
  70. package/dist/assets/{wardleyDiagram-NUSXRM2D-BJYVDJ4F.js → wardleyDiagram-NUSXRM2D-D7LJTuWq.js} +1 -1
  71. package/dist/assets/{xychartDiagram-5P7HB3ND-el5C4S1Z.js → xychartDiagram-5P7HB3ND-MW_KOomO.js} +1 -1
  72. package/dist/index.html +5 -5
  73. package/findcc.js +3 -3
  74. package/package.json +1 -1
  75. package/server/i18n.js +224 -8
  76. package/server/interceptor.js +21 -18
  77. package/server/lib/adapters/dingtalk-adapter.js +69 -0
  78. package/server/lib/adapters/discord-adapter.js +44 -1
  79. package/server/lib/adapters/feishu-adapter.js +56 -0
  80. package/server/lib/adapters/wecom-adapter.js +4 -0
  81. package/server/lib/ask-store.js +19 -90
  82. package/server/lib/async-file-lock.js +123 -0
  83. package/server/lib/async-write-queue.js +131 -0
  84. package/server/lib/git-diff.js +4 -1
  85. package/server/lib/im-bridge-core.js +178 -21
  86. package/server/lib/im-claude-md.js +37 -1
  87. package/server/lib/im-config.js +11 -6
  88. package/server/lib/im-process-manager.js +1 -1
  89. package/server/lib/im-senders.js +73 -0
  90. package/server/lib/jsonl-archive.js +0 -1
  91. package/server/lib/log-watcher.js +224 -177
  92. package/server/lib/plugin-manager.js +1 -1
  93. package/server/lib/updater.js +4 -2
  94. package/server/pty-manager.js +1 -1
  95. package/server/routes/ask-perm.js +2 -2
  96. package/server/routes/dingtalk.js +2 -0
  97. package/server/routes/files-fs.js +4 -4
  98. package/server/routes/im.js +117 -3
  99. package/server/routes/project-meta.js +18 -1
  100. package/server/routes/skills.js +180 -165
  101. package/server/routes/workspaces.js +7 -10
  102. package/server/server.js +23 -20
  103. package/server/workspace-registry.js +9 -53
  104. package/dist/assets/App-DRvRd96X.css +0 -1
  105. package/dist/assets/App-OM2oqZRW.js +0 -1
  106. package/dist/assets/classDiagram-6PBFFD2Q-CCwGJXEA.js +0 -1
  107. package/dist/assets/classDiagram-v2-HSJHXN6E-CCwGJXEA.js +0 -1
  108. package/dist/assets/clone-BuQbTPQO.js +0 -1
  109. package/dist/assets/index-CnWSVlWW.js +0 -2
  110. package/dist/assets/seqResourceLoaders-BZ6M3Jb-.js +0 -2
package/server/server.js CHANGED
@@ -40,13 +40,18 @@ import './lib/adapters/wecom-adapter.js'; // side-effect: registers the WeCom
40
40
  import './lib/adapters/discord-adapter.js'; // side-effect: registers the Discord adapter
41
41
  import { loadConfig } from './lib/im-config.js';
42
42
 
43
- const execFileAsync = promisify(execFile);
44
- const execAsync = promisify(exec);
43
+ // Windows:git.exe / cmd.exe 等 console-subsystem 子进程从无控制台的 worker node.exe 启动时
44
+ // 会各弹一个可见控制台窗口(diff/status 轮询路径高频闪现)。在 promisify 包装层统一默认
45
+ // windowsHide(POSIX 上为 no-op,调用方传入可覆盖)。deps.execFileAsync 注入下游路由同样受益。
46
+ const _execFileAsyncRaw = promisify(execFile);
47
+ const execFileAsync = (cmd, args, opts) => _execFileAsyncRaw(cmd, args, { windowsHide: true, ...opts });
48
+ const _execAsyncRaw = promisify(exec);
49
+ const execAsync = (cmd, opts) => _execAsyncRaw(cmd, { windowsHide: true, ...opts });
45
50
 
46
51
  // execFile with stdin input support (for git check-ignore --stdin)
47
52
  function execWithStdin(cmd, args, input, options) {
48
53
  return new Promise((resolve, reject) => {
49
- const child = spawn(cmd, args, { ...options, stdio: ['pipe', 'pipe', 'pipe'] });
54
+ const child = spawn(cmd, args, { ...options, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true });
50
55
  let stdout = '';
51
56
  let stderr = '';
52
57
  child.stdout.on('data', d => { stdout += d; });
@@ -70,7 +75,7 @@ import { loadAuthConfig, loadAuthState, saveAuthConfig, clearProjectOverride, ge
70
75
  import { checkAndUpdate } from './lib/updater.js';
71
76
  import { loadPlugins, runWaterfallHook, runParallelHook } from './lib/plugin-loader.js';
72
77
  import { CONTEXT_WINDOW_FILE, readModelContextSize } from './lib/context-watcher.js';
73
- import { watchLogFile, startWatching, getWatchedFiles, sendEventToClients, sendToClients } from './lib/log-watcher.js';
78
+ import { watchLogFile, startWatching, unwatchAll, sendEventToClients, sendToClients } from './lib/log-watcher.js';
74
79
  import { cleanupExtractCache } from './lib/jsonl-archive.js';
75
80
 
76
81
 
@@ -156,14 +161,13 @@ const ASK_HOOK_TIMEOUT_MS = ASK_TIMEOUT_MS;
156
161
  // 任何 pendingAskHooks.set(...) 后必须调 _persistAskEntry;.delete(...) 后必须调 _persistAskDelete。
157
162
  function _persistAskEntry(id, entry) {
158
163
  if (!entry || !Array.isArray(entry.questions)) return;
159
- // 异步触发:磁盘 IO 不阻塞 ask 主流程(落盘失败不影响业务)
160
164
  setImmediate(() => {
161
- try { askStoreSetEntry(id, { questions: entry.questions, createdAt: entry.createdAt }); } catch {}
165
+ askStoreSetEntry(id, { questions: entry.questions, createdAt: entry.createdAt }).catch(() => {});
162
166
  });
163
167
  }
164
168
  function _persistAskDelete(id) {
165
169
  setImmediate(() => {
166
- try { askStoreDeleteEntry(id); } catch {}
170
+ askStoreDeleteEntry(id).catch(() => {});
167
171
  });
168
172
  }
169
173
 
@@ -770,11 +774,11 @@ export async function startViewer() {
770
774
  // 内存 Map 不 hydrate:旧 res 已死、新 ask-bridge 重连同 toolUseId 会自动复用槽位
771
775
  // (server.js 已有"旧 res 已断 → 复用"分支),无需在这里主动重建内存态。
772
776
  // 留下来的 disk 镜像供 /api/pending-asks 端点查询,让浏览器重连后仍能看见 pending 列表。
773
- setImmediate(() => { try { askStorePruneStale(ASK_HOOK_TIMEOUT_MS); } catch {} });
777
+ setImmediate(() => { askStorePruneStale(ASK_HOOK_TIMEOUT_MS).catch(() => {}); });
774
778
  // 长跑进程兜底:短轮询路径下 markAnswered 标的终态 entry 若 ask-bridge 已死(GET 不再来 consume),
775
779
  // 仅靠启动 prune 永远清不掉。1h 周期触发一次,.unref() 不阻塞进程退出。
776
780
  const _pruneAskStoreInterval = setInterval(() => {
777
- try { askStorePruneStale(ASK_HOOK_TIMEOUT_MS); } catch {}
781
+ askStorePruneStale(ASK_HOOK_TIMEOUT_MS).catch(() => {});
778
782
  }, 60 * 60 * 1000);
779
783
  _pruneAskStoreInterval.unref();
780
784
 
@@ -1263,7 +1267,7 @@ async function setupTerminalWebSocket(httpServer) {
1263
1267
  // Phase 3: short-poll 模式不立即删 disk —— 落 answered 让 GET listener / disk consume 拿
1264
1268
  if (askEntry.shortPoll) {
1265
1269
  let wrote = false;
1266
- try { wrote = askStoreMarkAnswered(askId, msg.answers); } catch {}
1270
+ try { wrote = await askStoreMarkAnswered(askId, msg.answers); } catch {}
1267
1271
  if (wrote) {
1268
1272
  _notifyShortPollAnswer(askId, msg.answers);
1269
1273
  askAnswered = true;
@@ -1296,7 +1300,7 @@ async function setupTerminalWebSocket(httpServer) {
1296
1300
  // 不唤醒 listener(让 listener 等到 GET hit disk 拿到真实抢答者答案)—— 自然 idempotent。
1297
1301
  // 给当前 ws 发 ack-already-answered 让前端关 modal、不误覆盖灰态。
1298
1302
  let wrote = false;
1299
- try { wrote = askStoreMarkAnswered(askId, msg.answers); } catch {}
1303
+ try { wrote = await askStoreMarkAnswered(askId, msg.answers); } catch {}
1300
1304
  if (wrote) {
1301
1305
  _notifyShortPollAnswer(askId, msg.answers);
1302
1306
  askAnswered = true;
@@ -1406,7 +1410,7 @@ async function setupTerminalWebSocket(httpServer) {
1406
1410
  pendingAskHooks.delete(cancelId);
1407
1411
  // Phase 3: short-poll 同样要让 disk + listener 知道,否则 ask-bridge 永远收不到 cancelled
1408
1412
  if (askEntry.shortPoll) {
1409
- try { askStoreMarkCancelled(cancelId, cancelReason); } catch {}
1413
+ try { await askStoreMarkCancelled(cancelId, cancelReason); } catch {}
1410
1414
  _notifyShortPollCancel(cancelId, cancelReason);
1411
1415
  } else {
1412
1416
  _persistAskDelete(cancelId);
@@ -1424,7 +1428,7 @@ async function setupTerminalWebSocket(httpServer) {
1424
1428
  // first-wins:disk 已是终态(如另一 client 抢先 answer)时 markCancelled 返 false,
1425
1429
  // 不能唤醒 listener 用 cancel 覆盖真实 answer —— 让 listener 下次 GET consumeIfFinal
1426
1430
  // 拿到真实 disk 终态自然投递。
1427
- const wrote = askStoreMarkCancelled(cancelId, cancelReason);
1431
+ const wrote = await askStoreMarkCancelled(cancelId, cancelReason);
1428
1432
  if (wrote) {
1429
1433
  _notifyShortPollCancel(cancelId, cancelReason);
1430
1434
  handled = true;
@@ -1640,10 +1644,12 @@ const _pendingTurnEndTimers = new Map(); // key: sessionId(string) | null → {
1640
1644
  // 空串 / 非数 / 范围外都回 default + warn 一次。
1641
1645
  const TURN_END_DEBOUNCE_MS = (() => {
1642
1646
  const raw = process.env.CCV_TURN_END_DEBOUNCE_MS;
1643
- if (raw === undefined || raw === '' || /^\s*$/.test(raw)) return 10_000;
1647
+ // IM worker 需要快速 turn_end 以驱动队列——默认 200ms(够 coalesce 重复 POST,不拖延回复)。
1648
+ const imDefault = process.env.CCV_IM_PLATFORM ? 200 : 10_000;
1649
+ if (raw === undefined || raw === '' || /^\s*$/.test(raw)) return imDefault;
1644
1650
  const n = Number(raw);
1645
- if (!Number.isFinite(n)) { console.warn(`[turn-end] CCV_TURN_END_DEBOUNCE_MS=${raw} not finite, using 10000`); return 10_000; }
1646
- if (n < 100 || n > 60_000) { console.warn(`[turn-end] CCV_TURN_END_DEBOUNCE_MS=${n} out of [100,60000], using 10000`); return 10_000; }
1651
+ if (!Number.isFinite(n)) { console.warn(`[turn-end] CCV_TURN_END_DEBOUNCE_MS=${raw} not finite, using ${imDefault}`); return imDefault; }
1652
+ if (n < 100 || n > 60_000) { console.warn(`[turn-end] CCV_TURN_END_DEBOUNCE_MS=${n} out of [100,60000], using ${imDefault}`); return imDefault; }
1647
1653
  return n;
1648
1654
  })();
1649
1655
  let _isStopping = false;
@@ -1819,11 +1825,8 @@ async function _doStop() {
1819
1825
  }
1820
1826
  } catch { }
1821
1827
  }
1822
- for (const logFile of getWatchedFiles().keys()) {
1823
- unwatchFile(logFile);
1824
- }
1828
+ unwatchAll();
1825
1829
  unwatchFile(CONTEXT_WINDOW_FILE);
1826
- getWatchedFiles().clear();
1827
1830
  clients.forEach(client => client.end());
1828
1831
  // Truncate in place (not `clients = []`) so the array reference stays stable across
1829
1832
  // stop/start cycles — deps.clients and _logWatcherOpts() hold this same reference.
@@ -1,6 +1,7 @@
1
1
  // Workspace Registry - 工作区持久化管理
2
- import { readFileSync, writeFileSync, existsSync, mkdirSync, statSync, readdirSync, openSync, closeSync, unlinkSync } from 'node:fs';
2
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, statSync, readdirSync, unlinkSync } from 'node:fs';
3
3
  import { renameSyncWithRetry } from './lib/file-api.js';
4
+ import { withFileLockAsync } from './lib/async-file-lock.js';
4
5
  import { join, basename, resolve } from 'node:path';
5
6
  import { randomBytes } from 'node:crypto';
6
7
  import { LOG_DIR } from '../findcc.js';
@@ -9,51 +10,6 @@ import { LOG_DIR } from '../findcc.js';
9
10
  function getWorkspacesFile() { return join(LOG_DIR, 'workspaces.json'); }
10
11
  function getLockFile() { return join(LOG_DIR, 'workspaces.lock'); }
11
12
 
12
- function sleep(ms) {
13
- Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
14
- }
15
-
16
- function withLock(fn) {
17
- mkdirSync(LOG_DIR, { recursive: true });
18
- const deadline = Date.now() + 2000;
19
- // 如果锁文件超过 5 秒未更新,认为它是死锁(前一个进程崩溃)
20
- const STALE_THRESHOLD = 5000;
21
-
22
- while (true) {
23
- try {
24
- const fd = openSync(getLockFile(), 'wx');
25
- closeSync(fd);
26
- break;
27
- } catch (err) {
28
- if (err?.code === 'EEXIST') {
29
- if (Date.now() < deadline) {
30
- // 检查是否为陈旧锁
31
- try {
32
- const stats = statSync(getLockFile());
33
- if (Date.now() - stats.mtimeMs > STALE_THRESHOLD) {
34
- // 尝试强制移除锁
35
- try { unlinkSync(getLockFile()); } catch { }
36
- // 立即重试获取
37
- continue;
38
- }
39
- } catch {
40
- // stat 失败可能意味着锁刚被释放,继续循环尝试获取
41
- }
42
- sleep(25);
43
- continue;
44
- }
45
- }
46
- throw err;
47
- }
48
- }
49
-
50
- try {
51
- return fn();
52
- } finally {
53
- try { unlinkSync(getLockFile()); } catch { }
54
- }
55
- }
56
-
57
13
  export function loadWorkspaces() {
58
14
  try {
59
15
  if (!existsSync(getWorkspacesFile())) return [];
@@ -69,7 +25,7 @@ export function saveWorkspaces(list) {
69
25
  try {
70
26
  mkdirSync(LOG_DIR, { recursive: true });
71
27
  writeFileSync(tmpFile, JSON.stringify({ workspaces: list }, null, 2));
72
-
28
+
73
29
  // Windows 上 renameSync 可能会因为目标文件存在或被占用而失败。统一走 server/lib/file-api.js
74
30
  // renameSyncWithRetry helper(同款重试策略,跟 interceptor / log-management 一致)。
75
31
  renameSyncWithRetry(tmpFile, getWorkspacesFile());
@@ -87,8 +43,8 @@ function _invalidatePolicyCache() {
87
43
  .catch(() => { /* policy 模块可能在某些 entry 下未加载,无副作用即可 */ });
88
44
  }
89
45
 
90
- export function registerWorkspace(absolutePath) {
91
- const result = withLock(() => {
46
+ export async function registerWorkspace(absolutePath) {
47
+ const result = await withFileLockAsync(getLockFile(), () => {
92
48
  const resolvedPath = resolve(absolutePath);
93
49
  const projectName = basename(resolvedPath).replace(/[^a-zA-Z0-9_\-\.]/g, '_');
94
50
  const list = loadWorkspaces();
@@ -113,13 +69,13 @@ export function registerWorkspace(absolutePath) {
113
69
  list.push(entry);
114
70
  saveWorkspaces(list);
115
71
  return entry;
116
- });
72
+ }, { ensureDir: LOG_DIR });
117
73
  _invalidatePolicyCache();
118
74
  return result;
119
75
  }
120
76
 
121
- export function removeWorkspace(id) {
122
- const result = withLock(() => {
77
+ export async function removeWorkspace(id) {
78
+ const result = await withFileLockAsync(getLockFile(), () => {
123
79
  const list = loadWorkspaces();
124
80
  const filtered = list.filter(w => w.id !== id);
125
81
  if (filtered.length !== list.length) {
@@ -127,7 +83,7 @@ export function removeWorkspace(id) {
127
83
  return true;
128
84
  }
129
85
  return false;
130
- });
86
+ }, { ensureDir: LOG_DIR });
131
87
  if (result) _invalidatePolicyCache();
132
88
  return result;
133
89
  }
@@ -1 +0,0 @@
1
- ._liveTag_sg7sp_3{position:relative;display:inline-flex;align-items:center;justify-content:flex-start;border-radius:999px;border:1px solid;border-color:var(--ctx-color);color:var(--ctx-color);padding:0 10px;height:100%;font-size:12px;line-height:1;overflow:hidden;transition:border-color .3s,color .3s;white-space:nowrap;background:var(--bg-base-pure)}._liveTagFill_sg7sp_23{position:absolute;left:0;top:0;bottom:0;width:var(--ctx-percent, 0);background-color:var(--ctx-color);opacity:.35;transition:width .5s ease,background-color .3s;pointer-events:none}._liveTagContent_sg7sp_36{position:relative;z-index:1;display:inline-flex;align-items:center}._liveTagHistory_sg7sp_44{background:var(--bg-surface);border-color:var(--border-light);color:var(--text-primary)}._liveTagText_sg7sp_51{margin-left:4px;font-variant-numeric:tabular-nums}._cachePopoverPlaceholder_sg7sp_57{min-width:300px}._editButton_31hdb_10{display:inline-flex;align-items:center;justify-content:center;vertical-align:middle;background:transparent;border:none;padding:0 2px;margin-left:4px;cursor:pointer;font-size:inherit;line-height:1;color:var(--text-secondary, #888);opacity:0;border-radius:3px;transition:opacity .12s ease,color .12s ease,background-color .12s ease}._editButton_31hdb_10 .anticon{display:inline-flex;align-items:center;line-height:1;position:relative;top:-1px}._editButton_31hdb_10:hover,._editButton_31hdb_10:focus-visible{opacity:1;color:var(--text-primary, #333);background-color:var(--bg-hover, rgba(0, 0, 0, .04));outline:none}._editButton_31hdb_10:focus-visible{box-shadow:0 0 0 2px var(--focus-ring, rgba(64, 158, 255, .4))}._footer_31hdb_55{display:flex;justify-content:space-between;align-items:center;gap:8px}._footerLeft_31hdb_61,._footerRight_31hdb_65{display:flex;gap:8px}._projectNameRow_31hdb_70{display:flex;align-items:center;gap:8px;margin-bottom:12px;padding:6px 10px;background:var(--bg-secondary, rgba(0, 0, 0, .03));border-radius:4px;font-size:12px}._projectNameLabel_31hdb_80{color:var(--text-secondary, #888)}._projectNameValue_31hdb_83{color:var(--text-primary, #333);font-family:var(--font-mono, ui-monospace, SFMono-Regular, monospace);word-break:break-all}._panel_ziacd_1{display:flex;flex-direction:column;gap:14px}._required_ziacd_7{margin-left:2px;color:var(--color-error-light, #ff7b7b)}._optional_ziacd_12{margin-left:6px;font-size:12px;font-weight:400;color:var(--text-secondary)}._row_ziacd_19{display:flex;align-items:center;justify-content:space-between;gap:12px}._label_ziacd_26{font-size:14px;font-weight:500}._control_ziacd_31{display:inline-flex;align-items:center;gap:10px}._field_ziacd_37{display:flex;flex-direction:column;gap:6px}._fieldLabel_ziacd_43{font-size:13px;color:var(--text-secondary)}._help_ziacd_48{font-size:12px;color:var(--text-secondary);line-height:1.4}._warn_ziacd_54{font-size:12px;line-height:1.5;color:var(--color-error-light, #ff7b7b)}._hint_ziacd_60{font-size:12px;line-height:1.5;color:var(--text-secondary)}._detailsToggle_ziacd_66{display:inline-flex;align-items:center;gap:5px;align-self:flex-start;padding:0;border:none;background:none;cursor:pointer;font-size:12px;color:var(--text-secondary)}._detailsToggle_ziacd_66:hover{color:var(--text-primary, var(--text-secondary))}._details_ziacd_66{display:flex;flex-direction:column;gap:10px}._actions_ziacd_89{display:flex;justify-content:flex-end;gap:10px;margin-top:4px}._tabRow_1q32a_4{display:flex;align-items:flex-end;gap:6px;padding:0 8px;flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}._tabRow_1q32a_4::-webkit-scrollbar{display:none}._tabBtn_1q32a_24{display:inline-flex;align-items:center;gap:7px;padding:8px 16px;font-size:14px;line-height:1.5;border:1px solid transparent;border-radius:10px;background:transparent;color:var(--text-secondary);cursor:pointer;transition:color .18s,border-color .18s,background .18s;white-space:nowrap;flex-shrink:0;-webkit-user-select:none;user-select:none}._tabBtn_1q32a_24:hover{color:var(--color-primary)}._tabBtn_1q32a_24._tabBtnActive_1q32a_52,._tabBtn_1q32a_24._tabBtnActive_1q32a_52:hover{background:var(--bg-container);color:var(--color-primary);border-color:var(--border-primary);border-bottom:2px solid var(--bg-container);border-radius:10px 10px 0 0;font-weight:500;margin-bottom:-1px;position:relative;z-index:2}._toolBody_1q32a_8{border:1px solid var(--border-primary);border-top:none;border-radius:8px;background:var(--bg-container);padding:18px 20px;min-width:0}[data-theme=light] ._toolBody_1q32a_8{box-shadow:0 3px 8px #00000014}[data-theme=light] ._tabBtnActive_1q32a_52{box-shadow:0 -3px 8px #0000000f}[data-theme=dark] ._toolBody_1q32a_8 .ant-input,[data-theme=dark] ._toolBody_1q32a_8 .ant-input-affix-wrapper,[data-theme=dark] ._toolBody_1q32a_8 .ant-select-selector{background-color:var(--bg-elevated)}._scrollBody_1c36l_1{max-height:70vh;overflow-y:auto;overflow-x:hidden;scrollbar-gutter:stable;padding:4px 2px;background:var(--bg-container);border-radius:8px}._headerBar_1c36l_14{display:flex;align-items:center;gap:8px}._titleIcon_1c36l_20{display:inline-flex;align-items:center;width:18px;height:18px}._refreshBtn_1c36l_27{flex:0 0 auto}._center_1c36l_32{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;padding:40px 0;color:var(--text-secondary)}._hint_1c36l_42{color:var(--text-secondary);font-size:13px}._chip_bvaji_4{position:relative;line-height:0;cursor:pointer;-webkit-user-select:none;user-select:none;transition:opacity .15s}._chip_bvaji_4:hover{opacity:.75}._logo_bvaji_16{display:block;transition:color .15s}._connecting_bvaji_22{opacity:.5}._dotError_bvaji_27{position:absolute;right:-2px;top:-2px;width:6px;height:6px;border-radius:50%;background:var(--color-error, #ff4d4f);pointer-events:none}._modelCard_1gpju_3{border:1px solid var(--border-secondary);border-radius:6px;padding:8px 10px;background:var(--bg-container)}._modelName_1gpju_9{font-size:13px;font-weight:600;color:var(--text-primary);margin-bottom:8px;padding-bottom:4px;border-bottom:1px solid var(--border-secondary)}._statsTable_1gpju_17{width:100%;border-collapse:collapse}._th_1gpju_21{padding:2px 12px;font-size:12px;font-family:monospace;white-space:nowrap;color:var(--text-tertiary);font-weight:400;text-align:right}._td_1gpju_30{padding:2px 12px;font-size:12px;font-family:monospace;white-space:nowrap;color:var(--text-primary);text-align:right}._label_1gpju_38{padding:2px 12px;font-size:12px;font-family:monospace;white-space:nowrap;color:var(--text-light);font-weight:400;text-align:left}._rowBorder_1gpju_47{border-bottom:1px solid var(--border-primary)}._rebuildTotalRow_1gpju_50{border-top:1px solid var(--border-light)}._rebuildTotalRow_1gpju_50 td{font-weight:600}._cachePopoverEmpty_1gpju_56{padding:8px 4px;color:var(--text-tertiary);font-size:13px}._toolChipGrid_1gpju_61{display:flex;flex-wrap:wrap;gap:4px;padding:2px 0 6px 2px}._cacheToolChip_1gpju_67{font-size:11px;padding:0 6px;border-radius:3px;background:var(--bg-surface);color:var(--text-secondary);line-height:18px;max-width:280px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border:1px solid var(--border-primary);cursor:help}._titleIcon_1gpju_81{margin-right:8px}._detailMarkdownCard_1gpju_86{border:1px solid var(--border-secondary);border-radius:6px;padding:8px 10px;background:var(--bg-container)}._memoryMarkdown_1gpju_93{font-size:12.5px;line-height:1.55;color:var(--text-primary);word-break:break-word}._memoryMarkdown_1gpju_93 p{margin:0 0 6px}._memoryMarkdown_1gpju_93 ul,._memoryMarkdown_1gpju_93 ol{margin:4px 0 6px;padding-left:20px}._memoryMarkdown_1gpju_93 li{margin:2px 0}._memoryMarkdown_1gpju_93 h1,._memoryMarkdown_1gpju_93 h2,._memoryMarkdown_1gpju_93 h3,._memoryMarkdown_1gpju_93 h4{font-size:13px;font-weight:600;margin:8px 0 4px;color:var(--text-primary)}._memoryMarkdown_1gpju_93 h1{font-size:14px}._memoryMarkdown_1gpju_93 a{color:var(--primary-color, #1677ff);text-decoration:none;cursor:pointer}._memoryMarkdown_1gpju_93 a:hover{text-decoration:underline}._memoryMarkdown_1gpju_93 code{font-family:ui-monospace,Menlo,Consolas,monospace;font-size:12px;padding:1px 4px;border-radius:3px;background:var(--bg-surface);color:var(--text-primary)}._memoryMarkdown_1gpju_93 pre{margin:6px 0;padding:8px 10px;border-radius:4px;background:var(--bg-surface);overflow-x:auto}._memoryMarkdown_1gpju_93 pre code{padding:0;background:transparent;font-size:12px}._memoryMarkdown_1gpju_93 blockquote{margin:4px 0;padding:2px 8px;border-left:3px solid var(--border-hover);color:var(--text-secondary)}._memoryMarkdown_1gpju_93 hr{margin:8px 0;border:none;border-top:1px solid var(--border-secondary)}._headerBar_uzc7r_2{display:flex;align-items:center;justify-content:space-between;width:100%;height:100%}._logoWrap_uzc7r_10{display:inline-flex;align-items:center;position:relative;margin-top:14px}._logoWrapActive_uzc7r_17:after{content:"";position:absolute;top:-10px;bottom:-10px;left:0;right:-200px}._logoImage_uzc7r_26{height:24px;width:24px;border-radius:3px;vertical-align:middle;opacity:.75;transition:opacity .2s;cursor:pointer}._logoImageActive_uzc7r_36{opacity:1}._compactBtn_uzc7r_43{font-size:12px;height:30px;display:inline-flex;align-items:center;justify-content:center}._compactBtnNoBorder_uzc7r_52{width:30px;height:30px;min-width:30px;padding:0;border:none;font-size:18px;line-height:1;display:inline-flex;align-items:center;justify-content:center}._compactBtnNoBorder_uzc7r_52 .anticon{display:inline-flex;align-items:center;justify-content:center;line-height:0}._headerProjectName_uzc7r_79{font-size:12px;color:inherit;white-space:nowrap}._headerProjectName_uzc7r_79:hover [data-alias-edit-trigger],._headerProjectName_uzc7r_79:focus-within [data-alias-edit-trigger]{opacity:.55}._countdownStrong_uzc7r_96{font-variant-numeric:tabular-nums}._qrcodePopover_uzc7r_101{display:flex;flex-direction:column;align-items:center;padding:8px}._qrcodeSection_uzc7r_108{display:flex;flex-direction:column;align-items:center;padding:16px;margin-bottom:12px;border:1px solid var(--border-secondary);border-radius:8px;background:var(--bg-container)}._qrcodeTitle_uzc7r_119{font-size:14px;font-weight:600;color:var(--text-primary);margin-bottom:12px}._qrcodeUrlInput_uzc7r_126{margin-top:12px;font-size:12px;font-family:Menlo,Monaco,monospace}._qrcodeUrlCopy_uzc7r_132{cursor:pointer;color:var(--text-tertiary);transition:color .2s}._qrcodeUrlCopy_uzc7r_132:hover{color:var(--color-primary-light)}._authSection_uzc7r_143{display:flex;flex-direction:column;align-items:stretch;box-sizing:border-box;width:100%;margin-top:12px;padding:12px;border:1px solid var(--border-secondary);border-radius:8px;background:var(--bg-container);gap:8px}._authHeaderRow_uzc7r_157{display:flex;align-items:center;justify-content:space-between}._authTitle_uzc7r_163{font-size:13px;font-weight:600;color:var(--text-primary)}._authPasswordLabel_uzc7r_169{font-size:12px;color:var(--text-secondary)}._authPasswordInput_uzc7r_174{font-size:12px;font-family:Menlo,Monaco,monospace}._authSaveBtn_uzc7r_179{align-self:flex-end}._authEmptyWarn_uzc7r_183{font-size:12px;color:var(--color-error-light);line-height:1.4}._settingsGroupBox_uzc7r_191{border:1px solid var(--border-secondary);border-radius:8px;background:var(--bg-container);padding:4px 16px;margin-bottom:12px}._settingsGroupTitle_uzc7r_199{font-size:14px;font-weight:600;color:var(--text-primary);padding:12px 0 4px;border-bottom:1px solid var(--border-secondary)}._settingsItem_uzc7r_208{display:flex;justify-content:space-between;align-items:center;padding:12px 0}._settingsLabel_uzc7r_215{font-size:14px}._settingsHelpIcon_uzc7r_220{font-size:16px;color:var(--text-disabled);cursor:help;margin-left:4px}._settingsDivider_uzc7r_227{border-top:1px solid var(--border-primary);margin:12px 0}._logDirInput_uzc7r_232{margin-top:8px;background:var(--bg-base-alt);border-color:var(--border-light);color:var(--text-primary);font-family:monospace;font-size:13px}._tokenStatsEmpty_uzc7r_242{padding:8px 4px;color:var(--text-tertiary);font-size:13px}._tokenStatsContainer_uzc7r_249{display:flex;gap:12px;align-items:flex-start}._tokenStatsColumn_uzc7r_255{min-width:240px}._toolStatsColumn_uzc7r_259{min-width:180px}._modelCardSpaced_uzc7r_265{margin-bottom:10px}._rebuildCard_uzc7r_274{border:1px solid var(--border-secondary);border-radius:6px;padding:8px 10px;margin-top:10px;background:var(--bg-container)}._promptExportBar_uzc7r_283{margin-bottom:12px}._promptScrollArea_uzc7r_287{max-height:500px;overflow:auto}._promptEmpty_uzc7r_292{color:var(--text-tertiary);padding:12px}._promptTimestamp_uzc7r_298{color:var(--text-muted);font-size:12px;margin:12px 0 4px;padding-bottom:6px}._textPromptCard_uzc7r_306{margin:4px 0;background:var(--bg-container);border-radius:6px;border:1px solid var(--border-secondary);padding:10px 14px}._preText_uzc7r_315{white-space:pre-wrap;word-break:break-word;font-size:13px;line-height:1.6;color:var(--text-primary);margin:4px 0}._systemCollapse_uzc7r_325{margin:4px 0;background:var(--bg-elevated);border:1px solid var(--border-secondary);border-radius:6px}._systemLabel_uzc7r_332{color:var(--text-tertiary);font-size:12px}._preSys_uzc7r_337{white-space:pre-wrap;word-break:break-word;font-size:12px;line-height:1.5;color:var(--text-tertiary);margin:0}._promptTextarea_uzc7r_347{box-sizing:border-box;background:var(--bg-base-pure);width:100%;min-height:400px;color:var(--text-primary);font-family:monospace;font-size:13px;line-height:1.6;border:none;resize:vertical;padding:10px 14px;outline:none}._projectStatsCenter_uzc7r_363{display:flex;justify-content:center;padding:40px 0}._projectStatsEmpty_uzc7r_369{color:var(--text-tertiary);padding:40px 0;text-align:center;font-size:13px}._projectStatsContent_uzc7r_376{display:flex;flex-direction:column;gap:16px}._projectStatsUpdated_uzc7r_382{color:var(--text-muted);font-size:12px;text-align:right}._projectStatsSummary_uzc7r_388{display:grid;grid-template-columns:1fr 1fr;gap:10px}._projectStatCard_uzc7r_394{background:var(--bg-container);border:1px solid var(--border-secondary);border-radius:8px;padding:14px 12px;text-align:center}._projectStatValue_uzc7r_402{font-size:22px;font-weight:700;color:var(--text-primary);font-family:monospace;font-variant-numeric:tabular-nums}._projectStatLabel_uzc7r_410{font-size:12px;color:var(--text-tertiary);margin-top:4px}._projectStatsSection_uzc7r_416{display:flex;flex-direction:column;gap:10px}._projectStatsSectionTitle_uzc7r_422{font-size:14px;font-weight:600;color:var(--text-secondary);padding-bottom:4px;border-bottom:1px solid var(--border-secondary)}._projectStatsModelCard_uzc7r_430{background:var(--bg-container);border:1px solid var(--border-secondary);border-radius:6px;padding:10px 12px}._projectStatsModelHeader_uzc7r_437{display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;padding-bottom:4px;border-bottom:1px solid var(--border-secondary)}._projectStatsModelName_uzc7r_446{font-size:13px;font-weight:600;color:var(--text-primary)}._projectStatsModelCount_uzc7r_452{font-size:12px;color:var(--text-tertiary);font-family:monospace}._cacheCopyBtn_uzc7r_460{font-size:14px;color:var(--text-tertiary);cursor:pointer;transition:color .2s;margin-left:8px}._cacheCopyBtn_uzc7r_460:hover{color:var(--text-primary)}._cacheTokenInfo_uzc7r_472{display:flex;align-items:center;font-size:12px;font-family:monospace;color:var(--text-light);margin-bottom:8px}._cacheCodeBlock_uzc7r_485{white-space:pre-wrap;word-break:break-word;font-size:12px;line-height:1.5;color:var(--text-secondary);background:var(--bg-container);border:1px solid var(--border-primary);border-radius:4px;padding:8px;margin:4px 0;font-family:Menlo,Monaco,monospace}._cacheCodeBlockSystem_uzc7r_499{white-space:pre-wrap;word-break:break-word;font-size:12px;line-height:1.5;color:var(--text-secondary);background:var(--bg-code-system);border:1px solid var(--border-code-system);border-radius:4px;padding:8px;margin:4px 0;font-family:Menlo,Monaco,monospace}._cacheNavBtn_uzc7r_513{margin-left:auto;font-size:11px;color:var(--color-primary);cursor:pointer;border:1px solid var(--color-primary);border-radius:3px;padding:1px 6px;white-space:nowrap}._cacheNavBtn_uzc7r_513:hover{background:var(--color-primary-bg-light)}._cacheNavList_uzc7r_528{width:600px;max-height:300px;overflow-y:auto}._cacheNavItem_uzc7r_534{padding:4px 8px;font-size:12px;color:var(--text-secondary);cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;border-radius:3px}._cacheNavItem_uzc7r_534:hover{background:var(--color-primary-bg-lighter);color:var(--text-white)}._cacheBlockHighlight_uzc7r_550{box-shadow:0 0 10px var(--color-primary-shadow);transition:box-shadow .2s ease-in}._cacheBlockHighlightFading_uzc7r_555{box-shadow:0 0 10px transparent;transition:box-shadow 3s ease-out}._cacheBorderSvg_uzc7r_560{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;pointer-events:none;overflow:visible}._cacheBorderSvgFading_uzc7r_569{opacity:0;transition:opacity 3s ease-out}._cacheBorderRect_uzc7r_574{animation:_cacheDashRotate_uzc7r_1 4s linear infinite}@keyframes _cacheDashRotate_uzc7r_1{0%{stroke-dashoffset:0}to{stroke-dashoffset:-100}}._thLeft_uzc7r_584{text-align:left}._cacheWriteToken_uzc7r_599{color:var(--color-code-orange)}._cacheReadToken_uzc7r_603{color:var(--color-success)}._cacheCtxPercent_uzc7r_607{color:var(--text-tertiary);margin-left:6px}._qrcodeIcon_uzc7r_627{width:30px;height:30px;padding:6px;box-sizing:border-box;color:var(--text-secondary);cursor:pointer;border-radius:6px;transition:color .15s ease,background-color .15s ease;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle;background:none;border:none}._qrcodeIcon_uzc7r_627:hover{color:var(--text-primary);background:var(--bg-hover, rgba(0, 0, 0, .04))}._qrcodeIcon_uzc7r_627:focus-visible{outline:2px solid var(--primary-color, #1677ff);outline-offset:1px}._approvalBell_uzc7r_653{position:relative;width:30px;height:30px;padding:6px;box-sizing:border-box;color:var(--color-warning, #faad14);cursor:pointer;border-radius:6px;transition:color .15s ease,background-color .15s ease;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle;background:none;border:none}._approvalBell_uzc7r_653:hover{color:var(--text-primary);background:var(--bg-hover, rgba(0, 0, 0, .04))}._approvalBell_uzc7r_653:focus-visible{outline:2px solid var(--primary-color, #1677ff);outline-offset:1px}._approvalBellBadge_uzc7r_678{position:absolute;top:0;right:0;min-width:14px;height:14px;padding:0 3px;box-sizing:border-box;background:var(--color-error, #ff4d4f);color:#fff;font-size:9px;line-height:14px;border-radius:7px;text-align:center;font-weight:600}._proxySwapIcon_uzc7r_695{margin-right:4px;font-size:11px}._proxyProfileTag_uzc7r_701{border-radius:12px;background:var(--border-secondary);border:1px solid var(--border-light);color:var(--text-tertiary);font-size:12px;cursor:pointer;transition:color .2s,border-color .2s}._proxyProfileTag_uzc7r_701:hover{color:var(--text-secondary);border-color:var(--text-disabled)}._pinnedShortcut_uzc7r_717{height:24px;margin-top:11px;display:inline-flex;align-items:center;justify-content:center;font-size:16px;line-height:1;color:var(--text-tertiary);opacity:.75;cursor:pointer;transition:opacity .2s,color .2s}._pinnedShortcut_uzc7r_717:hover{opacity:1;color:var(--text-secondary)}._pinnedShortcut_uzc7r_717 .anticon{display:inline-flex;align-items:center;justify-content:center;line-height:0}._themeToggle_uzc7r_746{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle;width:30px;height:30px;padding:0;border:none;border-radius:6px;background:transparent;color:var(--text-secondary);cursor:pointer;transition:background-color .2s ease,color .2s ease;flex-shrink:0;outline:none}._themeToggle_uzc7r_746:hover{background:var(--color-bg-hover, rgba(127, 127, 127, .12));color:var(--text-primary)}._themeToggle_uzc7r_746:focus-visible{box-shadow:0 0 0 2px var(--primary-color, #1677ff)}._themeToggleIcon_uzc7r_772{display:block}._headerRightRow_uzc7r_777 .ant-space-item{display:inline-flex;align-items:center}._headerCountdownTag_uzc7r_783{height:30px;margin:0;padding:0 10px;display:inline-flex;align-items:center;background:var(--bg-surface);border:1px solid var(--border-hover);border-radius:6px;line-height:1}._centerEmpty_midza_1{display:flex;align-items:center;justify-content:center;height:100%}._scrollContainer_midza_8{overflow:auto;height:100%;-webkit-overflow-scrolling:touch;will-change:scroll-position}._listItem_midza_15{cursor:pointer;padding:8px 12px;border-left:6px solid transparent;border-right:1px solid var(--border-primary);border-top:1px solid transparent;border-bottom:1px solid var(--border-primary);transition:background .15s}._listItem_midza_15:hover{border-left-color:var(--border-hover)}._listItemActive_midza_29{background:var(--color-primary-bg-faint);border-left-color:var(--color-primary-light);border-right:1px solid var(--color-primary-light);border-top:1px solid var(--color-primary-light);border-bottom:1px solid var(--color-primary-light)}._listItemActive_midza_29,._listItemActive_midza_29:hover{background:var(--color-primary-bg-faint);border-left-color:var(--color-primary-light);border-right-color:var(--color-primary-light);border-top-color:var(--color-primary-light);border-bottom-color:var(--color-primary-light)}._itemContent_midza_46{width:100%;min-width:0}._itemHeader_midza_51{display:flex;align-items:center;gap:6px;margin-bottom:4px;font-size:12px}._tagNoMargin_midza_59{margin:0;font-size:12px}._modelName_midza_64{font-size:12px;color:var(--text-tertiary)}._modelNameMain_midza_69{color:var(--color-code-orange)}._time_midza_73{font-size:12px;color:var(--text-gray);margin-left:auto}._detailRow_midza_79{display:flex;gap:8px;font-size:12px;align-items:center}._urlText_midza_86{color:var(--text-disabled);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0}._duration_midza_95{color:var(--text-gray);flex-shrink:0}._statusOk_midza_100{color:var(--color-success);opacity:.5;flex-shrink:0}._statusErr_midza_106{color:var(--color-error);flex-shrink:0}._statusDefault_midza_111{color:var(--text-tertiary);flex-shrink:0}._usageBox_midza_116{background:var(--bg-container);border-radius:4px;padding:3px 6px;margin-top:4px;font-size:12px;color:var(--text-gray);line-height:1.6}._cacheDot_midza_126{display:inline-block;width:6px;height:6px;border-radius:50%;margin:0 3px;vertical-align:middle}._cacheDotLoss_midza_135{background-color:var(--color-red-dark-bg);cursor:help}._cacheDotNormal_midza_140{background-color:var(--border-hover)}._tagMainAgent_midza_144{color:var(--color-code-orange);border-color:var(--color-code-orange-border);background:var(--color-code-orange-bg)}._tagPlan_midza_150{color:var(--color-error-muted);border-color:var(--color-error-muted);background-color:var(--bg-base-pure)}._tagMuted_midza_156{color:var(--text-muted);border-color:var(--border-light);background-color:var(--bg-base-pure)}._tooltipPreLine_midza_162{white-space:pre-line}._GzYRV{line-height:1.2;white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word}._3eOF8{margin-right:5px;font-weight:700}._3eOF8+._3eOF8{margin-left:-5px}._1MFti{cursor:pointer}._f10Tu{font-size:1.2em;margin-right:5px;-webkit-user-select:none;-moz-user-select:none;user-select:none}._1UmXx:after{content:"▸"}._1LId0:after{content:"▾"}._1pNG9{margin-right:5px}._1pNG9:after{content:"...";font-size:.8em}._2IvMF{background:#eee}._2bkNM{margin:0;padding:0 10px}._1BXBN{margin:0;padding:0}._1MGIk{font-weight:600;margin-right:5px;color:#000}._3uHL6{color:#000}._2T6PJ,._1Gho6{color:#df113a}._vGjyY{color:#2a3f3c}._1bQdo{color:#0b75f5}._3zQKs{color:#469038}._1xvuR{color:#43413d}._oLqym,._2AXVT,._2KJWg{color:#000}._11RoI{background:#002b36}._17H2C,._3QHg2,._3fDAz{color:#fdf6e3}._2bSDX{font-weight:bolder;margin-right:5px;color:#fdf6e3}._gsbQL{color:#fdf6e3}._LaAZe,._GTKgm{color:#81b5ac}._Chy1W{color:#cb4b16}._2bveF{color:#d33682}._2vRm-{color:#ae81ff}._1prJR{color:#268bd2}._container_qeuid_1{background:var(--bg-container);border-radius:6px;border:1px solid var(--border-primary);padding:12px;font-size:13px;font-family:monospace;overflow:auto}._root_17dqd_1{display:flex;height:100%;min-height:0;gap:0}._sidebar_17dqd_9{width:220px;flex-shrink:0;border-right:1px solid var(--border-primary);overflow-y:auto;padding:4px 0;-webkit-overflow-scrolling:touch}._section_17dqd_18{-webkit-user-select:none;user-select:none}._sectionHeader_17dqd_22{display:flex;align-items:center;gap:6px;width:100%;padding:6px 10px;cursor:pointer;color:var(--text-primary);font-size:12px;font-weight:600;transition:background .15s;background:none;border:0;text-align:left;font:inherit}._sectionHeader_17dqd_22:hover{background:var(--overlay-light-faint)}._sectionHeader_17dqd_22:focus-visible{outline:1px solid var(--color-primary-outline);outline-offset:-1px}._arrow_17dqd_48{font-size:10px;color:var(--text-tertiary);flex-shrink:0}._sectionTitle_17dqd_54{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._sectionCount_17dqd_62{font-size:11px;color:var(--text-muted);background:var(--bg-elevated);border-radius:10px;padding:0 6px;line-height:18px}._sectionBody_17dqd_71{padding:2px 0}._historyToggle_17dqd_76{display:flex;align-items:center;gap:6px;width:100%;padding:4px 10px 4px 14px;cursor:pointer;color:var(--text-muted);font-size:11px;transition:color .15s,background .15s;background:none;border:0;text-align:left;font:inherit}._historyToggle_17dqd_76:hover{color:var(--text-tertiary);background:var(--overlay-light-faint)}._historyToggle_17dqd_76:focus-visible{outline:1px solid var(--color-primary-outline);outline-offset:-1px}._historyToggleLabel_17dqd_102{flex:1}._item_17dqd_107{display:flex;align-items:center;justify-content:space-between;width:100%;padding:4px 9px 4px 23px;font-size:12px;color:var(--text-tertiary);cursor:pointer;transition:background .15s,color .15s;background:none;border:1px solid transparent;border-radius:4px;box-sizing:border-box;text-align:left;font:inherit}._item_17dqd_107:hover{background:var(--overlay-light-faint);color:var(--text-primary)}._item_17dqd_107:focus-visible{outline:1px solid var(--color-primary-outline);outline-offset:-1px}._itemActive_17dqd_135,._itemActive_17dqd_135:hover{background:var(--color-primary-bg-faint);color:var(--color-primary);border-color:var(--color-primary-light)}._itemContent_17dqd_142{flex:1;min-width:0;overflow:hidden}._itemLabel_17dqd_148{font-family:monospace;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block}._itemSublabel_17dqd_156{font-size:10px;color:var(--text-disabled);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-top:1px}._itemTime_17dqd_165{font-size:9px;color:var(--text-disabled);flex-shrink:0;margin-left:4px;font-family:monospace}._content_17dqd_174{flex:1;min-width:0;overflow:auto;padding:12px 16px;-webkit-overflow-scrolling:touch}._contentEmpty_17dqd_182{height:100%;display:flex;align-items:center;justify-content:center}._contentInner_17dqd_189{padding-bottom:20px}._emptyWrap_17dqd_193{display:flex;align-items:center;justify-content:center;height:200px}._roleHeader_17dqd_201{display:flex;align-items:center;gap:8px;margin-bottom:8px;flex-wrap:nowrap}._roleBadge_17dqd_209{font-size:10px;font-weight:600;letter-spacing:.04em;padding:2px 7px;border-radius:4px;flex-shrink:0}._role_user_17dqd_218{background:var(--color-primary-bg-lighter);color:var(--color-primary-lighter);border:1px solid var(--color-primary-bg-medium)}._role_assistant_17dqd_224{background:var(--color-purple-bg);color:var(--color-code-purple);border:1px solid var(--color-purple-border)}._roleLabel_17dqd_230{font-size:11px;color:var(--text-muted);flex:1;min-width:0}._contentTime_17dqd_237{margin-left:auto;font-size:10px;color:var(--text-disabled);font-family:monospace;flex-shrink:0}._turnDivider_17dqd_245{border:none;border-top:1px solid var(--border-primary);margin:14px 0}._textBlock_17dqd_252{margin-bottom:8px;border:1px solid var(--border-primary);border-radius:6px;overflow:hidden}._textBlockBar_17dqd_259{display:flex;align-items:center;gap:6px;padding:4px 10px;background:var(--bg-container);border-bottom:1px solid var(--border-primary)}._textBlockBody_17dqd_268{padding:10px 12px;font-size:13px;line-height:1.7;color:var(--text-primary);word-break:break-word}._textBlockCompact_17dqd_276{position:relative;padding:8px 10px;font-size:12px;color:var(--text-light)}._textBlockCompactFloat_17dqd_283{float:right;margin-left:6px;margin-bottom:2px}._thinkingBlock_17dqd_290{margin-bottom:8px;border:1px solid var(--color-thinking-border);border-radius:6px;overflow:hidden;background:var(--color-thinking-bg)}._thinkingHeader_17dqd_298{display:flex;align-items:center;gap:6px;padding:5px 10px;cursor:pointer;font-size:12px;color:var(--text-tertiary);transition:background .15s}._thinkingHeader_17dqd_298:hover{background:var(--overlay-light-faint)}._thinkingPreview_17dqd_313{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text-muted);font-size:11px}._thinkingBody_17dqd_323{padding:8px 12px;border-top:1px solid var(--color-thinking-border)}._toolBlock_17dqd_329{margin-bottom:8px;border:1px solid var(--border-primary);border-radius:6px;overflow:hidden}._toolBlockResult_17dqd_336{border-color:var(--color-green-border)}._toolBlockError_17dqd_340{border-color:var(--color-red-dark-border)}._toolBlockHeader_17dqd_344{display:flex;align-items:center;gap:8px;padding:5px 10px;background:var(--bg-container);border-bottom:1px solid var(--border-primary);font-size:12px;flex-wrap:wrap}._toolBlockBody_17dqd_355{padding:8px 10px;font-size:12px}._toolName_17dqd_360{color:var(--text-primary);font-weight:500;font-family:monospace}._toolId_17dqd_366{color:var(--text-disabled);font-size:10px;font-family:monospace;margin-left:auto}._errorLabel_17dqd_373{font-size:10px;color:var(--color-error-light);background:var(--color-error-bg-light);border:1px solid var(--color-error-border);border-radius:3px;padding:1px 5px}._blockTag_17dqd_383{font-size:9px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;padding:1px 5px;border-radius:3px;background:var(--bg-elevated);color:var(--text-muted);border:1px solid var(--border-primary);flex-shrink:0}._blockTagText_17dqd_396{background:var(--color-primary-bg-faint);color:var(--color-primary-lighter);border-color:var(--color-primary-bg-lighter)}._blockTagThinking_17dqd_402{background:var(--color-warning-bg-faint);color:var(--color-warning);border-color:var(--color-warning-border-light)}._blockTagResult_17dqd_408{background:var(--color-green-dark-bg);color:var(--color-success);border-color:var(--color-green-dark-border)}._blockTagError_17dqd_414{background:var(--color-error-bg-faint);color:var(--color-error-light);border-color:var(--color-error-border-light)}._jsonBlock_17dqd_421{margin-bottom:8px;border:1px solid var(--border-primary);border-radius:6px;overflow:hidden}._jsonBlockLabel_17dqd_428{font-size:10px;color:var(--text-muted);padding:3px 10px;background:var(--bg-container);border-bottom:1px solid var(--border-primary);font-family:monospace}._blockSeparator_17dqd_438{border:none;border-top:1px solid var(--border-primary);margin:16px 0}._markdownBody_17dqd_445{font-size:13px;line-height:1.7;color:var(--text-primary);word-break:break-word}._container_rg6mx_1{height:100%;overflow:hidden;padding:0 16px;display:flex;flex-direction:column;background:var(--bg-base)}._emptyState_rg6mx_10{display:flex;align-items:center;justify-content:center;height:100%}._urlSection_rg6mx_17{padding:12px 0;border-bottom:1px solid var(--border-primary);display:flex;align-items:flex-start;flex-shrink:0}._urlLeft_rg6mx_25{flex:1;min-width:0}._tokenStatsBox_rg6mx_30{flex-shrink:0;padding-left:12px;display:flex;align-items:center}._tokenGrid_rg6mx_37{display:flex;border:1px solid var(--border-secondary);border-radius:6px;overflow:hidden;min-width:360px;font-size:11px;line-height:1.6}._tokenRows_rg6mx_47{flex:1}._tokenRow_rg6mx_47{display:flex}._tokenRowBorder_rg6mx_55{border-top:1px solid var(--border-secondary)}._tokenLabel_rg6mx_59{color:var(--text-tertiary);padding:4px 8px;white-space:nowrap;font-weight:600}._tokenTd_rg6mx_66{flex:1;color:var(--text-primary);text-align:right;padding:4px 8px;font-family:monospace;white-space:nowrap}._tokenHitRate_rg6mx_75{display:flex;flex-direction:column;align-items:center;justify-content:center;color:var(--text-primary);padding:4px 8px;font-family:monospace;white-space:nowrap;border-left:1px solid var(--border-secondary);min-width:100px}._tokenHitRateLabel_rg6mx_88{color:var(--text-tertiary);font-size:10px;font-family:sans-serif}._tokenRowBorder_rg6mx_55 td{border-top:1px solid var(--border-secondary)}._urlText_rg6mx_98{color:var(--text-primary);font-size:13px;margin-bottom:8px;word-break:break-all}._metaText_rg6mx_105,._headersContainer_rg6mx_109{font-size:12px}._headerRow_rg6mx_113{display:flex;padding:4px 0;border-bottom:1px solid var(--border-primary)}._headerKey_rg6mx_119{min-width:200px;flex-shrink:0}._headerValue_rg6mx_124{word-break:break-all;margin-left:8px}._streamingBox_rg6mx_129{padding:20px;background:var(--bg-elevated);border-radius:6px;border:1px solid var(--border-primary)}._bodyToolbar_rg6mx_136{display:flex;gap:8px;margin-bottom:8px}._rawTextPre_rg6mx_142{background:var(--bg-code-dark);border:1px solid var(--border-primary);border-radius:6px;padding:12px;font-size:12px;color:var(--text-primary);overflow:auto;max-height:600px;white-space:pre-wrap;word-break:break-all}._tabContent_rg6mx_155{padding:16px 0 0;height:100%;overflow-y:auto;-webkit-overflow-scrolling:touch}._collapseSpacing_rg6mx_163{margin-bottom:16px}._bodyLabel_rg6mx_167{margin:0}._bodyHeader_rg6mx_171{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}._diffSection_rg6mx_178{margin-bottom:16px}._diffToggle_rg6mx_182{display:inline-block;margin-bottom:8px;cursor:pointer}._diffIcon_rg6mx_188{font-size:12px;margin-left:4px}._viewInChatBtn_rg6mx_193{display:inline-flex;align-items:center;height:26px;border-radius:13px;border:1px solid var(--border-light);background:#0000;color:var(--text-tertiary);cursor:pointer;font-size:12px;transition:all .2s;padding:0 10px;white-space:nowrap}._viewInChatBtn_rg6mx_193:hover{border-color:var(--text-muted);color:var(--text-primary);background:var(--overlay-light-faint)}._reminderSelect_rg6mx_214{min-width:140px;font-size:12px}._reminderSelect_rg6mx_214 .ant-select-selector.ant-select-selector{border-radius:2px;border-color:var(--border-light);background:#0000;min-height:26px;height:auto;padding:0 8px;font-family:monospace}._reminderSelect_rg6mx_214 .ant-select-selection-placeholder{font-size:11px}._diffHeaderRow_rg6mx_233{display:flex;align-items:center;gap:8px}._diffSpaceRight_rg6mx_239{margin-left:auto}._reminderFilterWrapper_rg6mx_243{display:inline-flex;align-items:center;gap:4px}._reminderLabel_rg6mx_249{color:var(--text-tertiary);font-size:12px;font-family:monospace}._cacheTabContent_rg6mx_255{padding-top:0;overflow:hidden}._userPromptList_rg6mx_260{width:600px;max-height:300px;overflow-y:auto}._userPromptItem_rg6mx_266{padding:4px 8px;font-size:12px;color:var(--text-secondary);cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;border-radius:3px}._userPromptNavBtn_rg6mx_277{margin-left:auto;font-size:11px;color:var(--color-primary);cursor:pointer;border:1px solid var(--color-primary);border-radius:3px;padding:1px 6px;white-space:nowrap}._cacheContent_rg6mx_288{padding:8px 0;height:100%;display:flex;flex-direction:column}._cacheTokenBar_rg6mx_295{display:flex;align-items:center;font-size:12px;font-family:monospace;color:var(--text-light);margin-bottom:12px;flex-shrink:0}._cacheTokenWrite_rg6mx_305{color:var(--color-code-orange)}._cacheTokenRead_rg6mx_309{color:var(--color-success)}._cacheCopyIcon_rg6mx_313{margin-left:8px;cursor:pointer;color:var(--text-tertiary);transition:color .2s}._cacheScrollArea_rg6mx_320{flex:1;overflow-y:auto;min-height:0}._cacheSectionBlock_rg6mx_326{margin-bottom:12px}._cacheSectionHeader_rg6mx_330{font-size:13px;font-weight:600;color:var(--text-primary);margin-bottom:6px;cursor:pointer;-webkit-user-select:none;user-select:none;display:flex;align-items:center;gap:4px}._cacheCollapseArrow_rg6mx_342{display:inline-block;transition:transform .2s;font-size:10px}._cachePre_rg6mx_348{white-space:pre-wrap;word-break:break-word;font-size:12px;line-height:1.5;color:var(--text-secondary);background:var(--bg-container);border:1px solid var(--border-primary);border-radius:4px;padding:8px;margin:4px 0;font-family:Menlo,Monaco,monospace}._cacheHighlightSvg_rg6mx_362{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;pointer-events:none;overflow:visible}._cachePreSystem_rg6mx_371{white-space:pre-wrap;word-break:break-word;font-size:12px;line-height:1.5;color:var(--text-secondary);background:var(--bg-code-system);border:1px solid var(--border-code-system);border-radius:4px;padding:8px;margin:4px 0;font-family:Menlo,Monaco,monospace}._container_rg6mx_1 .ant-tabs>.ant-tabs-nav{margin-bottom:0}._container_rg6mx_1 .ant-tabs{flex:1;min-height:0;display:flex;flex-direction:column}._container_rg6mx_1 .ant-tabs>.ant-tabs-content-holder{flex:1;min-height:0}._container_rg6mx_1 .ant-tabs-content,._container_rg6mx_1 .ant-tabs-tabpane-active{height:100%}._resizer_pzn4b_1{width:6px;cursor:col-resize;background:var(--bg-elevated);flex-shrink:0;transition:background .2s}._resizer_pzn4b_1:hover{background:var(--color-primary-light)}._flag_1q4ri_3{display:inline-flex;align-items:center;justify-content:center;font-size:13px;line-height:1;cursor:help;-webkit-user-select:none;user-select:none;height:14px;background:none;border:none;padding:0;color:inherit;font-family:inherit}._flag_1q4ri_3:focus-visible{outline:2px solid var(--primary-color, #1677ff);outline-offset:2px;border-radius:2px}._popover_1q4ri_27{color:var(--text-secondary);font-size:13px;line-height:22px}._meta_1q4ri_33{color:var(--text-tertiary);font-size:12px}._usagePill_srdlo_4{position:relative;display:inline-flex;align-items:center;justify-content:flex-start;border-radius:999px;border:1px solid;border-color:var(--text-disabled);color:var(--text-disabled);padding:0 7px;height:15px;font-size:11px;line-height:1;overflow:hidden;white-space:nowrap;cursor:default;background:var(--bg-base-pure)}._usageFill_srdlo_25{position:absolute;left:0;top:0;bottom:0;width:var(--usage-percent, 0);background-color:var(--text-disabled);opacity:.25;transition:width .5s ease;pointer-events:none}._usageContent_srdlo_37{position:relative;z-index:1;display:inline-flex;align-items:center}._usageText_srdlo_44{font-variant-numeric:tabular-nums}._muted_srdlo_49{border-color:var(--border-light);color:var(--text-disabled);background:var(--bg-surface)}._pop_srdlo_56{min-width:220px;font-size:12px;color:var(--text-primary)}._popTitle_srdlo_62{font-weight:600;margin-bottom:6px}._popTable_srdlo_68{border-collapse:collapse}._popTable_srdlo_68 td{padding-top:3px;padding-bottom:3px;vertical-align:middle}._tdName_srdlo_73{color:var(--text-secondary);padding-right:5px;white-space:nowrap}._tdBar_srdlo_73{padding-right:5px;white-space:nowrap}._tdReset_srdlo_91{color:var(--text-secondary);font-variant-numeric:tabular-nums;white-space:nowrap}._bar_srdlo_98{position:relative;display:inline-flex;align-items:center;justify-content:center;width:100px;height:14px;border-radius:999px;border:1px solid var(--text-disabled);overflow:hidden;background:var(--bg-base-pure);vertical-align:middle}._barFill_srdlo_112{position:absolute;left:0;top:0;bottom:0;background-color:var(--text-disabled);opacity:.25;pointer-events:none}._barText_srdlo_122{position:relative;z-index:1;font-size:11px;line-height:1;font-variant-numeric:tabular-nums;color:var(--text-primary)}