@tonyclaw/agent-inspector 3.0.28 → 3.0.30

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 (156) hide show
  1. package/.output/cli.js +791 -191
  2. package/.output/nitro.json +1 -1
  3. package/.output/public/assets/CompareDrawer-B6cXJohL.js +1 -0
  4. package/.output/public/assets/InspectorPet-mAzeGmEE.js +4108 -0
  5. package/.output/public/assets/ProxyViewerContainer-CkFWv_Nm.js +126 -0
  6. package/.output/public/assets/{ReplayDialog-CZMApaF4.js → ReplayDialog-DodiTL6E.js} +1 -1
  7. package/.output/public/assets/{RequestAnatomy-DNWccR7O.js → RequestAnatomy-B3IauToI.js} +1 -1
  8. package/.output/public/assets/ResponseView-Hn-5ordK.js +3 -0
  9. package/.output/public/assets/StreamingChunkSequence-vLDOVQM_.js +1 -0
  10. package/.output/public/assets/_sessionId-BFH4TOaI.js +1 -0
  11. package/.output/public/assets/{_sessionId-DRfvuE2k.js → _sessionId-Cj_HIFZx.js} +1 -1
  12. package/.output/public/assets/{index-D4HkS7Ct.js → index-Bmj2lcWE.js} +1 -1
  13. package/.output/public/assets/index-CgJj-HBC.css +1 -0
  14. package/.output/public/assets/index-Ch7uqnCT.js +1 -0
  15. package/.output/public/assets/index-DkDdKvLl.js +76 -0
  16. package/.output/public/assets/{index-B3aAuqWq.js → index-ZlhqCrSg.js} +6 -6
  17. package/.output/public/assets/{json-viewer-wuJSKaed.js → json-viewer-BdrnVQu-.js} +1 -1
  18. package/.output/public/assets/jszip.min-CS_nt_o1.js +2 -0
  19. package/.output/public/assets/qwen-mMn3f5ul.webp +0 -0
  20. package/.output/server/_libs/jszip.mjs +35 -9
  21. package/.output/server/_libs/lucide-react.mjs +86 -86
  22. package/.output/server/_libs/radix-ui__react-dialog.mjs +3 -3
  23. package/.output/server/_libs/tanstack__react-router.mjs +1 -1
  24. package/.output/server/{_sessionId-BJTNiP_O.mjs → _sessionId-C5S3pGZd.mjs} +15 -15
  25. package/.output/server/_sessionId-g6D69lKq.mjs +81 -0
  26. package/.output/server/_ssr/{CompareDrawer-BMRH3N97.mjs → CompareDrawer-CqUmGHal.mjs} +138 -103
  27. package/.output/server/_ssr/InspectorPet-DI0UJd01.mjs +925 -0
  28. package/.output/server/_ssr/{ProxyViewerContainer-AFwcHAIR.mjs → ProxyViewerContainer-CvsUmbJ3.mjs} +1216 -1659
  29. package/.output/server/_ssr/{ReplayDialog-CbWvRHiN.mjs → ReplayDialog-DS48dpFG.mjs} +18 -18
  30. package/.output/server/_ssr/{RequestAnatomy-C4kcPyqN.mjs → RequestAnatomy-DxYVQU1C.mjs} +58 -58
  31. package/.output/server/_ssr/{ResponseView-D8VYt-gZ.mjs → ResponseView-BLXW73eq.mjs} +60 -60
  32. package/.output/server/_ssr/{StreamingChunkSequence-BUUo6vU0.mjs → StreamingChunkSequence-DD0iFuy0.mjs} +16 -16
  33. package/.output/server/_ssr/{index-DTwMEEXO.mjs → index-B10LIaK0.mjs} +15 -15
  34. package/.output/server/_ssr/index-RHVJnU2p.mjs +81 -0
  35. package/.output/server/_ssr/index.mjs +2 -2
  36. package/.output/server/_ssr/{json-viewer-BqF1pSQD.mjs → json-viewer-LDu2XBaK.mjs} +58 -58
  37. package/.output/server/_ssr/{router-C8BOns7y.mjs → router-GKvrwifJ.mjs} +9005 -6488
  38. package/.output/server/_tanstack-start-manifest_v-Df2n4mbT.mjs +4 -0
  39. package/.output/server/index.mjs +105 -77
  40. package/.output/workers/logFinalizer.worker.js +16908 -0
  41. package/.output/workers/sessionWorkerEntry.js +16904 -0
  42. package/README.md +21 -5
  43. package/package.json +6 -2
  44. package/src/assets/logos/qwen.webp +0 -0
  45. package/src/cli.ts +85 -10
  46. package/src/components/OnboardingBanner.tsx +41 -21
  47. package/src/components/ProxyViewer.tsx +198 -269
  48. package/src/components/ProxyViewerContainer.tsx +128 -17
  49. package/src/components/clients/ClientLogo.tsx +9 -6
  50. package/src/components/ecosystem/AgentLabDialog.tsx +166 -19
  51. package/src/components/errors/SafeErrorBoundary.tsx +201 -0
  52. package/src/components/pi-agent/PiAgentPanel.tsx +4 -1
  53. package/src/components/providers/ImportWizardDialog.tsx +18 -42
  54. package/src/components/providers/ProviderLogo.tsx +1 -1
  55. package/src/components/providers/ProvidersPanel.tsx +8 -5
  56. package/src/components/providers/SettingsDialog.tsx +34 -11
  57. package/src/components/proxy-viewer/ApplicationBar.tsx +63 -0
  58. package/src/components/proxy-viewer/CompareDrawer.tsx +92 -49
  59. package/src/components/proxy-viewer/ConversationGroupList.tsx +49 -34
  60. package/src/components/proxy-viewer/ConversationHeader.tsx +22 -18
  61. package/src/components/proxy-viewer/LiveConnectionStatus.tsx +186 -0
  62. package/src/components/proxy-viewer/LogEntry.tsx +283 -275
  63. package/src/components/proxy-viewer/RawExportWarning.tsx +77 -0
  64. package/src/components/proxy-viewer/SessionLoadProgressBar.tsx +61 -0
  65. package/src/components/proxy-viewer/ThreadConnector.tsx +16 -1
  66. package/src/components/proxy-viewer/TurnGroup.tsx +13 -2
  67. package/src/components/proxy-viewer/accessibility.ts +8 -0
  68. package/src/components/proxy-viewer/lazy.ts +4 -0
  69. package/src/components/proxy-viewer/liveConnectionState.ts +158 -0
  70. package/src/components/proxy-viewer/proxyViewerLogic.ts +10 -0
  71. package/src/components/proxy-viewer/viewerState.ts +2 -6
  72. package/src/components/ui/select.tsx +1 -1
  73. package/src/components/ui/tabs.tsx +3 -3
  74. package/src/components/ui/transient-toast.tsx +1 -1
  75. package/src/lib/apiClient.ts +17 -2
  76. package/src/lib/ecosystemContract.ts +34 -0
  77. package/src/lib/export-logs.ts +1 -1
  78. package/src/lib/providerContract.ts +70 -4
  79. package/src/lib/providerImportContract.ts +27 -0
  80. package/src/lib/providerModelMetadata.ts +16 -7
  81. package/src/lib/resourceLimits.ts +152 -0
  82. package/src/lib/safeDiagnostic.ts +38 -0
  83. package/src/lib/useProviders.ts +4 -4
  84. package/src/lib/utils.ts +5 -1
  85. package/src/mcp/server.ts +39 -6
  86. package/src/mcp/toolHandlers.ts +131 -4
  87. package/src/proxy/chunkStorage.ts +20 -6
  88. package/src/proxy/config.ts +20 -6
  89. package/src/proxy/dataDir.ts +3 -0
  90. package/src/proxy/ecosystemExecutionConfirmation.ts +114 -0
  91. package/src/proxy/ecosystemExecutionRoute.ts +116 -0
  92. package/src/proxy/ecosystemTasks.ts +48 -0
  93. package/src/proxy/evidenceExporter.ts +23 -9
  94. package/src/proxy/groupEvidenceExporter.ts +26 -5
  95. package/src/proxy/groupStore.ts +13 -3
  96. package/src/proxy/handler.ts +103 -20
  97. package/src/proxy/identityProxy.ts +333 -14
  98. package/src/proxy/logFinalizer.ts +73 -6
  99. package/src/proxy/logImportUpload.ts +128 -0
  100. package/src/proxy/logImporter.ts +321 -70
  101. package/src/proxy/logIndex.ts +16 -6
  102. package/src/proxy/logger.ts +294 -41
  103. package/src/proxy/privateDataPath.ts +183 -0
  104. package/src/proxy/providerScanStore.ts +87 -0
  105. package/src/proxy/providerSecretStore.ts +58 -19
  106. package/src/proxy/providers.ts +175 -58
  107. package/src/proxy/rawStreamCapture.ts +66 -5
  108. package/src/proxy/runStore.ts +13 -3
  109. package/src/proxy/runtimeAdmission.ts +52 -0
  110. package/src/proxy/runtimeHealth.ts +206 -0
  111. package/src/proxy/runtimeShutdown.ts +75 -0
  112. package/src/proxy/sessionArchive.ts +15 -2
  113. package/src/proxy/sessionProcess.ts +19 -0
  114. package/src/proxy/sessionRuntime.ts +7 -0
  115. package/src/proxy/shutdownCoordinator.ts +90 -0
  116. package/src/proxy/sqliteLogIndex.ts +18 -2
  117. package/src/proxy/store.ts +18 -2
  118. package/src/routes/__root.tsx +18 -1
  119. package/src/routes/api/alerts.summary.ts +12 -8
  120. package/src/routes/api/alerts.ts +27 -9
  121. package/src/routes/api/ecosystem.packages.$packageId.help.ts +3 -8
  122. package/src/routes/api/ecosystem.packages.$packageId.install.ts +3 -8
  123. package/src/routes/api/ecosystem.packages.$packageId.runner-presets.ts +3 -11
  124. package/src/routes/api/ecosystem.packages.$packageId.upgrade.ts +3 -8
  125. package/src/routes/api/ecosystem.recipes.$recipeId.run.ts +3 -8
  126. package/src/routes/api/health.ts +9 -2
  127. package/src/routes/api/knowledge.project-context.ts +11 -0
  128. package/src/routes/api/knowledge.search.ts +33 -2
  129. package/src/routes/api/logs.$id.body.ts +16 -2
  130. package/src/routes/api/logs.import.ts +7 -18
  131. package/src/routes/api/logs.stream.ts +147 -69
  132. package/src/routes/api/logs.ts +55 -14
  133. package/src/routes/api/providers.$providerId.model-metadata.ts +22 -4
  134. package/src/routes/api/providers.$providerId.ts +37 -6
  135. package/src/routes/api/providers.export.ts +34 -16
  136. package/src/routes/api/providers.import.ts +42 -8
  137. package/src/routes/api/providers.scan.ts +13 -8
  138. package/src/routes/api/providers.ts +36 -5
  139. package/src/routes/api/runs.ts +12 -12
  140. package/src/routes/api/sessions.ts +15 -8
  141. package/src/routes/index.tsx +6 -0
  142. package/src/routes/livez.ts +13 -0
  143. package/src/routes/readyz.ts +18 -0
  144. package/src/routes/session/$sessionId.tsx +6 -0
  145. package/styles/globals.css +19 -3
  146. package/.output/public/assets/CompareDrawer-TghZr5t1.js +0 -1
  147. package/.output/public/assets/ProxyViewerContainer-fShBAZjj.js +0 -4234
  148. package/.output/public/assets/ResponseView-d25MdFhY.js +0 -3
  149. package/.output/public/assets/StreamingChunkSequence-DIFZEnWe.js +0 -1
  150. package/.output/public/assets/index-BsxAGqMA.css +0 -1
  151. package/.output/public/assets/index-DzARL2Fi.js +0 -76
  152. package/.output/public/assets/qwen-CONDcHqt.png +0 -0
  153. package/.output/server/_tanstack-start-manifest_v-BBf2nRhb.mjs +0 -4
  154. package/src/assets/logos/mcp.png +0 -0
  155. package/src/assets/logos/qwen.png +0 -0
  156. package/src/components/ui/mcp-logo.tsx +0 -20
