@tonyclaw/agent-inspector 2.1.14 → 2.1.16
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/.output/nitro.json +1 -1
- package/.output/public/assets/CompareDrawer-Ccrrcx1j.js +1 -0
- package/.output/public/assets/ProxyViewerContainer-DLqClc9A.js +106 -0
- package/.output/public/assets/ReplayDialog-C7axhr-l.js +1 -0
- package/.output/public/assets/{RequestAnatomy-BNahe83D.js → RequestAnatomy-WOptg8j_.js} +1 -1
- package/.output/public/assets/{ResponseView-DSOnGqi6.js → ResponseView-CSAcxh_M.js} +2 -2
- package/.output/public/assets/{StreamingChunkSequence-BEKTDklB.js → StreamingChunkSequence-DJS5KhPx.js} +1 -1
- package/.output/public/assets/_sessionId-DUSalzKH.js +1 -0
- package/.output/public/assets/index-BPpA21dY.css +1 -0
- package/.output/public/assets/index-Bt0Az2I2.js +1 -0
- package/.output/public/assets/{index-DWOkqdCa.js → index-DMPNh46t.js} +1 -1
- package/.output/public/assets/{json-viewer-C2JpgcW0.js → json-viewer-inX5QSa3.js} +1 -1
- package/.output/public/assets/{main-CSONBwwn.js → main-aCAKYGSD.js} +2 -2
- package/.output/server/_libs/lucide-react.mjs +224 -194
- package/.output/server/{_sessionId-CPAa37n5.mjs → _sessionId-C0fhvQnn.mjs} +2 -2
- package/.output/server/_ssr/{CompareDrawer-ceW5VxMo.mjs → CompareDrawer-CO-Ti5sg.mjs} +36 -15
- package/.output/server/_ssr/{ProxyViewerContainer-CDfEE_w-.mjs → ProxyViewerContainer-N4J7uBCX.mjs} +1153 -494
- package/.output/server/_ssr/{ReplayDialog-V0s_eEbR.mjs → ReplayDialog-J1VxC0In.mjs} +14 -7
- package/.output/server/_ssr/{RequestAnatomy-f1ccwR9d.mjs → RequestAnatomy-DBH-F3rq.mjs} +3 -3
- package/.output/server/_ssr/{ResponseView-BIRrqG4H.mjs → ResponseView-DLFwV7Hd.mjs} +3 -3
- package/.output/server/_ssr/{StreamingChunkSequence-V3JFjCgX.mjs → StreamingChunkSequence-BywmuND0.mjs} +3 -3
- package/.output/server/_ssr/{index-DsykulzS.mjs → index-CStymIc0.mjs} +2 -2
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{json-viewer-Dcnm0Ivf.mjs → json-viewer-DlQu0N1x.mjs} +3 -3
- package/.output/server/_ssr/{router-4bdm6Mt2.mjs → router-CQ4Zxhmr.mjs} +118 -47
- package/.output/server/{_tanstack-start-manifest_v-Xp4CO64V.mjs → _tanstack-start-manifest_v-BHeJBGfo.mjs} +1 -1
- package/.output/server/index.mjs +75 -75
- package/package.json +1 -1
- package/src/components/ProxyViewer.tsx +174 -107
- package/src/components/ProxyViewerContainer.tsx +77 -67
- package/src/components/alerts/AlertsDialog.tsx +2 -1
- package/src/components/clients/ClientLogo.tsx +132 -0
- package/src/components/groups/GroupsDialog.tsx +37 -14
- package/src/components/providers/ProviderCard.tsx +1 -1
- package/src/components/providers/ProviderForm.tsx +18 -18
- package/src/components/providers/ProviderLogo.tsx +6 -1
- package/src/components/providers/ProvidersPanel.tsx +6 -6
- package/src/components/providers/SettingsDialog.tsx +13 -6
- package/src/components/proxy-viewer/AgentTraceSummary.tsx +62 -29
- package/src/components/proxy-viewer/CompareDrawer.tsx +38 -8
- package/src/components/proxy-viewer/ConversationGroup.tsx +43 -32
- package/src/components/proxy-viewer/ConversationGroupList.tsx +452 -89
- package/src/components/proxy-viewer/ConversationHeader.tsx +65 -61
- package/src/components/proxy-viewer/LogEntry.tsx +31 -18
- package/src/components/proxy-viewer/LogEntryHeader.tsx +42 -49
- package/src/components/proxy-viewer/ProviderLogoStack.tsx +60 -0
- package/src/components/proxy-viewer/ReplayDialog.tsx +8 -2
- package/src/components/proxy-viewer/RequestToolsPanel.tsx +9 -9
- package/src/components/proxy-viewer/ThreadConnector.tsx +22 -11
- package/src/components/proxy-viewer/TurnGroup.tsx +30 -36
- package/src/components/proxy-viewer/TurnGroupList.tsx +3 -0
- package/src/components/proxy-viewer/viewerState.ts +5 -6
- package/src/components/ui/icon-trigger.ts +2 -0
- package/src/components/ui/transient-toast.tsx +104 -0
- package/src/lib/sessionInfoContract.ts +5 -0
- package/src/lib/stopReason.ts +48 -16
- package/src/mcp/server.ts +71 -27
- package/src/mcp/toolHandlers.ts +23 -4
- package/src/proxy/formats/openai/alibabaProvider.ts +0 -4
- package/src/proxy/sessionInfo.ts +36 -3
- package/src/proxy/sessionSupervisor.ts +20 -1
- package/src/proxy/store.ts +1 -1
- package/src/routes/api/providers.$providerId.test.log.ts +8 -4
- package/styles/globals.css +180 -180
- package/.output/public/assets/CompareDrawer-DjgjIFx7.js +0 -1
- package/.output/public/assets/ProxyViewerContainer-CWUQZLYy.js +0 -106
- package/.output/public/assets/ReplayDialog-CU0Tbb2c.js +0 -1
- package/.output/public/assets/_sessionId-Cif8JZdn.js +0 -1
- package/.output/public/assets/index-D_WfwzUi.js +0 -1
- package/.output/public/assets/index-DtLuQrs0.css +0 -1
package/src/proxy/sessionInfo.ts
CHANGED
|
@@ -65,6 +65,9 @@ export function buildSessionLogSummary(log: CapturedLog): SessionLogSummary {
|
|
|
65
65
|
cacheRead: log.cacheReadInputTokens,
|
|
66
66
|
},
|
|
67
67
|
sessionId: normalizeString(log.sessionId),
|
|
68
|
+
userAgent: normalizeString(log.userAgent),
|
|
69
|
+
clientPid: log.clientPid ?? null,
|
|
70
|
+
clientProjectFolder: normalizeString(log.clientProjectFolder),
|
|
68
71
|
};
|
|
69
72
|
}
|
|
70
73
|
|
|
@@ -118,6 +121,30 @@ function collectSortedValues(values: readonly (string | null)[]): string[] {
|
|
|
118
121
|
return [...set].sort();
|
|
119
122
|
}
|
|
120
123
|
|
|
124
|
+
function firstSummaryUserAgent(summaries: readonly SessionLogSummary[]): string | null {
|
|
125
|
+
for (const summary of summaries) {
|
|
126
|
+
const value = normalizeString(summary.userAgent);
|
|
127
|
+
if (value !== null) return value;
|
|
128
|
+
}
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function firstSummaryClientPid(summaries: readonly SessionLogSummary[]): number | null {
|
|
133
|
+
for (const summary of summaries) {
|
|
134
|
+
const value = summary.clientPid;
|
|
135
|
+
if (value !== null && value !== undefined) return value;
|
|
136
|
+
}
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function firstSummaryProjectFolder(summaries: readonly SessionLogSummary[]): string | null {
|
|
141
|
+
for (const summary of summaries) {
|
|
142
|
+
const value = normalizeString(summary.clientProjectFolder);
|
|
143
|
+
if (value !== null) return value;
|
|
144
|
+
}
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
|
|
121
148
|
function countCompletedLogs(summaries: readonly SessionLogSummary[]): number {
|
|
122
149
|
let count = 0;
|
|
123
150
|
for (const summary of summaries) {
|
|
@@ -180,6 +207,10 @@ export function buildSessionInfo(input: BuildSessionInfoInput): SessionInfo {
|
|
|
180
207
|
const inspectorPath = getSessionPath(input.sessionId);
|
|
181
208
|
const apiPath = buildApiPath(input.sessionId);
|
|
182
209
|
const compactLogsPath = buildCompactLogsPath(input.sessionId);
|
|
210
|
+
const latestLogs = summaries.slice(0, latestLogLimit).map((summary, index) => ({
|
|
211
|
+
...summary,
|
|
212
|
+
sessionLogNumber: Math.max(1, requestCount - index),
|
|
213
|
+
}));
|
|
183
214
|
|
|
184
215
|
return {
|
|
185
216
|
id: input.sessionId,
|
|
@@ -211,8 +242,10 @@ export function buildSessionInfo(input: BuildSessionInfoInput): SessionInfo {
|
|
|
211
242
|
tokenUsage,
|
|
212
243
|
lastLogId: input.snapshot?.lastLogId ?? latestLog?.id ?? null,
|
|
213
244
|
lastModel: normalizeString(input.snapshot?.lastModel) ?? latestLog?.model ?? null,
|
|
214
|
-
|
|
215
|
-
|
|
245
|
+
clientUserAgent: firstSummaryUserAgent(summaries),
|
|
246
|
+
clientPid: input.snapshot?.clientPid ?? firstSummaryClientPid(summaries),
|
|
247
|
+
clientProjectFolder:
|
|
248
|
+
normalizeString(input.snapshot?.clientProjectFolder) ?? firstSummaryProjectFolder(summaries),
|
|
216
249
|
inspectorPath,
|
|
217
250
|
inspectorUrl: buildAbsoluteUrl(input.baseUrl, inspectorPath),
|
|
218
251
|
apiPath,
|
|
@@ -220,6 +253,6 @@ export function buildSessionInfo(input: BuildSessionInfoInput): SessionInfo {
|
|
|
220
253
|
compactLogsPath,
|
|
221
254
|
compactLogsUrl: buildAbsoluteUrl(input.baseUrl, compactLogsPath),
|
|
222
255
|
latestLogLimit,
|
|
223
|
-
latestLogs
|
|
256
|
+
latestLogs,
|
|
224
257
|
};
|
|
225
258
|
}
|
|
@@ -60,6 +60,18 @@ function normalizeExplicitSessionId(sessionId: string | null | undefined): strin
|
|
|
60
60
|
return trimmed.length > 0 ? trimmed : null;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
export function buildProviderTestSessionId(providerId: string): string {
|
|
64
|
+
const normalizedProviderId = normalizeExplicitSessionId(providerId);
|
|
65
|
+
if (normalizedProviderId === null) return PROVIDER_TEST_SESSION_ID;
|
|
66
|
+
return `${PROVIDER_TEST_SESSION_ID}:${normalizedProviderId}`;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function isProviderTestSessionId(sessionId: string): boolean {
|
|
70
|
+
return (
|
|
71
|
+
sessionId === PROVIDER_TEST_SESSION_ID || sessionId.startsWith(`${PROVIDER_TEST_SESSION_ID}:`)
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
63
75
|
function buildClientSessionId(clientInfo: SessionClientInfo): SessionIdentity {
|
|
64
76
|
const projectFolder = normalizeExplicitSessionId(clientInfo.projectFolder);
|
|
65
77
|
|
|
@@ -88,11 +100,18 @@ export function resolveSessionIdentity(input: {
|
|
|
88
100
|
clientInfo?: SessionClientInfo;
|
|
89
101
|
isTest?: boolean;
|
|
90
102
|
}): SessionIdentity {
|
|
103
|
+
const explicit = normalizeExplicitSessionId(input.explicitSessionId);
|
|
104
|
+
|
|
91
105
|
if (input.isTest === true) {
|
|
106
|
+
if (explicit !== null) {
|
|
107
|
+
return {
|
|
108
|
+
id: explicit,
|
|
109
|
+
source: isProviderTestSessionId(explicit) ? "provider-test" : "explicit",
|
|
110
|
+
};
|
|
111
|
+
}
|
|
92
112
|
return { id: PROVIDER_TEST_SESSION_ID, source: "provider-test" };
|
|
93
113
|
}
|
|
94
114
|
|
|
95
|
-
const explicit = normalizeExplicitSessionId(input.explicitSessionId);
|
|
96
115
|
if (explicit !== null) {
|
|
97
116
|
return { id: explicit, source: "explicit" };
|
|
98
117
|
}
|
package/src/proxy/store.ts
CHANGED
|
@@ -322,7 +322,7 @@ function prepareLogForList(log: CapturedLog, includeBodies: boolean): CapturedLo
|
|
|
322
322
|
|
|
323
323
|
/**
|
|
324
324
|
* Add a test log entry to the in-memory store and persistent log file.
|
|
325
|
-
* This is used by the provider test endpoint to seed
|
|
325
|
+
* This is used by the provider test endpoint to seed provider-test sessions.
|
|
326
326
|
*/
|
|
327
327
|
export async function addTestLogEntry(entry: Omit<CapturedLog, "id">): Promise<CapturedLog> {
|
|
328
328
|
const id = await getNextLogId();
|
|
@@ -2,6 +2,7 @@ import { createFileRoute } from "@tanstack/react-router";
|
|
|
2
2
|
import { getProvider, getModelUsageName } from "../../proxy/providers";
|
|
3
3
|
import { addTestLogEntry } from "../../proxy/store";
|
|
4
4
|
import { getConfig } from "../../proxy/config";
|
|
5
|
+
import { buildProviderTestSessionId } from "../../proxy/sessionSupervisor";
|
|
5
6
|
import { buildProviderTestRequestBody } from "../../lib/providerTestPrompt";
|
|
6
7
|
import {
|
|
7
8
|
ProviderTestResultsSchema,
|
|
@@ -52,6 +53,7 @@ function getResultTokensPerSecond(result: TestResult): number | null {
|
|
|
52
53
|
async function logModelResults(
|
|
53
54
|
displayName: string,
|
|
54
55
|
providerName: string,
|
|
56
|
+
providerSessionId: string,
|
|
55
57
|
anthropicUrl: string | undefined,
|
|
56
58
|
openaiUrl: string | undefined,
|
|
57
59
|
modelResults: {
|
|
@@ -76,7 +78,7 @@ async function logModelResults(
|
|
|
76
78
|
method: "POST",
|
|
77
79
|
path: "/v1/messages",
|
|
78
80
|
model: nonStreamingResult.model ?? displayName,
|
|
79
|
-
sessionId:
|
|
81
|
+
sessionId: providerSessionId,
|
|
80
82
|
rawRequestBody: requestBody,
|
|
81
83
|
responseStatus: getResultResponseStatus(nonStreamingResult),
|
|
82
84
|
responseText: getResultResponseText(nonStreamingResult),
|
|
@@ -106,7 +108,7 @@ async function logModelResults(
|
|
|
106
108
|
method: "POST",
|
|
107
109
|
path: "/v1/messages",
|
|
108
110
|
model: streamingResult.model ?? displayName,
|
|
109
|
-
sessionId:
|
|
111
|
+
sessionId: providerSessionId,
|
|
110
112
|
rawRequestBody: streamingRequestBody,
|
|
111
113
|
responseStatus: getResultResponseStatus(streamingResult),
|
|
112
114
|
responseText: getResultResponseText(streamingResult),
|
|
@@ -144,7 +146,7 @@ async function logModelResults(
|
|
|
144
146
|
method: "POST",
|
|
145
147
|
path: "/v1/chat/completions",
|
|
146
148
|
model: nonStreamingResult.model ?? displayName,
|
|
147
|
-
sessionId:
|
|
149
|
+
sessionId: providerSessionId,
|
|
148
150
|
rawRequestBody: requestBody,
|
|
149
151
|
responseStatus: getResultResponseStatus(nonStreamingResult),
|
|
150
152
|
responseText: getResultResponseText(nonStreamingResult),
|
|
@@ -174,7 +176,7 @@ async function logModelResults(
|
|
|
174
176
|
method: "POST",
|
|
175
177
|
path: "/v1/chat/completions",
|
|
176
178
|
model: streamingResult.model ?? displayName,
|
|
177
|
-
sessionId:
|
|
179
|
+
sessionId: providerSessionId,
|
|
178
180
|
rawRequestBody: streamingRequestBody,
|
|
179
181
|
responseStatus: getResultResponseStatus(streamingResult),
|
|
180
182
|
responseText: getResultResponseText(streamingResult),
|
|
@@ -224,6 +226,7 @@ export const Route = createFileRoute("/api/providers/$providerId/test/log")({
|
|
|
224
226
|
}
|
|
225
227
|
|
|
226
228
|
const results = parsed.data;
|
|
229
|
+
const providerSessionId = buildProviderTestSessionId(params.providerId);
|
|
227
230
|
const captureFullDetails = getConfig().captureMode === "full";
|
|
228
231
|
const anthropicUrl =
|
|
229
232
|
provider.anthropicBaseUrl !== undefined && provider.anthropicBaseUrl.length > 0
|
|
@@ -241,6 +244,7 @@ export const Route = createFileRoute("/api/providers/$providerId/test/log")({
|
|
|
241
244
|
logModelResults(
|
|
242
245
|
modelName,
|
|
243
246
|
provider.name,
|
|
247
|
+
providerSessionId,
|
|
244
248
|
anthropicUrl,
|
|
245
249
|
openaiUrl,
|
|
246
250
|
modelResult,
|
package/styles/globals.css
CHANGED
|
@@ -1,183 +1,183 @@
|
|
|
1
|
-
@import "tailwindcss";
|
|
2
|
-
@import "tw-animate-css";
|
|
3
|
-
@plugin "@tailwindcss/typography";
|
|
4
|
-
|
|
5
|
-
@custom-variant dark (&:is(.dark *));
|
|
6
|
-
|
|
7
|
-
@theme inline {
|
|
8
|
-
--color-background: var(--background);
|
|
9
|
-
--color-foreground: var(--foreground);
|
|
10
|
-
--color-sidebar-ring: var(--sidebar-ring);
|
|
11
|
-
--color-sidebar-border: var(--sidebar-border);
|
|
12
|
-
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
13
|
-
--color-sidebar-accent: var(--sidebar-accent);
|
|
14
|
-
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
15
|
-
--color-sidebar-primary: var(--sidebar-primary);
|
|
16
|
-
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
17
|
-
--color-sidebar: var(--sidebar);
|
|
18
|
-
--color-chart-5: var(--chart-5);
|
|
19
|
-
--color-chart-4: var(--chart-4);
|
|
20
|
-
--color-chart-3: var(--chart-3);
|
|
21
|
-
--color-chart-2: var(--chart-2);
|
|
22
|
-
--color-chart-1: var(--chart-1);
|
|
23
|
-
--color-ring: var(--ring);
|
|
24
|
-
--color-input: var(--input);
|
|
25
|
-
--color-border: var(--border);
|
|
26
|
-
--color-destructive: var(--destructive);
|
|
27
|
-
--color-accent-foreground: var(--accent-foreground);
|
|
28
|
-
--color-accent: var(--accent);
|
|
29
|
-
--color-muted-foreground: var(--muted-foreground);
|
|
30
|
-
--color-muted: var(--muted);
|
|
31
|
-
--color-secondary-foreground: var(--secondary-foreground);
|
|
32
|
-
--color-secondary: var(--secondary);
|
|
33
|
-
--color-primary-foreground: var(--primary-foreground);
|
|
34
|
-
--color-primary: var(--primary);
|
|
35
|
-
--color-popover-foreground: var(--popover-foreground);
|
|
36
|
-
--color-popover: var(--popover);
|
|
37
|
-
--color-card-foreground: var(--card-foreground);
|
|
38
|
-
--color-card: var(--card);
|
|
39
|
-
--radius-sm: calc(var(--radius) - 4px);
|
|
40
|
-
--radius-md: calc(var(--radius) - 2px);
|
|
41
|
-
--radius-lg: var(--radius);
|
|
42
|
-
--radius-xl: calc(var(--radius) + 4px);
|
|
43
|
-
--animate-crab-crawl: crab-crawl-down 0.6s ease-in-out infinite;
|
|
44
|
-
--animate-crab-appear: crab-appear 300ms ease-out;
|
|
45
|
-
--animate-crab-settle: crab-settle 400ms ease-in-out;
|
|
46
|
-
--animate-crab-piano-pop: crab-piano-pop 400ms cubic-bezier(0.34, 1.56, 0.64, 1) backwards;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
:root {
|
|
50
|
-
--radius: 0.625rem;
|
|
51
|
-
--background: oklch(1 0 0);
|
|
52
|
-
--foreground: oklch(0.145 0 0);
|
|
53
|
-
--card: oklch(1 0 0);
|
|
54
|
-
--card-foreground: oklch(0.145 0 0);
|
|
55
|
-
--popover: oklch(1 0 0);
|
|
56
|
-
--popover-foreground: oklch(0.145 0 0);
|
|
57
|
-
--primary: oklch(0.205 0 0);
|
|
58
|
-
--primary-foreground: oklch(0.985 0 0);
|
|
59
|
-
--secondary: oklch(0.97 0 0);
|
|
60
|
-
--secondary-foreground: oklch(0.205 0 0);
|
|
61
|
-
--muted: oklch(0.97 0 0);
|
|
62
|
-
--muted-foreground: oklch(0.556 0 0);
|
|
63
|
-
--accent: oklch(0.97 0 0);
|
|
64
|
-
--accent-foreground: oklch(0.205 0 0);
|
|
65
|
-
--destructive: oklch(0.577 0.245 27.325);
|
|
66
|
-
--border: oklch(0.922 0 0);
|
|
67
|
-
--input: oklch(0.922 0 0);
|
|
68
|
-
--ring: oklch(0.708 0 0);
|
|
69
|
-
--chart-1: oklch(0.646 0.222 41.116);
|
|
70
|
-
--chart-2: oklch(0.6 0.118 184.704);
|
|
71
|
-
--chart-3: oklch(0.398 0.07 227.392);
|
|
72
|
-
--chart-4: oklch(0.828 0.189 84.429);
|
|
73
|
-
--chart-5: oklch(0.769 0.188 70.08);
|
|
74
|
-
--sidebar: oklch(0.985 0 0);
|
|
75
|
-
--sidebar-foreground: oklch(0.145 0 0);
|
|
76
|
-
--sidebar-primary: oklch(0.205 0 0);
|
|
77
|
-
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
78
|
-
--sidebar-accent: oklch(0.97 0 0);
|
|
79
|
-
--sidebar-accent-foreground: oklch(0.205 0 0);
|
|
80
|
-
--sidebar-border: oklch(0.922 0 0);
|
|
81
|
-
--sidebar-ring: oklch(0.708 0 0);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
.dark {
|
|
85
|
-
--background: oklch(0.145 0 0);
|
|
86
|
-
--foreground: oklch(0.985 0 0);
|
|
87
|
-
--card: oklch(0.205 0 0);
|
|
88
|
-
--card-foreground: oklch(0.985 0 0);
|
|
89
|
-
--popover: oklch(0.205 0 0);
|
|
90
|
-
--popover-foreground: oklch(0.985 0 0);
|
|
91
|
-
--primary: oklch(0.922 0 0);
|
|
92
|
-
--primary-foreground: oklch(0.205 0 0);
|
|
93
|
-
--secondary: oklch(0.269 0 0);
|
|
94
|
-
--secondary-foreground: oklch(0.985 0 0);
|
|
95
|
-
--muted: oklch(0.269 0 0);
|
|
96
|
-
--muted-foreground: oklch(0.708 0 0);
|
|
97
|
-
--accent: oklch(0.269 0 0);
|
|
98
|
-
--accent-foreground: oklch(0.985 0 0);
|
|
99
|
-
--destructive: oklch(0.704 0.191 22.216);
|
|
100
|
-
--border: oklch(1 0 0 / 10%);
|
|
101
|
-
--input: oklch(1 0 0 / 15%);
|
|
102
|
-
--ring: oklch(0.556 0 0);
|
|
103
|
-
--chart-1: oklch(0.488 0.243 264.376);
|
|
104
|
-
--chart-2: oklch(0.696 0.17 162.48);
|
|
105
|
-
--chart-3: oklch(0.769 0.188 70.08);
|
|
106
|
-
--chart-4: oklch(0.627 0.265 303.9);
|
|
107
|
-
--chart-5: oklch(0.645 0.246 16.439);
|
|
108
|
-
--sidebar: oklch(0.205 0 0);
|
|
109
|
-
--sidebar-foreground: oklch(0.985 0 0);
|
|
110
|
-
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
111
|
-
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
112
|
-
--sidebar-accent: oklch(0.269 0 0);
|
|
113
|
-
--sidebar-accent-foreground: oklch(0.985 0 0);
|
|
114
|
-
--sidebar-border: oklch(1 0 0 / 10%);
|
|
115
|
-
--sidebar-ring: oklch(0.556 0 0);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
@keyframes crab-crawl-down {
|
|
119
|
-
0%, 100% {
|
|
120
|
-
transform: translateY(0px);
|
|
121
|
-
}
|
|
122
|
-
25% {
|
|
123
|
-
transform: translateY(2px);
|
|
124
|
-
}
|
|
125
|
-
75% {
|
|
126
|
-
transform: translateY(-1px);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
@keyframes crab-appear {
|
|
131
|
-
0% {
|
|
132
|
-
transform: scale(0.5);
|
|
133
|
-
opacity: 0;
|
|
134
|
-
}
|
|
135
|
-
100% {
|
|
136
|
-
transform: scale(1);
|
|
137
|
-
opacity: 1;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
@keyframes crab-settle {
|
|
142
|
-
0% {
|
|
143
|
-
transform: scale(1);
|
|
144
|
-
}
|
|
145
|
-
50% {
|
|
146
|
-
transform: scale(1.15);
|
|
147
|
-
}
|
|
148
|
-
100% {
|
|
149
|
-
transform: scale(1);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
@keyframes crab-piano-pop {
|
|
154
|
-
0% {
|
|
155
|
-
transform: scale(0) translateY(0);
|
|
156
|
-
opacity: 0;
|
|
157
|
-
}
|
|
158
|
-
60% {
|
|
159
|
-
transform: scale(1.3) translateY(-4px);
|
|
160
|
-
opacity: 1;
|
|
161
|
-
}
|
|
162
|
-
100% {
|
|
163
|
-
transform: scale(1) translateY(0);
|
|
164
|
-
opacity: 1;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
@media (prefers-reduced-motion: reduce) {
|
|
169
|
-
.animate-crab-piano-pop {
|
|
170
|
-
animation: none !important;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
[data-deep-link-highlight="true"] {
|
|
175
|
-
background: color-mix(in oklch, var(--chart-2) 18%, transparent);
|
|
176
|
-
box-shadow:
|
|
177
|
-
inset 0 0 0 1px color-mix(in oklch, var(--chart-2) 65%, transparent),
|
|
178
|
-
0 0 0 3px color-mix(in oklch, var(--chart-2) 20%, transparent);
|
|
179
|
-
}
|
|
180
|
-
|
|
1
|
+
@import "tailwindcss";
|
|
2
|
+
@import "tw-animate-css";
|
|
3
|
+
@plugin "@tailwindcss/typography";
|
|
4
|
+
|
|
5
|
+
@custom-variant dark (&:is(.dark *));
|
|
6
|
+
|
|
7
|
+
@theme inline {
|
|
8
|
+
--color-background: var(--background);
|
|
9
|
+
--color-foreground: var(--foreground);
|
|
10
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
11
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
12
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
13
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
14
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
15
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
16
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
17
|
+
--color-sidebar: var(--sidebar);
|
|
18
|
+
--color-chart-5: var(--chart-5);
|
|
19
|
+
--color-chart-4: var(--chart-4);
|
|
20
|
+
--color-chart-3: var(--chart-3);
|
|
21
|
+
--color-chart-2: var(--chart-2);
|
|
22
|
+
--color-chart-1: var(--chart-1);
|
|
23
|
+
--color-ring: var(--ring);
|
|
24
|
+
--color-input: var(--input);
|
|
25
|
+
--color-border: var(--border);
|
|
26
|
+
--color-destructive: var(--destructive);
|
|
27
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
28
|
+
--color-accent: var(--accent);
|
|
29
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
30
|
+
--color-muted: var(--muted);
|
|
31
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
32
|
+
--color-secondary: var(--secondary);
|
|
33
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
34
|
+
--color-primary: var(--primary);
|
|
35
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
36
|
+
--color-popover: var(--popover);
|
|
37
|
+
--color-card-foreground: var(--card-foreground);
|
|
38
|
+
--color-card: var(--card);
|
|
39
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
40
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
41
|
+
--radius-lg: var(--radius);
|
|
42
|
+
--radius-xl: calc(var(--radius) + 4px);
|
|
43
|
+
--animate-crab-crawl: crab-crawl-down 0.6s ease-in-out infinite;
|
|
44
|
+
--animate-crab-appear: crab-appear 300ms ease-out;
|
|
45
|
+
--animate-crab-settle: crab-settle 400ms ease-in-out;
|
|
46
|
+
--animate-crab-piano-pop: crab-piano-pop 400ms cubic-bezier(0.34, 1.56, 0.64, 1) backwards;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
:root {
|
|
50
|
+
--radius: 0.625rem;
|
|
51
|
+
--background: oklch(1 0 0);
|
|
52
|
+
--foreground: oklch(0.145 0 0);
|
|
53
|
+
--card: oklch(1 0 0);
|
|
54
|
+
--card-foreground: oklch(0.145 0 0);
|
|
55
|
+
--popover: oklch(1 0 0);
|
|
56
|
+
--popover-foreground: oklch(0.145 0 0);
|
|
57
|
+
--primary: oklch(0.205 0 0);
|
|
58
|
+
--primary-foreground: oklch(0.985 0 0);
|
|
59
|
+
--secondary: oklch(0.97 0 0);
|
|
60
|
+
--secondary-foreground: oklch(0.205 0 0);
|
|
61
|
+
--muted: oklch(0.97 0 0);
|
|
62
|
+
--muted-foreground: oklch(0.556 0 0);
|
|
63
|
+
--accent: oklch(0.97 0 0);
|
|
64
|
+
--accent-foreground: oklch(0.205 0 0);
|
|
65
|
+
--destructive: oklch(0.577 0.245 27.325);
|
|
66
|
+
--border: oklch(0.922 0 0);
|
|
67
|
+
--input: oklch(0.922 0 0);
|
|
68
|
+
--ring: oklch(0.708 0 0);
|
|
69
|
+
--chart-1: oklch(0.646 0.222 41.116);
|
|
70
|
+
--chart-2: oklch(0.6 0.118 184.704);
|
|
71
|
+
--chart-3: oklch(0.398 0.07 227.392);
|
|
72
|
+
--chart-4: oklch(0.828 0.189 84.429);
|
|
73
|
+
--chart-5: oklch(0.769 0.188 70.08);
|
|
74
|
+
--sidebar: oklch(0.985 0 0);
|
|
75
|
+
--sidebar-foreground: oklch(0.145 0 0);
|
|
76
|
+
--sidebar-primary: oklch(0.205 0 0);
|
|
77
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
78
|
+
--sidebar-accent: oklch(0.97 0 0);
|
|
79
|
+
--sidebar-accent-foreground: oklch(0.205 0 0);
|
|
80
|
+
--sidebar-border: oklch(0.922 0 0);
|
|
81
|
+
--sidebar-ring: oklch(0.708 0 0);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.dark {
|
|
85
|
+
--background: oklch(0.145 0 0);
|
|
86
|
+
--foreground: oklch(0.985 0 0);
|
|
87
|
+
--card: oklch(0.205 0 0);
|
|
88
|
+
--card-foreground: oklch(0.985 0 0);
|
|
89
|
+
--popover: oklch(0.205 0 0);
|
|
90
|
+
--popover-foreground: oklch(0.985 0 0);
|
|
91
|
+
--primary: oklch(0.922 0 0);
|
|
92
|
+
--primary-foreground: oklch(0.205 0 0);
|
|
93
|
+
--secondary: oklch(0.269 0 0);
|
|
94
|
+
--secondary-foreground: oklch(0.985 0 0);
|
|
95
|
+
--muted: oklch(0.269 0 0);
|
|
96
|
+
--muted-foreground: oklch(0.708 0 0);
|
|
97
|
+
--accent: oklch(0.269 0 0);
|
|
98
|
+
--accent-foreground: oklch(0.985 0 0);
|
|
99
|
+
--destructive: oklch(0.704 0.191 22.216);
|
|
100
|
+
--border: oklch(1 0 0 / 10%);
|
|
101
|
+
--input: oklch(1 0 0 / 15%);
|
|
102
|
+
--ring: oklch(0.556 0 0);
|
|
103
|
+
--chart-1: oklch(0.488 0.243 264.376);
|
|
104
|
+
--chart-2: oklch(0.696 0.17 162.48);
|
|
105
|
+
--chart-3: oklch(0.769 0.188 70.08);
|
|
106
|
+
--chart-4: oklch(0.627 0.265 303.9);
|
|
107
|
+
--chart-5: oklch(0.645 0.246 16.439);
|
|
108
|
+
--sidebar: oklch(0.205 0 0);
|
|
109
|
+
--sidebar-foreground: oklch(0.985 0 0);
|
|
110
|
+
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
111
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
112
|
+
--sidebar-accent: oklch(0.269 0 0);
|
|
113
|
+
--sidebar-accent-foreground: oklch(0.985 0 0);
|
|
114
|
+
--sidebar-border: oklch(1 0 0 / 10%);
|
|
115
|
+
--sidebar-ring: oklch(0.556 0 0);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
@keyframes crab-crawl-down {
|
|
119
|
+
0%, 100% {
|
|
120
|
+
transform: translateY(0px);
|
|
121
|
+
}
|
|
122
|
+
25% {
|
|
123
|
+
transform: translateY(2px);
|
|
124
|
+
}
|
|
125
|
+
75% {
|
|
126
|
+
transform: translateY(-1px);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
@keyframes crab-appear {
|
|
131
|
+
0% {
|
|
132
|
+
transform: scale(0.5);
|
|
133
|
+
opacity: 0;
|
|
134
|
+
}
|
|
135
|
+
100% {
|
|
136
|
+
transform: scale(1);
|
|
137
|
+
opacity: 1;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
@keyframes crab-settle {
|
|
142
|
+
0% {
|
|
143
|
+
transform: scale(1);
|
|
144
|
+
}
|
|
145
|
+
50% {
|
|
146
|
+
transform: scale(1.15);
|
|
147
|
+
}
|
|
148
|
+
100% {
|
|
149
|
+
transform: scale(1);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
@keyframes crab-piano-pop {
|
|
154
|
+
0% {
|
|
155
|
+
transform: scale(0) translateY(0);
|
|
156
|
+
opacity: 0;
|
|
157
|
+
}
|
|
158
|
+
60% {
|
|
159
|
+
transform: scale(1.3) translateY(-4px);
|
|
160
|
+
opacity: 1;
|
|
161
|
+
}
|
|
162
|
+
100% {
|
|
163
|
+
transform: scale(1) translateY(0);
|
|
164
|
+
opacity: 1;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
@media (prefers-reduced-motion: reduce) {
|
|
169
|
+
.animate-crab-piano-pop {
|
|
170
|
+
animation: none !important;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
[data-deep-link-highlight="true"] {
|
|
175
|
+
background: color-mix(in oklch, var(--chart-2) 18%, transparent);
|
|
176
|
+
box-shadow:
|
|
177
|
+
inset 0 0 0 1px color-mix(in oklch, var(--chart-2) 65%, transparent),
|
|
178
|
+
0 0 0 3px color-mix(in oklch, var(--chart-2) 20%, transparent);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
181
|
@layer base {
|
|
182
182
|
* {
|
|
183
183
|
@apply border-border outline-ring/50;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as h,j as t}from"./main-CSONBwwn.js";import{c as X,g as I,r as P,a as q,X as Y,b as m,B as Z,f as $,R as ee,C as te,M as J,d as V,e as _,h as M,i as re,j as ne,k as se,L as ae}from"./ProxyViewerContainer-CWUQZLYy.js";const oe=[["line",{x1:"5",x2:"19",y1:"9",y2:"9",key:"1nwqeh"}],["line",{x1:"5",x2:"19",y1:"15",y2:"15",key:"g8yjpy"}]],de=X("equal",oe),ie="";function j(e){if(e.length===0)return ie;let r="";for(let n=0;n<e.length;n++){const s=e[n];s!==void 0&&(typeof s=="number"?r+=`[${s}]`:n===0?r+=s:r+=`.${s}`)}return r}function le(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(le(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 ce(e,r){const n=[];return R([],e,r,n),n}function R(e,r,n,s){const d=j(e);if(S(r,n)){s.push({kind:"equal",path:d,value:r});return}if(r.kind!==n.kind){s.push({kind:"changed",path:d,left:r,right:n});return}if(r.kind==="primitive"&&n.kind==="primitive"){s.push({kind:"changed",path:d,left:r,right:n});return}if(r.kind==="object"&&n.kind==="object"){const o=Object.keys(r.value),a=Object.keys(n.value),x=new Set(a);for(const i of o){const f=r.value[i];if(f!==void 0)if(!x.has(i))s.push({kind:"removed",path:j([...e,i]),value:f});else{const p=n.value[i];if(p===void 0)continue;R([...e,i],f,p,s)}}for(const i of a){if(o.includes(i))continue;const f=n.value[i];f!==void 0&&s.push({kind:"added",path:j([...e,i]),value:f})}return}if(r.kind==="array"&&n.kind==="array"){const o=Math.min(r.value.length,n.value.length);for(let a=0;a<o;a++){const x=r.value[a],i=n.value[a];x===void 0||i===void 0||R([...e,a],x,i,s)}for(let a=o;a<n.value.length;a++){const x=n.value[a];x!==void 0&&s.push({kind:"added",path:j([...e,a]),value:x})}for(let a=o;a<r.value.length;a++){const x=r.value[a];x!==void 0&&s.push({kind:"removed",path:j([...e,a]),value:x})}}}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 s=e.value[n],d=r.value[n];if(s===void 0||d===void 0||!S(s,d))return!1}return!0}if(e.kind==="object"&&r.kind==="object"){const n=Object.keys(e.value),s=Object.keys(r.value);if(n.length!==s.length)return!1;for(const d of n){const o=e.value[d],a=r.value[d];if(o===void 0||a===void 0||!S(o,a))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,s]of Object.entries(e.value))r[n]=E(s);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(ae,{text:e,defaultExpandDepth:r})})}function L(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 K(e){return e.kind==="equal"&&(e.value.kind==="object"||e.value.kind==="array")}function ue(e){const r=[];let n=0;for(;n<e.length;){const s=e[n];if(s!==void 0&&K(s)){const d=L(s.path);let o=n+1;for(;o<e.length;){const a=e[o];if(a===void 0||!K(a)||L(a.path)!==d)break;o++}if(o-n>1){const a=[];for(let x=n;x<o;x++){const i=e[x];i!==void 0&&i.kind==="equal"&&a.push(i)}r.push({kind:"equal-run",ops:a}),n=o;continue}}s!==void 0&&r.push({kind:"single",op:s}),n++}return r}const B={added:{icon:V,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:J,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:_,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:de,accent:"text-muted-foreground/70",bg:"bg-muted/20 hover:bg-muted/30",border:"border-l-muted-foreground/20",label:"EQUAL"}};function xe({ops:e,expanded:r,onToggle:n}){const s=e[0],d=e[e.length-1];if(s===void 0||d===void 0)return t.jsx("div",{className:"text-muted-foreground/40 text-xs",children:"—"});const o=s.path,a=d.path,x=e.length===1?o:`${o} … ${a}`,i=s.value.kind==="array"?`${e.length} equal arrays`:s.value.kind==="object"?`${e.length} equal objects`:"equal",f=B.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(M,{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:`${o} … ${a}`,children:x}),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:["(",i,")"]})]}),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 me({op:e,idx:r,copiedPath:n,onCopyPath:s,expanded:d,onToggle:o}){const a=B[e.kind],x=a.icon,i=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",a.border,a.bg),children:[t.jsxs("button",{type:"button",onClick:o,disabled:!i,className:m("w-full flex items-center gap-2 text-xs text-left rounded-sm",i?"cursor-pointer":"cursor-default"),"aria-expanded":i?d:void 0,"aria-label":i?d?`Collapse ${e.path||"root"}`:`Expand ${e.path||"root"}`:void 0,children:[i?t.jsx(M,{className:m("size-3 shrink-0 transition-transform",a.accent,d&&"rotate-90")}):t.jsx("span",{className:"size-3 shrink-0","aria-hidden":"true"}),t.jsx(x,{className:m("size-3.5 shrink-0",a.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",a.accent,e.kind==="equal"?"bg-muted/40":"bg-background/60"),children:a.label}),e.path!==""&&t.jsx("span",{role:"button",tabIndex:0,onClick:b=>{b.stopPropagation(),s(e.path)},onKeyDown:b=>{(b.key==="Enter"||b.key===" ")&&(b.stopPropagation(),b.preventDefault(),s(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(re,{className:"size-3"}):t.jsx(ne,{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&&i?"2000px":"0"},"aria-hidden":!d,children:d&&i&&e.kind!=="equal"?t.jsx(fe,{op:e}):null})]})}function fe({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 pe({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(J,{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(V,{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(_,{className:"size-3"}),e.changed," changed"]})]})}function he({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(ee,{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(te,{className:"size-3"}),"Split"]})]})}function A({log:e,side:r}){const n=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(Z,{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",children:["#",e.id]}),e.model!==null&&t.jsx("span",{className:"font-mono text-muted-foreground truncate",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 +",$(e.cacheCreationInputTokens)]}),e.cacheReadInputTokens!==null&&e.cacheReadInputTokens>0&&t.jsxs("span",{className:"text-purple-400",children:["KV Cache ~",$(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:n,children:["session: ",n]})]})}function ke({left:e,right:r,onClose:n}){const s=h.useMemo(()=>{const l=I(P(e)).analyzeRequest(e.rawRequestBody),c=I(P(r)).analyzeRequest(r.rawRequestBody),u=D(l.comparisonValue),g=D(c.comparisonValue);return ce(u,g)},[e.apiFormat,e.path,e.rawRequestBody,r.apiFormat,r.path,r.rawRequestBody]),d=h.useMemo(()=>ue(s),[s]),o=h.useMemo(()=>{let l=0,c=0,u=0;for(const g of d)if(g.kind==="single")switch(g.op.kind){case"added":l++;break;case"removed":c++;break;case"changed":u++;break}return{added:l,removed:c,changed:u}},[d]),[a,x]=h.useState(new Set),i=l=>{x(c=>{const u=new Set(c);return u.has(l)?u.delete(l):u.add(l),u})},[f,p]=h.useState(new Set),b=l=>{p(c=>{const u=new Set(c);return u.has(l)?u.delete(l):u.add(l),u})};h.useEffect(()=>{p(new Set)},[e.id,r.id]);const[y,F]=h.useState("unified"),T=h.useRef(null),[U,z]=h.useState(null),k=h.useRef(null),H=l=>{se(l).then(c=>{c&&(z(l),k.current!==null&&clearTimeout(k.current),k.current=setTimeout(()=>z(null),1500))})};h.useEffect(()=>()=>{k.current!==null&&clearTimeout(k.current)},[]);const G=l=>{const c=d.findIndex(O=>O.kind==="single"&&O.op.kind===l);if(c===-1)return;const u=T.current;if(u===null)return;const g=u.querySelector(`[data-diff-idx="${c}"]`);g!==null&&g.scrollIntoView({behavior:"smooth",block:"center"})};h.useEffect(()=>{const l=u=>{u.key==="Escape"&&n()};document.addEventListener("keydown",l);const c=document.body.style.overflow;return document.body.style.overflow="hidden",()=>{document.removeEventListener("keydown",l),document.body.style.overflow=c}},[n]);const Q=q(e)===q(r),W=s.length===1&&s[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:n,"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:l=>l.stopPropagation(),onKeyDown:l=>l.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(A,{log:e,side:"left"}),t.jsx(A,{log:r,side:"right"})]}),t.jsxs("div",{className:"flex items-center gap-2 shrink-0",children:[t.jsx(he,{mode:y,onChange:F}),t.jsx("button",{type:"button",onClick:n,"aria-label":"Close",className:"p-1 rounded text-muted-foreground hover:text-foreground hover:bg-muted cursor-pointer",children:t.jsx(Y,{className:"size-4"})})]})]}),!Q&&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."}),W?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(pe,{counts:o,onJumpTo:G}),t.jsx("div",{ref:T,className:"flex-1 min-h-0 overflow-y-auto",children:y==="unified"?t.jsx("div",{className:"px-3 py-2 space-y-0.5",children:d.map((l,c)=>{if(l.kind==="equal-run")return t.jsx(xe,{ops:l.ops,expanded:a.has(c),onToggle:()=>i(c)},`r${c}`);const u=l.op;return t.jsx(me,{op:u,idx:c,copiedPath:U,onCopyPath:H,expanded:f.has(c),onToggle:()=>b(c)},`o${c}`)})}):t.jsx(be,{grouped:d,left:e,right:r})})]})]})]})}function be({grouped:e,left:r,right:n}){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",{children:["Left (Log #",r.id,")"]}),t.jsxs("span",{children:["Right (Log #",n.id,")"]})]}),e.map((s,d)=>{if(s.kind==="equal-run")return t.jsxs("div",{className:"col-span-3 px-2 py-1 text-xs text-muted-foreground/60",children:[s.ops.length," equal siblings collapsed — switch to Unified to expand"]},d);const o=s.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)})]},d):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)]})]},d):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)]})]},d):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)})]})]},d)})]})}export{ke as CompareDrawer};
|