@tonyclaw/llm-inspector 1.16.3 → 1.16.4

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.
@@ -70,7 +70,7 @@ function RootDocument({ children }) {
70
70
  ] })
71
71
  ] });
72
72
  }
73
- const $$splitComponentImporter = () => import("./index-CjvQZBI0.mjs");
73
+ const $$splitComponentImporter = () => import("./index-C-z-fZtq.mjs");
74
74
  const Route$j = createFileRoute("/")({
75
75
  component: lazyRouteComponent($$splitComponentImporter, "component")
76
76
  });
@@ -1,4 +1,4 @@
1
- const tsrStartManifest = () => ({ "routes": { "__root__": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/__root.tsx", "children": ["/", "/api/config", "/api/health", "/api/logs", "/api/mcp", "/api/models", "/api/providers", "/api/sessions", "/proxy/$"], "preloads": ["/assets/main-Cpts3Ifr.js"], "assets": [] }, "/": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/index.tsx", "assets": [], "preloads": ["/assets/index-DfjhkDNi.js"] }, "/api/config": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/config.ts", "children": ["/api/config/paths"] }, "/api/health": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/health.ts" }, "/api/logs": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/logs.ts", "children": ["/api/logs/$id", "/api/logs/stream"] }, "/api/mcp": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/mcp.ts" }, "/api/models": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/models.ts" }, "/api/providers": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.ts", "children": ["/api/providers/$providerId", "/api/providers/export", "/api/providers/import", "/api/providers/scan"] }, "/api/sessions": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/sessions.ts" }, "/proxy/$": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/proxy/$.ts" }, "/api/config/paths": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/config.paths.ts" }, "/api/logs/$id": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/logs.$id.ts", "children": ["/api/logs/$id/chunks", "/api/logs/$id/replay"] }, "/api/logs/stream": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/logs.stream.ts" }, "/api/providers/$providerId": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.$providerId.ts", "children": ["/api/providers/$providerId/test"] }, "/api/providers/export": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.export.ts" }, "/api/providers/import": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.import.ts" }, "/api/providers/scan": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.scan.ts" }, "/api/logs/$id/chunks": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/logs.$id.chunks.ts" }, "/api/logs/$id/replay": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/logs.$id.replay.ts" }, "/api/providers/$providerId/test": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.$providerId.test.ts", "children": ["/api/providers/$providerId/test/log"] }, "/api/providers/$providerId/test/log": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.$providerId.test.log.ts" } }, "clientEntry": "/assets/main-Cpts3Ifr.js" });
1
+ const tsrStartManifest = () => ({ "routes": { "__root__": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/__root.tsx", "children": ["/", "/api/config", "/api/health", "/api/logs", "/api/mcp", "/api/models", "/api/providers", "/api/sessions", "/proxy/$"], "preloads": ["/assets/main-DbWwVQFh.js"], "assets": [] }, "/": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/index.tsx", "assets": [], "preloads": ["/assets/index-X7CHS7fS.js"] }, "/api/config": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/config.ts", "children": ["/api/config/paths"] }, "/api/health": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/health.ts" }, "/api/logs": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/logs.ts", "children": ["/api/logs/$id", "/api/logs/stream"] }, "/api/mcp": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/mcp.ts" }, "/api/models": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/models.ts" }, "/api/providers": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.ts", "children": ["/api/providers/$providerId", "/api/providers/export", "/api/providers/import", "/api/providers/scan"] }, "/api/sessions": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/sessions.ts" }, "/proxy/$": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/proxy/$.ts" }, "/api/config/paths": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/config.paths.ts" }, "/api/logs/$id": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/logs.$id.ts", "children": ["/api/logs/$id/chunks", "/api/logs/$id/replay"] }, "/api/logs/stream": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/logs.stream.ts" }, "/api/providers/$providerId": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.$providerId.ts", "children": ["/api/providers/$providerId/test"] }, "/api/providers/export": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.export.ts" }, "/api/providers/import": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.import.ts" }, "/api/providers/scan": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.scan.ts" }, "/api/logs/$id/chunks": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/logs.$id.chunks.ts" }, "/api/logs/$id/replay": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/logs.$id.replay.ts" }, "/api/providers/$providerId/test": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.$providerId.test.ts", "children": ["/api/providers/$providerId/test/log"] }, "/api/providers/$providerId/test/log": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.$providerId.test.log.ts" } }, "clientEntry": "/assets/main-DbWwVQFh.js" });
2
2
  export {
3
3
  tsrStartManifest
4
4
  };