@@ -1,8 +1,14 @@
1
1
  import { createFileRoute } from "@tanstack/react-router";
2
2
  import { z } from "zod";
3
3
  import { getProviders, addProvider, redactProvider, redactProviders } from "../../proxy/providers";
4
- import { ProviderModelMetadataSchema } from "../../lib/providerContract";
4
+ import {
5
+ getProviderModelLimitViolation,
6
+ ProviderModelMetadataListSchema,
7
+ ProviderModelNameSchema,
8
+ ProviderModelsSchema,
9
+ } from "../../lib/providerContract";
5
10
  import { evaluateUpstreamUrl } from "../../lib/ssrfGuard";
11
+ import { resourceLimitResponse } from "../../lib/resourceLimits";
6
12
 
7
13
  const ALLOW_LOOPBACK = process.env["AGENT_INSPECTOR_ALLOW_LOOPBACK"] === "1";
8
14
 
@@ -13,12 +19,12 @@ const ProviderInputSchema = z.object({
13
19
  anthropicBaseUrl: z.string().optional(),
14
20
  openaiBaseUrl: z.string().optional(),
15
21
  openaiResponsesBaseUrl: z.string().optional(),
16
- models: z.array(z.string()).min(1, "At least one model is required"),
17
- model: z.string().optional(),
22
+ models: ProviderModelsSchema.min(1, "At least one model is required"),
23
+ model: ProviderModelNameSchema.optional(),
18
24
  authHeader: z.enum(["bearer", "x-api-key"]).optional().default("bearer"),
19
25
  apiDocsUrl: z.string().optional(),
20
26
  modelMetadataUrl: z.string().optional(),
21
- modelMetadata: z.array(ProviderModelMetadataSchema).optional(),
27
+ modelMetadata: ProviderModelMetadataListSchema.optional(),
22
28
  source: z.enum(["company", "personal"]).optional(),
23
29
  });
