@tonyclaw/agent-inspector 3.0.18 → 3.0.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/.output/cli.js +1257 -506
  2. package/.output/nitro.json +3 -3
  3. package/.output/public/assets/CompareDrawer-CV7rBBty.js +1 -0
  4. package/.output/public/assets/ProxyViewerContainer-CqRfBWJ3.js +127 -0
  5. package/.output/public/assets/ReplayDialog-yDeF-z9y.js +1 -0
  6. package/.output/public/assets/RequestAnatomy-BXxKNdgk.js +1 -0
  7. package/.output/public/assets/ResponseView-BIYNgUNB.js +3 -0
  8. package/.output/public/assets/StreamingChunkSequence-C1faiChu.js +1 -0
  9. package/.output/public/assets/_sessionId-B34PrfCQ.js +1 -0
  10. package/.output/public/assets/index-B3YOj8-_.css +1 -0
  11. package/.output/public/assets/index-BLwqIxup.js +12 -0
  12. package/.output/public/assets/{index-ClQ7Vi3J.js → index-DOspyaW6.js} +1 -1
  13. package/.output/public/assets/index-DT476lno.js +1 -0
  14. package/.output/public/assets/json-viewer-C1S08J_2.js +1 -0
  15. package/.output/server/_chunks/ssr-renderer.mjs +18 -2
  16. package/.output/server/_libs/@radix-ui/react-dismissable-layer+[...].mjs +165 -31
  17. package/.output/server/_libs/@radix-ui/react-use-callback-ref+[...].mjs +1 -1
  18. package/.output/server/_libs/@radix-ui/react-use-controllable-state+[...].mjs +2 -2
  19. package/.output/server/_libs/@radix-ui/react-use-is-hydrated+[...].mjs +28 -1
  20. package/.output/server/_libs/mistralai__mistralai.mjs +1 -1
  21. package/.output/server/_libs/modelcontextprotocol__server.mjs +11571 -8127
  22. package/.output/server/_libs/radix-ui__primitive.mjs +1 -1
  23. package/.output/server/_libs/radix-ui__react-collapsible.mjs +1 -1
  24. package/.output/server/_libs/radix-ui__react-collection.mjs +8 -8
  25. package/.output/server/_libs/radix-ui__react-compose-refs.mjs +0 -1
  26. package/.output/server/_libs/radix-ui__react-context.mjs +4 -18
  27. package/.output/server/_libs/radix-ui__react-dialog.mjs +41 -88
  28. package/.output/server/_libs/radix-ui__react-focus-guards.mjs +15 -5
  29. package/.output/server/_libs/radix-ui__react-focus-scope.mjs +6 -2
  30. package/.output/server/_libs/radix-ui__react-id.mjs +3 -3
  31. package/.output/server/_libs/radix-ui__react-popper.mjs +62 -8
  32. package/.output/server/_libs/radix-ui__react-portal.mjs +2 -2
  33. package/.output/server/_libs/radix-ui__react-presence.mjs +50 -5
  34. package/.output/server/_libs/radix-ui__react-roving-focus.mjs +15 -4
  35. package/.output/server/_libs/radix-ui__react-scroll-area.mjs +30 -20
  36. package/.output/server/_libs/radix-ui__react-select.mjs +167 -123
  37. package/.output/server/_libs/radix-ui__react-slot.mjs +74 -41
  38. package/.output/server/_libs/radix-ui__react-tabs.mjs +6 -1
  39. package/.output/server/_libs/radix-ui__react-tooltip.mjs +6 -3
  40. package/.output/server/_libs/react-dom.mjs +13 -15
  41. package/.output/server/_libs/react.mjs +45 -45
  42. package/.output/server/_libs/srvx.mjs +409 -53
  43. package/.output/server/_libs/swr.mjs +10 -2
  44. package/.output/server/_libs/tailwind-merge.mjs +286 -41
  45. package/.output/server/_libs/tanstack__history.mjs +9 -13
  46. package/.output/server/_libs/tanstack__react-router.mjs +788 -1092
  47. package/.output/server/_libs/tanstack__react-store.mjs +1 -1
  48. package/.output/server/_libs/tanstack__react-virtual.mjs +82 -7
  49. package/.output/server/_libs/tanstack__router-core.mjs +1841 -2060
  50. package/.output/server/_libs/tanstack__virtual-core.mjs +116 -45
  51. package/.output/server/_libs/use-sync-external-store.mjs +1 -1
  52. package/.output/server/_libs/zod-to-json-schema.mjs +1 -1
  53. package/.output/server/_libs/zod.mjs +5085 -200
  54. package/.output/server/{_sessionId-Bi3ZIrqT.mjs → _sessionId-CmoBbtKT.mjs} +30 -32
  55. package/.output/server/_ssr/{CompareDrawer-BYZS_hCR.mjs → CompareDrawer-BsXnVK4e.mjs} +29 -31
  56. package/.output/server/_ssr/{ProxyViewerContainer-BE4umfVs.mjs → ProxyViewerContainer-D-_7pyfx.mjs} +54 -52
  57. package/.output/server/_ssr/{ReplayDialog-BlID2ZH4.mjs → ReplayDialog-deDQA2M5.mjs} +30 -32
  58. package/.output/server/_ssr/{RequestAnatomy-CGJ2lkzT.mjs → RequestAnatomy-CX-cCRdX.mjs} +29 -31
  59. package/.output/server/_ssr/{ResponseView-DDjcGf7M.mjs → ResponseView-D0LJR1qj.mjs} +29 -31
  60. package/.output/server/_ssr/{StreamingChunkSequence-G7B8M5G2.mjs → StreamingChunkSequence-CJRECetE.mjs} +29 -31
  61. package/.output/server/_ssr/empty-plugin-adapters-BFgPZ6_d.mjs +6 -0
  62. package/.output/server/_ssr/{index-ClQ9FvRJ.mjs → index-CYWOXS4d.mjs} +31 -33
  63. package/.output/server/_ssr/index.mjs +1102 -784
  64. package/.output/server/_ssr/{json-viewer-CFbpkiBJ.mjs → json-viewer-CCneYiCn.mjs} +29 -31
  65. package/.output/server/_ssr/{router-Cq8LEvhE.mjs → router-D-PAN8IK.mjs} +182 -67
  66. package/.output/server/_tanstack-start-manifest_v-CVZ9yh4R.mjs +4 -0
  67. package/.output/server/index.mjs +74 -92
  68. package/README.md +4 -4
  69. package/package.json +17 -8
  70. package/src/cli/onboard.ts +1 -1
  71. package/src/cli.ts +2 -2
  72. package/src/components/clients/ClientLogo.tsx +5 -1
  73. package/src/components/proxy-viewer/RequestToolsPanel.tsx +1 -0
  74. package/src/components/proxy-viewer/ResponseView.tsx +1 -0
  75. package/src/components/proxy-viewer/StreamingChunkSequence.tsx +1 -0
  76. package/src/components/proxy-viewer/TurnGroup.tsx +1 -0
  77. package/src/components/proxy-viewer/anatomy/SegmentBar.tsx +1 -0
  78. package/src/components/proxy-viewer/formats/anthropic/ContentBlocks.tsx +4 -0
  79. package/src/components/proxy-viewer/formats/anthropic/ResponseView.tsx +1 -0
  80. package/src/components/proxy-viewer/formats/openai/ResponseView.tsx +2 -0
  81. package/src/components/ui/dialog.tsx +1 -1
  82. package/src/components/ui/json-viewer.tsx +2 -0
  83. package/src/components/ui/select.tsx +1 -1
  84. package/src/contracts/json.ts +7 -2
  85. package/src/lib/providerContract.ts +25 -5
  86. package/src/mcp/server.ts +12 -3
  87. package/src/mcp/toolHandlers.ts +6 -1
  88. package/src/proxy/handler.ts +17 -7
  89. package/src/proxy/logFinalizer.ts +76 -8
  90. package/src/proxy/logIndex.ts +16 -32
  91. package/src/proxy/providers.ts +22 -1
  92. package/src/proxy/sessionProcess.ts +15 -1
  93. package/src/proxy/upstream.ts +4 -2
  94. package/src/router.tsx +9 -0
  95. package/.output/public/assets/CompareDrawer-Daj03-RL.js +0 -1
  96. package/.output/public/assets/ProxyViewerContainer-BLCRQtU_.js +0 -106
  97. package/.output/public/assets/ReplayDialog-5FR5crdo.js +0 -1
  98. package/.output/public/assets/RequestAnatomy-DF0hHdQY.js +0 -1
  99. package/.output/public/assets/ResponseView-BwkMSsUa.js +0 -3
  100. package/.output/public/assets/StreamingChunkSequence-CKeUd58x.js +0 -1
  101. package/.output/public/assets/_sessionId-CThgXa41.js +0 -1
  102. package/.output/public/assets/index-BHXN1Fsx.css +0 -1
  103. package/.output/public/assets/index-gm3A0idN.js +0 -1
  104. package/.output/public/assets/json-viewer-BA-W-PZq.js +0 -1
  105. package/.output/public/assets/main-BnRC1932.js +0 -18
  106. package/.output/server/_libs/@radix-ui/react-use-escape-keydown+[...].mjs +0 -17
  107. package/.output/server/_libs/cfworker__json-schema.mjs +0 -1
  108. package/.output/server/_libs/tiny-invariant.mjs +0 -12
  109. package/.output/server/_libs/tiny-warning.mjs +0 -5
  110. package/.output/server/_tanstack-start-manifest_v-p7J0QCMh.mjs +0 -4