@@ -35,54 +35,54 @@ const headers = ((m) => function headersRouteRule(event) {
35
35
  }
36
36
  });
37
37
  const assets = {
38
- "/assets/index-DRRCmu5p.css": {
39
- "type": "text/css; charset=utf-8",
40
- "etag": '"15b6a-YPwntwMQpIU2AWIj8lgGWZpCwQw"',
41
- "mtime": "2026-06-13T12:48:36.706Z",
42
- "size": 88938,
43
- "path": "../public/assets/index-DRRCmu5p.css"
44
- },
45
38
  "/assets/minimax-BPMzvuL-.jpeg": {
46
39
  "type": "image/jpeg",
47
40
  "etag": '"1b06-IwivU89ko5UTMUM1/t7hn4sQK9A"',
48
- "mtime": "2026-06-13T12:48:36.706Z",
41
+ "mtime": "2026-06-15T02:31:02.872Z",
49
42
  "size": 6918,
50
43
  "path": "../public/assets/minimax-BPMzvuL-.jpeg"
51
44
  },
52
- "/assets/main-Cpts3Ifr.js": {
53
- "type": "text/javascript; charset=utf-8",
54
- "etag": '"50599-992xZ6dW7zT04aVitINzzELxGm4"',
55
- "mtime": "2026-06-13T12:48:36.706Z",
56
- "size": 329113,
57
- "path": "../public/assets/main-Cpts3Ifr.js"
58
- },
59
45
  "/assets/alibaba-TTwafVwX.svg": {
60
46
  "type": "image/svg+xml",
61
47
  "etag": '"171b-6dyV5K8QjiaY35sN9qNprh9zDIs"',
62
- "mtime": "2026-06-13T12:48:36.706Z",
48
+ "mtime": "2026-06-15T02:31:02.873Z",
63
49
  "size": 5915,
64
50
  "path": "../public/assets/alibaba-TTwafVwX.svg"
65
51
  },
66
- "/assets/qwen-CONDcHqt.png": {
67
- "type": "image/png",
68
- "etag": '"572c3-cdJAPaHdOvFCGzuaQjagdgOu6XE"',
69
- "mtime": "2026-06-13T12:48:36.706Z",
70
- "size": 357059,
71
- "path": "../public/assets/qwen-CONDcHqt.png"
52
+ "/assets/index-DRRCmu5p.css": {
53
+ "type": "text/css; charset=utf-8",
54
+ "etag": '"15b6a-YPwntwMQpIU2AWIj8lgGWZpCwQw"',
55
+ "mtime": "2026-06-15T02:31:02.875Z",
56
+ "size": 88938,
57
+ "path": "../public/assets/index-DRRCmu5p.css"
58
+ },
59
+ "/assets/main-DbWwVQFh.js": {
60
+ "type": "text/javascript; charset=utf-8",
61
+ "etag": '"50599-mPNNNxfSpwFWn5i6kPquWEqJjGk"',
62
+ "mtime": "2026-06-15T02:31:02.875Z",
63
+ "size": 329113,
64
+ "path": "../public/assets/main-DbWwVQFh.js"
72
65
  },
73
66
  "/assets/zhipuai-BPNAnxo-.svg": {
74
67
  "type": "image/svg+xml",
75
68
  "etag": '"2bf8-hNaLCTi89nOFCsIIfWpP/jrfo0s"',
76
- "mtime": "2026-06-13T12:48:36.703Z",
69
+ "mtime": "2026-06-15T02:31:02.873Z",
77
70
  "size": 11256,
78
71
  "path": "../public/assets/zhipuai-BPNAnxo-.svg"
79
72
  },
80
- "/assets/index-DfjhkDNi.js": {
73
+ "/assets/qwen-CONDcHqt.png": {
74
+ "type": "image/png",
75
+ "etag": '"572c3-cdJAPaHdOvFCGzuaQjagdgOu6XE"',
76
+ "mtime": "2026-06-15T02:31:02.875Z",
77
+ "size": 357059,
78
+ "path": "../public/assets/qwen-CONDcHqt.png"
79
+ },
80
+ "/assets/index-X7CHS7fS.js": {
81
81
  "type": "text/javascript; charset=utf-8",
82
- "etag": '"9be42-R0QrjTKfN+Fk+ayVkm0/P4pzR2w"',
83
- "mtime": "2026-06-13T12:48:36.706Z",
84
- "size": 638530,
85
- "path": "../public/assets/index-DfjhkDNi.js"
82
+ "etag": '"9c554-RW/7IDotWnzOK06cvwJGAOWPrdk"',
83
+ "mtime": "2026-06-15T02:31:02.875Z",
84
+ "size": 640340,
85
+ "path": "../public/assets/index-X7CHS7fS.js"
86
86
  }
87
87
  };
88
88
  function readAsset(id) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tonyclaw/llm-inspector",
3
- "version": "1.16.3",
3
+ "version": "1.16.4",
4
4
  "type": "module",
5
5
  "description": "LLM API proxy inspector — captures and displays requests/responses from AI coding tools in a web UI",
6
6
  "license": "MIT",
@@ -221,7 +221,7 @@ function EqualRunRow({
221
221
  {ops.map((op) => (
222
222
  <div key={op.path} className="border border-border/50 rounded p-2 bg-muted/20">
223
223
  <div className="font-mono text-xs text-muted-foreground mb-1">{op.path}</div>
224
- <JsonViewerFromString text={nodeToJsonString(op.value)} defaultExpandDepth={2} />
224
+ <JsonViewerFromString text={nodeToJsonString(op.value)} defaultExpandDepth={0} />
225
225
  </div>
226
226
  ))}
227
227
  </div>
@@ -360,8 +360,8 @@ function UnifiedOpRow({
360
360
  ? "text-emerald-500"
361
361
  : "text-muted-foreground/50 hover:text-foreground hover:bg-muted",
362
362
  )}
363
- aria-label={justCopied ? "Copied" : "Copy path"}
364
- title={justCopied ? "Copied!" : "Copy path"}
363
+ aria-label={justCopied ? "Copied" : "Copy"}
364
+ title={justCopied ? "Copied!" : "Copy"}
365
365
  >
366
366
  {justCopied ? <Check className="size-3" /> : <Copy className="size-3" />}
367
367
  </span>
@@ -392,7 +392,7 @@ function ExpandedSubtree({ op }: { op: AddedOp | RemovedOp | ChangedOp }): JSX.E
392
392
  if (op.kind === "added" || op.kind === "removed") {
393
393
  return (
394
394
  <div className="pl-5 mt-2 border border-border/50 rounded p-2 bg-muted/20">
395
- <JsonViewerFromString text={nodeToJsonString(op.value)} defaultExpandDepth={2} />
395
+ <JsonViewerFromString text={nodeToJsonString(op.value)} defaultExpandDepth={0} />
396
396
  </div>
397
397
  );
398
398
  }
@@ -410,11 +410,11 @@ function ExpandedSubtree({ op }: { op: AddedOp | RemovedOp | ChangedOp }): JSX.E
410
410
  <div className="pl-5 mt-2 grid grid-cols-1 md:grid-cols-2 gap-2">
411
411
  <div className="border border-rose-500/30 rounded p-2 bg-rose-500/5">
412
412
  <div className="text-[10px] uppercase tracking-wider text-rose-500 mb-1">Old</div>
413
- <JsonViewerFromString text={nodeToJsonString(op.left)} defaultExpandDepth={2} />
413
+ <JsonViewerFromString text={nodeToJsonString(op.left)} defaultExpandDepth={0} />
414
414
  </div>
415
415
  <div className="border border-emerald-500/30 rounded p-2 bg-emerald-500/5">
416
416
  <div className="text-[10px] uppercase tracking-wider text-emerald-500 mb-1">New</div>
417
- <JsonViewerFromString text={nodeToJsonString(op.right)} defaultExpandDepth={2} />
417
+ <JsonViewerFromString text={nodeToJsonString(op.right)} defaultExpandDepth={0} />
418
418
  </div>
419
419
  </div>
420
420
  );
@@ -6,7 +6,12 @@ import type { CapturedLog } from "../../proxy/schemas";
6
6
  import { stripClaudeCodeBillingHeader } from "../../proxy/claudeCodeStrip";
7
7
  import { Button } from "../ui/button";
8
8
  import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from "../ui/tooltip";
9
- import { JsonViewerFromString } from "../ui/json-viewer";
9
+ import {
10
+ JsonViewer,
11
+ JsonViewerFromString,
12
+ JsonExpansionButton,
13
+ useJsonBulkExpansion,
14
+ } from "../ui/json-viewer";
10
15
  import { Tabs, TabsContent, TabsList, TabsTrigger } from "../ui/tabs";
11
16
  import { computeHeadersDiff, computeRequestDiff, DiffView } from "./diff";
12
17
  import { LogEntryHeader } from "./LogEntryHeader";
@@ -230,6 +235,8 @@ export const LogEntry = memo(function ({
230
235
  const requestCopy = useCopyFeedback(displayedRequestBody);
231
236
  const rawRequestCopy = useCopyFeedback(log.rawRequestBody);
232
237
  const responseCopy = useCopyFeedback(log.responseText);
238
+ const requestExpansion = useJsonBulkExpansion(displayedRequestBody);
239
+ const rawRequestExpansion = useJsonBulkExpansion(log.rawRequestBody);
233
240
 
234
241
  return (
235
242
  <TooltipProvider>
@@ -262,18 +269,32 @@ export const LogEntry = memo(function ({
262
269
  <TabsContent value="raw-request">
263
270
  {activeTab === "raw-request" && (
264
271
  <div className="px-4 py-3">
265
- <div className="flex justify-end mb-2">
272
+ <div className="flex justify-end gap-2 mb-2">
273
+ <JsonExpansionButton
274
+ policy={rawRequestExpansion.policy}
275
+ isExpanded={rawRequestExpansion.isExpanded}
276
+ isPending={rawRequestExpansion.isPending}
277
+ onToggle={rawRequestExpansion.toggle}
278
+ />
266
279
  <CopyButton
267
280
  text={log.rawRequestBody}
268
- label="Copy Raw Request"
281
+ label="Copy"
269
282
  copied={rawRequestCopy.copied}
270
283
  onCopy={rawRequestCopy.copy}
271
284
  />
272
285
  </div>
273
- {log.rawRequestBody !== null ? (
274
- <JsonViewerFromString text={log.rawRequestBody} defaultExpandDepth={1} />
275
- ) : (
286
+ {log.rawRequestBody === null ? (
276
287
  <p className="text-xs text-muted-foreground italic">No request body</p>
288
+ ) : rawRequestExpansion.parsedData !== null ? (
289
+ <JsonViewer
290
+ data={rawRequestExpansion.parsedData}
291
+ bulkDepth={rawRequestExpansion.bulkDepth}
292
+ bulkRevision={rawRequestExpansion.bulkRevision}
293
+ />
294
+ ) : (
295
+ <pre className="font-mono text-xs whitespace-pre-wrap break-words">
296
+ {log.rawRequestBody}
297
+ </pre>
277
298
  )}
278
299
  </div>
279
300
  )}
@@ -336,9 +357,15 @@ export const LogEntry = memo(function ({
336
357
  </TooltipTrigger>
337
358
  <TooltipContent>Re-send this request to the provider</TooltipContent>
338
359
  </Tooltip>
360
+ <JsonExpansionButton
361
+ policy={requestExpansion.policy}
362
+ isExpanded={requestExpansion.isExpanded}
363
+ isPending={requestExpansion.isPending}
364
+ onToggle={requestExpansion.toggle}
365
+ />
339
366
  <CopyButton
340
367
  text={displayedRequestBody}
341
- label="Copy Request"
368
+ label="Copy"
342
369
  copied={requestCopy.copied}
343
370
  onCopy={requestCopy.copy}
344
371
  />
@@ -349,10 +376,18 @@ export const LogEntry = memo(function ({
349
376
  displayedBody={displayedRequestBody}
350
377
  emptyLabel="No transformation applied — raw and sent request bodies are identical."
351
378
  />
352
- ) : displayedRequestBody !== null ? (
353
- <JsonViewerFromString text={displayedRequestBody} defaultExpandDepth={1} />
354
- ) : (
379
+ ) : displayedRequestBody === null ? (
355
380
  <p className="text-xs text-muted-foreground italic">No request body</p>
381
+ ) : requestExpansion.parsedData !== null ? (
382
+ <JsonViewer
383
+ data={requestExpansion.parsedData}
384
+ bulkDepth={requestExpansion.bulkDepth}
385
+ bulkRevision={requestExpansion.bulkRevision}
386
+ />
387
+ ) : (
388
+ <pre className="font-mono text-xs whitespace-pre-wrap break-words">
389
+ {displayedRequestBody}
390
+ </pre>
356
391
  )}
357
392
  </div>
358
393
  )}
@@ -446,13 +481,13 @@ export const LogEntry = memo(function ({
446
481
  <div className="flex justify-end">
447
482
  <CopyButton
448
483
  text={log.responseText}
449
- label="Copy Response"
484
+ label="Copy"
450
485
  copied={responseCopy.copied}
451
486
  onCopy={responseCopy.copy}
452
487
  />
453
488
  </div>
454
489
  {log.responseText !== null ? (
455
- <JsonViewerFromString text={log.responseText} defaultExpandDepth={1} />
490
+ <JsonViewerFromString text={log.responseText} defaultExpandDepth={0} />
456
491
  ) : (
457
492
  <p className="text-xs text-muted-foreground italic">No response</p>
458
493
  )}
@@ -140,7 +140,7 @@ export const StreamingChunkSequence = memo(function StreamingChunkSequence({
140
140
  {chunk.type}
141
141
  </span>
142
142
  </div>
143
- <JsonViewer data={chunk} defaultExpandDepth={1} showCopy />
143
+ <JsonViewer data={chunk} defaultExpandDepth={0} showCopy />
144
144
  </div>
145
145
  ))}
146
146
  </div>
@@ -149,7 +149,7 @@ export const ToolUseBlock = memo(function ToolUseBlock({
149
149
  <CollapsibleContent>
150
150
  <div className="px-3 pb-2">
151
151
  <ScrollArea className="max-h-[60vh]">
152
- <JsonViewer data={safeJsonValue(input)} defaultExpandDepth={2} />
152
+ <JsonViewer data={safeJsonValue(input)} defaultExpandDepth={0} />
153
153
  </ScrollArea>
154
154
  </div>
155
155
  </CollapsibleContent>
@@ -64,7 +64,7 @@ function OpenAIToolCallBlock({ call }: { call: OpenAIToolCall }): JSX.Element {
64
64
  {call.function.arguments}
65
65
  </pre>
66
66
  ) : (
67
- <JsonViewer data={safeJsonValue(parsed)} defaultExpandDepth={2} />
67
+ <JsonViewer data={safeJsonValue(parsed)} defaultExpandDepth={0} />
68
68
  )}
69
69
  </ScrollArea>
70
70
  </div>