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.
- package/README.md +3 -1
- package/dist/assets/App-Bs6-c4Ov.css +1 -0
- package/dist/assets/App-CYvr5YQv.js +2 -0
- package/dist/assets/{MdxEditorPanel-BAE_5ssH.js → MdxEditorPanel-D1MOJabL.js} +1 -1
- package/dist/assets/Mobile-B7GXxkfK.js +1 -0
- package/dist/assets/ProxyStatsModal-BqH9cIks.js +1 -0
- package/dist/assets/ProxyStatsModal-Dz5GuoUa.css +1 -0
- package/dist/assets/{_baseUniq-BkQkqbX3.js → _baseUniq-aTokVjQN.js} +1 -1
- package/dist/assets/{arc-BKY9CS7c.js → arc-mxp8gSRQ.js} +1 -1
- package/dist/assets/{architectureDiagram-Q4EWVU46-f8VVp6F9.js → architectureDiagram-Q4EWVU46-msh8IODx.js} +1 -1
- package/dist/assets/{blockDiagram-DXYQGD6D-3h2PkZUH.js → blockDiagram-DXYQGD6D-BUatNJTI.js} +1 -1
- package/dist/assets/{c4Diagram-AHTNJAMY-DigIDzhn.js → c4Diagram-AHTNJAMY-CJ92TNZe.js} +1 -1
- package/dist/assets/{channel-5ajs7xDK.js → channel-CTM7CJrB.js} +1 -1
- package/dist/assets/{chunk-4BX2VUAB-BvwhA1RA.js → chunk-4BX2VUAB-Bdv98T9c.js} +1 -1
- package/dist/assets/{chunk-4TB4RGXK-GHcSNG2k.js → chunk-4TB4RGXK-DaIEuSP0.js} +1 -1
- package/dist/assets/{chunk-55IACEB6-DWO0TwNe.js → chunk-55IACEB6-Bi9130Nu.js} +1 -1
- package/dist/assets/{chunk-EDXVE4YY-0ycrM2oE.js → chunk-EDXVE4YY-CZw-Vwwn.js} +1 -1
- package/dist/assets/{chunk-FMBD7UC4-DmdCml-0.js → chunk-FMBD7UC4-BBI7swjg.js} +1 -1
- package/dist/assets/{chunk-OYMX7WX6-fg2n9B_W.js → chunk-OYMX7WX6-CHKotm_J.js} +1 -1
- package/dist/assets/{chunk-QZHKN3VN-Bg3VPGcJ.js → chunk-QZHKN3VN-ECW0McUe.js} +1 -1
- package/dist/assets/{chunk-YZCP3GAM-BV1RGRqK.js → chunk-YZCP3GAM-DLdAqU2z.js} +1 -1
- package/dist/assets/classDiagram-6PBFFD2Q-CkmfHfqf.js +1 -0
- package/dist/assets/classDiagram-v2-HSJHXN6E-CkmfHfqf.js +1 -0
- package/dist/assets/clone-pjnYCaC4.js +1 -0
- package/dist/assets/{cose-bilkent-S5V4N54A-CjAVlyw6.js → cose-bilkent-S5V4N54A-CfMuBnZy.js} +1 -1
- package/dist/assets/{dagre-KV5264BT-DZV42aOy.js → dagre-KV5264BT-xxdATAWV.js} +1 -1
- package/dist/assets/{diagram-5BDNPKRD-DpDA9ZeE.js → diagram-5BDNPKRD-s8izYXws.js} +1 -1
- package/dist/assets/{diagram-G4DWMVQ6-86vmHGG_.js → diagram-G4DWMVQ6-BaZWrq-d.js} +1 -1
- package/dist/assets/{diagram-MMDJMWI5-CzLVfy9C.js → diagram-MMDJMWI5-DlzU0RKB.js} +1 -1
- package/dist/assets/{diagram-TYMM5635-C1n6QVNv.js → diagram-TYMM5635-Fej8ir1x.js} +1 -1
- package/dist/assets/{erDiagram-SMLLAGMA-BWST8PqT.js → erDiagram-SMLLAGMA-Bwg0_DNs.js} +1 -1
- package/dist/assets/{flowDiagram-DWJPFMVM-zfku-qzI.js → flowDiagram-DWJPFMVM-pJ8Bv6wt.js} +1 -1
- package/dist/assets/{ganttDiagram-T4ZO3ILL-BIxQMxEL.js → ganttDiagram-T4ZO3ILL-DvgJ4Q6n.js} +1 -1
- package/dist/assets/{gitGraphDiagram-UUTBAWPF-E7gXMGl0.js → gitGraphDiagram-UUTBAWPF-Du8KitZ0.js} +1 -1
- package/dist/assets/{graph-Chi_Do3A.js → graph-57Q-0mNG.js} +1 -1
- package/dist/assets/{index-BsRFLaCT.js → index-BOryMxum.js} +1 -1
- package/dist/assets/{index-CyMcZjWq.js → index-Bt7QsK9T.js} +1 -1
- package/dist/assets/{index-BbuqKcgW.js → index-CVh-Zo2A.js} +1 -1
- package/dist/assets/{index-BVkdlwjO.js → index-Cf77lzSr.js} +1 -1
- package/dist/assets/{index-Batfx707.js → index-Cn0akK9k.js} +1 -1
- package/dist/assets/{index-CaTBBfzw.js → index-EFFRo37G.js} +1 -1
- package/dist/assets/{index-Bp83Qa3f.js → index-mpHzrAV9.js} +2 -2
- package/dist/assets/{index-BrmFDbRb.js → index-zljZK-NO.js} +1 -1
- package/dist/assets/{infoDiagram-42DDH7IO-CJSIzH2A.js → infoDiagram-42DDH7IO-DZz6OAQe.js} +1 -1
- package/dist/assets/{ishikawaDiagram-UXIWVN3A-B631W1wW.js → ishikawaDiagram-UXIWVN3A-Chrlpw73.js} +1 -1
- package/dist/assets/{journeyDiagram-VCZTEJTY-ChtGieBW.js → journeyDiagram-VCZTEJTY-D-fCEwg9.js} +1 -1
- package/dist/assets/{jszip.min-MLKd3flP.js → jszip.min-mU_-As7x.js} +1 -1
- package/dist/assets/{kanban-definition-6JOO6SKY-hLAy-WRt.js → kanban-definition-6JOO6SKY-DFdrm5t-.js} +1 -1
- package/dist/assets/{layout-cxTukSs_.js → layout-Dh-E01gA.js} +1 -1
- package/dist/assets/{linear-lKN6YVn3.js → linear-BjXnK-6T.js} +1 -1
- package/dist/assets/{mermaid.core-BYpzUgET.js → mermaid.core-Cbqxn86C.js} +2 -2
- package/dist/assets/{min-BvhzyJ7G.js → min-B4n9eIGL.js} +1 -1
- package/dist/assets/{mindmap-definition-QFDTVHPH-DLmLjuqG.js → mindmap-definition-QFDTVHPH-Bw49x4oU.js} +1 -1
- package/dist/assets/{pieDiagram-DEJITSTG-CpQId_ss.js → pieDiagram-DEJITSTG-D-iq9rKK.js} +1 -1
- package/dist/assets/{quadrantDiagram-34T5L4WZ-B2xWOHsh.js → quadrantDiagram-34T5L4WZ-QtFjo8i4.js} +1 -1
- package/dist/assets/{requirementDiagram-MS252O5E-CfCJaJBw.js → requirementDiagram-MS252O5E-BwmEZf4F.js} +1 -1
- package/dist/assets/{sankeyDiagram-XADWPNL6-CSClMzTh.js → sankeyDiagram-XADWPNL6-CTtXN32x.js} +1 -1
- package/dist/assets/seqResourceLoaders-DMyPYdA-.js +2 -0
- package/dist/assets/{sequenceDiagram-FGHM5R23-D5WoARR1.js → sequenceDiagram-FGHM5R23-DC00gRqs.js} +1 -1
- package/dist/assets/{stateDiagram-FHFEXIEX-DC1_JCl1.js → stateDiagram-FHFEXIEX-CT963BWJ.js} +1 -1
- package/dist/assets/{stateDiagram-v2-QKLJ7IA2-BOndcGRp.js → stateDiagram-v2-QKLJ7IA2-1T7yDlvQ.js} +1 -1
- package/dist/assets/{timeline-definition-GMOUNBTQ-Bm3Lk96s.js → timeline-definition-GMOUNBTQ-CDu66c9j.js} +1 -1
- package/dist/assets/vendor-antd-DADYo_zg.js +17 -0
- package/dist/assets/{vendor-codemirror-BD02EJx5.js → vendor-codemirror-tF6HNoR6.js} +1 -1
- package/dist/assets/vendor-mdxeditor-CFAmRN3Y.js +2 -0
- package/dist/assets/vendor-qrcode-DYKmbePy.js +6 -0
- package/dist/assets/vendor-virtuoso-TxPxvPjL.js +1 -0
- package/dist/assets/{vennDiagram-DHZGUBPP-CA8MWsbD.js → vennDiagram-DHZGUBPP-DSm6yR_C.js} +1 -1
- package/dist/assets/{wardley-RL74JXVD-Dw7GlJWj.js → wardley-RL74JXVD-kFdCN4XL.js} +1 -1
- package/dist/assets/{wardleyDiagram-NUSXRM2D-woq7iHEC.js → wardleyDiagram-NUSXRM2D-BY1GQbCO.js} +1 -1
- package/dist/assets/{xychartDiagram-5P7HB3ND-B4JCiFF4.js → xychartDiagram-5P7HB3ND-ONnFdWbS.js} +1 -1
- package/dist/index.html +4 -4
- package/findcc.js +103 -6
- package/package.json +1 -1
- package/server/lib/proxy-stats.js +75 -32
- package/dist/assets/App-BfzeNwOB.css +0 -1
- package/dist/assets/App-Bqz6Y5h4.js +0 -2
- package/dist/assets/Mobile-2LDWfaUe.js +0 -1
- package/dist/assets/UnifiedProxyRetryPage-CFz4vOH5.css +0 -1
- package/dist/assets/UnifiedProxyRetryPage-DFyS9doh.js +0 -1
- package/dist/assets/classDiagram-6PBFFD2Q-CnUCTEpg.js +0 -1
- package/dist/assets/classDiagram-v2-HSJHXN6E-CnUCTEpg.js +0 -1
- package/dist/assets/clone-D0NlqTo0.js +0 -1
- package/dist/assets/seqResourceLoaders-DIUJh1ym.js +0 -2
- package/dist/assets/vendor-antd-CyudKxuD.js +0 -17
- package/dist/assets/vendor-mdxeditor-C3Q4i3LX.js +0 -2
- package/dist/assets/vendor-qrcode-DK9W5Ghb.js +0 -6
- 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
|
-
|
|
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
|
-
|
|
345
|
+
const out = execFileSync(cmd, args, {
|
|
307
346
|
encoding: 'utf-8',
|
|
308
347
|
windowsHide: true,
|
|
309
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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 {
|
|
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
|
-
|
|
151
|
-
|
|
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:
|
|
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
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
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
|
-
//
|
|
355
|
-
|
|
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)}
|