@@ -197,14 +197,24 @@ function handleStreamingResponse(
197
197
  return new Response("No response body", { status: STATUS_BAD_GATEWAY });
198
198
  }
199
199
 
200
- const loggedStream = upstreamRes.body.pipeThrough(transform);
201
-
202
- req.signal?.addEventListener("abort", () => {
203
- if (log.responseText === null) {
204
- logger.info(`[handler] Streaming client aborted: ${log.method} ${log.path}`);
205
- scheduleStreamingFinalization("stream-abort");
206
- }
200
+ // pipeTo returns a promise that rejects when either side errors. Without
201
+ // this catch, an upstream connection drop skips flush() and leaves the log
202
+ // permanently un-finalized with a leaked temp file.
203
+ void upstreamRes.body.pipeTo(transform.writable).catch(() => {
204
+ scheduleStreamingFinalization("streaming");
207
205
  });
206
+ const loggedStream = transform.readable;
207
+
208
+ if (req.signal === undefined) {
209
+ logger.warn("[handler] req.signal is undefined; abort detection disabled for this request");
210
+ } else {
211
+ req.signal.addEventListener("abort", () => {
212
+ if (log.responseText === null) {
213
+ logger.info(`[handler] Streaming client aborted: ${log.method} ${log.path}`);
214
+ scheduleStreamingFinalization("stream-abort");
215
+ }
216
+ });
217
+ }
208
218
 
209
219
  const responseHeaders = new Headers(upstreamRes.headers);
210
220
  responseHeaders.delete(HEADER_CONTENT_ENCODING);
@@ -10,6 +10,7 @@ import { getSessionProcess, isSessionProcessAvailable } from "./sessionProcess";
10
10
  import { finalizeLogUpdate } from "./store";
11
11
  import { computeTokensPerSecond } from "./streamTiming";
12
12
  import { analyzeToolSchemaWarnings } from "./toolSchemaWarnings";
13
+ import { isPlainRecord, safeGetOwnProperty } from "../lib/objectUtils";
13
14
 
14
15
  type BaseFinalizeLogJob = {
15
16
  log: CapturedLog;
@@ -151,6 +152,11 @@ function applyOptionalStreamingTiming(log: CapturedLog, job: FinalizeLogJob): vo
151
152
  totalStreamMs: job.totalStreamMs,
152
153
  });
153
154
  return;
155
+ default: {
156
+ const _exhaustive: never = job;
157
+ logger.error(`[logFinalizer] Unhandled job type: ${JSON.stringify(_exhaustive)}`);
158
+ return;
159
+ }
154
160
  }
155
161
  }
156
162
 
@@ -241,6 +247,11 @@ function cleanupPathForRawStream(rawStream: string | RawStreamSource): string |
241
247
  return null;
242
248
  case "file":
243
249
  return rawStream.path;
250
+ default: {
251
+ const _exhaustive: never = rawStream;
252
+ logger.error(`[logFinalizer] Unhandled raw stream type: ${JSON.stringify(_exhaustive)}`);
253
+ return null;
254
+ }
244
255
  }
245
256
  }
246
257
 
@@ -263,6 +274,11 @@ function rawStreamByteLength(rawStream: string | RawStreamSource): number | null
263
274
  } catch {
264
275
  return null;
265
276
  }
