@tonyclaw/llm-inspector 1.10.0 → 1.11.0
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/index-BIZeMR5N.js +105 -0
- package/.output/public/assets/index-SmtLx1lM.css +1 -0
- package/.output/public/assets/main-QfbQ5oBP.js +17 -0
- package/.output/server/_libs/@radix-ui/react-use-controllable-state+[...].mjs +1 -1
- package/.output/server/_libs/ajv-formats.mjs +18 -18
- package/.output/server/_libs/ajv.mjs +6306 -942
- package/.output/server/_libs/cookie-es.mjs +21 -7
- package/.output/server/_libs/diff.mjs +320 -0
- package/.output/server/_libs/floating-ui__core.mjs +17 -18
- package/.output/server/_libs/floating-ui__dom.mjs +20 -24
- package/.output/server/_libs/floating-ui__react-dom.mjs +28 -55
- package/.output/server/_libs/floating-ui__utils.mjs +36 -36
- package/.output/server/_libs/h3-v2.mjs +9 -20
- package/.output/server/_libs/isbot.mjs +2 -3
- package/.output/server/_libs/json-schema-traverse.mjs +90 -1
- package/.output/server/_libs/jszip.mjs +28 -28
- package/.output/server/_libs/lucide-react.mjs +103 -80
- package/.output/server/_libs/mdast-util-from-markdown.mjs +1 -1
- package/.output/server/_libs/pako.mjs +13 -13
- package/.output/server/_libs/property-information.mjs +1 -13
- package/.output/server/_libs/radix-ui__react-collection.mjs +1 -1
- package/.output/server/_libs/radix-ui__react-id.mjs +1 -1
- package/.output/server/_libs/react-dom.mjs +10 -10
- package/.output/server/_libs/react.mjs +44 -44
- package/.output/server/_libs/readable-stream.mjs +15 -15
- package/.output/server/_libs/rou3.mjs +7 -1
- package/.output/server/_libs/safe-buffer.mjs +3 -3
- package/.output/server/_libs/semver.mjs +10 -10
- package/.output/server/_libs/seroval-plugins.mjs +5 -5
- package/.output/server/_libs/seroval.mjs +596 -606
- package/.output/server/_libs/srvx.mjs +245 -10
- package/.output/server/_libs/swr.mjs +1 -1
- package/.output/server/_libs/tailwind-merge.mjs +41 -286
- package/.output/server/_libs/tanstack__history.mjs +44 -31
- package/.output/server/_libs/tanstack__react-router.mjs +1089 -780
- package/.output/server/_libs/tanstack__react-store.mjs +1 -1
- package/.output/server/_libs/tanstack__react-virtual.mjs +7 -82
- package/.output/server/_libs/tanstack__router-core.mjs +2331 -2226
- package/.output/server/_libs/tanstack__virtual-core.mjs +17 -58
- package/.output/server/_libs/tiny-invariant.mjs +12 -0
- package/.output/server/_libs/tiny-warning.mjs +5 -0
- package/.output/server/_libs/ungap__structured-clone.mjs +2 -14
- package/.output/server/_libs/use-sync-external-store.mjs +1 -1
- package/.output/server/_libs/zod.mjs +207 -505
- package/.output/server/_ssr/{index-XyU4WVWt.mjs → index-I_Nx8QEB.mjs} +532 -79
- package/.output/server/_ssr/index.mjs +776 -1098
- package/.output/server/_ssr/{router-BR4XO8XJ.mjs → router-BVxfVFsb.mjs} +98 -53
- package/.output/server/_tanstack-start-manifest_v-Cm2Owszu.mjs +4 -0
- package/.output/server/index.mjs +28 -28
- package/README.md +1 -1
- package/package.json +2 -1
- package/src/components/ProxyViewer.tsx +10 -3
- package/src/components/ProxyViewerContainer.tsx +6 -0
- package/src/components/proxy-viewer/ConversationGroup.tsx +10 -1
- package/src/components/proxy-viewer/LogEntry.tsx +114 -5
- package/src/components/proxy-viewer/diff/DiffView.tsx +319 -0
- package/src/components/proxy-viewer/diff/computeDiff.ts +178 -0
- package/src/components/proxy-viewer/diff/index.ts +3 -0
- package/src/components/ui/crab-logo.tsx +45 -0
- package/src/proxy/config.ts +3 -17
- package/src/proxy/dataDir.ts +56 -0
- package/src/proxy/formats/anthropic/stream.ts +5 -2
- package/src/proxy/formats/jsonSchema.ts +12 -0
- package/src/proxy/formats/openai/stream.ts +21 -16
- package/src/proxy/handler.ts +15 -5
- package/src/proxy/providers.ts +61 -1
- package/src/proxy/schemas.ts +42 -0
- package/src/proxy/store.ts +6 -23
- package/.output/public/assets/index-BFuUQkWu.js +0 -11
- package/.output/public/assets/index-F2ojFPJp.css +0 -1
- package/.output/public/assets/index-nKnhyW4Y.js +0 -122
- package/.output/server/_ssr/empty-plugin-adapters-BFgPZ6_d.mjs +0 -6
- package/.output/server/_tanstack-start-manifest_v-DFoSjBkb.mjs +0 -4
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { r as reactExports, j as jsxRuntimeExports,
|
|
2
|
-
import { C as CapturedLogSchema,
|
|
1
|
+
import { r as reactExports, j as jsxRuntimeExports, a as React } from "../_libs/react.mjs";
|
|
2
|
+
import { C as CapturedLogSchema, R as RuntimeConfigSchema, a as parseRequest, s as stripClaudeCodeBillingHeader, p as parseOpenAIResponse, I as InspectorResponseSchema } from "./router-BVxfVFsb.mjs";
|
|
3
|
+
import { u as useSWR, a as useSWRConfig } from "../_libs/swr.mjs";
|
|
3
4
|
import { u as useVirtualizer } from "../_libs/tanstack__react-virtual.mjs";
|
|
4
5
|
import { J as JSZip } from "../_libs/jszip.mjs";
|
|
5
6
|
import { c as clsx } from "../_libs/clsx.mjs";
|
|
6
7
|
import { t as twMerge } from "../_libs/tailwind-merge.mjs";
|
|
7
8
|
import { c as cva } from "../_libs/class-variance-authority.mjs";
|
|
8
|
-
import {
|
|
9
|
+
import { d as diffLines, a as diffJson } from "../_libs/diff.mjs";
|
|
9
10
|
import { R as Root, T as Trigger$1, C as Content, a as Close, b as Title, P as Portal$1, O as Overlay } from "../_libs/radix-ui__react-dialog.mjs";
|
|
10
11
|
import { R as Root2, T as Trigger, I as Icon, V as Value, P as Portal, C as Content2, a as Viewport, b as Item, c as ItemIndicator, d as ItemText, S as ScrollUpButton, e as ScrollDownButton } from "../_libs/radix-ui__react-select.mjs";
|
|
11
|
-
import { D as Download, L as LayoutGrid, a as List, S as Settings, C as ChevronDown, b as Check, R as RotateCcw, X, U as Upload, P as Plus, c as Copy, d as CircleAlert, e as ChevronUp, f as ChevronRight, g as Clock, M as MessageSquare, Z as Zap, h as LoaderCircle, W as Wrench, G as Globe, i as User, F as FileTerminal, j as Radio, E as ExternalLink,
|
|
12
|
+
import { D as Download, L as LayoutGrid, a as List, S as Settings, C as ChevronDown, b as Check, R as RotateCcw, X, U as Upload, P as Plus, c as Copy, d as CircleAlert, e as ChevronUp, f as ChevronRight, g as Clock, M as MessageSquare, Z as Zap, h as LoaderCircle, W as Wrench, G as Globe, i as User, F as FileTerminal, j as Radio, k as GitCompareArrows, l as Rows3, m as Columns2, E as ExternalLink, n as EyeOff, o as Eye, p as RotateCw, q as Pencil, T as Trash2, r as TriangleAlert, s as Minus, t as CircleCheckBig, u as CircleStop, v as CircleQuestionMark, w as Server, x as Gauge, y as Lock, z as Wifi, A as WifiOff, B as ChevronsUp, H as ChevronsDown, I as Brain, J as Terminal } from "../_libs/lucide-react.mjs";
|
|
12
13
|
import { M as Markdown } from "../_libs/react-markdown.mjs";
|
|
13
14
|
import { a as array, s as string, u as union, o as object, l as literal, n as number, b as boolean } from "../_libs/zod.mjs";
|
|
14
15
|
import { R as Root2$1, L as List$1, T as Trigger$2, C as Content$1 } from "../_libs/radix-ui__react-tabs.mjs";
|
|
@@ -18,9 +19,11 @@ import { R as Root$1 } from "../_libs/radix-ui__react-separator.mjs";
|
|
|
18
19
|
import { R as Root$2, C as CollapsibleTrigger$1, a as CollapsibleContent$1 } from "../_libs/radix-ui__react-collapsible.mjs";
|
|
19
20
|
import { R as Root$3, V as Viewport$1, C as Corner, S as ScrollAreaScrollbar, a as ScrollAreaThumb } from "../_libs/radix-ui__react-scroll-area.mjs";
|
|
20
21
|
import "../_libs/tanstack__react-router.mjs";
|
|
22
|
+
import "../_libs/tiny-warning.mjs";
|
|
21
23
|
import "../_libs/tanstack__router-core.mjs";
|
|
22
|
-
import "../_libs/tanstack__history.mjs";
|
|
23
24
|
import "../_libs/cookie-es.mjs";
|
|
25
|
+
import "../_libs/tanstack__history.mjs";
|
|
26
|
+
import "../_libs/tiny-invariant.mjs";
|
|
24
27
|
import "../_libs/seroval.mjs";
|
|
25
28
|
import "../_libs/seroval-plugins.mjs";
|
|
26
29
|
import "node:stream/web";
|
|
@@ -159,6 +162,62 @@ import "../_libs/hast-util-whitespace.mjs";
|
|
|
159
162
|
import "../_libs/estree-util-is-identifier-name.mjs";
|
|
160
163
|
import "../_libs/html-url-attributes.mjs";
|
|
161
164
|
import "../_libs/radix-ui__react-roving-focus.mjs";
|
|
165
|
+
const STRIP_CONFIG_SWR_KEY = "/api/config";
|
|
166
|
+
async function fetcher$1(url) {
|
|
167
|
+
const response = await fetch(url);
|
|
168
|
+
if (!response.ok) {
|
|
169
|
+
throw new Error(`Failed to fetch ${url}: ${response.status}`);
|
|
170
|
+
}
|
|
171
|
+
const data = await response.json();
|
|
172
|
+
return RuntimeConfigSchema.parse(data);
|
|
173
|
+
}
|
|
174
|
+
function extractErrorMessage(errorBody, fallback) {
|
|
175
|
+
if (typeof errorBody !== "object" || errorBody === null) return fallback;
|
|
176
|
+
const candidate = errorBody.error;
|
|
177
|
+
return typeof candidate === "string" ? candidate : fallback;
|
|
178
|
+
}
|
|
179
|
+
async function setRuntimeConfig(patch) {
|
|
180
|
+
const response = await fetch(STRIP_CONFIG_SWR_KEY, {
|
|
181
|
+
method: "PATCH",
|
|
182
|
+
headers: { "content-type": "application/json" },
|
|
183
|
+
body: JSON.stringify(patch)
|
|
184
|
+
});
|
|
185
|
+
if (!response.ok) {
|
|
186
|
+
const errorBody = await response.json().catch(() => ({}));
|
|
187
|
+
throw new Error(extractErrorMessage(errorBody, `PATCH failed with status ${response.status}`));
|
|
188
|
+
}
|
|
189
|
+
const data = await response.json();
|
|
190
|
+
return RuntimeConfigSchema.parse(data);
|
|
191
|
+
}
|
|
192
|
+
function useStripConfig() {
|
|
193
|
+
const response = useSWR(
|
|
194
|
+
STRIP_CONFIG_SWR_KEY,
|
|
195
|
+
fetcher$1,
|
|
196
|
+
{
|
|
197
|
+
revalidateOnFocus: false,
|
|
198
|
+
revalidateIfStale: false
|
|
199
|
+
}
|
|
200
|
+
);
|
|
201
|
+
const { mutate: globalMutate } = useSWRConfig();
|
|
202
|
+
const strip = response.data?.stripClaudeCodeBillingHeader ?? false;
|
|
203
|
+
const setStrip = async (next) => {
|
|
204
|
+
await globalMutate(
|
|
205
|
+
STRIP_CONFIG_SWR_KEY,
|
|
206
|
+
setRuntimeConfig({ stripClaudeCodeBillingHeader: next }),
|
|
207
|
+
{
|
|
208
|
+
optimisticData: { stripClaudeCodeBillingHeader: next },
|
|
209
|
+
rollbackOnError: true,
|
|
210
|
+
revalidate: false
|
|
211
|
+
}
|
|
212
|
+
);
|
|
213
|
+
};
|
|
214
|
+
return {
|
|
215
|
+
strip,
|
|
216
|
+
isLoading: response.isLoading,
|
|
217
|
+
isError: response.error !== void 0,
|
|
218
|
+
setStrip
|
|
219
|
+
};
|
|
220
|
+
}
|
|
162
221
|
async function fetchStreamingChunks(logId) {
|
|
163
222
|
try {
|
|
164
223
|
const response = await fetch(`/api/logs/${logId}/chunks`);
|
|
@@ -198,7 +257,7 @@ async function exportLogsAsZip(logs) {
|
|
|
198
257
|
document.body.removeChild(anchor);
|
|
199
258
|
URL.revokeObjectURL(url);
|
|
200
259
|
}
|
|
201
|
-
const version = "1.
|
|
260
|
+
const version = "1.11.0";
|
|
202
261
|
const packageJson = {
|
|
203
262
|
version
|
|
204
263
|
};
|
|
@@ -391,62 +450,6 @@ function groupLogsByConversation(logs) {
|
|
|
391
450
|
result.sort((a, b) => (a.logs[0]?.timestamp ?? "").localeCompare(b.logs[0]?.timestamp ?? ""));
|
|
392
451
|
return result;
|
|
393
452
|
}
|
|
394
|
-
const STRIP_CONFIG_SWR_KEY = "/api/config";
|
|
395
|
-
async function fetcher$1(url) {
|
|
396
|
-
const response = await fetch(url);
|
|
397
|
-
if (!response.ok) {
|
|
398
|
-
throw new Error(`Failed to fetch ${url}: ${response.status}`);
|
|
399
|
-
}
|
|
400
|
-
const data = await response.json();
|
|
401
|
-
return RuntimeConfigSchema.parse(data);
|
|
402
|
-
}
|
|
403
|
-
function extractErrorMessage(errorBody, fallback) {
|
|
404
|
-
if (typeof errorBody !== "object" || errorBody === null) return fallback;
|
|
405
|
-
const candidate = errorBody.error;
|
|
406
|
-
return typeof candidate === "string" ? candidate : fallback;
|
|
407
|
-
}
|
|
408
|
-
async function setRuntimeConfig(patch) {
|
|
409
|
-
const response = await fetch(STRIP_CONFIG_SWR_KEY, {
|
|
410
|
-
method: "PATCH",
|
|
411
|
-
headers: { "content-type": "application/json" },
|
|
412
|
-
body: JSON.stringify(patch)
|
|
413
|
-
});
|
|
414
|
-
if (!response.ok) {
|
|
415
|
-
const errorBody = await response.json().catch(() => ({}));
|
|
416
|
-
throw new Error(extractErrorMessage(errorBody, `PATCH failed with status ${response.status}`));
|
|
417
|
-
}
|
|
418
|
-
const data = await response.json();
|
|
419
|
-
return RuntimeConfigSchema.parse(data);
|
|
420
|
-
}
|
|
421
|
-
function useStripConfig() {
|
|
422
|
-
const response = useSWR(
|
|
423
|
-
STRIP_CONFIG_SWR_KEY,
|
|
424
|
-
fetcher$1,
|
|
425
|
-
{
|
|
426
|
-
revalidateOnFocus: false,
|
|
427
|
-
revalidateIfStale: false
|
|
428
|
-
}
|
|
429
|
-
);
|
|
430
|
-
const { mutate: globalMutate } = useSWRConfig();
|
|
431
|
-
const strip = response.data?.stripClaudeCodeBillingHeader ?? false;
|
|
432
|
-
const setStrip = async (next) => {
|
|
433
|
-
await globalMutate(
|
|
434
|
-
STRIP_CONFIG_SWR_KEY,
|
|
435
|
-
setRuntimeConfig({ stripClaudeCodeBillingHeader: next }),
|
|
436
|
-
{
|
|
437
|
-
optimisticData: { stripClaudeCodeBillingHeader: next },
|
|
438
|
-
rollbackOnError: true,
|
|
439
|
-
revalidate: false
|
|
440
|
-
}
|
|
441
|
-
);
|
|
442
|
-
};
|
|
443
|
-
return {
|
|
444
|
-
strip,
|
|
445
|
-
isLoading: response.isLoading,
|
|
446
|
-
isError: response.error !== void 0,
|
|
447
|
-
setStrip
|
|
448
|
-
};
|
|
449
|
-
}
|
|
450
453
|
const buttonVariants = cva(
|
|
451
454
|
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
452
455
|
{
|
|
@@ -958,6 +961,332 @@ function TabsContent({
|
|
|
958
961
|
}
|
|
959
962
|
);
|
|
960
963
|
}
|
|
964
|
+
function normalizeHeaders(headers) {
|
|
965
|
+
if (headers === void 0) return [];
|
|
966
|
+
return Object.entries(headers).map((entry) => [entry[0].toLowerCase(), entry[1]]).sort(([a], [b]) => a.localeCompare(b));
|
|
967
|
+
}
|
|
968
|
+
function headerLine([key, value]) {
|
|
969
|
+
return `${key}: ${value}`;
|
|
970
|
+
}
|
|
971
|
+
function changesToLines(changes) {
|
|
972
|
+
const lines = [];
|
|
973
|
+
let oldNum = 0;
|
|
974
|
+
let newNum = 0;
|
|
975
|
+
for (const change of changes) {
|
|
976
|
+
const parts = change.value.split("\n");
|
|
977
|
+
if (parts.length > 0 && parts[parts.length - 1] === "") parts.pop();
|
|
978
|
+
for (const text of parts) {
|
|
979
|
+
if (change.added) {
|
|
980
|
+
newNum += 1;
|
|
981
|
+
lines.push({ kind: "added", text, oldLineNumber: null, newLineNumber: newNum });
|
|
982
|
+
} else if (change.removed) {
|
|
983
|
+
oldNum += 1;
|
|
984
|
+
lines.push({ kind: "removed", text, oldLineNumber: oldNum, newLineNumber: null });
|
|
985
|
+
} else {
|
|
986
|
+
oldNum += 1;
|
|
987
|
+
newNum += 1;
|
|
988
|
+
lines.push({
|
|
989
|
+
kind: "context",
|
|
990
|
+
text,
|
|
991
|
+
oldLineNumber: oldNum,
|
|
992
|
+
newLineNumber: newNum
|
|
993
|
+
});
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
return lines;
|
|
998
|
+
}
|
|
999
|
+
function computeHeadersDiff(rawHeaders, processedHeaders) {
|
|
1000
|
+
const left = normalizeHeaders(rawHeaders).map(headerLine).join("\n");
|
|
1001
|
+
const right = normalizeHeaders(processedHeaders).map(headerLine).join("\n");
|
|
1002
|
+
if (left === right) {
|
|
1003
|
+
return { lines: [], isEmpty: true };
|
|
1004
|
+
}
|
|
1005
|
+
const changes = diffLines(left, right);
|
|
1006
|
+
return { lines: changesToLines(changes), isEmpty: false };
|
|
1007
|
+
}
|
|
1008
|
+
function tryParseJson(text) {
|
|
1009
|
+
try {
|
|
1010
|
+
const parsed = JSON.parse(text);
|
|
1011
|
+
if (parsed === null) return parsed;
|
|
1012
|
+
if (typeof parsed === "string" || typeof parsed === "object") return parsed;
|
|
1013
|
+
return null;
|
|
1014
|
+
} catch {
|
|
1015
|
+
return null;
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
function computeRequestDiff(rawBody, processedBody) {
|
|
1019
|
+
const left = rawBody ?? "";
|
|
1020
|
+
const right = processedBody ?? "";
|
|
1021
|
+
if (left === right) {
|
|
1022
|
+
return { lines: [], isEmpty: true };
|
|
1023
|
+
}
|
|
1024
|
+
const leftJson = tryParseJson(left);
|
|
1025
|
+
const rightJson = tryParseJson(right);
|
|
1026
|
+
if (leftJson !== null && rightJson !== null) {
|
|
1027
|
+
const changes2 = diffJson(leftJson, rightJson) ?? [];
|
|
1028
|
+
if (changes2.length === 1) {
|
|
1029
|
+
const first = changes2[0];
|
|
1030
|
+
if (first !== void 0 && !first.added && !first.removed) {
|
|
1031
|
+
return { lines: [], isEmpty: true };
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
return { lines: changesToLines(changes2), isEmpty: false };
|
|
1035
|
+
}
|
|
1036
|
+
const changes = diffLines(left, right);
|
|
1037
|
+
return { lines: changesToLines(changes), isEmpty: false };
|
|
1038
|
+
}
|
|
1039
|
+
const ESTIMATED_LINE_HEIGHT = 22;
|
|
1040
|
+
const MAX_RENDERED_LINES = 1e4;
|
|
1041
|
+
function kindPrefix(kind) {
|
|
1042
|
+
if (kind === "added") return "+";
|
|
1043
|
+
if (kind === "removed") return "-";
|
|
1044
|
+
return " ";
|
|
1045
|
+
}
|
|
1046
|
+
function kindClass(kind) {
|
|
1047
|
+
if (kind === "added") {
|
|
1048
|
+
return "bg-green-500/10 text-green-700 dark:text-green-300";
|
|
1049
|
+
}
|
|
1050
|
+
if (kind === "removed") {
|
|
1051
|
+
return "bg-red-500/10 text-red-700 dark:text-red-300";
|
|
1052
|
+
}
|
|
1053
|
+
return "text-foreground/80";
|
|
1054
|
+
}
|
|
1055
|
+
function DiffView({ result, emptyLabel }) {
|
|
1056
|
+
const [mode, setMode] = reactExports.useState("unified");
|
|
1057
|
+
const scrollRef = reactExports.useRef(null);
|
|
1058
|
+
const virtualizer = useVirtualizer({
|
|
1059
|
+
count: result.lines.length,
|
|
1060
|
+
getScrollElement: () => scrollRef.current,
|
|
1061
|
+
estimateSize: () => ESTIMATED_LINE_HEIGHT,
|
|
1062
|
+
overscan: 10
|
|
1063
|
+
});
|
|
1064
|
+
if (result.isEmpty) {
|
|
1065
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
1066
|
+
"div",
|
|
1067
|
+
{
|
|
1068
|
+
className: "rounded border border-dashed border-border bg-muted/30 px-4 py-6 text-center text-xs text-muted-foreground",
|
|
1069
|
+
"data-testid": "diff-empty",
|
|
1070
|
+
children: emptyLabel ?? "No transformation applied — raw and processed are identical."
|
|
1071
|
+
}
|
|
1072
|
+
);
|
|
1073
|
+
}
|
|
1074
|
+
const totalLines = result.lines.length;
|
|
1075
|
+
const truncated = totalLines > MAX_RENDERED_LINES;
|
|
1076
|
+
const visibleLines = truncated ? result.lines.slice(0, MAX_RENDERED_LINES) : result.lines;
|
|
1077
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
|
|
1078
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between text-xs text-muted-foreground", children: [
|
|
1079
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
1080
|
+
totalLines.toLocaleString(),
|
|
1081
|
+
" line",
|
|
1082
|
+
totalLines === 1 ? "" : "s",
|
|
1083
|
+
truncated && ` (showing first ${MAX_RENDERED_LINES.toLocaleString()})`
|
|
1084
|
+
] }),
|
|
1085
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "inline-flex rounded-md border border-border overflow-hidden", children: [
|
|
1086
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
1087
|
+
"button",
|
|
1088
|
+
{
|
|
1089
|
+
type: "button",
|
|
1090
|
+
onClick: () => setMode("unified"),
|
|
1091
|
+
"aria-pressed": mode === "unified",
|
|
1092
|
+
className: cn(
|
|
1093
|
+
"flex items-center gap-1 px-2 py-1 transition-colors",
|
|
1094
|
+
mode === "unified" ? "bg-muted text-foreground" : "hover:bg-muted/50"
|
|
1095
|
+
),
|
|
1096
|
+
title: "Unified diff (single column)",
|
|
1097
|
+
children: [
|
|
1098
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Rows3, { className: "size-3" }),
|
|
1099
|
+
"Unified"
|
|
1100
|
+
]
|
|
1101
|
+
}
|
|
1102
|
+
),
|
|
1103
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
1104
|
+
"button",
|
|
1105
|
+
{
|
|
1106
|
+
type: "button",
|
|
1107
|
+
onClick: () => setMode("split"),
|
|
1108
|
+
"aria-pressed": mode === "split",
|
|
1109
|
+
className: cn(
|
|
1110
|
+
"flex items-center gap-1 px-2 py-1 transition-colors border-l border-border",
|
|
1111
|
+
mode === "split" ? "bg-muted text-foreground" : "hover:bg-muted/50"
|
|
1112
|
+
),
|
|
1113
|
+
title: "Split diff (side by side)",
|
|
1114
|
+
children: [
|
|
1115
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Columns2, { className: "size-3" }),
|
|
1116
|
+
"Split"
|
|
1117
|
+
]
|
|
1118
|
+
}
|
|
1119
|
+
)
|
|
1120
|
+
] })
|
|
1121
|
+
] }),
|
|
1122
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
1123
|
+
"div",
|
|
1124
|
+
{
|
|
1125
|
+
ref: scrollRef,
|
|
1126
|
+
className: "max-h-[60vh] overflow-auto rounded border border-border bg-background font-mono text-xs",
|
|
1127
|
+
"data-testid": "diff-viewport",
|
|
1128
|
+
children: mode === "unified" ? /* @__PURE__ */ jsxRuntimeExports.jsx(UnifiedRows, { virtualizer, lines: visibleLines }) : /* @__PURE__ */ jsxRuntimeExports.jsx(SplitRows, { lines: visibleLines })
|
|
1129
|
+
}
|
|
1130
|
+
)
|
|
1131
|
+
] });
|
|
1132
|
+
}
|
|
1133
|
+
function UnifiedRows({
|
|
1134
|
+
virtualizer,
|
|
1135
|
+
lines
|
|
1136
|
+
}) {
|
|
1137
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
1138
|
+
"div",
|
|
1139
|
+
{
|
|
1140
|
+
style: {
|
|
1141
|
+
height: `${virtualizer.getTotalSize()}px`,
|
|
1142
|
+
width: "100%",
|
|
1143
|
+
position: "relative"
|
|
1144
|
+
},
|
|
1145
|
+
children: virtualizer.getVirtualItems().map((virtualRow) => {
|
|
1146
|
+
const line = lines[virtualRow.index];
|
|
1147
|
+
if (line === void 0) return null;
|
|
1148
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
1149
|
+
"div",
|
|
1150
|
+
{
|
|
1151
|
+
"data-index": virtualRow.index,
|
|
1152
|
+
ref: virtualizer.measureElement,
|
|
1153
|
+
className: cn("flex items-start gap-3 px-2", kindClass(line.kind)),
|
|
1154
|
+
style: {
|
|
1155
|
+
position: "absolute",
|
|
1156
|
+
top: 0,
|
|
1157
|
+
left: 0,
|
|
1158
|
+
width: "100%",
|
|
1159
|
+
transform: `translateY(${virtualRow.start}px)`
|
|
1160
|
+
},
|
|
1161
|
+
children: [
|
|
1162
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "select-none text-muted-foreground/60 w-10 text-right tabular-nums", children: line.oldLineNumber ?? "" }),
|
|
1163
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "select-none text-muted-foreground/60 w-10 text-right tabular-nums", children: line.newLineNumber ?? "" }),
|
|
1164
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
1165
|
+
"span",
|
|
1166
|
+
{
|
|
1167
|
+
className: cn(
|
|
1168
|
+
"select-none w-3 text-right font-bold",
|
|
1169
|
+
line.kind === "added" && "text-green-600 dark:text-green-400",
|
|
1170
|
+
line.kind === "removed" && "text-red-600 dark:text-red-400"
|
|
1171
|
+
),
|
|
1172
|
+
children: kindPrefix(line.kind)
|
|
1173
|
+
}
|
|
1174
|
+
),
|
|
1175
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "whitespace-pre-wrap break-all flex-1", children: line.text })
|
|
1176
|
+
]
|
|
1177
|
+
},
|
|
1178
|
+
virtualRow.key
|
|
1179
|
+
);
|
|
1180
|
+
})
|
|
1181
|
+
}
|
|
1182
|
+
);
|
|
1183
|
+
}
|
|
1184
|
+
function buildSplitRows(lines) {
|
|
1185
|
+
const rows = [];
|
|
1186
|
+
let i = 0;
|
|
1187
|
+
while (i < lines.length) {
|
|
1188
|
+
const line = lines[i];
|
|
1189
|
+
if (line === void 0) break;
|
|
1190
|
+
if (line.kind === "context") {
|
|
1191
|
+
rows.push({
|
|
1192
|
+
left: { text: line.text, lineNumber: line.oldLineNumber },
|
|
1193
|
+
right: { text: line.text, lineNumber: line.newLineNumber },
|
|
1194
|
+
kind: "equal"
|
|
1195
|
+
});
|
|
1196
|
+
i += 1;
|
|
1197
|
+
continue;
|
|
1198
|
+
}
|
|
1199
|
+
const removes = [];
|
|
1200
|
+
const adds = [];
|
|
1201
|
+
while (i < lines.length && lines[i]?.kind === "removed") {
|
|
1202
|
+
const removed = lines[i];
|
|
1203
|
+
if (removed !== void 0) removes.push(removed);
|
|
1204
|
+
i += 1;
|
|
1205
|
+
}
|
|
1206
|
+
while (i < lines.length && lines[i]?.kind === "added") {
|
|
1207
|
+
const added = lines[i];
|
|
1208
|
+
if (added !== void 0) adds.push(added);
|
|
1209
|
+
i += 1;
|
|
1210
|
+
}
|
|
1211
|
+
const pairCount = Math.max(removes.length, adds.length);
|
|
1212
|
+
for (let p = 0; p < pairCount; p += 1) {
|
|
1213
|
+
const r = removes[p];
|
|
1214
|
+
const a = adds[p];
|
|
1215
|
+
if (r !== void 0 && a !== void 0) {
|
|
1216
|
+
rows.push({
|
|
1217
|
+
left: { text: r.text, lineNumber: r.oldLineNumber },
|
|
1218
|
+
right: { text: a.text, lineNumber: a.newLineNumber },
|
|
1219
|
+
kind: "changed"
|
|
1220
|
+
});
|
|
1221
|
+
} else if (r !== void 0) {
|
|
1222
|
+
rows.push({
|
|
1223
|
+
left: { text: r.text, lineNumber: r.oldLineNumber },
|
|
1224
|
+
right: null,
|
|
1225
|
+
kind: "removed"
|
|
1226
|
+
});
|
|
1227
|
+
} else if (a !== void 0) {
|
|
1228
|
+
rows.push({
|
|
1229
|
+
left: null,
|
|
1230
|
+
right: { text: a.text, lineNumber: a.newLineNumber },
|
|
1231
|
+
kind: "added"
|
|
1232
|
+
});
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
return rows;
|
|
1237
|
+
}
|
|
1238
|
+
function SplitRowClass(kind) {
|
|
1239
|
+
switch (kind) {
|
|
1240
|
+
case "changed":
|
|
1241
|
+
return "bg-amber-500/10";
|
|
1242
|
+
case "removed":
|
|
1243
|
+
return "bg-red-500/10";
|
|
1244
|
+
case "added":
|
|
1245
|
+
return "bg-green-500/10";
|
|
1246
|
+
case "equal":
|
|
1247
|
+
return "";
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
function SplitRows({ lines }) {
|
|
1251
|
+
const rows = buildSplitRows(lines);
|
|
1252
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { "data-testid": "diff-split", children: rows.map((row, idx) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
1253
|
+
"div",
|
|
1254
|
+
{
|
|
1255
|
+
className: cn("grid grid-cols-2 font-mono text-xs", SplitRowClass(row.kind)),
|
|
1256
|
+
children: [
|
|
1257
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-2 px-2 border-r border-border/50", children: [
|
|
1258
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "select-none text-muted-foreground/60 w-8 text-right tabular-nums", children: row.left?.lineNumber ?? "" }),
|
|
1259
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
1260
|
+
"span",
|
|
1261
|
+
{
|
|
1262
|
+
className: cn(
|
|
1263
|
+
"select-none w-3 text-right font-bold",
|
|
1264
|
+
(row.kind === "removed" || row.kind === "changed") && "text-red-600 dark:text-red-400"
|
|
1265
|
+
),
|
|
1266
|
+
children: row.left !== null ? "-" : " "
|
|
1267
|
+
}
|
|
1268
|
+
),
|
|
1269
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "whitespace-pre-wrap break-all flex-1", children: row.left?.text ?? "" })
|
|
1270
|
+
] }),
|
|
1271
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-2 px-2", children: [
|
|
1272
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "select-none text-muted-foreground/60 w-8 text-right tabular-nums", children: row.right?.lineNumber ?? "" }),
|
|
1273
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
1274
|
+
"span",
|
|
1275
|
+
{
|
|
1276
|
+
className: cn(
|
|
1277
|
+
"select-none w-3 text-right font-bold",
|
|
1278
|
+
(row.kind === "added" || row.kind === "changed") && "text-green-600 dark:text-green-400"
|
|
1279
|
+
),
|
|
1280
|
+
children: row.right !== null ? "+" : " "
|
|
1281
|
+
}
|
|
1282
|
+
),
|
|
1283
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "whitespace-pre-wrap break-all flex-1", children: row.right?.text ?? "" })
|
|
1284
|
+
] })
|
|
1285
|
+
]
|
|
1286
|
+
},
|
|
1287
|
+
idx
|
|
1288
|
+
)) });
|
|
1289
|
+
}
|
|
961
1290
|
const AnthropicLogoSvg = "data:image/svg+xml,%3csvg%20height='2500'%20viewBox='0%206.603%201192.672%201193.397'%20width='2500'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='m233.96%20800.215%20234.684-131.678%203.947-11.436-3.947-6.363h-11.436l-39.221-2.416-134.094-3.624-116.296-4.832-112.67-6.04-28.35-6.04-26.577-35.035%202.738-17.477%2023.84-16.027%2034.147%202.98%2075.463%205.155%20113.235%207.812%2082.147%204.832%20121.692%2012.644h19.329l2.738-7.812-6.604-4.832-5.154-4.832-117.182-79.41-126.845-83.92-66.443-48.321-35.92-24.484-18.12-22.953-7.813-50.093%2032.618-35.92%2043.812%202.98%2011.195%202.98%2044.375%2034.147%2094.792%2073.37%20123.786%2091.167%2018.12%2015.06%207.249-5.154.886-3.624-8.135-13.61-67.329-121.692-71.838-123.785-31.974-51.302-8.456-30.765c-2.98-12.645-5.154-23.275-5.154-36.242l37.127-50.416%2020.537-6.604%2049.53%206.604%2020.86%2018.121%2030.765%2070.39%2049.852%20110.818%2077.315%20150.684%2022.631%2044.698%2012.08%2041.396%204.51%2012.645h7.813v-7.248l6.362-84.886%2011.759-104.215%2011.436-134.094%203.946-37.772%2018.685-45.262%2037.127-24.482%2028.994%2013.852%2023.839%2034.148-3.303%2022.067-14.174%2092.134-27.785%20144.323-18.121%2096.644h10.55l12.08-12.08%2048.887-64.913%2082.147-102.685%2036.242-40.752%2042.282-45.02%2027.14-21.423h51.303l37.772%2056.135-16.913%2057.986-52.832%2067.007-43.812%2056.779-62.82%2084.563-39.22%2067.651%203.623%205.396%209.343-.886%20141.906-30.201%2076.671-13.852%2091.49-15.705%2041.396%2019.329%204.51%2019.65-16.269%2040.189-97.852%2024.16-114.764%2022.954-170.9%2040.43-2.093%201.53%202.416%202.98%2076.993%207.248%2032.94%201.771h80.617l150.12%2011.195%2039.222%2025.933%2023.517%2031.732-3.946%2024.16-60.403%2030.766-81.503-19.33-190.228-45.26-65.235-16.27h-9.02v5.397l54.362%2053.154%2099.624%2089.96%20124.752%20115.973%206.362%2028.671-16.027%2022.63-16.912-2.415-109.611-82.47-42.282-37.127-95.758-80.618h-6.363v8.456l22.067%2032.296%20116.537%20175.167%206.04%2053.719-8.456%2017.476-30.201%2010.55-33.181-6.04-68.215-95.758-70.39-107.84-56.778-96.644-6.926%203.947-33.503%20360.886-15.705%2018.443-36.243%2013.852-30.201-22.953-16.027-37.127%2016.027-73.37%2019.329-95.758%2015.704-76.107%2014.175-94.55%208.456-31.41-.563-2.094-6.927.886-71.275%2097.852-108.402%20146.497-85.772%2091.812-20.537%208.134-35.597-18.443%203.301-32.94%2019.893-29.315%20118.712-151.007%2071.597-93.583%2046.228-54.04-.322-7.813h-2.738l-315.302%20204.725-56.135%207.248-24.16-22.63%202.98-37.128%2011.435-12.08%2094.792-65.236-.322.323z'%20fill='%23d97757'/%3e%3c/svg%3e";
|
|
962
1291
|
const OpenAILogoSvg = "data:image/svg+xml,%3csvg%20height='2500'%20viewBox='-1%20-.1%20949.1%20959.8'%20width='2474'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='m925.8%20456.3c10.4%2023.2%2017%2048%2019.7%2073.3%202.6%2025.3%201.3%2050.9-4.1%2075.8-5.3%2024.9-14.5%2048.8-27.3%2070.8-8.4%2014.7-18.3%2028.5-29.7%2041.2-11.3%2012.6-23.9%2024-37.6%2034-13.8%2010-28.5%2018.4-44.1%2025.3-15.5%206.8-31.7%2012-48.3%2015.4-7.8%2024.2-19.4%2047.1-34.4%2067.7-14.9%2020.6-33%2038.7-53.6%2053.6-20.6%2015-43.4%2026.6-67.6%2034.4-24.2%207.9-49.5%2011.8-75%2011.8-16.9.1-33.9-1.7-50.5-5.1-16.5-3.5-32.7-8.8-48.2-15.7s-30.2-15.5-43.9-25.5c-13.6-10-26.2-21.5-37.4-34.2-25%205.4-50.6%206.7-75.9%204.1-25.3-2.7-50.1-9.3-73.4-19.7-23.2-10.3-44.7-24.3-63.6-41.4s-35-37.1-47.7-59.1c-8.5-14.7-15.5-30.2-20.8-46.3s-8.8-32.7-10.6-49.6c-1.8-16.8-1.7-33.8.1-50.7%201.8-16.8%205.5-33.4%2010.8-49.5-17-18.9-31-40.4-41.4-63.6-10.3-23.3-17-48-19.6-73.3-2.7-25.3-1.3-50.9%204-75.8s14.5-48.8%2027.3-70.8c8.4-14.7%2018.3-28.6%2029.6-41.2s24-24%2037.7-34%2028.5-18.5%2044-25.3c15.6-6.9%2031.8-12%2048.4-15.4%207.8-24.3%2019.4-47.1%2034.3-67.7%2015-20.6%2033.1-38.7%2053.7-53.7%2020.6-14.9%2043.4-26.5%2067.6-34.4%2024.2-7.8%2049.5-11.8%2075-11.7%2016.9-.1%2033.9%201.6%2050.5%205.1s32.8%208.7%2048.3%2015.6c15.5%207%2030.2%2015.5%2043.9%2025.5%2013.7%2010.1%2026.3%2021.5%2037.5%2034.2%2024.9-5.3%2050.5-6.6%2075.8-4s50%209.3%2073.3%2019.6c23.2%2010.4%2044.7%2024.3%2063.6%2041.4%2018.9%2017%2035%2036.9%2047.7%2059%208.5%2014.6%2015.5%2030.1%2020.8%2046.3%205.3%2016.1%208.9%2032.7%2010.6%2049.6%201.8%2016.9%201.8%2033.9-.1%2050.8-1.8%2016.9-5.5%2033.5-10.8%2049.6%2017.1%2018.9%2031%2040.3%2041.4%2063.6zm-333.2%20426.9c21.8-9%2041.6-22.3%2058.3-39s30-36.5%2039-58.4c9-21.8%2013.7-45.2%2013.7-68.8v-223q-.1-.3-.2-.7-.1-.3-.3-.6-.2-.3-.5-.5-.3-.3-.6-.4l-80.7-46.6v269.4c0%202.7-.4%205.5-1.1%208.1-.7%202.7-1.7%205.2-3.1%207.6s-3%204.6-5%206.5a32.1%2032.1%200%200%201%20-6.5%205l-191.1%20110.3c-1.6%201-4.3%202.4-5.7%203.2%207.9%206.7%2016.5%2012.6%2025.5%2017.8%209.1%205.2%2018.5%209.6%2028.3%2013.2%209.8%203.5%2019.9%206.2%2030.1%208%2010.3%201.8%2020.7%202.7%2031.1%202.7%2023.6%200%2047-4.7%2068.8-13.8zm-455.1-151.4c11.9%2020.5%2027.6%2038.3%2046.3%2052.7%2018.8%2014.4%2040.1%2024.9%2062.9%2031s46.6%207.7%2070%204.6%2045.9-10.7%2066.4-22.5l193.2-111.5.5-.5q.2-.2.3-.6.2-.3.3-.6v-94l-233.2%20134.9c-2.4%201.4-4.9%202.4-7.5%203.2-2.7.7-5.4%201-8.2%201-2.7%200-5.4-.3-8.1-1-2.6-.8-5.2-1.8-7.6-3.2l-191.1-110.4c-1.7-1-4.2-2.5-5.6-3.4-1.8%2010.3-2.7%2020.7-2.7%2031.1s1%2020.8%202.8%2031.1c1.8%2010.2%204.6%2020.3%208.1%2030.1%203.6%209.8%208%2019.2%2013.2%2028.2zm-50.2-417c-11.8%2020.5-19.4%2043.1-22.5%2066.5s-1.5%2047.1%204.6%2070c6.1%2022.8%2016.6%2044.1%2031%2062.9%2014.4%2018.7%2032.3%2034.4%2052.7%2046.2l193.1%20111.6q.3.1.7.2h.7q.4%200%20.7-.2.3-.1.6-.3l81-46.8-233.2-134.6c-2.3-1.4-4.5-3.1-6.5-5a32.1%2032.1%200%200%201%20-5-6.5c-1.3-2.4-2.4-4.9-3.1-7.6-.7-2.6-1.1-5.3-1-8.1v-227.1c-9.8%203.6-19.3%208-28.3%2013.2-9%205.3-17.5%2011.3-25.5%2018-7.9%206.7-15.3%2014.1-22%2022.1-6.7%207.9-12.6%2016.5-17.8%2025.5zm663.3%20154.4c2.4%201.4%204.6%203%206.6%205%201.9%201.9%203.6%204.1%205%206.5%201.3%202.4%202.4%205%203.1%207.6.6%202.7%201%205.4.9%208.2v227.1c32.1-11.8%2060.1-32.5%2080.8-59.7%2020.8-27.2%2033.3-59.7%2036.2-93.7s-3.9-68.2-19.7-98.5-39.9-55.5-69.5-72.5l-193.1-111.6q-.3-.1-.7-.2h-.7q-.3.1-.7.2-.3.1-.6.3l-80.6%2046.6%20233.2%20134.7zm80.5-121h-.1v.1zm-.1-.1c5.8-33.6%201.9-68.2-11.3-99.7-13.1-31.5-35-58.6-63-78.2-28-19.5-61-30.7-95.1-32.2-34.2-1.4-68%206.9-97.6%2023.9l-193.1%20111.5q-.3.2-.5.5l-.4.6q-.1.3-.2.7-.1.3-.1.7v93.2l233.2-134.7c2.4-1.4%205-2.4%207.6-3.2%202.7-.7%205.4-1%208.1-1%202.8%200%205.5.3%208.2%201%202.6.8%205.1%201.8%207.5%203.2l191.1%20110.4c1.7%201%204.2%202.4%205.6%203.3zm-505.3-103.2c0-2.7.4-5.4%201.1-8.1.7-2.6%201.7-5.2%203.1-7.6%201.4-2.3%203-4.5%205-6.5%201.9-1.9%204.1-3.6%206.5-4.9l191.1-110.3c1.8-1.1%204.3-2.5%205.7-3.2-26.2-21.9-58.2-35.9-92.1-40.2-33.9-4.4-68.3%201-99.2%2015.5-31%2014.5-57.2%2037.6-75.5%2066.4-18.3%2028.9-28%2062.3-28%2096.5v223q.1.4.2.7.1.3.3.6.2.3.5.6.2.2.6.4l80.7%2046.6zm43.8%20294.7%20103.9%2060%20103.9-60v-119.9l-103.8-60-103.9%2060z'/%3e%3c/svg%3e";
|
|
963
1292
|
const DeepSeekLogoSvg = "data:image/svg+xml,%3csvg%20fill='none'%20height='1320'%20viewBox='3.771%206.973%2023.993%2017.652'%20width='2500'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='m27.501%208.469c-.252-.123-.36.111-.508.23-.05.04-.093.09-.135.135-.368.395-.797.652-1.358.621-.821-.045-1.521.213-2.14.842-.132-.776-.57-1.238-1.235-1.535-.349-.155-.701-.309-.944-.645-.171-.238-.217-.504-.303-.765-.054-.159-.108-.32-.29-.348-.197-.031-.274.135-.352.273-.31.567-.43%201.192-.419%201.825.028%201.421.628%202.554%201.82%203.36.136.093.17.186.128.321-.081.278-.178.547-.264.824-.054.178-.135.217-.324.14a5.448%205.448%200%200%201%20-1.719-1.169c-.848-.82-1.614-1.726-2.57-2.435-.225-.166-.449-.32-.681-.467-.976-.95.128-1.729.383-1.82.267-.096.093-.428-.77-.424s-1.653.293-2.659.677a2.782%202.782%200%200%201%20-.46.135%209.554%209.554%200%200%200%20-2.853-.1c-1.866.21-3.356%201.092-4.452%202.6-1.315%201.81-1.625%203.87-1.246%206.018.399%202.261%201.552%204.136%203.326%205.601%201.837%201.518%203.955%202.262%206.37%202.12%201.466-.085%203.1-.282%204.942-1.842.465.23.952.322%201.762.392.623.059%201.223-.031%201.687-.127.728-.154.677-.828.414-.953-2.132-.994-1.665-.59-2.09-.916%201.084-1.285%202.717-2.619%203.356-6.94.05-.343.007-.558%200-.837-.004-.168.034-.235.228-.254a4.084%204.084%200%200%200%201.529-.47c1.382-.757%201.938-1.997%202.07-3.485.02-.227-.004-.463-.243-.582zm-12.041%2013.391c-2.067-1.627-3.07-2.162-3.483-2.138-.387.021-.318.465-.233.754.089.285.205.482.368.732.113.166.19.414-.112.598-.666.414-1.823-.139-1.878-.166-1.347-.793-2.473-1.842-3.267-3.276-.765-1.38-1.21-2.861-1.284-4.441-.02-.383.093-.518.472-.586a4.692%204.692%200%200%201%201.514-.04c2.109.31%203.905%201.255%205.41%202.749.86.853%201.51%201.871%202.18%202.865.711%201.057%201.478%202.063%202.454%202.887.343.289.619.51.881.672-.792.088-2.117.107-3.022-.61zm.99-6.38a.304.304%200%201%201%20.609%200c0%20.17-.136.304-.306.304a.3.3%200%200%201%20-.303-.305zm3.077%201.581c-.197.08-.394.15-.584.159a1.246%201.246%200%200%201%20-.79-.252c-.27-.227-.463-.354-.546-.752a1.752%201.752%200%200%201%20.016-.582c.07-.324-.008-.531-.235-.72-.187-.155-.422-.196-.682-.196a.551.551%200%200%201%20-.252-.078c-.108-.055-.197-.19-.112-.356.027-.053.159-.183.19-.207.352-.201.758-.135%201.134.016.349.142.611.404.99.773.388.448.457.573.678.906.174.264.333.534.441.842.066.192-.02.35-.248.448z'%20fill='%234d6bfe'/%3e%3c/svg%3e";
|
|
@@ -1958,6 +2287,12 @@ function StreamingChunkSequence({
|
|
|
1958
2287
|
function shouldShowRawRequestTab(apiFormat, viewMode, strip) {
|
|
1959
2288
|
return apiFormat === "anthropic" && viewMode === "full" && strip;
|
|
1960
2289
|
}
|
|
2290
|
+
function shouldShowHeadersDiffButton(viewMode, hasRawHeaders) {
|
|
2291
|
+
return viewMode === "full" && hasRawHeaders;
|
|
2292
|
+
}
|
|
2293
|
+
function shouldShowRequestDiffButton(apiFormat, viewMode, strip, hasRawRequest) {
|
|
2294
|
+
return apiFormat === "anthropic" && viewMode === "full" && strip && hasRawRequest;
|
|
2295
|
+
}
|
|
1961
2296
|
function CopyButton({
|
|
1962
2297
|
text,
|
|
1963
2298
|
label,
|
|
@@ -1981,17 +2316,41 @@ function CopyButton({
|
|
|
1981
2316
|
}
|
|
1982
2317
|
);
|
|
1983
2318
|
}
|
|
2319
|
+
function DiffToggleButton({
|
|
2320
|
+
active,
|
|
2321
|
+
onClick
|
|
2322
|
+
}) {
|
|
2323
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
2324
|
+
"button",
|
|
2325
|
+
{
|
|
2326
|
+
type: "button",
|
|
2327
|
+
onClick,
|
|
2328
|
+
"aria-pressed": active,
|
|
2329
|
+
className: cn(
|
|
2330
|
+
"flex items-center gap-1.5 text-xs px-2 py-1 rounded transition-colors",
|
|
2331
|
+
active ? "bg-primary/10 text-primary" : "text-muted-foreground hover:text-foreground hover:bg-muted"
|
|
2332
|
+
),
|
|
2333
|
+
title: active ? "Hide diff with raw" : "Diff this view against the raw version",
|
|
2334
|
+
children: [
|
|
2335
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(GitCompareArrows, { className: "size-3" }),
|
|
2336
|
+
active ? "Showing diff" : "Diff with Raw"
|
|
2337
|
+
]
|
|
2338
|
+
}
|
|
2339
|
+
);
|
|
2340
|
+
}
|
|
1984
2341
|
const LogEntry = reactExports.memo(function({
|
|
1985
2342
|
log,
|
|
1986
2343
|
viewMode = "simple",
|
|
1987
|
-
suppressApiFormatBadge = false
|
|
2344
|
+
suppressApiFormatBadge = false,
|
|
2345
|
+
strip
|
|
1988
2346
|
}) {
|
|
1989
2347
|
const [expanded, setExpanded] = reactExports.useState(false);
|
|
1990
2348
|
const [requestCopied, setRequestCopied] = reactExports.useState(false);
|
|
1991
2349
|
const [rawRequestCopied, setRawRequestCopied] = reactExports.useState(false);
|
|
1992
2350
|
const [responseCopied, setResponseCopied] = reactExports.useState(false);
|
|
1993
2351
|
const [replayOpen, setReplayOpen] = reactExports.useState(false);
|
|
1994
|
-
const
|
|
2352
|
+
const [headersDiff, setHeadersDiff] = reactExports.useState(false);
|
|
2353
|
+
const [requestDiff, setRequestDiff] = reactExports.useState(false);
|
|
1995
2354
|
const parsedRequest = reactExports.useMemo(() => parseRequest(log.rawRequestBody), [log.rawRequestBody]);
|
|
1996
2355
|
const strippedRequestBody = reactExports.useMemo(() => {
|
|
1997
2356
|
if (!strip || log.apiFormat !== "anthropic" || log.rawRequestBody === null) {
|
|
@@ -2000,6 +2359,14 @@ const LogEntry = reactExports.memo(function({
|
|
|
2000
2359
|
return stripClaudeCodeBillingHeader(log.rawRequestBody).body;
|
|
2001
2360
|
}, [log.rawRequestBody, log.apiFormat, strip]);
|
|
2002
2361
|
const displayedRequestBody = strippedRequestBody ?? log.rawRequestBody;
|
|
2362
|
+
const headersDiffResult = reactExports.useMemo(
|
|
2363
|
+
() => computeHeadersDiff(log.rawHeaders, log.headers),
|
|
2364
|
+
[log.rawHeaders, log.headers]
|
|
2365
|
+
);
|
|
2366
|
+
const requestDiffResult = reactExports.useMemo(
|
|
2367
|
+
() => computeRequestDiff(log.rawRequestBody, displayedRequestBody),
|
|
2368
|
+
[log.rawRequestBody, displayedRequestBody]
|
|
2369
|
+
);
|
|
2003
2370
|
function handleCopyRequest(e) {
|
|
2004
2371
|
e.stopPropagation();
|
|
2005
2372
|
if (displayedRequestBody === null) return;
|
|
@@ -2059,6 +2426,21 @@ const LogEntry = reactExports.memo(function({
|
|
|
2059
2426
|
] }) }),
|
|
2060
2427
|
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "request", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-3", children: [
|
|
2061
2428
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-end gap-2 mb-2", children: [
|
|
2429
|
+
shouldShowRequestDiffButton(
|
|
2430
|
+
log.apiFormat,
|
|
2431
|
+
viewMode,
|
|
2432
|
+
strip,
|
|
2433
|
+
log.rawRequestBody !== null
|
|
2434
|
+
) && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2435
|
+
DiffToggleButton,
|
|
2436
|
+
{
|
|
2437
|
+
active: requestDiff,
|
|
2438
|
+
onClick: (e) => {
|
|
2439
|
+
e.stopPropagation();
|
|
2440
|
+
setRequestDiff(!requestDiff);
|
|
2441
|
+
}
|
|
2442
|
+
}
|
|
2443
|
+
),
|
|
2062
2444
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
2063
2445
|
Button,
|
|
2064
2446
|
{
|
|
@@ -2085,15 +2467,42 @@ const LogEntry = reactExports.memo(function({
|
|
|
2085
2467
|
}
|
|
2086
2468
|
)
|
|
2087
2469
|
] }),
|
|
2088
|
-
|
|
2470
|
+
requestDiff ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2471
|
+
DiffView,
|
|
2472
|
+
{
|
|
2473
|
+
result: requestDiffResult,
|
|
2474
|
+
emptyLabel: "No transformation applied — raw and sent request bodies are identical."
|
|
2475
|
+
}
|
|
2476
|
+
) : displayedRequestBody !== null ? /* @__PURE__ */ jsxRuntimeExports.jsx(JsonViewerFromString, { text: displayedRequestBody, defaultExpandDepth: 1 }) : /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground italic", children: "No request body" })
|
|
2477
|
+
] }) }),
|
|
2478
|
+
viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "headers", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-3", children: [
|
|
2479
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex justify-end gap-2 mb-2", children: shouldShowHeadersDiffButton(
|
|
2480
|
+
viewMode,
|
|
2481
|
+
log.rawHeaders !== void 0 && Object.keys(log.rawHeaders).length > 0
|
|
2482
|
+
) && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2483
|
+
DiffToggleButton,
|
|
2484
|
+
{
|
|
2485
|
+
active: headersDiff,
|
|
2486
|
+
onClick: (e) => {
|
|
2487
|
+
e.stopPropagation();
|
|
2488
|
+
setHeadersDiff(!headersDiff);
|
|
2489
|
+
}
|
|
2490
|
+
}
|
|
2491
|
+
) }),
|
|
2492
|
+
headersDiff ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2493
|
+
DiffView,
|
|
2494
|
+
{
|
|
2495
|
+
result: headersDiffResult,
|
|
2496
|
+
emptyLabel: "No transformation applied — raw and processed headers are identical."
|
|
2497
|
+
}
|
|
2498
|
+
) : log.headers && Object.keys(log.headers).length > 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1 font-mono text-xs", children: Object.entries(log.headers).sort(([a], [b]) => a.localeCompare(b)).map(([key, value]) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
|
|
2499
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-blue-600 dark:text-blue-400 font-semibold shrink-0", children: [
|
|
2500
|
+
key,
|
|
2501
|
+
":"
|
|
2502
|
+
] }),
|
|
2503
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground truncate", title: value, children: value })
|
|
2504
|
+
] }, key)) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground italic", children: "No headers captured" })
|
|
2089
2505
|
] }) }),
|
|
2090
|
-
viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "headers", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-4 py-3", children: log.headers && Object.keys(log.headers).length > 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1 font-mono text-xs", children: Object.entries(log.headers).sort(([a], [b]) => a.localeCompare(b)).map(([key, value]) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
|
|
2091
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-blue-600 dark:text-blue-400 font-semibold shrink-0", children: [
|
|
2092
|
-
key,
|
|
2093
|
-
":"
|
|
2094
|
-
] }),
|
|
2095
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground truncate", title: value, children: value })
|
|
2096
|
-
] }, key)) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground italic", children: "No headers captured" }) }) }),
|
|
2097
2506
|
viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "raw-headers", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-4 py-3", children: log.rawHeaders && Object.keys(log.rawHeaders).length > 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1 font-mono text-xs", children: Object.entries(log.rawHeaders).sort(([a], [b]) => a.localeCompare(b)).map(([key, value]) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
|
|
2098
2507
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-blue-600 dark:text-blue-400 font-semibold shrink-0", children: [
|
|
2099
2508
|
key,
|
|
@@ -2154,7 +2563,8 @@ function computeStats(logs) {
|
|
|
2154
2563
|
}
|
|
2155
2564
|
const ConversationGroup = reactExports.memo(function({
|
|
2156
2565
|
group,
|
|
2157
|
-
viewMode = "simple"
|
|
2566
|
+
viewMode = "simple",
|
|
2567
|
+
strip
|
|
2158
2568
|
}) {
|
|
2159
2569
|
const [expanded, setExpanded] = reactExports.useState(false);
|
|
2160
2570
|
const stats = computeStats(group.logs);
|
|
@@ -2178,9 +2588,46 @@ const ConversationGroup = reactExports.memo(function({
|
|
|
2178
2588
|
hideApiFormat: mixed
|
|
2179
2589
|
}
|
|
2180
2590
|
),
|
|
2181
|
-
expanded && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "pl-4 border-l-2 border-muted ml-3", children: group.logs.map((log) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2591
|
+
expanded && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "pl-4 border-l-2 border-muted ml-3", children: group.logs.map((log) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2592
|
+
LogEntry,
|
|
2593
|
+
{
|
|
2594
|
+
log,
|
|
2595
|
+
viewMode,
|
|
2596
|
+
suppressApiFormatBadge: !mixed,
|
|
2597
|
+
strip
|
|
2598
|
+
},
|
|
2599
|
+
log.id
|
|
2600
|
+
)) })
|
|
2182
2601
|
] });
|
|
2183
2602
|
});
|
|
2603
|
+
function CrabLogo({ className }) {
|
|
2604
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
2605
|
+
"svg",
|
|
2606
|
+
{
|
|
2607
|
+
viewBox: "0 0 24 24",
|
|
2608
|
+
fill: "none",
|
|
2609
|
+
stroke: "currentColor",
|
|
2610
|
+
strokeWidth: "1.5",
|
|
2611
|
+
strokeLinecap: "round",
|
|
2612
|
+
strokeLinejoin: "round",
|
|
2613
|
+
"aria-hidden": "true",
|
|
2614
|
+
className: cn("inline-block size-5", className),
|
|
2615
|
+
children: [
|
|
2616
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M5 13 C5 9 8 7 12 7 C16 7 19 9 19 13 C19 16 16 18 12 18 C8 18 5 16 5 13 Z" }),
|
|
2617
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M5 11 C3.5 9.5 1.5 10 2 12.5 C2.5 14 4 13.5 5 12.5" }),
|
|
2618
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M19 11 C20.5 9.5 22.5 10 22 12.5 C21.5 14 20 13.5 19 12.5" }),
|
|
2619
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10", y1: "7", x2: "9.5", y2: "5" }),
|
|
2620
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14", y1: "7", x2: "14.5", y2: "5" }),
|
|
2621
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "9.5", cy: "4.5", r: "0.9", fill: "currentColor", stroke: "none" }),
|
|
2622
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "14.5", cy: "4.5", r: "0.9", fill: "currentColor", stroke: "none" }),
|
|
2623
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "6.5", y1: "16", x2: "4.5", y2: "19.5" }),
|
|
2624
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "9", y1: "17.5", x2: "8", y2: "20.5" }),
|
|
2625
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "15", y1: "17.5", x2: "16", y2: "20.5" }),
|
|
2626
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "17.5", y1: "16", x2: "19.5", y2: "19.5" })
|
|
2627
|
+
]
|
|
2628
|
+
}
|
|
2629
|
+
);
|
|
2630
|
+
}
|
|
2184
2631
|
function Select({
|
|
2185
2632
|
...props
|
|
2186
2633
|
}) {
|
|
@@ -3334,7 +3781,8 @@ function ProxyViewer({
|
|
|
3334
3781
|
onModelChange,
|
|
3335
3782
|
onClearAll,
|
|
3336
3783
|
viewMode,
|
|
3337
|
-
onViewModeChange
|
|
3784
|
+
onViewModeChange,
|
|
3785
|
+
strip
|
|
3338
3786
|
}) {
|
|
3339
3787
|
const { totalIn, totalOut } = computeTokenSummary(logs);
|
|
3340
3788
|
const [groupedView, setGroupedView] = reactExports.useState(true);
|
|
@@ -3359,7 +3807,10 @@ function ProxyViewer({
|
|
|
3359
3807
|
});
|
|
3360
3808
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "max-w-[1200px] mx-auto flex flex-col h-screen", style: { maxHeight: "100vh" }, children: [
|
|
3361
3809
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-4 mb-4 px-6 pt-6", children: [
|
|
3362
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
3810
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("h1", { className: "text-lg font-bold flex-1 flex items-center gap-2", children: [
|
|
3811
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(CrabLogo, { className: "size-10 text-amber-500" }),
|
|
3812
|
+
"LLM Inspector"
|
|
3813
|
+
] }),
|
|
3363
3814
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground text-xs font-mono", children: [
|
|
3364
3815
|
"v",
|
|
3365
3816
|
packageJson.version
|
|
@@ -3484,7 +3935,7 @@ function ProxyViewer({
|
|
|
3484
3935
|
width: "100%",
|
|
3485
3936
|
transform: `translateY(${virtualRow.start}px)`
|
|
3486
3937
|
},
|
|
3487
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsx(ConversationGroup, { group, viewMode })
|
|
3938
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(ConversationGroup, { group, viewMode, strip })
|
|
3488
3939
|
},
|
|
3489
3940
|
group.id
|
|
3490
3941
|
);
|
|
@@ -3503,7 +3954,7 @@ function ProxyViewer({
|
|
|
3503
3954
|
width: "100%",
|
|
3504
3955
|
transform: `translateY(${virtualRow.start}px)`
|
|
3505
3956
|
},
|
|
3506
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsx(LogEntry, { log, viewMode })
|
|
3957
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(LogEntry, { log, viewMode, strip })
|
|
3507
3958
|
},
|
|
3508
3959
|
log.id
|
|
3509
3960
|
);
|
|
@@ -3664,6 +4115,7 @@ function ProxyViewerContainer() {
|
|
|
3664
4115
|
}
|
|
3665
4116
|
})();
|
|
3666
4117
|
}, []);
|
|
4118
|
+
const { strip } = useStripConfig();
|
|
3667
4119
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
3668
4120
|
error !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fixed top-4 right-4 bg-destructive text-destructive-foreground px-4 py-2 rounded-md text-sm z-50", children: error }),
|
|
3669
4121
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -3678,7 +4130,8 @@ function ProxyViewerContainer() {
|
|
|
3678
4130
|
onModelChange: setSelectedModel,
|
|
3679
4131
|
onClearAll: handleClearAll,
|
|
3680
4132
|
viewMode,
|
|
3681
|
-
onViewModeChange: setViewMode
|
|
4133
|
+
onViewModeChange: setViewMode,
|
|
4134
|
+
strip
|
|
3682
4135
|
}
|
|
3683
4136
|
)
|
|
3684
4137
|
] });
|