cc-viewer 1.7.7 → 1.7.9

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 (88) hide show
  1. package/README.md +3 -1
  2. package/dist/assets/App-Bs6-c4Ov.css +1 -0
  3. package/dist/assets/App-CYvr5YQv.js +2 -0
  4. package/dist/assets/{MdxEditorPanel-BAE_5ssH.js → MdxEditorPanel-D1MOJabL.js} +1 -1
  5. package/dist/assets/Mobile-B7GXxkfK.js +1 -0
  6. package/dist/assets/ProxyStatsModal-BqH9cIks.js +1 -0
  7. package/dist/assets/ProxyStatsModal-Dz5GuoUa.css +1 -0
  8. package/dist/assets/{_baseUniq-BkQkqbX3.js → _baseUniq-aTokVjQN.js} +1 -1
  9. package/dist/assets/{arc-BKY9CS7c.js → arc-mxp8gSRQ.js} +1 -1
  10. package/dist/assets/{architectureDiagram-Q4EWVU46-f8VVp6F9.js → architectureDiagram-Q4EWVU46-msh8IODx.js} +1 -1
  11. package/dist/assets/{blockDiagram-DXYQGD6D-3h2PkZUH.js → blockDiagram-DXYQGD6D-BUatNJTI.js} +1 -1
  12. package/dist/assets/{c4Diagram-AHTNJAMY-DigIDzhn.js → c4Diagram-AHTNJAMY-CJ92TNZe.js} +1 -1
  13. package/dist/assets/{channel-5ajs7xDK.js → channel-CTM7CJrB.js} +1 -1
  14. package/dist/assets/{chunk-4BX2VUAB-BvwhA1RA.js → chunk-4BX2VUAB-Bdv98T9c.js} +1 -1
  15. package/dist/assets/{chunk-4TB4RGXK-GHcSNG2k.js → chunk-4TB4RGXK-DaIEuSP0.js} +1 -1
  16. package/dist/assets/{chunk-55IACEB6-DWO0TwNe.js → chunk-55IACEB6-Bi9130Nu.js} +1 -1
  17. package/dist/assets/{chunk-EDXVE4YY-0ycrM2oE.js → chunk-EDXVE4YY-CZw-Vwwn.js} +1 -1
  18. package/dist/assets/{chunk-FMBD7UC4-DmdCml-0.js → chunk-FMBD7UC4-BBI7swjg.js} +1 -1
  19. package/dist/assets/{chunk-OYMX7WX6-fg2n9B_W.js → chunk-OYMX7WX6-CHKotm_J.js} +1 -1
  20. package/dist/assets/{chunk-QZHKN3VN-Bg3VPGcJ.js → chunk-QZHKN3VN-ECW0McUe.js} +1 -1
  21. package/dist/assets/{chunk-YZCP3GAM-BV1RGRqK.js → chunk-YZCP3GAM-DLdAqU2z.js} +1 -1
  22. package/dist/assets/classDiagram-6PBFFD2Q-CkmfHfqf.js +1 -0
  23. package/dist/assets/classDiagram-v2-HSJHXN6E-CkmfHfqf.js +1 -0
  24. package/dist/assets/clone-pjnYCaC4.js +1 -0
  25. package/dist/assets/{cose-bilkent-S5V4N54A-CjAVlyw6.js → cose-bilkent-S5V4N54A-CfMuBnZy.js} +1 -1
  26. package/dist/assets/{dagre-KV5264BT-DZV42aOy.js → dagre-KV5264BT-xxdATAWV.js} +1 -1
  27. package/dist/assets/{diagram-5BDNPKRD-DpDA9ZeE.js → diagram-5BDNPKRD-s8izYXws.js} +1 -1
  28. package/dist/assets/{diagram-G4DWMVQ6-86vmHGG_.js → diagram-G4DWMVQ6-BaZWrq-d.js} +1 -1
  29. package/dist/assets/{diagram-MMDJMWI5-CzLVfy9C.js → diagram-MMDJMWI5-DlzU0RKB.js} +1 -1
  30. package/dist/assets/{diagram-TYMM5635-C1n6QVNv.js → diagram-TYMM5635-Fej8ir1x.js} +1 -1
  31. package/dist/assets/{erDiagram-SMLLAGMA-BWST8PqT.js → erDiagram-SMLLAGMA-Bwg0_DNs.js} +1 -1
  32. package/dist/assets/{flowDiagram-DWJPFMVM-zfku-qzI.js → flowDiagram-DWJPFMVM-pJ8Bv6wt.js} +1 -1
  33. package/dist/assets/{ganttDiagram-T4ZO3ILL-BIxQMxEL.js → ganttDiagram-T4ZO3ILL-DvgJ4Q6n.js} +1 -1
  34. package/dist/assets/{gitGraphDiagram-UUTBAWPF-E7gXMGl0.js → gitGraphDiagram-UUTBAWPF-Du8KitZ0.js} +1 -1
  35. package/dist/assets/{graph-Chi_Do3A.js → graph-57Q-0mNG.js} +1 -1
  36. package/dist/assets/{index-BsRFLaCT.js → index-BOryMxum.js} +1 -1
  37. package/dist/assets/{index-CyMcZjWq.js → index-Bt7QsK9T.js} +1 -1
  38. package/dist/assets/{index-BbuqKcgW.js → index-CVh-Zo2A.js} +1 -1
  39. package/dist/assets/{index-BVkdlwjO.js → index-Cf77lzSr.js} +1 -1
  40. package/dist/assets/{index-Batfx707.js → index-Cn0akK9k.js} +1 -1
  41. package/dist/assets/{index-CaTBBfzw.js → index-EFFRo37G.js} +1 -1
  42. package/dist/assets/{index-Bp83Qa3f.js → index-mpHzrAV9.js} +2 -2
  43. package/dist/assets/{index-BrmFDbRb.js → index-zljZK-NO.js} +1 -1
  44. package/dist/assets/{infoDiagram-42DDH7IO-CJSIzH2A.js → infoDiagram-42DDH7IO-DZz6OAQe.js} +1 -1
  45. package/dist/assets/{ishikawaDiagram-UXIWVN3A-B631W1wW.js → ishikawaDiagram-UXIWVN3A-Chrlpw73.js} +1 -1
  46. package/dist/assets/{journeyDiagram-VCZTEJTY-ChtGieBW.js → journeyDiagram-VCZTEJTY-D-fCEwg9.js} +1 -1
  47. package/dist/assets/{jszip.min-MLKd3flP.js → jszip.min-mU_-As7x.js} +1 -1
  48. package/dist/assets/{kanban-definition-6JOO6SKY-hLAy-WRt.js → kanban-definition-6JOO6SKY-DFdrm5t-.js} +1 -1
  49. package/dist/assets/{layout-cxTukSs_.js → layout-Dh-E01gA.js} +1 -1
  50. package/dist/assets/{linear-lKN6YVn3.js → linear-BjXnK-6T.js} +1 -1
  51. package/dist/assets/{mermaid.core-BYpzUgET.js → mermaid.core-Cbqxn86C.js} +2 -2
  52. package/dist/assets/{min-BvhzyJ7G.js → min-B4n9eIGL.js} +1 -1
  53. package/dist/assets/{mindmap-definition-QFDTVHPH-DLmLjuqG.js → mindmap-definition-QFDTVHPH-Bw49x4oU.js} +1 -1
  54. package/dist/assets/{pieDiagram-DEJITSTG-CpQId_ss.js → pieDiagram-DEJITSTG-D-iq9rKK.js} +1 -1
  55. package/dist/assets/{quadrantDiagram-34T5L4WZ-B2xWOHsh.js → quadrantDiagram-34T5L4WZ-QtFjo8i4.js} +1 -1
  56. package/dist/assets/{requirementDiagram-MS252O5E-CfCJaJBw.js → requirementDiagram-MS252O5E-BwmEZf4F.js} +1 -1
  57. package/dist/assets/{sankeyDiagram-XADWPNL6-CSClMzTh.js → sankeyDiagram-XADWPNL6-CTtXN32x.js} +1 -1
  58. package/dist/assets/seqResourceLoaders-DMyPYdA-.js +2 -0
  59. package/dist/assets/{sequenceDiagram-FGHM5R23-D5WoARR1.js → sequenceDiagram-FGHM5R23-DC00gRqs.js} +1 -1
  60. package/dist/assets/{stateDiagram-FHFEXIEX-DC1_JCl1.js → stateDiagram-FHFEXIEX-CT963BWJ.js} +1 -1
  61. package/dist/assets/{stateDiagram-v2-QKLJ7IA2-BOndcGRp.js → stateDiagram-v2-QKLJ7IA2-1T7yDlvQ.js} +1 -1
  62. package/dist/assets/{timeline-definition-GMOUNBTQ-Bm3Lk96s.js → timeline-definition-GMOUNBTQ-CDu66c9j.js} +1 -1
  63. package/dist/assets/vendor-antd-DADYo_zg.js +17 -0
  64. package/dist/assets/{vendor-codemirror-BD02EJx5.js → vendor-codemirror-tF6HNoR6.js} +1 -1
  65. package/dist/assets/vendor-mdxeditor-CFAmRN3Y.js +2 -0
  66. package/dist/assets/vendor-qrcode-DYKmbePy.js +6 -0
  67. package/dist/assets/vendor-virtuoso-TxPxvPjL.js +1 -0
  68. package/dist/assets/{vennDiagram-DHZGUBPP-CA8MWsbD.js → vennDiagram-DHZGUBPP-DSm6yR_C.js} +1 -1
  69. package/dist/assets/{wardley-RL74JXVD-Dw7GlJWj.js → wardley-RL74JXVD-kFdCN4XL.js} +1 -1
  70. package/dist/assets/{wardleyDiagram-NUSXRM2D-woq7iHEC.js → wardleyDiagram-NUSXRM2D-BY1GQbCO.js} +1 -1
  71. package/dist/assets/{xychartDiagram-5P7HB3ND-B4JCiFF4.js → xychartDiagram-5P7HB3ND-ONnFdWbS.js} +1 -1
  72. package/dist/index.html +4 -4
  73. package/findcc.js +103 -6
  74. package/package.json +1 -1
  75. package/server/lib/proxy-stats.js +75 -32
  76. package/dist/assets/App-BfzeNwOB.css +0 -1
  77. package/dist/assets/App-Bqz6Y5h4.js +0 -2
  78. package/dist/assets/Mobile-2LDWfaUe.js +0 -1
  79. package/dist/assets/UnifiedProxyRetryPage-CFz4vOH5.css +0 -1
  80. package/dist/assets/UnifiedProxyRetryPage-DFyS9doh.js +0 -1
  81. package/dist/assets/classDiagram-6PBFFD2Q-CnUCTEpg.js +0 -1
  82. package/dist/assets/classDiagram-v2-HSJHXN6E-CnUCTEpg.js +0 -1
  83. package/dist/assets/clone-D0NlqTo0.js +0 -1
  84. package/dist/assets/seqResourceLoaders-DIUJh1ym.js +0 -2
  85. package/dist/assets/vendor-antd-CyudKxuD.js +0 -17
  86. package/dist/assets/vendor-mdxeditor-C3Q4i3LX.js +0 -2
  87. package/dist/assets/vendor-qrcode-DK9W5Ghb.js +0 -6
  88. package/dist/assets/vendor-virtuoso-C82iSAZx.js +0 -1