24
30
 
@@ -29,7 +35,26 @@ export const Route = createFileRoute("/api/providers")({
29
35
  return Response.json(redactProviders(getProviders()));
30
36
  },
31
37
  POST: async ({ request }: { request: Request }) => {
32
- const parsed = ProviderInputSchema.safeParse(await request.json());
38
+ let body: unknown;
39
+ try {
40
+ body = await request.json();
41
+ } catch {
42
+ return Response.json({ error: "Invalid JSON body" }, { status: 400 });
43
+ }
44
+
45
+ const violation = getProviderModelLimitViolation(body);
46
+ if (violation !== null) {
47
+ return resourceLimitResponse({
48
+ error: `Provider model collections may contain at most ${String(violation.limit)} entries.`,
49
+ code: "provider-model-limit-exceeded",
50
+ status: 413,
51
+ resource: violation.resource,
52
+ limit: violation.limit,
53
+ retryable: false,
54
+ });
55
+ }
56
+
57
+ const parsed = ProviderInputSchema.safeParse(body);
33
58
  if (!parsed.success) {
34
59
  return Response.json({ error: parsed.error.message }, { status: 400 });
35
60
  }
@@ -59,6 +84,12 @@ export const Route = createFileRoute("/api/providers")({
59
84
  parsed.data.modelMetadata,
60
85
  parsed.data.openaiResponsesBaseUrl,
61
86
  );
87
+ if (newProvider === null) {
88
+ return Response.json(
89
+ { error: "Secure provider storage is unavailable; provider was not created" },
90
+ { status: 503 },
91
+ );
92
+ }
62
93
  return Response.json(redactProvider(newProvider), { status: 201 });
63
94
  },
64
95
  },
@@ -6,6 +6,8 @@ import {
6
6
  listInspectorRecentFailures,
7
7
  listInspectorRuns,
8
8
  } from "../../services/runs";
9
+ import { RECENT_FAILURES_MAX_LIMIT } from "../../proxy/runFailures";
10
+ import { parseBoundedIntegerParameter } from "../../lib/resourceLimits";
9
11
 
10
12
  type JsonBodyResult = { ok: true; value: unknown } | { ok: false };
11
13
 
@@ -19,24 +21,22 @@ async function readJsonBody(request: Request): Promise<JsonBodyResult> {
19
21
  }
20
22
  }