277
+ default: {
278
+ const _exhaustive: never = rawStream;
279
+ logger.error(`[logFinalizer] Unhandled raw stream type: ${JSON.stringify(_exhaustive)}`);
280
+ return null;
281
+ }
266
282
  }
267
283
  }
268
284
 
@@ -304,6 +320,11 @@ function readRawStream(rawStream: string | RawStreamSource): {
304
320
  rawStreamText: readFileSync(rawStream.path, "utf-8"),
305
321
  cleanupRawStreamPath: rawStream.path,
306
322
  };
323
+ default: {
324
+ const _exhaustive: never = rawStream;
325
+ logger.error(`[logFinalizer] Unhandled raw stream type: ${JSON.stringify(_exhaustive)}`);
326
+ return { rawStreamText: "", cleanupRawStreamPath: null };
327
+ }
307
328
  }
308
329
  }
309
330
 
@@ -423,6 +444,7 @@ function finalizeStreamAbort(job: FinalizeStreamAbortLogJob, log: CapturedLog):
423
444
 
424
445
  export function buildFinalizeLogResult(job: FinalizeLogJob): FinalizeLogResult {
425
446
  const log = cloneLog(job.log);
447
+ const upstreamUrl = job.upstreamUrl;
426
448
 
427
449
  switch (job.type) {
428
450
  case "non-streaming":
@@ -431,6 +453,16 @@ export function buildFinalizeLogResult(job: FinalizeLogJob): FinalizeLogResult {
431
453
  return finalizeStreaming(job, log);
432
454
  case "stream-abort":
433
455
  return finalizeStreamAbort(job, log);
456
+ default: {
457
+ const _exhaustive: never = job;
458
+ logger.error(`[logFinalizer] Unhandled job type: ${JSON.stringify(_exhaustive)}`);
459
+ return {
460
+ log,
461
+ upstreamUrl,
462
+ error: "Unhandled job type",
463
+ cleanupRawStreamPath: null,
464
+ };
465
+ }
434
466
  }
435
467
  }
436
468
 
@@ -504,12 +536,25 @@ function resolveBuildPromise(job: FinalizeLogJob): Promise<FinalizeLogResult> {
504
536
  return executeBuildInWorker(job);
505
537
  case "inline":
506
538
  return Promise.resolve(buildFinalizeLogResult(job));
539
+ default: {
540
+ const _exhaustive: never = RUNTIME;
541
+ logger.error(`[logFinalizer] Unhandled runtime: ${JSON.stringify(_exhaustive)}`);
542
+ return Promise.resolve({
543
+ log: job.log,
544
+ upstreamUrl: job.upstreamUrl,
545
+ error: "Unhandled runtime",
546
+ cleanupRawStreamPath: null,
547
+ });
548
+ }
507
549
  }
508
550
  }
509
551
 
510
552
  const WORKER_COUNT = Math.max(1, Number(process.env["FINALIZER_WORKER_COUNT"]) || 4);
511
553
  let _workers: Worker[] | null = null;
512
- const _pending = new Map<string, (result: FinalizeLogResult) => void>();
554
+ const _pending = new Map<
555
+ string,
556
+ { resolve: (result: FinalizeLogResult) => void; reject: (err: Error) => void }
557
+ >();
513
558
  let _nextWorker = 0;
514
559
  let _jobSeq = 0;
515
560
 