package/findcc.js CHANGED
@@ -248,14 +248,19 @@ export function resolvePreferredClaudeSelection({ prefsFile } = {}) {
248
248
  const codeFusePath = resolveCodeFuseClaudePath();
249
249
  if (codeFusePath) return describeClaudeSelection(codeFusePath, false, 'codefuse');
250
250
 
251
+ // Native path (platform-specific binary) takes priority over PATH-based and
252
+ // npm-based resolution. On Windows, PATH may surface a postinstall stub that
253
+ // causes ERROR_BAD_EXE_FORMAT (193 / 216); the platform binary bypasses that.
254
+ const nativePath = resolveNativePath();
255
+ if (nativePath) return describeClaudeSelection(nativePath, false, 'native');
256
+
251
257
  const pathSelection = resolveClaudeFromPath();
252
258
  if (pathSelection) return describeClaudeSelection(pathSelection.path, pathSelection.isNpmVersion, 'path');
253
259
 
254
260
  const npmPath = resolveNpmClaudePath();
255
261
  if (npmPath) return describeClaudeSelection(npmPath, true, 'npm');
256
262
 
257
- const nativePath = resolveNativePath();
258
- return nativePath ? describeClaudeSelection(nativePath, false, 'native') : null;
263
+ return null;
259
264
  }
260
265
 
261
266
  // The import statement injected at the top of @anthropic-ai/claude-code/cli.js.
@@ -301,17 +306,109 @@ export function isBrowserOpenSuppressed() {
301
306
  }
302
307
  // ████████████████████████████████████████████████████████████████████████████
303
308
 
309
+ // `npm root -g` — the single source of truth for the global node_modules root.
310
+ //
311
+ // Windows: npm ships as `npm.cmd`, and since the CVE-2024-27980 fix (Node
312
+ // 18.20.2 / 20.12.2 / 22.0.0) handing a `.cmd`/`.bat` target to execFileSync
313
+ // throws EINVAL *synchronously*. That threw straight into the catch below and
314
+ // returned null, so every Claude-discovery path that depends on the global root
315
+ // silently missed an `npm i -g @anthropic-ai/claude-code` install and `ccv`
316
+ // died with "cli.js not found" (issue #137).
317
+ //
318
+ // `cmd.exe /c npm root -g` is the doc-sanctioned non-shell route: the executed
319
+ // image is cmd.exe (a real PE), and the argv is a fixed literal — no caller or
320
+ // user input is ever interpolated, so there is no command-injection surface.
321
+ // Exported for unit tests: the win32 branch must be assertable off-Windows.
322
+ export function buildNpmRootCommand(platform = process.platform, env = process.env) {
323
+ if (platform === 'win32') {
324
+ return {
325
+ cmd: env.COMSPEC || 'cmd.exe',
326
+ args: ['/d', '/s', '/c', 'npm root -g'],
327
+ // cmd.exe must receive `npm root -g` as one token; Node's default quoting
328
+ // would wrap it in quotes that cmd then fails to parse.
329
+ windowsVerbatimArguments: true,
330
+ };
331
+ }
332
+ return { cmd: 'npm', args: ['root', '-g'], windowsVerbatimArguments: false };
333
+ }
334
+
335
+ // npm may prepend warnings (funding/update notices) to stdout; the resolved path
336
+ // is the last non-empty line. Exported for unit tests.
337
+ export function parseNpmRootOutput(raw) {
338
+ const lines = String(raw ?? '').split(/\r?\n/).map(s => s.trim()).filter(Boolean);
339
+ return lines.length ? lines[lines.length - 1] : null;
340
+ }
341
+
304
342
  export function getGlobalNodeModulesDir() {
343
+ const { cmd, args, windowsVerbatimArguments } = buildNpmRootCommand();
305
344
  try {
306
- return execFileSync(process.platform === 'win32' ? 'npm.cmd' : 'npm', ['root', '-g'], {
345
+ const out = execFileSync(cmd, args, {
307
346
  encoding: 'utf-8',
308
347
  windowsHide: true,
309
- timeout: 2000,
348
+ // npm on Windows (cmd.exe + Defender) is routinely slower than 2s; a
349
+ // premature timeout was itself a source of "claude not found".
350
+ timeout: 10000,
310
351
  maxBuffer: 1024 * 1024,
311
- }).trim();
352
+ stdio: ['ignore', 'pipe', 'ignore'],
353
+ windowsVerbatimArguments,
354
+ });
355
+ const dir = parseNpmRootOutput(out);
356
+ if (dir && existsSync(dir)) return dir;
357
+ return dir || inferGlobalNodeModulesDir();
312
358
  } catch {
313
- return null;
359
+ // npm missing, not on PATH, or slower than the timeout — fall back to the
360
+ // well-known layouts so discovery still works without ever running npm.
361
+ return inferGlobalNodeModulesDir();
362
+ }
363
+ }
364
+
365
+ // Ordered candidate list for the npm-free global-root fallback. Pure (no fs
366
+ // access) and parameterized so tests can assert the win32 ordering off-Windows.
367
+ export function globalNodeModulesCandidates(platform = process.platform, env = process.env, home = homedir()) {
368
+ // Use the target platform's separator so the win32 branch is assertable from a
369
+ // POSIX test run (at runtime on Windows this is exactly what `join` does).
370
+ const pj = platform === 'win32' ? win32.join : join;
371
+ const candidates = [];
372
+ const prefix = env.NPM_CONFIG_PREFIX || env.npm_config_prefix;
373
+ if (prefix) {
374
+ // Windows installs land directly in <prefix>/node_modules; POSIX adds lib/.
375
+ candidates.push(pj(prefix, 'node_modules'), pj(prefix, 'lib', 'node_modules'));
376
+ }
377
+ if (platform === 'win32') {
378
+ // The default `npm i -g` target for the official Node installer.
379
+ if (env.APPDATA) candidates.push(pj(env.APPDATA, 'npm', 'node_modules'));
380
+ if (env.ProgramFiles) candidates.push(pj(env.ProgramFiles, 'nodejs', 'node_modules'));
381
+ if (env.LOCALAPPDATA) {
382
+ candidates.push(pj(env.LOCALAPPDATA, 'nvm', 'node_modules'));
383
+ candidates.push(pj(env.LOCALAPPDATA, 'Volta', 'tools', 'image', 'node_modules'));
384
+ }
385
+ } else {
386
+ candidates.push(
387
+ pj(home, '.npm-global', 'lib', 'node_modules'),
388
+ '/usr/local/lib/node_modules',
389
+ '/opt/homebrew/lib/node_modules',
390
+ pj(home, '.volta', 'tools', 'image', 'node_modules'),
391
+ );
314
392
  }
393
+ // The dir holding cc-viewer itself IS a global node_modules when ccv was
394
+ // installed with `npm i -g` — a reliable last resort on any platform.
395
+ candidates.push(NODE_MODULES);
396
+ return candidates.filter(Boolean);
397
+ }
398
+
399
+ // npm-free fallback for the global node_modules root. `npm root -g` can fail for
400
+ // reasons that have nothing to do with whether Claude Code is installed (npm not
401
+ // on a GUI process's PATH, a corporate shim that is slow to start, EINVAL as
402
+ // above). These are the canonical global prefixes; the first one that exists wins.
403
+ // L7: these are absolute machine paths that ignore PATH/HOME isolation exactly
404
+ // like the raw NATIVE_CANDIDATES — blocked under test context, where `npm root -g`
405
+ // (real or fixture) remains the only sanctioned seam.
406
+ export function inferGlobalNodeModulesDir() {
407
+ if (isRealClaudeLookupBlocked()) return null;
408
+ for (const dir of globalNodeModulesCandidates()) {
409
+ if (existsSync(dir)) return dir;
410
+ }
411
+ return null;
315
412
  }