21
23
 
22
- function parsePositiveInt(value: string | null, fallback: number): number {
23
- if (value === null) return fallback;
24
- const parsed = Number(value);
25
- if (!Number.isInteger(parsed) || parsed < 1) return fallback;
26
- return parsed;
27
- }
28
-
29
24
  export const Route = createFileRoute("/api/runs")({
30
25
  server: {
31
26
  handlers: {
32
27
  GET: ({ request }: { request: Request }) => {
33
28
  const url = new URL(request.url);
34
29
  if (url.searchParams.get("failures") === "1") {
35
- const limit = parsePositiveInt(
36
- url.searchParams.get("limit"),
37
- RECENT_FAILURES_DEFAULT_LIMIT,
38
- );
39
- return Response.json(listInspectorRecentFailures(limit));
30
+ const limitResult = parseBoundedIntegerParameter({
31
+ value: url.searchParams.get("limit"),
32
+ parameter: "limit",
33
+ fallback: RECENT_FAILURES_DEFAULT_LIMIT,
34
+ minimum: 1,
35
+ maximum: RECENT_FAILURES_MAX_LIMIT,
36
+ resource: "recent-failures-page-size",
37
+ });
38
+ if (!limitResult.ok) return limitResult.response;
39
+ return Response.json(listInspectorRecentFailures(limitResult.value));
40
40
  }
41
41
 
42
42
  return Response.json(listInspectorRuns());
@@ -1,12 +1,10 @@
1
1
  import { createFileRoute } from "@tanstack/react-router";
2
2
  import { getSessionInfo, getSessionSnapshots, listSessions } from "../../proxy/store";
3
-
4
- function parsePositiveInt(value: string | null): number | undefined {
5
- if (value === null) return undefined;
6
- const parsed = Number(value);
7
- if (!Number.isInteger(parsed) || parsed < 1) return undefined;
8
- return parsed;
9
- }
3
+ import {
4
+ SESSION_INFO_DEFAULT_LATEST_LOG_LIMIT,
5
+ SESSION_INFO_MAX_LATEST_LOG_LIMIT,
6
+ } from "../../proxy/sessionInfo";
7
+ import { parseBoundedIntegerParameter } from "../../lib/resourceLimits";
10
8
 
11
9
  function parseBooleanFlag(value: string | null): boolean {
12
10
  return value === "1" || value === "true";
@@ -22,10 +20,19 @@ export const Route = createFileRoute("/api/sessions")({
22
20
  if (sessionId.length === 0) {
23
21
  return Response.json({ error: "sessionId is required" }, { status: 400 });
24
22
  }
23
+ const limitResult = parseBoundedIntegerParameter({
24
+ value: url.searchParams.get("limit"),
25
+ parameter: "limit",
26
+ fallback: SESSION_INFO_DEFAULT_LATEST_LOG_LIMIT,
27
+ minimum: 1,
28
+ maximum: SESSION_INFO_MAX_LATEST_LOG_LIMIT,
29
+ resource: "session-log-page-size",
30
+ });
31
+ if (!limitResult.ok) return limitResult.response;
25
32
  const info = await getSessionInfo(sessionId, {
26
33
  baseUrl: url.origin,
27
34
  includeHistory: parseBooleanFlag(url.searchParams.get("includeHistory")),
28
- latestLogLimit: parsePositiveInt(url.searchParams.get("limit")),
35
+ latestLogLimit: limitResult.value,
29
36
  });
30
37
  if (info === null) {
31
38
  return Response.json({ error: "Session not found" }, { status: 404 });
@@ -1,12 +1,18 @@
1
1
  import { createFileRoute } from "@tanstack/react-router";
2
2
  import { useEffect, useState, type JSX } from "react";
3
+ import { SafeRouteError } from "../components/errors/SafeErrorBoundary";
3
4
  import { ProxyViewerContainer } from "../components/ProxyViewerContainer";
4
5
 
5
6
  export const Route = createFileRoute("/")({
6
7
  ssr: false,
7
8
  component: ClientOnlyProxyViewerRoute,
9
+ errorComponent: HomeRouteError,
8
10
  });
9
11
 
12
+ function HomeRouteError({ error, reset }: { error: Error; reset: () => void }): JSX.Element {
13
+ return <SafeRouteError error={error} reset={reset} scope="home-route" />;
14
+ }
15
+
10
16
  function ClientOnlyProxyViewerRoute(): JSX.Element {
11
17
  const [mounted, setMounted] = useState(false);
12
18
 
@@ -0,0 +1,13 @@
1
+ import { createFileRoute } from "@tanstack/react-router";
2
+
3
+ export function livenessResponse(): Response {
4
+ return Response.json({ status: "ok" }, { headers: { "cache-control": "no-store" } });
5
+ }
6
+
7
+ export const Route = createFileRoute("/livez")({
8
+ server: {
9
+ handlers: {
10
+ GET: livenessResponse,
11
+ },
12
+ },
13
+ });
@@ -0,0 +1,18 @@
1
+ import { createFileRoute } from "@tanstack/react-router";
2
+ import { getRuntimeReadiness } from "../proxy/runtimeHealth";
3
+
4
+ export async function readinessResponse(): Promise<Response> {
5
+ const readiness = await getRuntimeReadiness();
6
+ return Response.json(readiness, {
7
+ status: readiness.status === "unavailable" ? 503 : 200,
8
+ headers: { "cache-control": "no-store" },
9
+ });
10
+ }
11
+
12
+ export const Route = createFileRoute("/readyz")({
13
+ server: {
14
+ handlers: {
15
+ GET: readinessResponse,
16
+ },
17
+ },
18
+ });
@@ -1,5 +1,6 @@
1
1
  import { createFileRoute } from "@tanstack/react-router";
2
2
  import { useEffect, useState, type JSX } from "react";
3
+ import { SafeRouteError } from "../../components/errors/SafeErrorBoundary";
3
4
  import { ProxyViewerContainer } from "../../components/ProxyViewerContainer";
4
5
  import { decodeSessionIdFromPath, encodeSessionIdForPath } from "../../lib/sessionUrl";
5
6
 
@@ -11,6 +12,7 @@ import { decodeSessionIdFromPath, encodeSessionIdForPath } from "../../lib/sessi
11
12
  export const Route = createFileRoute("/session/$sessionId")({
12
13
  ssr: false,
13
14
  component: SessionViewerRoute,
15
+ errorComponent: SessionRouteError,
14
16
  parseParams: (params) => ({
15
17
  sessionId: decodeSessionIdFromPath(params.sessionId),
16
18
  }),
@@ -19,6 +21,10 @@ export const Route = createFileRoute("/session/$sessionId")({
19
21
  }),
20
22
  });
21
23
 
24
+ function SessionRouteError({ error, reset }: { error: Error; reset: () => void }): JSX.Element {
25
+ return <SafeRouteError error={error} reset={reset} scope="session-route" />;
26
+ }
27
+
22
28
  function SessionViewerRoute(): JSX.Element {
23
29
  const { sessionId } = Route.useParams();
24
30
  return <ClientOnlySessionViewer sessionId={sessionId} />;
@@ -25,6 +25,13 @@
25
25
  --color-input: var(--input);
26
26
  --color-border: var(--border);
27
27
  --color-destructive: var(--destructive);
28
+ --color-warning: var(--warning);
29
+ --color-status-cool: var(--inspector-status-cool);
30
+ --color-status-info: var(--inspector-status-info);
31
+ --color-status-success: var(--inspector-status-success);
32
+ --color-status-watch: var(--inspector-status-watch);
33
+ --color-status-danger: var(--inspector-status-danger);
34
+ --color-status-accent: var(--inspector-status-accent);
28
35
  --color-accent-foreground: var(--accent-foreground);
29
36
  --color-accent: var(--accent);
30
37
  --color-muted-foreground: var(--muted-foreground);
@@ -51,9 +58,11 @@
51
58
  --radius: 0.625rem;
52
59
  --inspector-ui-scale: 1;
53
60
  --inspector-root-font-size: 16px;
54
- --inspector-font-9: 9px;
55
- --inspector-font-10: 10px;
56
- --inspector-font-11: 11px;
61
+ --inspector-minimum-font-size: 0.6875rem;
62
+ --inspector-font-8: var(--inspector-minimum-font-size);
63
+ --inspector-font-9: var(--inspector-minimum-font-size);
64
+ --inspector-font-10: var(--inspector-minimum-font-size);
65
+ --inspector-font-11: var(--inspector-minimum-font-size);
57
66
  --inspector-font-13: 13px;
58
67
  --inspector-surface-low: color-mix(in oklch, var(--foreground) 3.5%, transparent);
59
68
  --inspector-surface-medium: color-mix(in oklch, var(--foreground) 6%, transparent);
@@ -78,6 +87,7 @@
78
87
  --accent: oklch(0.91 0.018 235);
79
88
  --accent-foreground: oklch(0.24 0.035 240);
80
89
  --destructive: oklch(0.5 0.2 27);
90
+ --warning: oklch(0.43 0.12 70);
81
91
  --border: oklch(0.85 0.01 250);
82
92
  --input: oklch(0.78 0.015 250);
83
93
  --ring: oklch(0.48 0.11 230);
@@ -112,6 +122,7 @@
112
122
  --accent: oklch(0.269 0 0);
113
123
  --accent-foreground: oklch(0.985 0 0);
114
124
  --destructive: oklch(0.704 0.191 22.216);
125
+ --warning: oklch(0.76 0.14 78);
115
126
  --border: oklch(1 0 0 / 10%);
116
127
  --input: oklch(1 0 0 / 15%);
117
128
  --ring: oklch(0.556 0 0);
@@ -152,6 +163,7 @@
152
163
  --accent: oklch(0.84 0.045 148);
153
164
  --accent-foreground: oklch(0.25 0.055 151);
154
165
  --destructive: oklch(0.47 0.17 28);
166
+ --warning: oklch(0.4 0.1 70);
155
167
  --border: oklch(0.76 0.028 132);
156
168
  --input: oklch(0.7 0.034 132);
157
169
  --ring: oklch(0.42 0.1 154);
@@ -331,6 +343,10 @@
331
343
  }
332
344
 
333
345
  @layer utilities {
346
+ [class~="text-[8px]"] {
347
+ font-size: var(--inspector-font-8);
348
+ }
349
+
334
350
  [class~="text-[9px]"] {
335
351
  font-size: var(--inspector-font-9);
336
352
  }
@@ -1 +0,0 @@
1
- import{r as h,j as t}from"./index-DzARL2Fi.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-fShBAZjj.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};