@@ -518,11 +563,24 @@ function getWorkers(): Worker[] {
518
563
  _workers = [];
519
564
  for (let i = 0; i < WORKER_COUNT; i++) {
520
565
  const w = new Worker(new URL("./logFinalizer.worker.ts", import.meta.url));
521
- w.on("message", (msg: { id: string; result: FinalizeLogResult }) => {
522
- const resolve = _pending.get(msg.id);
523
- if (resolve !== undefined) {
566
+ w.on("message", (raw: unknown) => {
567
+ if (!isPlainRecord(raw)) {
568
+ logger.error("[logFinalizer] Received malformed IPC message from worker, discarding");
569
+ return;
570
+ }
571
+ const id = safeGetOwnProperty(raw, "id");
572
+ const result = safeGetOwnProperty(raw, "result");
573
+ if (typeof id !== "string" || !isPlainRecord(result)) {
574
+ logger.error("[logFinalizer] Received malformed IPC message from worker, discarding");
575
+ return;
576
+ }
577
+ // Runtime shape validated above; the cast bridges unknown → FinalizeLogResult.
578
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
579
+ const msg = { id, result: result as FinalizeLogResult };
580
+ const entry = _pending.get(msg.id);
581
+ if (entry !== undefined) {
524
582
  _pending.delete(msg.id);
525
- resolve(msg.result);
583
+ entry.resolve(msg.result);
526
584
  }
527
585
  });
528
586
  w.on("error", (err) => {
@@ -530,6 +588,13 @@ function getWorkers(): Worker[] {
530
588
  "[logFinalizer] Worker error:",
531
589
  err instanceof Error ? err.message : String(err),
532
590
  );
591
+ // Reject all pending jobs for this worker so callers don't hang forever
592
+ for (const [id, entry] of _pending) {
593
+ _pending.delete(id);
594
+ entry.reject(
595
+ new Error(`Worker crashed: ${err instanceof Error ? err.message : String(err)}`),
596
+ );
597
+ }
533
598
  });
534
599
  _workers.push(w);
535
600
  }
@@ -537,15 +602,18 @@ function getWorkers(): Worker[] {
537
602
  }
538
603
 
539
604
  export function executeBuildInWorker(job: FinalizeLogJob): Promise<FinalizeLogResult> {
540
- return new Promise((resolve) => {
605
+ return new Promise((resolve, reject) => {
541
606
  const list = getWorkers();
542
607
  // getWorkers() always returns at least 1 worker; the array index is safe
543
608
  const idx = _nextWorker % list.length;
544
609
  _nextWorker++;
545
610
  const w = list[idx];
546
- if (w === undefined) return; // unreachable, satisfies type-checker
611
+ if (w === undefined) {
612
+ reject(new Error("No workers available"));
613
+ return;
614
+ }
547
615
  const id = String(++_jobSeq);
548
- _pending.set(id, resolve);
616
+ _pending.set(id, { resolve, reject });
549
617
  w.postMessage({ id, job });
550
618
  });
551
619
  }
@@ -468,38 +468,24 @@ export async function rebuildIndex(): Promise<LogIndex> {
468
468
  return newIndex;
469
469
  }
470
470
 
471
- // Async mutex for atomic ID generation to prevent race conditions
472
- // Uses a promise queue instead of busy-waiting
473
- let idGenerationPromise: Promise<void> | null = null;
474
- let releaseLock: (() => void) | null = null;
475
-
476
- async function acquireLock(): Promise<void> {
477
- if (releaseLock === null) {
478
- idGenerationPromise = new Promise<void>((resolve) => {
479
- releaseLock = resolve;
480
- });
481
- } else {
482
- // Wait for the previous lock to be released
483
- await idGenerationPromise;
484
- // After waiting, we need to create a new promise for the next waiter
485
- idGenerationPromise = new Promise<void>((resolve) => {
486
- releaseLock = resolve;
487
- });
488
- }
489
- }
490
-
491
- function releaseLockFn(): void {
492
- if (releaseLock) {
493
- const resolve = releaseLock;
494
- releaseLock = null;
495
- idGenerationPromise = null;
496
- resolve();
497
- }
471
+ // Promise-chaining queue for atomic ID generation. Each caller chains on the
472
+ // previous promise, guaranteeing mutual exclusion without the broken
473
+ // releaseLock pattern that allowed concurrent entry when 3+ callers waited.
474
+ let idGenerationChain: Promise<void> = Promise.resolve();
475
+
476
+ async function withIdLock<T>(fn: () => Promise<T>): Promise<T> {
477
+ const run = idGenerationChain.then(fn);
478
+ // Keep the chain alive regardless of success/failure so the next caller
479
+ // never sees a rejected antecedent.
480
+ idGenerationChain = run.then(
481
+ () => {},
482
+ () => {},
483
+ );
484
+ return run;
498
485
  }
499
486
 
500
487
  export async function getNextLogId(): Promise<number> {
501
- await acquireLock();
502
- try {
488
+ return withIdLock(async () => {
503
489
  const index = await loadIndex();
504
490
  const sqliteMaxId = await getSqliteLogIndexMaxId();
505
491
  const nextId = Math.max(index.maxId, sqliteMaxId ?? 0) + 1;
@@ -507,9 +493,7 @@ export async function getNextLogId(): Promise<number> {
507
493
  // Synchronously update the index in memory (disk write is deferred via batching)
508
494
  cachedIndex = index;
509
495
  return nextId;
510
- } finally {
511
- releaseLockFn();
512
- }
496
+ });
513
497
  }
514
498
 
515
499
  export function getCurrentLogFile(): string {
@@ -379,7 +379,28 @@ if (providersJson !== undefined) {
379
379
  }
380
380
 
381
381
  export function getProviders(): ProviderConfig[] {
382
- return store.get("providers", []);
382
+ const raw = store.get("providers", []);
383
+ // Validate the on-disk store entry-by-entry so a single corrupted record
384
+ // cannot wipe out the entire provider list. The whole-store safeParse was
385
+ // too strict — once any legacy/in-flight provider failed validation the
386
+ // whole list was discarded, which broke `updateProvider` and routing.
387
+ const valid: ProviderConfig[] = [];
388
+ for (const candidate of raw) {
389
+ const entry = ProviderConfigSchema.safeParse(candidate);
390
+ if (entry.success) {
391
+ valid.push(entry.data);
392
+ continue;
393
+ }
394
+ let candidateName = "<unknown>";
395
+ if (typeof candidate === "object" && candidate !== null) {
396
+ const nameResult = z.object({ name: z.string() }).safeParse(candidate);
397
+ if (nameResult.success) candidateName = nameResult.data.name;
398
+ }
399
+ logger.warn(
400
+ `[providers] Skipping invalid on-disk provider "${candidateName}": ${entry.error.message}`,
401
+ );
402
+ }
403
+ return valid;
383
404
  }
384
405
 
385
406
  export function getProvider(id: string): ProviderConfig | undefined {
@@ -3,6 +3,7 @@ import { existsSync } from "node:fs";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { logger } from "./logger";
5
5
  import type { FinalizeLogJob, FinalizeLogResult } from "./logFinalizer";
6
+ import { isPlainRecord, safeGetOwnProperty } from "../lib/objectUtils";
6
7
 
7
8
  const IDLE_TIMEOUT_MS = Number(process.env["SESSION_PROCESS_IDLE_MS"]) || 5 * 60 * 1000; // 5 min default
8
9
  const MAX_RESTARTS = 3;
@@ -53,7 +54,20 @@ export class SessionProcess {
53
54
 
54
55
  this.restartCount += 1;
55
56
 
56
- this.child.on("message", (msg: { id: string; result: FinalizeLogResult }) => {
57
+ this.child.on("message", (raw: unknown) => {
58
+ if (!isPlainRecord(raw)) {
59
+ logger.error("[sessionProcess] Received malformed IPC message from worker, discarding");
60
+ return;
61
+ }
62
+ const id = safeGetOwnProperty(raw, "id");
63
+ const result = safeGetOwnProperty(raw, "result");
64
+ if (typeof id !== "string" || !isPlainRecord(result)) {
65
+ logger.error("[sessionProcess] Received malformed IPC message from worker, discarding");
66
+ return;
67
+ }
68
+ // Runtime shape validated above; the cast bridges unknown → FinalizeLogResult.
69
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
70
+ const msg = { id, result: result as FinalizeLogResult };
57
71
  const pending = this.pending.get(msg.id);
58
72
  if (pending !== undefined) {
59
73
  this.pending.delete(msg.id);
@@ -1,4 +1,5 @@
1
1
  import type { ProviderConfig } from "./providers";
2
+ import { logger } from "./logger";
2
3
  import {
3
4
  AUTH_HEADER_X_API_KEY,
4
5
  DEFAULT_OPENAI_UPSTREAM,
@@ -77,8 +78,9 @@ export function setUpstreamHost(headers: Headers, upstreamBase: string): void {
77
78
  try {
78
79
  headers.set(HEADER_HOST, new URL(upstreamBase).host);
79
80
  } catch {
80
- // Invalid provider URLs are rejected by the UI. Retain the historical default
81
- // for imported or manually edited config that bypassed that validation.
81
+ logger.warn(
82
+ `[upstream] Invalid provider URL "${upstreamBase}" falling back to api.anthropic.com for Host header`,
83
+ );
82
84
  headers.set(HEADER_HOST, "api.anthropic.com");
83
85
  }
84
86
  }
package/src/router.tsx CHANGED
@@ -13,6 +13,15 @@ export function getRouter() {
13
13
  function attachServerSsrStoreCompatibility(
14
14
  router: Readonly<{ state: Readonly<{ matches: unknown }> }>,
15
15
  ): void {
16
+ // TanStack >= 1.168 refactored `state` from an own data property into a
17
+ // prototype getter backed by lazily-created `stores` (`this.stores.__store`).
18
+ // Installing a `stores` value here would shadow that lazy init
19
+ // (`if (!this.stores && this.latestLocation) { this.stores = … }`) and break
20
+ // `router.state`. When `state` is already a prototype accessor the new store
21
+ // architecture handles SSR natively and this shim is obsolete.
22
+ const stateDesc = Object.getOwnPropertyDescriptor(router, "state");
23
+ if (stateDesc === undefined) return;
24
+
16
25
  const existingStores = Object.getOwnPropertyDescriptor(router, "stores");
17
26
  if (existingStores !== undefined) return;
18
27
 
@@ -1 +0,0 @@
1
- import{r as h,j as t}from"./main-BnRC1932.js";import{c as Z,g as $,r as L,a as q,X as ee,b as m,B as te,f as P,R as re,C as ne,M as V,d as _,e as M,h as B,i as se,j as ae,k as oe,L as ie}from"./ProxyViewerContainer-BLCRQtU_.js";const de=[["line",{x1:"5",x2:"19",y1:"9",y2:"9",key:"1nwqeh"}],["line",{x1:"5",x2:"19",y1:"15",y2:"15",key:"g8yjpy"}]],le=Z("equal",de),ce="";function j(e){if(e.length===0)return ce;let r="";for(let n=0;n<e.length;n++){const a=e[n];a!==void 0&&(typeof a=="number"?r+=`[${a}]`:n===0?r+=a:r+=`.${a}`)}return r}function ue(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function D(e){if(typeof e=="string")try{return C(JSON.parse(e))}catch{return{kind:"primitive",value:e}}return C(e)}function C(e){if(e===null)return{kind:"primitive",value:null};if(typeof e=="string")return{kind:"primitive",value:e};if(typeof e=="number")return{kind:"primitive",value:e};if(typeof e=="boolean")return{kind:"primitive",value:e};if(Array.isArray(e))return{kind:"array",value:e.map(r=>C(r))};if(ue(e)){const r={};for(const n of Object.keys(e).sort())r[n]=C(e[n]);return{kind:"object",value:r}}return{kind:"primitive",value:null}}function xe(e,r){const n=[];return R([],e,r,n),n}function R(e,r,n,a){const d=j(e);if(S(r,n)){a.push({kind:"equal",path:d,value:r});return}if(r.kind!==n.kind){a.push({kind:"changed",path:d,left:r,right:n});return}if(r.kind==="primitive"&&n.kind==="primitive"){a.push({kind:"changed",path:d,left:r,right:n});return}if(r.kind==="object"&&n.kind==="object"){const i=Object.keys(r.value),s=Object.keys(n.value),o=new Set(s);for(const l of i){const f=r.value[l];if(f!==void 0)if(!o.has(l))a.push({kind:"removed",path:j([...e,l]),value:f});else{const p=n.value[l];if(p===void 0)continue;R([...e,l],f,p,a)}}for(const l of s){if(i.includes(l))continue;const f=n.value[l];f!==void 0&&a.push({kind:"added",path:j([...e,l]),value:f})}return}if(r.kind==="array"&&n.kind==="array"){const i=Math.min(r.value.length,n.value.length);for(let s=0;s<i;s++){const o=r.value[s],l=n.value[s];o===void 0||l===void 0||R([...e,s],o,l,a)}for(let s=i;s<n.value.length;s++){const o=n.value[s];o!==void 0&&a.push({kind:"added",path:j([...e,s]),value:o})}for(let s=i;s<r.value.length;s++){const o=r.value[s];o!==void 0&&a.push({kind:"removed",path:j([...e,s]),value:o})}}}function S(e,r){if(e.kind!==r.kind)return!1;if(e.kind==="primitive"&&r.kind==="primitive")return e.value===r.value;if(e.kind==="array"&&r.kind==="array"){if(e.value.length!==r.value.length)return!1;for(let n=0;n<e.value.length;n++){const a=e.value[n],d=r.value[n];if(a===void 0||d===void 0||!S(a,d))return!1}return!0}if(e.kind==="object"&&r.kind==="object"){const n=Object.keys(e.value),a=Object.keys(r.value);if(n.length!==a.length)return!1;for(const d of n){const i=e.value[d],s=r.value[d];if(i===void 0||s===void 0||!S(i,s))return!1}return!0}return!1}function v(e,r=80){let n;switch(e.kind){case"primitive":n=e.value===null?"null":JSON.stringify(e.value);break;case"array":n=`[… ${e.value.length} items]`;break;case"object":n=`{… ${Object.keys(e.value).length} keys}`;break}return n.length>r&&(n=`${n.slice(0,r-1)}…`),n}function N(e,r=2){return JSON.stringify(E(e),null,r)}function E(e){switch(e.kind){case"primitive":return e.value;case"array":return e.value.map(E);case"object":{const r={};for(const[n,a]of Object.entries(e.value))r[n]=E(a);return r}}}function w({text:e,defaultExpandDepth:r}){return t.jsx(h.Suspense,{fallback:t.jsx("div",{className:"text-xs text-muted-foreground",children:"Loading JSON..."}),children:t.jsx(ie,{text:e,defaultExpandDepth:r})})}function K(e){if(e==="")return"";for(let r=e.length-1;r>=0;r--){const n=e[r];if(n==="."||n==="[")return e.substring(0,r)}return""}function A(e){return e.kind==="equal"&&(e.value.kind==="object"||e.value.kind==="array")}function me(e){const r=[];let n=0;for(;n<e.length;){const a=e[n];if(a!==void 0&&A(a)){const d=K(a.path);let i=n+1;for(;i<e.length;){const s=e[i];if(s===void 0||!A(s)||K(s.path)!==d)break;i++}if(i-n>1){const s=[];for(let o=n;o<i;o++){const l=e[o];l!==void 0&&l.kind==="equal"&&s.push(l)}r.push({kind:"equal-run",ops:s}),n=i;continue}}a!==void 0&&r.push({kind:"single",op:a}),n++}return r}const F={added:{icon:_,accent:"text-emerald-600 dark:text-emerald-400",bg:"bg-emerald-500/5 hover:bg-emerald-500/10",border:"border-l-emerald-500",label:"ADDED"},removed:{icon:V,accent:"text-rose-600 dark:text-rose-400",bg:"bg-rose-500/5 hover:bg-rose-500/10",border:"border-l-rose-500",label:"REMOVED"},changed:{icon:M,accent:"text-amber-600 dark:text-amber-400",bg:"bg-amber-500/5 hover:bg-amber-500/10",border:"border-l-amber-500",label:"CHANGED"},equal:{icon:le,accent:"text-muted-foreground/70",bg:"bg-muted/20 hover:bg-muted/30",border:"border-l-muted-foreground/20",label:"EQUAL"}};function fe({ops:e,expanded:r,onToggle:n}){const a=e[0],d=e[e.length-1];if(a===void 0||d===void 0)return t.jsx("div",{className:"text-muted-foreground/40 text-xs",children:"—"});const i=a.path,s=d.path,o=e.length===1?i:`${i} … ${s}`,l=a.value.kind==="array"?`${e.length} equal arrays`:a.value.kind==="object"?`${e.length} equal objects`:"equal",f=F.equal;return t.jsxs("div",{className:m("border-l-4 rounded-sm",f.border,f.bg),children:[t.jsxs("button",{type:"button",onClick:n,className:"w-full text-left flex items-center gap-2 px-3 py-1.5 text-xs text-muted-foreground cursor-pointer",children:[t.jsx(B,{className:m("size-3 transition-transform shrink-0",r&&"rotate-90")}),t.jsx(f.icon,{className:m("size-3 shrink-0",f.accent)}),t.jsx("span",{className:"font-mono truncate flex-1",title:`${i} … ${s}`,children:o}),t.jsx("span",{className:m("text-[10px] uppercase tracking-wider shrink-0",f.accent),children:f.label}),t.jsxs("span",{className:"text-muted-foreground/60 shrink-0",children:["(",l,")"]})]}),r&&t.jsx("div",{className:"ml-5 mt-1 mb-2 space-y-2 pr-2",children:e.map(p=>t.jsxs("div",{className:"border border-border/50 rounded p-2 bg-muted/20",children:[t.jsx("div",{className:"font-mono text-xs text-muted-foreground mb-1",children:p.path}),t.jsx(w,{text:N(p.value),defaultExpandDepth:0})]},p.path))})]})}function pe({op:e,idx:r,copiedPath:n,onCopyPath:a,expanded:d,onToggle:i}){const s=F[e.kind],o=s.icon,l=e.kind==="added"||e.kind==="removed"?e.value.kind==="object"||e.value.kind==="array":e.kind==="changed"?e.left.kind==="object"||e.left.kind==="array"||e.right.kind==="object"||e.right.kind==="array":!1,f=e.kind==="changed"?[{text:v(e.left,400),tone:"text-rose-700 dark:text-rose-300 line-through"},{text:v(e.right,400),tone:"text-emerald-700 dark:text-emerald-300"}]:e.kind==="removed"?[{text:v(e.value,400),tone:"text-rose-700 dark:text-rose-300 line-through"}]:e.kind==="added"?[{text:v(e.value,400),tone:"text-emerald-700 dark:text-emerald-300"}]:[{text:v(e.value,400),tone:"text-muted-foreground"}],p=n===e.path&&e.path!=="";return t.jsxs("div",{"data-diff-idx":r,"data-diff-kind":e.kind,className:m("border-l-4 rounded-sm px-3 py-2 my-0.5 transition-colors",s.border,s.bg),children:[t.jsxs("button",{type:"button",onClick:i,disabled:!l,className:m("w-full flex items-center gap-2 text-xs text-left rounded-sm",l?"cursor-pointer":"cursor-default"),"aria-expanded":l?d:void 0,"aria-label":l?d?`Collapse ${e.path||"root"}`:`Expand ${e.path||"root"}`:void 0,children:[l?t.jsx(B,{className:m("size-3 shrink-0 transition-transform",s.accent,d&&"rotate-90")}):t.jsx("span",{className:"size-3 shrink-0","aria-hidden":"true"}),t.jsx(o,{className:m("size-3.5 shrink-0",s.accent),strokeWidth:2.5}),t.jsx("span",{className:"font-mono truncate flex-1 min-w-0",title:e.path||"(root)",children:e.path===""?"(root)":e.path}),t.jsx("span",{className:m("text-[9px] font-bold uppercase tracking-wider shrink-0 px-1.5 py-0.5 rounded",s.accent,e.kind==="equal"?"bg-muted/40":"bg-background/60"),children:s.label}),e.path!==""&&t.jsx("span",{role:"button",tabIndex:0,onClick:b=>{b.stopPropagation(),a(e.path)},onKeyDown:b=>{(b.key==="Enter"||b.key===" ")&&(b.stopPropagation(),b.preventDefault(),a(e.path))},className:m("shrink-0 p-1 rounded transition-colors cursor-pointer inline-flex items-center justify-center",p?"text-emerald-500":"text-muted-foreground/50 hover:text-foreground hover:bg-muted"),"aria-label":p?"Copied":"Copy",title:p?"Copied!":"Copy",children:p?t.jsx(se,{className:"size-3"}):t.jsx(ae,{className:"size-3"})})]}),f.map((b,y)=>t.jsx("div",{className:m("font-mono text-xs mt-1 break-all pl-5",b.tone),children:b.text},y)),t.jsx("div",{className:"overflow-hidden transition-all duration-200",style:{maxHeight:d&&l?"2000px":"0"},"aria-hidden":!d,children:d&&l&&e.kind!=="equal"?t.jsx(he,{op:e}):null})]})}function he({op:e}){if(e.kind==="added"||e.kind==="removed")return t.jsx("div",{className:"pl-5 mt-2 border border-border/50 rounded p-2 bg-muted/20",children:t.jsx(w,{text:N(e.value),defaultExpandDepth:0})});const r=e.left.kind==="object"||e.left.kind==="array",n=e.right.kind==="object"||e.right.kind==="array";return!r&&!n?t.jsx("div",{className:"pl-5 mt-2 text-xs text-muted-foreground/70 italic",children:"Primitive values are shown inline above."}):t.jsxs("div",{className:"pl-5 mt-2 grid grid-cols-1 md:grid-cols-2 gap-2",children:[t.jsxs("div",{className:"border border-rose-500/30 rounded p-2 bg-rose-500/5",children:[t.jsx("div",{className:"text-[10px] uppercase tracking-wider text-rose-500 mb-1",children:"Old"}),t.jsx(w,{text:N(e.left),defaultExpandDepth:0})]}),t.jsxs("div",{className:"border border-emerald-500/30 rounded p-2 bg-emerald-500/5",children:[t.jsx("div",{className:"text-[10px] uppercase tracking-wider text-emerald-500 mb-1",children:"New"}),t.jsx(w,{text:N(e.right),defaultExpandDepth:0})]})]})}function be({counts:e,onJumpTo:r}){const n=e.added+e.removed+e.changed;return t.jsxs("div",{className:"px-4 py-2 border-b border-border bg-muted/20 flex items-center gap-2 text-xs flex-wrap",children:[t.jsxs("span",{className:"text-muted-foreground font-medium",children:[n," ",n===1?"change":"changes"]}),t.jsxs("button",{type:"button",onClick:()=>r("removed"),disabled:e.removed===0,className:m("inline-flex items-center gap-1 px-2 py-0.5 rounded-full border cursor-pointer transition-colors",e.removed>0?"border-rose-500/40 text-rose-600 dark:text-rose-400 bg-rose-500/10 hover:bg-rose-500/20":"border-border text-muted-foreground/40 cursor-not-allowed"),title:e.removed>0?"Jump to first removed":"No removals",children:[t.jsx(V,{className:"size-3"}),e.removed," removed"]}),t.jsxs("button",{type:"button",onClick:()=>r("added"),disabled:e.added===0,className:m("inline-flex items-center gap-1 px-2 py-0.5 rounded-full border cursor-pointer transition-colors",e.added>0?"border-emerald-500/40 text-emerald-600 dark:text-emerald-400 bg-emerald-500/10 hover:bg-emerald-500/20":"border-border text-muted-foreground/40 cursor-not-allowed"),title:e.added>0?"Jump to first added":"No additions",children:[t.jsx(_,{className:"size-3"}),e.added," added"]}),t.jsxs("button",{type:"button",onClick:()=>r("changed"),disabled:e.changed===0,className:m("inline-flex items-center gap-1 px-2 py-0.5 rounded-full border cursor-pointer transition-colors",e.changed>0?"border-amber-500/40 text-amber-600 dark:text-amber-400 bg-amber-500/10 hover:bg-amber-500/20":"border-border text-muted-foreground/40 cursor-not-allowed"),title:e.changed>0?"Jump to first changed":"No changes",children:[t.jsx(M,{className:"size-3"}),e.changed," changed"]})]})}function ve({mode:e,onChange:r}){return t.jsxs("div",{className:"inline-flex rounded-md border border-border overflow-hidden",children:[t.jsxs("button",{type:"button",onClick:()=>r("unified"),"aria-pressed":e==="unified",className:m("flex items-center gap-1 px-2 py-1 text-xs transition-colors cursor-pointer",e==="unified"?"bg-muted text-foreground":"hover:bg-muted/50 text-muted-foreground"),title:"Unified view (single column, emphasized diffs)",children:[t.jsx(re,{className:"size-3"}),"Unified"]}),t.jsxs("button",{type:"button",onClick:()=>r("split"),"aria-pressed":e==="split",className:m("flex items-center gap-1 px-2 py-1 text-xs transition-colors border-l border-border cursor-pointer",e==="split"?"bg-muted text-foreground":"hover:bg-muted/50 text-muted-foreground"),title:"Split view (path | left | right)",children:[t.jsx(ne,{className:"size-3"}),"Split"]})]})}function J({log:e,side:r,displayNumber:n}){const a=q(e);return t.jsxs("div",{className:"flex-1 min-w-0 space-y-1 text-xs",children:[t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsx(te,{variant:"outline",className:m("text-[10px] px-1.5 py-0 h-5 font-mono shrink-0",r==="left"?"border-rose-500/40 text-rose-400":"border-emerald-500/40 text-emerald-400"),children:r==="left"?"← Left":"Right →"}),t.jsxs("span",{className:"font-mono text-blue-400/80",title:`Log ID ${String(e.id)}`,children:["#",n]}),e.model!==null&&t.jsx("span",{className:"font-mono leading-snug text-muted-foreground",children:e.model})]}),t.jsxs("div",{className:"flex items-center gap-3 text-muted-foreground font-mono",children:[e.cacheCreationInputTokens!==null&&e.cacheCreationInputTokens>0&&t.jsxs("span",{className:"text-emerald-400",children:["KV Cache +",P(e.cacheCreationInputTokens)]}),e.cacheReadInputTokens!==null&&e.cacheReadInputTokens>0&&t.jsxs("span",{className:"text-purple-400",children:["KV Cache ~",P(e.cacheReadInputTokens)]}),t.jsx("span",{className:"truncate",title:e.timestamp,children:e.timestamp})]}),t.jsxs("div",{className:"text-muted-foreground/70 font-mono truncate",title:a,children:["session: ",a]})]})}function ye({left:e,right:r,leftDisplayNumber:n,rightDisplayNumber:a,onClose:d}){const i=h.useMemo(()=>{const c=$(L(e)).analyzeRequest(e.rawRequestBody),u=$(L(r)).analyzeRequest(r.rawRequestBody),x=D(c.comparisonValue),g=D(u.comparisonValue);return xe(x,g)},[e.apiFormat,e.path,e.rawRequestBody,r.apiFormat,r.path,r.rawRequestBody]),s=h.useMemo(()=>me(i),[i]),o=h.useMemo(()=>{let c=0,u=0,x=0;for(const g of s)if(g.kind==="single")switch(g.op.kind){case"added":c++;break;case"removed":u++;break;case"changed":x++;break}return{added:c,removed:u,changed:x}},[s]),[l,f]=h.useState(new Set),p=c=>{f(u=>{const x=new Set(u);return x.has(c)?x.delete(c):x.add(c),x})},[b,y]=h.useState(new Set),U=c=>{y(u=>{const x=new Set(u);return x.has(c)?x.delete(c):x.add(c),x})};h.useEffect(()=>{y(new Set)},[e.id,r.id]);const[T,H]=h.useState("unified"),I=h.useRef(null),[G,z]=h.useState(null),k=h.useRef(null),Q=c=>{oe(c).then(u=>{u&&(z(c),k.current!==null&&clearTimeout(k.current),k.current=setTimeout(()=>z(null),1500))})};h.useEffect(()=>()=>{k.current!==null&&clearTimeout(k.current)},[]);const W=c=>{const u=s.findIndex(O=>O.kind==="single"&&O.op.kind===c);if(u===-1)return;const x=I.current;if(x===null)return;const g=x.querySelector(`[data-diff-idx="${u}"]`);g!==null&&g.scrollIntoView({behavior:"smooth",block:"center"})};h.useEffect(()=>{const c=x=>{x.key==="Escape"&&d()};document.addEventListener("keydown",c);const u=document.body.style.overflow;return document.body.style.overflow="hidden",()=>{document.removeEventListener("keydown",c),document.body.style.overflow=u}},[d]);const X=q(e)===q(r),Y=i.length===1&&i[0]?.kind==="equal";return t.jsxs("div",{className:"fixed inset-0 z-50 flex justify-end",role:"dialog","aria-modal":"true","aria-label":"Compare two log requests",children:[t.jsx("button",{type:"button",onClick:d,"aria-label":"Close compare drawer",className:"absolute inset-0 bg-black/40 cursor-default",tabIndex:-1}),t.jsxs("div",{className:m("relative bg-background border-l border-border shadow-xl","w-full md:w-[70vw] max-w-[1100px] flex flex-col h-full"),onClick:c=>c.stopPropagation(),onKeyDown:c=>c.stopPropagation(),children:[t.jsxs("div",{className:"flex items-start gap-4 px-4 py-3 border-b border-border",children:[t.jsxs("div",{className:"flex-1 flex gap-4 min-w-0",children:[t.jsx(J,{log:e,side:"left",displayNumber:n}),t.jsx(J,{log:r,side:"right",displayNumber:a})]}),t.jsxs("div",{className:"flex items-center gap-2 shrink-0",children:[t.jsx(ve,{mode:T,onChange:H}),t.jsx("button",{type:"button",onClick:d,"aria-label":"Close",className:"p-1 rounded text-muted-foreground hover:text-foreground hover:bg-muted cursor-pointer",children:t.jsx(ee,{className:"size-4"})})]})]}),!X&&t.jsx("div",{className:"px-4 py-1.5 text-xs text-amber-400 bg-amber-500/10 border-b border-border",children:"Heads up: the two selected logs are from different sessions."}),Y?t.jsx("div",{className:"flex-1 min-h-0 overflow-y-auto flex items-center justify-center text-muted-foreground text-sm",children:"The two Request payloads are identical."}):t.jsxs(t.Fragment,{children:[t.jsx(be,{counts:o,onJumpTo:W}),t.jsx("div",{ref:I,className:"flex-1 min-h-0 overflow-y-auto",children:T==="unified"?t.jsx("div",{className:"px-3 py-2 space-y-0.5",children:s.map((c,u)=>{if(c.kind==="equal-run")return t.jsx(fe,{ops:c.ops,expanded:l.has(u),onToggle:()=>p(u)},`r${u}`);const x=c.op;return t.jsx(pe,{op:x,idx:u,copiedPath:G,onCopyPath:Q,expanded:b.has(u),onToggle:()=>U(u)},`o${u}`)})}):t.jsx(ge,{grouped:s,left:e,right:r,leftDisplayNumber:n,rightDisplayNumber:a})})]})]})]})}function ge({grouped:e,left:r,right:n,leftDisplayNumber:a,rightDisplayNumber:d}){return t.jsxs("div",{className:"grid grid-cols-[200px_1fr_1fr] gap-x-2 gap-y-0.5 px-3 py-2 text-xs",children:[t.jsxs("div",{className:"grid grid-cols-[200px_1fr_1fr] gap-x-2 col-span-3 pb-2 mb-2 border-b border-border text-[10px] uppercase tracking-wider text-muted-foreground",children:[t.jsx("span",{children:"Path"}),t.jsxs("span",{title:`Log ID ${String(r.id)}`,children:["Left (Log #",a,")"]}),t.jsxs("span",{title:`Log ID ${String(n.id)}`,children:["Right (Log #",d,")"]})]}),e.map((i,s)=>{if(i.kind==="equal-run")return t.jsxs("div",{className:"col-span-3 px-2 py-1 text-xs text-muted-foreground/60",children:[i.ops.length," equal siblings collapsed — switch to Unified to expand"]},s);const o=i.op;return o.kind==="equal"?t.jsxs("div",{className:"col-span-3 grid grid-cols-[200px_1fr_1fr] gap-x-2 px-2 py-0.5 text-muted-foreground",children:[t.jsx("span",{className:"font-mono text-xs truncate",title:o.path,children:o.path}),t.jsx("span",{className:"font-mono text-xs break-all opacity-60",children:v(o.value,200)}),t.jsx("span",{className:"font-mono text-xs break-all opacity-60",children:v(o.value,200)})]},s):o.kind==="added"?t.jsxs("div",{className:"col-span-3 px-2 py-1 rounded text-xs border-l-2 border-l-emerald-400/70 bg-emerald-500/5",children:[t.jsx("div",{className:"font-mono text-xs text-muted-foreground mb-0.5",children:o.path}),t.jsxs("div",{className:"font-mono break-all text-emerald-300/90",children:["+ ",v(o.value,400)]})]},s):o.kind==="removed"?t.jsxs("div",{className:"col-span-3 px-2 py-1 rounded text-xs border-l-2 border-l-rose-400/70 bg-rose-500/5",children:[t.jsx("div",{className:"font-mono text-xs text-muted-foreground mb-0.5",children:o.path}),t.jsxs("div",{className:"font-mono break-all text-rose-300/90 line-through",children:["− ",v(o.value,400)]})]},s):t.jsxs("div",{className:"col-span-3 px-2 py-1 rounded text-xs border-l-2 border-l-amber-400/70 bg-amber-500/5",children:[t.jsx("div",{className:"font-mono text-xs text-muted-foreground mb-1",children:o.path}),t.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[t.jsx("div",{className:"font-mono text-rose-300/90 break-all line-through",children:v(o.left,400)}),t.jsx("div",{className:"font-mono text-emerald-300/90 break-all",children:v(o.right,400)})]})]},s)})]})}export{ye as CompareDrawer};