316
413
 
317
414
  export function resolveCliPath() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-viewer",
3
- "version": "1.7.7",
3
+ "version": "1.7.9",
4
4
  "description": "Claude Code logging, visualization, and management toolkit — launch a web viewer alongside Claude Code with full request/response tracing, proxy, and mobile support",
5
5
  "license": "MIT",
6
6
  "main": "server.js",
@@ -9,6 +9,7 @@
9
9
  import { mkdirSync } from 'node:fs';
10
10
  import { join } from 'node:path';
11
11
  import { AsyncWriteQueue } from './async-write-queue.js';
12
+ import { reportSwallowed } from './error-report.js';
12
13
 
13
14
  // ── Detail record schema ──────────────────────────────────────────────
14
15
  // Appends one JSON line after each proxied LLM API request completes. Fields align with llm-retry-proxy's retry records.
@@ -120,7 +121,11 @@ export function appendRecord(filePath, record, onDone) {
120
121
  try {
121
122
  mkdirSync(dir, { recursive: true });
122
123
  _dirsEnsured.add(dir);
123
- } catch { /* No permission — the queued append will surface the failure as a silent no-op */ }
124
+ } catch (err) {
125
+ // No permission / read-only fs — the queued append will surface the failure
126
+ // as a silent no-op. Record it so the cause isn't fully invisible.
127
+ reportSwallowed('proxyStats.mkdir', err);
128
+ }
124
129
  }
125
130
  _statsWriteQueue.appendTo(filePath, JSON.stringify(record) + '\n', onDone);
126
131
  }
@@ -147,9 +152,9 @@ export function emitProxyStatsUpdate(fileName) {
147
152
  try {
148
153
  _statsUpdateListener(fileName);
149
154
  } catch (err) {
150
- if (process.env.CCV_DEBUG) {
151
- console.error('[CC-Viewer Proxy] proxy stats notify failed:', err?.message);
152
- }
155
+ // A throwing listener would silently break stats propagation (the SSE push,
156
+ // recompute trigger, etc.). Record it instead of swallowing silently.
157
+ reportSwallowed('proxyStats.emit', err);
153
158
  }
154
159
  }
155
160
 
@@ -196,6 +201,37 @@ export function computeStreak(records) {
196
201
  return { current: { type: curType || 'success', count: curCount }, worstFailure };
197
202
  }
198
203
 
204
+ /**
205
+ * Retry-burden bucket definitions: turns the raw retry-count distribution into
206
+ * actionable buckets (0 / 1-5 / 6-20 / 21-50 / >50). Aligned with llm-retry-proxy's
207
+ * renderBurdenChart buckets. `key` is the stable i18n id (ui.proxyStats.retryBurdenBuckets.<key>).
208
+ *
209
+ * `range` is [min, max] with `max: null` meaning "open ended". Deliberately not
210
+ * `Infinity`: this table's shape is mirrored into the stats JSON, and
211
+ * JSON.stringify(Infinity) is `null` anyway — spelling it null keeps the
212
+ * in-process value and the serialized value identical.
213
+ *
214
+ * Exposed for tests that want to assert the frozen bucket contract without re-typing
215
+ * the boundaries.
216
+ */
217
+ export const RETRY_BURDEN_BUCKETS = [
218
+ { key: '0', range: [0, 0] },
219
+ { key: '1_5', range: [1, 5] },
220
+ { key: '6_20', range: [6, 20] },
221
+ { key: '21_50', range: [21, 50] },
222
+ { key: 'over50', range: [51, null] },
223
+ ];
224
+
225
+ // Bump the bucket whose range covers `retries`. Buckets are ordered low→high
226
+ // and non-overlapping, so the first match wins; returns void (mutates `counts`).
227
+ // A null upper bound is open ended.
228
+ function bumpBurden(counts, retries) {
229
+ for (const b of counts) {
230
+ const [min, max] = b.range;
231
+ if (retries >= min && (max === null || retries <= max)) { b.count++; return; }
232
+ }
233
+ }
234
+
199
235
  /**
200
236
  * Aggregate a batch of detail records into a stats structure. Called by stats-worker, also used directly by /api/proxy-stats.
201
237
  *
@@ -233,6 +269,8 @@ export function aggregateRecords(records, opts = {}) {
233
269
  const byModelMap = new Map();
234
270
  const byPathMap = new Map();
235
271
  const byProfileMap = new Map();
272
+ // Retry-burden buckets bumped inline during the main loop (avoids a second O(n) pass).
273
+ const retryBurdenCounts = RETRY_BURDEN_BUCKETS.map(b => ({ ...b, count: 0 }));
236
274
  let slowest = null;
237
275
  let fastest = null;
238
276
 
@@ -249,21 +287,22 @@ export function aggregateRecords(records, opts = {}) {
249
287
  }
250
288
  durations.push(dur);
251
289
  retryDist.set(retries, (retryDist.get(retries) || 0) + 1);
290
+ bumpBurden(retryBurdenCounts, retries);
252
291
  for (const c of (r.retry_codes || [])) {
253
292
  retryCodeCounts.set(c, (retryCodeCounts.get(c) || 0) + 1);
254
293
  }
255
294
  // by model
256
295
  const model = r.model || '(unknown)';
257
296
  if (!byModelMap.has(model)) byModelMap.set(model, newBucket());
258
- accBucket(byModelMap.get(model), retries, ok, dur);
297
+ accBucket(byModelMap.get(model), retries, ok, dur, r.retry_codes);
259
298
  // by path
260
299
  const path = r.path || '/';
261
300
  if (!byPathMap.has(path)) byPathMap.set(path, newBucket());
262
- accBucket(byPathMap.get(path), retries, ok, dur);
301
+ accBucket(byPathMap.get(path), retries, ok, dur, r.retry_codes);
263
302
  // by profile
264
303
  const profileKey = r.profile_id || 'default';
265
304
  if (!byProfileMap.has(profileKey)) byProfileMap.set(profileKey, { ...newBucket(), profile_name: r.profile_name || 'Default' });
266
- accBucket(byProfileMap.get(profileKey), retries, ok, dur);
305
+ accBucket(byProfileMap.get(profileKey), retries, ok, dur, r.retry_codes);
267
306
  // slowest / fastest (fastest only counts successes with dur>0)
268
307
  const candidate = { ts: r.ts, path, model, attempts: r.attempts, retries, duration_ms: dur, final_status: r.final_status, retry_codes: r.retry_codes || [] };
269
308
  if (!slowest || dur > slowest.duration_ms) slowest = candidate;
@@ -301,10 +340,11 @@ export function aggregateRecords(records, opts = {}) {
301
340
  },
302
341
  byModel: mapToSortedArray(byModelMap, 'model'),
303
342
  byPath: mapToSortedArray(byPathMap, 'path').slice(0, 10), // Top 10 path
304
- byProfile: mapToSortedArrayWithExtra(byProfileMap, 'profile_id', 'profile_name'),
343
+ byProfile: mapToSortedArray(byProfileMap, 'profile_id', 'profile_name'),
305
344
  retryDistribution: [...retryDist.entries()]
306
345
  .sort((a, b) => a[0] - b[0])
307
346
  .map(([retries, count]) => ({ retries, count })),
347
+ retryBurden: retryBurdenCounts,
308
348
  retryCodes: [...retryCodeCounts.entries()]
309
349
  .sort((a, b) => b[1] - a[1])
310
350
  .map(([code, count]) => ({ code, count })),
@@ -315,10 +355,10 @@ export function aggregateRecords(records, opts = {}) {
315
355
  }
316
356
 
317
357
  function newBucket() {
318
- return { requests: 0, retries: 0, succeeded: 0, firstOk: 0, failed: 0, durations: [] };
358
+ return { requests: 0, retries: 0, succeeded: 0, firstOk: 0, failed: 0, durations: [], retryCodeCounts: new Map() };
319
359
  }
320
360
 
321
- function accBucket(b, retries, ok, dur) {
361
+ function accBucket(b, retries, ok, dur, retryCodes) {
322
362
  b.requests++;
323
363
  b.retries += retries;
324
364
  if (ok) {
@@ -328,46 +368,48 @@ function accBucket(b, retries, ok, dur) {
328
368
  b.failed++;
329
369
  }
330
370
  b.durations.push(dur);
371
+ for (const c of (retryCodes || [])) {
372
+ if (Number.isFinite(c)) b.retryCodeCounts.set(c, (b.retryCodeCounts.get(c) || 0) + 1);
373
+ }
331
374
  }
332
375
 
333
- function mapToSortedArray(map, keyName) {
334
- const arr = [];
335
- for (const [k, b] of map.entries()) {
336
- b.durations.sort((a, c) => a - c);
337
- const entry = {
338
- [keyName]: k,
339
- requests: b.requests,
340
- retries: b.retries,
341
- succeeded: b.succeeded,
342
- firstOk: b.firstOk,
343
- failed: b.failed,
344
- availabilityPct: b.requests ? round2(b.succeeded / b.requests * 100) : 0,
345
- upstreamAvailabilityPct: b.requests ? round2(b.firstOk / b.requests * 100) : 0,
346
- p95Ms: round3(percentile(b.durations, 0.95)),
347
- };
348
- arr.push(entry);
349
- }
350
- arr.sort((a, b) => b.requests - a.requests);
351
- return arr;
376
+ // Finalize a bucket's per-bucket retry-code map into top-5 array + dominant fail code.
377
+ function finalizeRetryCodes(b) {
378
+ const arr = [...(b.retryCodeCounts?.entries() || [])]
379
+ .sort((a, c) => c[1] - a[1])
380
+ .slice(0, 5)
381
+ .map(([code, count]) => ({ code, count }));
382
+ const top = arr[0] || null;
383
+ return {
384
+ retryCodeCounts: arr,
385
+ dominantFailStatus: top ? top.code : null,
386
+ dominantFailCount: top ? top.count : 0,
387
+ };
352
388
  }
353
389
 
354
- // byProfile-specific: the bucket carries an extra profile_name field, included in the output
355
- function mapToSortedArrayWithExtra(map, keyName, extraName) {
390
+ // Flatten a dimension's bucket map into a sorted entry array.
391
+ // `extraName` (optional, used by byProfile) emits an extra `[extraName]: bucket[extraName] || k`
392
+ // field — the only structural difference between the byModel/byPath and byProfile outputs.
393
+ function mapToSortedArray(map, keyName, extraName) {
356
394
  const arr = [];
357
395
  for (const [k, b] of map.entries()) {
358
396
  b.durations.sort((a, c) => a - c);
397
+ const fin = finalizeRetryCodes(b);
359
398
  const entry = {
360
399
  [keyName]: k,
361
- [extraName]: b[extraName] || k,
362
400
  requests: b.requests,
363
401
  retries: b.retries,
364
402
  succeeded: b.succeeded,
365
403
  firstOk: b.firstOk,
366
404
  failed: b.failed,
405
+ retryCodeCounts: fin.retryCodeCounts,
406
+ dominantFailStatus: fin.dominantFailStatus,
407
+ dominantFailCount: fin.dominantFailCount,
367
408
  availabilityPct: b.requests ? round2(b.succeeded / b.requests * 100) : 0,
368
409
  upstreamAvailabilityPct: b.requests ? round2(b.firstOk / b.requests * 100) : 0,
369
410
  p95Ms: round3(percentile(b.durations, 0.95)),
370
411
  };
412
+ if (extraName) entry[extraName] = b[extraName] || k;
371
413
  arr.push(entry);
372
414
  }
373
415
  arr.sort((a, b) => b.requests - a.requests);
@@ -386,6 +428,7 @@ function emptyStats() {
386
428
  byPath: [],
387
429
  byProfile: [],
388
430
  retryDistribution: [],
431
+ retryBurden: [],
389
432
  retryCodes: [],
390
433
  slowest: null,
391
434
  fastest: null,
@@ -1 +0,0 @@
1
- ._liveTag_8g4c3_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_8g4c3_23{position:absolute;left:0;top:0;bottom:0;width:var(--ctx-percent, 0);background-color:var(--ctx-color);background-image:repeating-linear-gradient(135deg,rgba(255,255,255,.25) 0,rgba(255,255,255,.25) 2px,transparent 2px,transparent 7px);opacity:.35;transition:width .5s ease,background-color .3s;pointer-events:none}._liveTagContent_8g4c3_44{position:relative;z-index:1;display:inline-flex;align-items:center}._liveTagHistory_8g4c3_52{background:var(--bg-surface);border-color:var(--border-light);color:var(--text-primary)}._liveTagText_8g4c3_59{margin-left:4px;font-variant-numeric:tabular-nums}._cachePopoverPlaceholder_8g4c3_65{min-width:300px}._form_5wfub_3{display:flex;flex-direction:column;gap:2px}._row_5wfub_9{display:flex;flex-direction:column;margin-bottom:6px}._label_5wfub_15{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--text-tertiary);margin-bottom:4px}._hint_5wfub_24{font-size:11px;color:var(--text-tertiary);line-height:1.5;margin-top:3px}._divider_5wfub_31{border-top:1px dashed var(--border-secondary);margin:8px 0 6px}._fullWidth_5wfub_36{width:100%}._numField_5wfub_40{display:flex;align-items:center;gap:6px}._unit_5wfub_46{font-size:11px;color:var(--text-gray)}._reservedTag_5wfub_51{font-size:10px;padding:0 4px;border-radius:3px;background:var(--color-warning-dark-bg);color:var(--color-warning-light);line-height:16px}._footer_5wfub_60{display:flex;align-items:center;justify-content:space-between;margin-top:14px;gap:8px}._footerRight_5wfub_68{display:flex;gap:8px}._note_5wfub_73{font-size:11px;color:var(--text-gray);line-height:1.5;margin-top:10px;padding:8px 10px;border-radius:4px;background:var(--bg-elevated);border:1px solid var(--border-secondary)}._scroll_5wfub_84{flex:1;min-height:0;overflow:auto;padding:12px 16px 0}._modeRow_1hjkn_1{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:10px}._modeLeft_1hjkn_9{display:flex;align-items:center;gap:10px}._modeRight_1hjkn_15{display:flex;align-items:center;gap:8px}._overrideWarn_1hjkn_22{font-size:12px;color:var(--color-warning, #d4810a)}._previewLabel_1hjkn_27{font-size:13px;color:var(--text-secondary, #888)}._previewBox_1hjkn_36{border:1px solid var(--border-primary);border-radius:8px;background:transparent;padding:12px 14px;min-height:320px;max-height:60vh;overflow:auto}._previewEmpty_1hjkn_46{font-size:13px;color:var(--text-secondary, #888)}._hint_1hjkn_51{margin-top:10px;font-size:12px;color:var(--text-secondary, #888);line-height:1.6}._dirLine_1hjkn_58{word-break:break-all}._warn_1hjkn_62{margin-top:10px;font-size:12px;color:var(--color-warning, #d4810a)}._tabRow_1hjkn_71{display:flex;align-items:flex-end;gap:8px;padding:0 4px;flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}._tabRow_1hjkn_71::-webkit-scrollbar{display:none}._tabBtn_1hjkn_90{display:inline-flex;align-items:center;gap:5px;padding:9px 14px;font-size:12px;line-height:1.6;border:1px solid transparent;border-radius:14px;background:transparent;color:var(--text-secondary);cursor:pointer;transition:all .2s;-webkit-user-select:none;user-select:none;white-space:nowrap;flex-shrink:0}._tabBtn_1hjkn_90:hover{color:var(--color-primary)}._tabBtn_1hjkn_90:focus-visible{outline:2px solid var(--color-primary);outline-offset:1px}._tabBtn_1hjkn_90._tabActive_1hjkn_118{background:var(--bg-container);color:var(--color-primary);border-color:var(--border-primary);border-bottom-color:var(--bg-container);border-radius:10px 10px 0 0;font-weight:500;margin-bottom:-1px;position:relative;z-index:1}._tabRow_1hjkn_71>._tabBtn_1hjkn_90._tabActive_1hjkn_118,._tabWrap_1hjkn_132:has(>._tabBtn_1hjkn_90._tabActive_1hjkn_118){position:sticky;left:0;right:0;z-index:2}[data-theme=light] ._tabBtn_1hjkn_90._tabActive_1hjkn_118{box-shadow:0 -3px 8px #0000000f}._editorBox_1hjkn_33{background:var(--bg-container);border-radius:8px;overflow:hidden;padding:4px;position:relative}[data-theme=light] ._editorBox_1hjkn_33{box-shadow:0 3px 8px #00000014}._editorBox_1hjkn_33 .ant-input{background:transparent;border:1px solid var(--border-primary);border-radius:8px;box-shadow:none;padding:12px 14px;font-size:12px;line-height:1.5;color:var(--text-primary)}._editorBox_1hjkn_33 .ant-input:hover{border-color:var(--border-primary);background:transparent}._editorBox_1hjkn_33 .ant-input:focus{border-color:var(--color-primary-pale);box-shadow:none}._editorBox_1hjkn_33 .ant-input[disabled]{color:var(--text-muted);background:transparent}._tabWrap_1hjkn_132{position:relative;display:inline-flex;align-items:center;flex-shrink:0}._tabTitle_1hjkn_199{white-space:nowrap}._tabDelete_1hjkn_204{position:absolute;top:2px;inset-inline-end:4px;width:14px;height:14px;border-radius:50%;background:var(--bg-elevated);border:1px solid var(--border-primary);color:var(--text-secondary);font-size:10px;line-height:1;display:flex;align-items:center;justify-content:center;cursor:pointer;opacity:0;transition:opacity .15s;z-index:2}._tabWrap_1hjkn_132:hover ._tabDelete_1hjkn_204{opacity:1}._tabDelete_1hjkn_204:hover{color:var(--color-error, #d4380d);border-color:var(--color-error, #d4380d)}@media(max-width:768px){._tabDelete_1hjkn_204{opacity:1}}._addBtn_1hjkn_237{display:inline-flex;align-items:center;align-self:center;gap:5px;padding:6px 14px;font-size:12px;line-height:1.6;margin-left:4px;margin-bottom:2px;border:none;border-radius:14px;background:transparent;color:var(--text-muted);cursor:pointer;transition:background .15s,color .15s;-webkit-user-select:none;user-select:none;white-space:nowrap;flex-shrink:0}._addBtn_1hjkn_237:hover{color:var(--color-primary);background:var(--bg-surface)}._addBtn_1hjkn_237:disabled{cursor:not-allowed;opacity:.5}[data-theme=light] ._addBtn_1hjkn_237{color:var(--text-secondary)}._scopeBadge_1hjkn_270{font-size:10px;line-height:1.4;padding:0 4px;border-radius:6px;background:var(--bg-surface);color:var(--text-muted)}._dirtyDot_1hjkn_280{width:6px;height:6px;border-radius:50%;background:var(--color-primary);flex-shrink:0}._titleRow_1hjkn_289{display:inline-flex;align-items:center;gap:8px}._helpBtn_1hjkn_297{align-self:center;width:16px;height:16px;border-radius:50%;border:1px solid var(--border-primary);background:var(--bg-elevated);color:var(--text-secondary);font-size:11px;line-height:1;display:inline-flex;align-items:center;justify-content:center;cursor:help;flex-shrink:0;-webkit-user-select:none;user-select:none}._helpBtn_1hjkn_297:hover{color:var(--color-primary);border-color:var(--color-primary)}._paramDocBtn_1hjkn_320{align-self:center;height:18px;padding:0 8px;border-radius:999px;border:1px solid var(--border-primary);background:var(--bg-elevated);color:var(--text-secondary);font-size:11px;font-weight:400;line-height:1;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;flex-shrink:0;-webkit-user-select:none;user-select:none;white-space:nowrap;max-width:40vw;overflow:hidden;text-overflow:ellipsis}._paramDocBtn_1hjkn_320:hover{color:var(--color-primary);border-color:var(--color-primary)}._paramDocBtn_1hjkn_320:focus-visible{outline:2px solid var(--color-primary);outline-offset:1px}._docBox_1hjkn_352{max-height:65vh;overflow:auto;font-size:13px;line-height:1.6}._docIntro_1hjkn_361{color:var(--text-secondary);font-size:12px;line-height:1.6;margin:0 0 12px;padding-bottom:10px;border-bottom:1px solid var(--border-primary)}._addModalBody_1hjkn_371{display:flex;flex-direction:column;gap:14px;margin-top:4px}._addModalField_1hjkn_377{display:flex;flex-direction:column;gap:6px}._fieldLabelRow_1hjkn_382{display:inline-flex;align-items:center;gap:6px;font-size:13px;color:var(--text-secondary, #888)}._addError_1hjkn_390{font-size:12px;color:var(--color-error, #d4380d)}._presetSelect_1hjkn_394{width:100%}._presetMatched_1hjkn_397{font-size:11px;color:var(--color-text-secondary, #888)}._editButton_1r9yr_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_1r9yr_10 .anticon{display:inline-flex;align-items:center;line-height:1;position:relative;top:-1px}._editButton_1r9yr_10:hover,._editButton_1r9yr_10:focus-visible{opacity:1;color:var(--text-primary, #333);background-color:var(--bg-hover, rgba(0, 0, 0, .04));outline:none}._editButton_1r9yr_10:focus-visible{box-shadow:0 0 0 2px var(--focus-ring, rgba(64, 158, 255, .4))}._footer_1r9yr_55{display:flex;justify-content:space-between;align-items:center;gap:8px}._footerLeft_1r9yr_61,._footerRight_1r9yr_65{display:flex;gap:8px}._projectNameRow_1r9yr_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_1r9yr_80{color:var(--text-secondary, #888)}._projectNameValue_1r9yr_83{color:var(--text-primary, #333);font-family:var(--font-mono);word-break:break-all}._panel_1nxl3_1{display:flex;flex-direction:column;gap:14px}._required_1nxl3_7{margin-left:2px;color:var(--color-error-light, #ff7b7b)}._optional_1nxl3_12{margin-left:6px;font-size:12px;font-weight:400;color:var(--text-secondary)}._row_1nxl3_19{display:flex;align-items:center;justify-content:space-between;gap:12px}._label_1nxl3_26{font-size:14px;font-weight:500}._control_1nxl3_31{display:inline-flex;align-items:center;gap:10px}._field_1nxl3_37{display:flex;flex-direction:column;gap:6px}._fieldLabel_1nxl3_43{font-size:13px;color:var(--text-secondary)}._help_1nxl3_48{font-size:12px;color:var(--text-secondary);line-height:1.4}._warn_1nxl3_54{font-size:12px;line-height:1.5;color:var(--color-error-light, #ff7b7b)}._hint_1nxl3_60{font-size:12px;line-height:1.5;color:var(--text-secondary)}._helpIcon_1nxl3_67{margin-left:6px;color:var(--text-tertiary, #999);cursor:help;font-size:13px}._detailsToggle_1nxl3_74{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_1nxl3_74:hover{color:var(--text-primary, var(--text-secondary))}._details_1nxl3_74{display:flex;flex-direction:column;gap:10px}._actions_1nxl3_98{display:flex;justify-content:flex-end;gap:10px;margin-top:16px;padding-top:16px;border-top:1px solid var(--border-secondary)}._testBtn_1nxl3_108{margin-right:auto}._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_mzpnt_1{height:100%;box-sizing:border-box;overflow-y:auto;overflow-x:hidden;scrollbar-gutter:stable;padding:4px 2px;background:var(--bg-container)}._headerBar_mzpnt_15{display:flex;align-items:center;gap:8px}._refreshBtn_mzpnt_21{flex:0 0 auto}._statusTag_mzpnt_27{display:inline-flex;align-items:center;gap:8px;margin-left:auto}._statusTag_mzpnt_27 .ant-tag{margin-inline-end:0}._center_mzpnt_38{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;padding:40px 0;color:var(--text-secondary)}._hint_mzpnt_48{color:var(--text-secondary);font-size:13px}._chip_dnl8s_4{position:relative;line-height:0;cursor:pointer;-webkit-user-select:none;user-select:none;transition:opacity .15s}._chip_dnl8s_4:hover{opacity:.75}._logo_dnl8s_16{display:block;transition:color .15s}._connecting_dnl8s_22{opacity:.5}._dotError_dnl8s_27{position:absolute;right:-2px;top:-2px;width:6px;height:6px;border-radius:50%;background:var(--color-error, #ff4d4f);pointer-events:none}._dotReconnecting_dnl8s_39{position:absolute;right:-2px;top:-2px;width:6px;height:6px;border-radius:50%;background:var(--color-warning, #f59e0b);pointer-events:none;animation:_imDotPulse_dnl8s_1 1.2s ease-in-out infinite}@keyframes _imDotPulse_dnl8s_1{0%,to{opacity:1}50%{opacity:.3}}@media(prefers-reduced-motion:reduce){._dotReconnecting_dnl8s_39{animation:none}}._modelCard_1tsd3_3{border:1px solid var(--border-secondary);border-radius:6px;padding:8px 10px;background:var(--bg-container)}._modelName_1tsd3_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_1tsd3_17{width:100%;border-collapse:collapse}._th_1tsd3_21{padding:2px 12px;font-size:12px;font-family:var(--font-mono);white-space:nowrap;color:var(--text-tertiary);font-weight:400;text-align:right}._td_1tsd3_30{padding:2px 12px;font-size:12px;font-family:var(--font-mono);white-space:nowrap;color:var(--text-primary);text-align:right}._label_1tsd3_38{padding:2px 12px;font-size:12px;font-family:var(--font-mono);white-space:nowrap;color:var(--text-light);font-weight:400;text-align:left}._rowBorder_1tsd3_47{border-bottom:1px solid var(--border-primary)}._rebuildTotalRow_1tsd3_50{border-top:1px solid var(--border-light)}._rebuildTotalRow_1tsd3_50 td{font-weight:600}._cachePopoverEmpty_1tsd3_56{padding:8px 4px;color:var(--text-tertiary);font-size:13px}._toolChipGrid_1tsd3_61{display:flex;flex-wrap:wrap;gap:4px;padding:2px 0 6px 2px}._cacheToolChip_1tsd3_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_1tsd3_81{margin-right:8px}._detailMarkdownCard_1tsd3_86{border:1px solid var(--border-secondary);border-radius:6px;padding:8px 10px;background:var(--bg-container)}._memoryMarkdown_1tsd3_93{font-size:12.5px;line-height:1.55;color:var(--text-primary);word-break:break-word}._memoryMarkdown_1tsd3_93 p{margin:0 0 6px}._memoryMarkdown_1tsd3_93 ul,._memoryMarkdown_1tsd3_93 ol{margin:4px 0 6px;padding-left:20px}._memoryMarkdown_1tsd3_93 li{margin:2px 0}._memoryMarkdown_1tsd3_93 h1,._memoryMarkdown_1tsd3_93 h2,._memoryMarkdown_1tsd3_93 h3,._memoryMarkdown_1tsd3_93 h4{font-size:13px;font-weight:600;margin:8px 0 4px;color:var(--text-primary)}._memoryMarkdown_1tsd3_93 h1{font-size:14px}._memoryMarkdown_1tsd3_93 a{color:var(--primary-color, #1677ff);text-decoration:none;cursor:pointer}._memoryMarkdown_1tsd3_93 a:hover{text-decoration:underline}._memoryMarkdown_1tsd3_93 code{font-family:var(--font-mono);font-size:12px;padding:1px 4px;border-radius:3px;background:var(--bg-surface);color:var(--text-primary)}._memoryMarkdown_1tsd3_93 pre{margin:6px 0;padding:8px 10px;border-radius:4px;background:var(--bg-surface);overflow-x:auto}._memoryMarkdown_1tsd3_93 pre code{padding:0;background:transparent;font-size:12px}._memoryMarkdown_1tsd3_93 blockquote{margin:4px 0;padding:2px 8px;border-left:3px solid var(--border-hover);color:var(--text-secondary)}._memoryMarkdown_1tsd3_93 hr{margin:8px 0;border:none;border-top:1px solid var(--border-secondary)}._quickMenuGroup_1tsd3_164{position:relative}._quickMenuRow_1tsd3_168{display:flex;align-items:center;gap:6px;width:100%;background:none;border:none;color:var(--text-primary);font-size:13px;padding:6px 12px;text-align:left;cursor:pointer;border-radius:4px;white-space:nowrap}._quickMenuGroup_1tsd3_164:hover ._quickMenuRow_1tsd3_168,._quickMenuGroupOpen_1tsd3_185 ._quickMenuRow_1tsd3_168{background:var(--border-secondary)}._quickMenuRowIcon_1tsd3_189{display:flex;align-items:center;color:var(--text-tertiary)}._quickMenuRowIcon_1tsd3_189 svg{width:14px;height:14px}._quickMenuLabel_1tsd3_200{flex:1}._quickMenuValue_1tsd3_205{color:var(--text-tertiary);font-size:12px}._quickMenuCaret_1tsd3_210{color:var(--text-tertiary);font-size:10px}._quickMenuSubWrap_1tsd3_218{display:none;position:absolute;left:100%;bottom:-5px;padding-left:6px;z-index:1}._quickMenuGroupOpen_1tsd3_185 ._quickMenuSubWrap_1tsd3_218{display:block}._quickMenuSub_1tsd3_218{display:flex;flex-direction:column;background:var(--bg-elevated);border:1px solid var(--border-hover);border-radius:8px;padding:4px;min-width:76px;max-height:60vh;overflow-y:auto;box-shadow:0 6px 16px #0000002e}._quickMenuOption_1tsd3_248{background:none;border:none;color:var(--text-primary);font-size:13px;padding:5px 12px;text-align:left;cursor:pointer;border-radius:4px;white-space:nowrap}._quickMenuOption_1tsd3_248:hover{background:var(--border-secondary)}._quickMenuOption_1tsd3_248._quickMenuOptionActive_1tsd3_264{color:var(--color-primary);font-weight:500}._headerBar_jseur_2{display:flex;align-items:center;justify-content:space-between;width:100%;height:100%}._logoWrap_jseur_10{display:inline-flex;align-items:center;position:relative;margin-top:14px}._logoWrapActive_jseur_17:after{content:"";position:absolute;top:-10px;bottom:-10px;left:0;right:-200px}._logoImage_jseur_26{height:24px;width:24px;border-radius:3px;vertical-align:middle;opacity:.75;transition:opacity .2s;cursor:pointer}._logoImageActive_jseur_36{opacity:1}._compactBtn_jseur_43{font-size:12px;height:30px;display:inline-flex;align-items:center;justify-content:center}._compactBtnNoBorder_jseur_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_jseur_52 .anticon{display:inline-flex;align-items:center;justify-content:center;line-height:0}._headerProjectName_jseur_79{font-size:12px;color:inherit;white-space:nowrap}._headerProjectName_jseur_79:hover [data-alias-edit-trigger],._headerProjectName_jseur_79:focus-within [data-alias-edit-trigger]{opacity:.55}._countdownStrong_jseur_96{font-variant-numeric:tabular-nums}._qrcodePopover_jseur_101{display:flex;flex-direction:column;align-items:center;padding:8px}._qrcodeSection_jseur_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_jseur_119{font-size:14px;font-weight:600;color:var(--text-primary);margin-bottom:12px}._qrcodeUrlInput_jseur_126{margin-top:12px;font-size:12px;font-family:var(--font-mono)}._qrcodeUrlCopy_jseur_132{cursor:pointer;color:var(--text-tertiary);transition:color .2s}._qrcodeUrlCopy_jseur_132:hover{color:var(--color-primary-light)}._authSection_jseur_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_jseur_157{display:flex;align-items:center;justify-content:space-between}._authTitle_jseur_163{font-size:13px;font-weight:600;color:var(--text-primary)}._authPasswordLabel_jseur_169{font-size:12px;color:var(--text-secondary)}._authPasswordInput_jseur_174{font-size:12px;font-family:var(--font-mono)}._authSaveBtn_jseur_179{align-self:flex-end}._authEmptyWarn_jseur_183{font-size:12px;color:var(--color-error-light);line-height:1.4}._settingsGroupBox_jseur_191{border:1px solid var(--border-secondary);border-radius:8px;background:var(--bg-container);padding:4px 16px;margin-bottom:12px}._settingsGroupTitle_jseur_199{font-size:14px;font-weight:600;color:var(--text-primary);padding:12px 0 4px;border-bottom:1px solid var(--border-secondary)}._settingsItem_jseur_208{display:flex;justify-content:space-between;align-items:center;padding:12px 0}._settingsLabel_jseur_215{font-size:14px}._settingsHelpIcon_jseur_220{font-size:16px;color:var(--text-disabled);cursor:help;margin-left:4px}._settingsDivider_jseur_227{border-top:1px solid var(--border-primary);margin:12px 0}._logDirInput_jseur_232{margin-top:8px;background:var(--bg-base-alt);border-color:var(--border-light);color:var(--text-primary);font-family:var(--font-mono);font-size:13px}._claudeExecutableInput_jseur_241{width:100%;margin-top:8px;font-family:var(--font-mono);font-size:12px}._claudeExecutableHint_jseur_248{margin-top:6px;color:var(--text-tertiary);font-size:12px;line-height:1.5;overflow-wrap:anywhere}._tokenStatsEmpty_jseur_257{padding:8px 4px;color:var(--text-tertiary);font-size:13px}._tokenStatsContainer_jseur_264{display:flex;gap:12px;align-items:flex-start}._tokenStatsColumn_jseur_270{min-width:240px}._toolStatsColumn_jseur_274{min-width:180px}._modelCardSpaced_jseur_280{margin-bottom:10px}._rebuildCard_jseur_289{border:1px solid var(--border-secondary);border-radius:6px;padding:8px 10px;margin-top:10px;background:var(--bg-container)}._promptExportBar_jseur_298{margin-bottom:12px}._promptScrollArea_jseur_302{max-height:500px;overflow:auto}._promptEmpty_jseur_307{color:var(--text-tertiary);padding:12px}._promptTimestamp_jseur_313{color:var(--text-muted);font-size:12px;margin:12px 0 4px;padding-bottom:6px}._textPromptCard_jseur_321{margin:4px 0;background:var(--bg-container);border-radius:6px;border:1px solid var(--border-secondary);padding:10px 14px}._preText_jseur_330{white-space:pre-wrap;word-break:break-word;font-size:13px;line-height:1.6;color:var(--text-primary);margin:4px 0}._systemCollapse_jseur_340{margin:4px 0;background:var(--bg-elevated);border:1px solid var(--border-secondary);border-radius:6px}._systemLabel_jseur_347{color:var(--text-tertiary);font-size:12px}._preSys_jseur_352{white-space:pre-wrap;word-break:break-word;font-size:12px;line-height:1.5;color:var(--text-tertiary);margin:0}._promptTextarea_jseur_362{box-sizing:border-box;background:var(--bg-base-pure);width:100%;min-height:400px;color:var(--text-primary);font-family:var(--font-mono);font-size:13px;line-height:1.6;border:none;resize:vertical;padding:10px 14px;outline:none}._projectStatsCenter_jseur_378{display:flex;justify-content:center;padding:40px 0}._projectStatsEmpty_jseur_384{color:var(--text-tertiary);padding:40px 0;text-align:center;font-size:13px}._projectStatsContent_jseur_391{display:flex;flex-direction:column;gap:16px}._projectStatsUpdated_jseur_397{color:var(--text-muted);font-size:12px;text-align:right}._projectStatsSummary_jseur_403{display:grid;grid-template-columns:1fr 1fr;gap:10px}._projectStatCard_jseur_409{background:var(--bg-container);border:1px solid var(--border-secondary);border-radius:8px;padding:14px 12px;text-align:center}._projectStatValue_jseur_417{font-size:22px;font-weight:700;color:var(--text-primary);font-family:var(--font-mono);font-variant-numeric:tabular-nums}._projectStatLabel_jseur_425{font-size:12px;color:var(--text-tertiary);margin-top:4px}._projectStatsSection_jseur_431{display:flex;flex-direction:column;gap:10px}._projectStatsSectionTitle_jseur_437{font-size:14px;font-weight:600;color:var(--text-secondary);padding-bottom:4px;border-bottom:1px solid var(--border-secondary)}._projectStatsModelCard_jseur_445{background:var(--bg-container);border:1px solid var(--border-secondary);border-radius:6px;padding:10px 12px}._projectStatsModelHeader_jseur_452{display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;padding-bottom:4px;border-bottom:1px solid var(--border-secondary)}._projectStatsModelName_jseur_461{font-size:13px;font-weight:600;color:var(--text-primary)}._projectStatsModelCount_jseur_467{font-size:12px;color:var(--text-tertiary);font-family:var(--font-mono)}._cacheCopyBtn_jseur_475{font-size:14px;color:var(--text-tertiary);cursor:pointer;transition:color .2s;margin-left:8px}._cacheCopyBtn_jseur_475:hover{color:var(--text-primary)}._cacheTokenInfo_jseur_487{display:flex;align-items:center;font-size:12px;font-family:var(--font-mono);color:var(--text-light);margin-bottom:8px}._cacheCodeBlock_jseur_500{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:var(--font-mono)}._cacheCodeBlockSystem_jseur_514{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:var(--font-mono)}._cacheNavBtn_jseur_528{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_jseur_528:hover{background:var(--color-primary-bg-light)}._cacheNavList_jseur_543{width:600px;max-height:300px;overflow-y:auto}._cacheNavItem_jseur_549{padding:4px 8px;font-size:12px;color:var(--text-secondary);cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;border-radius:3px}._cacheNavItem_jseur_549:hover{background:var(--color-primary-bg-lighter);color:var(--text-white)}._cacheBlockHighlight_jseur_565{box-shadow:0 0 10px var(--color-primary-shadow);transition:box-shadow .2s ease-in}._cacheBlockHighlightFading_jseur_570{box-shadow:0 0 10px transparent;transition:box-shadow 3s ease-out}._cacheBorderSvg_jseur_575{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;pointer-events:none;overflow:visible}._cacheBorderSvgFading_jseur_584{opacity:0;transition:opacity 3s ease-out}._cacheBorderRect_jseur_589{animation:_cacheDashRotate_jseur_1 4s linear infinite}@keyframes _cacheDashRotate_jseur_1{0%{stroke-dashoffset:0}to{stroke-dashoffset:-100}}._thLeft_jseur_599{text-align:left}._cacheWriteToken_jseur_614{color:var(--color-code-orange)}._cacheReadToken_jseur_618{color:var(--color-success)}._cacheCtxPercent_jseur_622{color:var(--text-tertiary);margin-left:6px}._qrcodeIcon_jseur_642{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_jseur_642:hover{color:var(--text-primary);background:var(--bg-hover, rgba(0, 0, 0, .04))}._qrcodeIcon_jseur_642:focus-visible{outline:2px solid var(--primary-color, #1677ff);outline-offset:1px}._approvalBell_jseur_668{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_jseur_668:hover{color:var(--text-primary);background:var(--bg-hover, rgba(0, 0, 0, .04))}._approvalBell_jseur_668:focus-visible{outline:2px solid var(--primary-color, #1677ff);outline-offset:1px}._approvalBellBadge_jseur_693{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_jseur_710{margin-right:4px;font-size:11px}._proxyProfileTag_jseur_716{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_jseur_716:hover{color:var(--text-secondary);border-color:var(--text-disabled)}._pinnedShortcut_jseur_732{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_jseur_732:hover{opacity:1;color:var(--text-secondary)}._pinnedShortcut_jseur_732 .anticon{display:inline-flex;align-items:center;justify-content:center;line-height:0}._themeToggle_jseur_761{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_jseur_761:hover{background:var(--color-bg-hover, rgba(127, 127, 127, .12));color:var(--text-primary)}._themeToggle_jseur_761:focus-visible{box-shadow:0 0 0 2px var(--primary-color, #1677ff)}._themeToggleIcon_jseur_787{display:block}._headerRightRow_jseur_792 .ant-space-item{display:inline-flex;align-items:center}._headerCountdownTag_jseur_798{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_1ivpu_1{display:flex;align-items:center;justify-content:center;height:100%}._scrollContainer_1ivpu_8{overflow:auto;height:100%;-webkit-overflow-scrolling:touch;will-change:scroll-position}._listItem_1ivpu_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_1ivpu_15:hover{border-left-color:var(--border-hover)}._listItemActive_1ivpu_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_1ivpu_29,._listItemActive_1ivpu_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_1ivpu_46{width:100%;min-width:0}._itemHeader_1ivpu_51{display:flex;align-items:center;gap:6px;margin-bottom:4px;font-size:12px}._tagNoMargin_1ivpu_59{margin:0;font-size:12px}._modelName_1ivpu_64{font-size:12px;color:var(--text-tertiary)}._modelNameMain_1ivpu_69{color:var(--color-code-orange)}._time_1ivpu_73{font-size:12px;color:var(--text-gray);margin-left:auto}._detailRow_1ivpu_79{display:flex;gap:8px;font-size:12px;align-items:center}._urlText_1ivpu_86{color:var(--text-disabled);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0}._duration_1ivpu_95{color:var(--text-gray);flex-shrink:0}._statusOk_1ivpu_100{color:var(--color-success);opacity:.5;flex-shrink:0}._statusErr_1ivpu_106{color:var(--color-error);flex-shrink:0}._statusDefault_1ivpu_111{color:var(--text-tertiary);flex-shrink:0}._usageBox_1ivpu_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_1ivpu_126{display:inline-block;width:6px;height:6px;border-radius:50%;margin:0 3px;vertical-align:middle}._cacheDotLoss_1ivpu_135{background-color:var(--color-red-dark-bg);cursor:help}._cacheDotNormal_1ivpu_140{background-color:var(--border-hover)}._cacheDotTools_1ivpu_145{background-color:var(--color-code-purple);box-shadow:0 0 0 1.5px var(--color-purple-border)}._tagMainAgent_1ivpu_150{color:var(--color-code-orange);border-color:var(--color-code-orange-border);background:var(--color-code-orange-bg)}._tagPlan_1ivpu_156{color:var(--color-error-muted);border-color:var(--color-error-muted);background-color:var(--bg-base-pure)}._tagMuted_1ivpu_162{color:var(--text-muted);border-color:var(--border-light);background-color:var(--bg-base-pure)}._tooltipPreLine_1ivpu_168{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_b5r6a_1{background:var(--bg-container);border-radius:6px;border:1px solid var(--border-primary);padding:12px;font-size:13px;font-family:var(--font-mono);overflow:auto}._root_1eor3_1{display:flex;height:100%;min-height:0;gap:0}._sidebar_1eor3_9{width:220px;flex-shrink:0;border-right:1px solid var(--border-primary);overflow-y:auto;padding:4px 0;-webkit-overflow-scrolling:touch}._section_1eor3_18{-webkit-user-select:none;user-select:none}._sectionHeader_1eor3_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_1eor3_22:hover{background:var(--overlay-light-faint)}._sectionHeader_1eor3_22:focus-visible{outline:1px solid var(--color-primary-outline);outline-offset:-1px}._arrow_1eor3_48{font-size:10px;color:var(--text-tertiary);flex-shrink:0}._sectionTitle_1eor3_54{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._sectionCount_1eor3_62{font-size:11px;color:var(--text-muted);background:var(--bg-elevated);border-radius:10px;padding:0 6px;line-height:18px}._sectionBody_1eor3_71{padding:2px 0}._historyToggle_1eor3_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_1eor3_76:hover{color:var(--text-tertiary);background:var(--overlay-light-faint)}._historyToggle_1eor3_76:focus-visible{outline:1px solid var(--color-primary-outline);outline-offset:-1px}._historyToggleLabel_1eor3_102{flex:1}._item_1eor3_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_1eor3_107:hover{background:var(--overlay-light-faint);color:var(--text-primary)}._item_1eor3_107:focus-visible{outline:1px solid var(--color-primary-outline);outline-offset:-1px}._itemActive_1eor3_135,._itemActive_1eor3_135:hover{background:var(--color-primary-bg-faint);color:var(--color-primary);border-color:var(--color-primary-light)}._itemContent_1eor3_142{flex:1;min-width:0;overflow:hidden}._itemLabel_1eor3_148{font-family:var(--font-mono);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block}._itemSublabel_1eor3_156{font-size:10px;color:var(--text-disabled);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-top:1px}._itemTime_1eor3_165{font-size:9px;color:var(--text-disabled);flex-shrink:0;margin-left:4px;font-family:var(--font-mono)}._contentWrap_1eor3_176{flex:1;min-width:0;display:flex;flex-direction:column}._content_1eor3_174{flex:1;min-width:0;min-height:0;overflow:auto;padding:12px 16px;-webkit-overflow-scrolling:touch}._contentEmpty_1eor3_192{height:100%;display:flex;align-items:center;justify-content:center}._contentInner_1eor3_199{padding-bottom:20px}._emptyWrap_1eor3_203{display:flex;align-items:center;justify-content:center;height:200px}._roleHeader_1eor3_211{display:flex;align-items:center;gap:8px;margin-bottom:8px;flex-wrap:nowrap}._roleBadge_1eor3_219{font-size:10px;font-weight:600;letter-spacing:.04em;padding:2px 7px;border-radius:4px;flex-shrink:0}._role_user_1eor3_228{background:var(--color-primary-bg-lighter);color:var(--color-primary-lighter);border:1px solid var(--color-primary-bg-medium)}._role_assistant_1eor3_234{background:var(--color-purple-bg);color:var(--color-code-purple);border:1px solid var(--color-purple-border)}._role_system_1eor3_240{background:var(--color-warning-bg-faint);color:var(--color-warning);border:1px solid var(--color-warning-border-light)}._roleLabel_1eor3_246{font-size:11px;color:var(--text-muted);flex:1;min-width:0}._contentTime_1eor3_253{margin-left:auto;font-size:10px;color:var(--text-disabled);font-family:var(--font-mono);flex-shrink:0}._turnDivider_1eor3_261{border:none;border-top:1px solid var(--border-primary);margin:14px 0}._textBlock_1eor3_268{margin-bottom:8px;border:1px solid var(--border-primary);border-radius:6px;overflow:hidden}._textBlockBar_1eor3_275{display:flex;align-items:center;gap:6px;padding:4px 10px;background:var(--bg-container);border-bottom:1px solid var(--border-primary)}._textBlockBody_1eor3_284{padding:10px 12px;font-size:13px;line-height:1.7;color:var(--text-primary);word-break:break-word}._textBlockCompact_1eor3_292{position:relative;padding:8px 10px;font-size:12px;color:var(--text-light)}._textBlockCompactFloat_1eor3_299{float:right;margin-left:6px;margin-bottom:2px}._thinkingBlock_1eor3_306{margin-bottom:8px;border:1px solid var(--color-thinking-border);border-radius:6px;overflow:hidden;background:var(--color-thinking-bg)}._thinkingHeader_1eor3_314{display:flex;align-items:center;gap:6px;padding:5px 10px;cursor:pointer;font-size:12px;color:var(--text-tertiary);transition:background .15s}._thinkingHeader_1eor3_314:hover{background:var(--overlay-light-faint)}._thinkingPreview_1eor3_329{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text-muted);font-size:11px}._thinkingBody_1eor3_339{padding:8px 12px;border-top:1px solid var(--color-thinking-border)}._toolBlock_1eor3_345{margin-bottom:8px;border:1px solid var(--border-primary);border-radius:6px;overflow:hidden}._toolBlockResult_1eor3_352{border-color:var(--color-green-border)}._toolBlockError_1eor3_356{border-color:var(--color-red-dark-border)}._toolBlockHeader_1eor3_360{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_1eor3_371{padding:8px 10px;font-size:12px}._toolName_1eor3_376{color:var(--text-primary);font-weight:500;font-family:var(--font-mono)}._toolId_1eor3_382{color:var(--text-disabled);font-size:10px;font-family:var(--font-mono);margin-left:auto}._errorLabel_1eor3_389{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_1eor3_399{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_1eor3_412{background:var(--color-primary-bg-faint);color:var(--color-primary-lighter);border-color:var(--color-primary-bg-lighter)}._blockTagThinking_1eor3_418{background:var(--color-warning-bg-faint);color:var(--color-warning);border-color:var(--color-warning-border-light)}._blockTagResult_1eor3_424{background:var(--color-green-dark-bg);color:var(--color-success);border-color:var(--color-green-dark-border)}._blockTagError_1eor3_430{background:var(--color-error-bg-faint);color:var(--color-error-light);border-color:var(--color-error-border-light)}._jsonBlock_1eor3_437{margin-bottom:8px;border:1px solid var(--border-primary);border-radius:6px;overflow:hidden}._jsonBlockLabel_1eor3_444{font-size:10px;color:var(--text-muted);padding:3px 10px;background:var(--bg-container);border-bottom:1px solid var(--border-primary);font-family:var(--font-mono)}._blockSeparator_1eor3_454{border:none;border-top:1px solid var(--border-primary);margin:16px 0}._markdownBody_1eor3_461{font-size:13px;line-height:1.7;color:var(--text-primary);word-break:break-word}._contentToolbar_1eor3_469{display:flex;justify-content:flex-end;align-items:center;gap:8px;padding:8px 16px 0;flex-shrink:0}._contentToolbarLabel_1eor3_478{font-size:11px;color:var(--text-muted)}._rawPre_1eor3_484{background:var(--bg-code-dark);border:1px solid var(--border-primary);border-radius:6px;padding:12px;font-size:12px;color:var(--text-primary);white-space:pre-wrap;word-break:break-all;margin:0}._toolAdded_1eor3_497{color:var(--color-success)}._toolRemoved_1eor3_501{color:var(--color-error);text-decoration:line-through}._toolDiffTag_1eor3_506{margin-left:6px;font-size:9px;font-family:var(--font-ui);text-decoration:none;opacity:.85}._toolDiffSummary_1eor3_514{margin-left:6px;font-size:11px;font-family:var(--font-mono);display:inline-flex;gap:4px;flex-shrink:0}._toolDiffSummaryAdd_1eor3_523{color:var(--color-success)}._toolDiffSummaryRemove_1eor3_527{color:var(--color-error)}._container_1958y_1{height:100%;overflow:hidden;padding:0 16px;display:flex;flex-direction:column;background:var(--bg-base)}._emptyState_1958y_10{display:flex;align-items:center;justify-content:center;height:100%}._urlSection_1958y_17{padding:12px 0;border-bottom:1px solid var(--border-primary);display:flex;align-items:flex-start;flex-shrink:0}._urlLeft_1958y_25{flex:1;min-width:0}._tokenStatsBox_1958y_30{flex-shrink:0;padding-left:12px;display:flex;align-items:center}._tokenGrid_1958y_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_1958y_47{flex:1}._tokenRow_1958y_47{display:flex}._tokenRowBorder_1958y_55{border-top:1px solid var(--border-secondary)}._tokenLabel_1958y_59{color:var(--text-tertiary);padding:4px 8px;white-space:nowrap;font-weight:600}._tokenTd_1958y_66{flex:1;color:var(--text-primary);text-align:right;padding:4px 8px;font-family:var(--font-mono);white-space:nowrap}._tokenHitRate_1958y_75{display:flex;flex-direction:column;align-items:center;justify-content:center;color:var(--text-primary);padding:4px 8px;font-family:var(--font-mono);white-space:nowrap;border-left:1px solid var(--border-secondary);min-width:100px}._tokenHitRateLabel_1958y_88{color:var(--text-tertiary);font-size:10px;font-family:var(--font-ui)}._tokenRowBorder_1958y_55 td{border-top:1px solid var(--border-secondary)}._urlText_1958y_98{color:var(--text-primary);font-size:13px;margin-bottom:8px;word-break:break-all}._metaText_1958y_105,._headersContainer_1958y_109{font-size:12px}._headerRow_1958y_113{display:flex;padding:4px 0;border-bottom:1px solid var(--border-primary)}._headerKey_1958y_119{min-width:200px;flex-shrink:0}._headerValue_1958y_124{word-break:break-all;margin-left:8px}._streamingBox_1958y_129{padding:20px;background:var(--bg-elevated);border-radius:6px;border:1px solid var(--border-primary)}._bodyToolbar_1958y_136{display:flex;gap:8px;margin-bottom:8px}._rawTextPre_1958y_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_1958y_155{padding:16px 0 0;height:100%;overflow-y:auto;-webkit-overflow-scrolling:touch}._collapseSpacing_1958y_163{margin-bottom:16px}._bodyLabel_1958y_167{margin:0}._bodyHeader_1958y_171{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}._diffSection_1958y_178{margin-bottom:16px}._diffToggle_1958y_182{display:inline-block;margin-bottom:8px;cursor:pointer}._diffIcon_1958y_188{font-size:12px;margin-left:4px}._viewInChatBtn_1958y_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_1958y_193:hover{border-color:var(--text-muted);color:var(--text-primary);background:var(--overlay-light-faint)}._reminderSelect_1958y_214{min-width:140px;font-size:12px}._reminderSelect_1958y_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:var(--font-mono)}._reminderSelect_1958y_214 .ant-select-selection-placeholder{font-size:11px}._diffHeaderRow_1958y_233{display:flex;align-items:center;gap:8px}._diffSpaceRight_1958y_239{margin-left:auto}._reminderFilterWrapper_1958y_243{display:inline-flex;align-items:center;gap:4px}._reminderLabel_1958y_249{color:var(--text-tertiary);font-size:12px;font-family:var(--font-mono)}._cacheTabContent_1958y_255{padding-top:0;overflow:hidden}._userPromptList_1958y_260{width:600px;max-height:300px;overflow-y:auto}._userPromptItem_1958y_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_1958y_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_1958y_288{padding:8px 0;height:100%;display:flex;flex-direction:column}._cacheTokenBar_1958y_295{display:flex;align-items:center;font-size:12px;font-family:var(--font-mono);color:var(--text-light);margin-bottom:12px;flex-shrink:0}._cacheTokenWrite_1958y_305{color:var(--color-code-orange)}._cacheTokenRead_1958y_309{color:var(--color-success)}._cacheCopyIcon_1958y_313{margin-left:8px;cursor:pointer;color:var(--text-tertiary);transition:color .2s}._cacheScrollArea_1958y_320{flex:1;overflow-y:auto;min-height:0}._cacheSectionBlock_1958y_326{margin-bottom:12px}._cacheSectionHeader_1958y_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_1958y_342{display:inline-block;transition:transform .2s;font-size:10px}._cachePre_1958y_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:var(--font-mono)}._cacheHighlightSvg_1958y_362{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;pointer-events:none;overflow:visible}._cachePreSystem_1958y_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:var(--font-mono)}._container_1958y_1 .ant-tabs>.ant-tabs-nav{margin-bottom:0}._container_1958y_1 .ant-tabs{flex:1;min-height:0;display:flex;flex-direction:column}._container_1958y_1 .ant-tabs>.ant-tabs-content-holder{flex:1;min-height:0}._container_1958y_1 .ant-tabs-content,._container_1958y_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_18dz6_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_18dz6_12{position:absolute;left:0;top:0;bottom:0;width:var(--usage-percent, 0);background-color:#999;opacity:.2;transition:width .5s ease;pointer-events:none}._usageContent_18dz6_38{position:relative;z-index:1;display:inline-flex;align-items:center}._usageText_18dz6_45{font-variant-numeric:tabular-nums}._muted_18dz6_50{border-color:var(--border-light);color:var(--text-disabled);background:var(--bg-surface)}._pop_18dz6_57{min-width:220px;font-size:12px;color:var(--text-primary)}._popTitle_18dz6_63{font-weight:600;margin-bottom:6px}._popTable_18dz6_69{border-collapse:collapse}._popTable_18dz6_69 td{padding-top:3px;padding-bottom:3px;vertical-align:middle}._tdName_18dz6_74{color:var(--text-secondary);padding-right:5px;white-space:nowrap}._tdBar_18dz6_74{padding-right:5px;white-space:nowrap}._tdReset_18dz6_92{color:var(--text-secondary);font-variant-numeric:tabular-nums;white-space:nowrap}._bar_18dz6_101{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_18dz6_115{position:absolute;left:0;top:0;bottom:0;background-color:var(--text-secondary);opacity:.15;pointer-events:none}._barText_18dz6_125{position:relative;z-index:1;font-size:11px;line-height:1;font-variant-numeric:tabular-nums;color:var(--text-primary)}