@tonyclaw/llm-inspector 1.18.1 → 1.18.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/{CompareDrawer-CAhlM_Gq.js → CompareDrawer-C-4ypEWs.js} +1 -1
  3. package/.output/public/assets/ProxyViewerContainer-WRenRpeh.js +101 -0
  4. package/.output/public/assets/{ReplayDialog-Bqu2f5HE.js → ReplayDialog-CyBKOgba.js} +1 -1
  5. package/.output/public/assets/{RequestAnatomy-CpVNH0CD.js → RequestAnatomy-C0IrVQ3q.js} +1 -1
  6. package/.output/public/assets/{ResponseView-B_Gg37Lr.js → ResponseView-MogToC4i.js} +1 -1
  7. package/.output/public/assets/{StreamingChunkSequence-E2M_SS1A.js → StreamingChunkSequence-ClhUhT-s.js} +1 -1
  8. package/.output/public/assets/_sessionId-BO47oA3Z.js +1 -0
  9. package/.output/public/assets/index-BRvz6-L6.css +1 -0
  10. package/.output/public/assets/index-Btw8ec7-.js +1 -0
  11. package/.output/public/assets/{json-viewer-DqhA-ODG.js → json-viewer-BicGakI5.js} +1 -1
  12. package/.output/public/assets/{main-DpH7JlHv.js → main-Be2qqUUW.js} +7 -7
  13. package/.output/server/_libs/lucide-react.mjs +20 -14
  14. package/.output/server/{_sessionId-DcJ0RDNl.mjs → _sessionId-DhKJIdQC.mjs} +3 -3
  15. package/.output/server/_ssr/{CompareDrawer-DajC3x7u.mjs → CompareDrawer-BGUgukJ8.mjs} +5 -5
  16. package/.output/server/_ssr/{ProxyViewerContainer-C2dnFXoC.mjs → ProxyViewerContainer--3K3o3Sm.mjs} +212 -74
  17. package/.output/server/_ssr/{ReplayDialog-BnCLuA5z.mjs → ReplayDialog-Bo86xZI4.mjs} +5 -5
  18. package/.output/server/_ssr/{RequestAnatomy-OHE3iT-f.mjs → RequestAnatomy-jRU5qgwB.mjs} +4 -4
  19. package/.output/server/_ssr/{ResponseView-NPshHwOv.mjs → ResponseView-DdO_-79a.mjs} +5 -5
  20. package/.output/server/_ssr/{StreamingChunkSequence-BfukoR7F.mjs → StreamingChunkSequence-BigLwhh4.mjs} +5 -5
  21. package/.output/server/_ssr/{index-CF8M0tsv.mjs → index-BHG6vOnr.mjs} +3 -3
  22. package/.output/server/_ssr/index.mjs +2 -2
  23. package/.output/server/_ssr/{json-viewer-CHBa-Oas.mjs → json-viewer-B4c_WjXD.mjs} +4 -4
  24. package/.output/server/_ssr/{router-B5hOtKSn.mjs → router-DVixpJO-.mjs} +32 -17
  25. package/.output/server/{_tanstack-start-manifest_v-CFyWvIH6.mjs → _tanstack-start-manifest_v-BbvWUF4v.mjs} +1 -1
  26. package/.output/server/index.mjs +63 -63
  27. package/README.md +109 -59
  28. package/package.json +1 -1
  29. package/src/assets/logos/mcp.png +0 -0
  30. package/src/components/ProxyViewer.tsx +203 -53
  31. package/src/components/ProxyViewerContainer.tsx +24 -9
  32. package/src/components/proxy-viewer/ConversationHeader.tsx +7 -22
  33. package/src/components/ui/mcp-logo.tsx +20 -0
  34. package/src/lib/sessionUrl.ts +44 -0
  35. package/src/routes/session/$sessionId.tsx +5 -57
  36. package/.output/public/assets/ProxyViewerContainer--miVHNPZ.js +0 -101
  37. package/.output/public/assets/_sessionId-P9LgC1bF.js +0 -1
  38. package/.output/public/assets/index-C0wv3YP9.css +0 -1
  39. package/.output/public/assets/index-kboKku6a.js +0 -1
@@ -75,11 +75,16 @@ const createLucideIcon = (iconName, iconNode) => {
75
75
  Component.displayName = toPascalCase(iconName);
76
76
  return Component;
77
77
  };
78
- const __iconNode$N = [
78
+ const __iconNode$O = [
79
79
  ["path", { d: "M12 5v14", key: "s699le" }],
80
80
  ["path", { d: "m19 12-7 7-7-7", key: "1idqje" }]
81
81
  ];
82
- const ArrowDown = createLucideIcon("arrow-down", __iconNode$N);
82
+ const ArrowDown = createLucideIcon("arrow-down", __iconNode$O);
83
+ const __iconNode$N = [
84
+ ["path", { d: "m12 19-7-7 7-7", key: "1l729n" }],
85
+ ["path", { d: "M19 12H5", key: "x3x0zl" }]
86
+ ];
87
+ const ArrowLeft = createLucideIcon("arrow-left", __iconNode$N);
83
88
  const __iconNode$M = [
84
89
  ["path", { d: "m5 12 7-7 7 7", key: "hav0vg" }],
85
90
  ["path", { d: "M12 19V5", key: "x0mq9r" }]
@@ -412,33 +417,34 @@ const __iconNode = [
412
417
  ];
413
418
  const Zap = createLucideIcon("zap", __iconNode);
414
419
  export {
415
- ArrowUp as A,
416
- Rows3 as B,
420
+ ArrowLeft as A,
421
+ ArrowDown as B,
417
422
  Check as C,
418
423
  Download as D,
419
424
  ExternalLink as E,
420
425
  FileTerminal as F,
421
426
  GitCompareArrows as G,
422
- Columns2 as H,
423
- Equal as I,
424
- Info as J,
425
- CircleStop as K,
427
+ Rows3 as H,
428
+ Columns2 as I,
429
+ Equal as J,
430
+ Info as K,
426
431
  LoaderCircle as L,
427
432
  MessageSquare as M,
428
- Brain as N,
433
+ CircleStop as N,
429
434
  OctagonAlert as O,
430
435
  Plus as P,
431
- Terminal as Q,
436
+ Brain as Q,
432
437
  RotateCw as R,
433
438
  Settings as S,
434
439
  Trash2 as T,
435
440
  Upload as U,
441
+ Terminal as V,
436
442
  Wrench as W,
437
443
  X,
438
444
  Zap as Z,
439
- ChevronDown as a,
440
- Scan as b,
441
- Copy as c,
445
+ Copy as a,
446
+ ChevronDown as b,
447
+ Scan as c,
442
448
  CircleAlert as d,
443
449
  ChevronUp as e,
444
450
  ChevronRight as f,
@@ -461,5 +467,5 @@ export {
461
467
  Lock as w,
462
468
  Wifi as x,
463
469
  WifiOff as y,
464
- ArrowDown as z
470
+ ArrowUp as z
465
471
  };
@@ -1,6 +1,6 @@
1
1
  import { j as jsxRuntimeExports } from "./_libs/react.mjs";
2
- import { P as ProxyViewerContainer } from "./_ssr/ProxyViewerContainer-C2dnFXoC.mjs";
3
- import { R as Route$j } from "./_ssr/router-B5hOtKSn.mjs";
2
+ import { P as ProxyViewerContainer } from "./_ssr/ProxyViewerContainer--3K3o3Sm.mjs";
3
+ import { R as Route$j } from "./_ssr/router-DVixpJO-.mjs";
4
4
  import "./_libs/jszip.mjs";
5
5
  import "./_libs/modelcontextprotocol__server.mjs";
6
6
  import "./_libs/swr.mjs";
@@ -56,9 +56,9 @@ import "./_libs/radix-ui__react-use-previous.mjs";
56
56
  import "./_libs/@radix-ui/react-visually-hidden+[...].mjs";
57
57
  import "./_libs/lucide-react.mjs";
58
58
  import "./_libs/zod.mjs";
59
+ import "./_libs/radix-ui__react-tooltip.mjs";
59
60
  import "./_libs/radix-ui__react-tabs.mjs";
60
61
  import "./_libs/radix-ui__react-roving-focus.mjs";
61
- import "./_libs/radix-ui__react-tooltip.mjs";
62
62
  import "./_libs/tanstack__react-router.mjs";
63
63
  import "./_libs/tiny-warning.mjs";
64
64
  import "./_libs/tanstack__router-core.mjs";
@@ -1,10 +1,10 @@
1
1
  import { r as reactExports, j as jsxRuntimeExports } from "../_libs/react.mjs";
2
- import { g as getLogFormatAdapter, r as resolveLogFormat, a as getConversationId, c as cn, B as Badge, f as formatTokens } from "./ProxyViewerContainer-C2dnFXoC.mjs";
3
- import { JsonViewerFromString } from "./json-viewer-CHBa-Oas.mjs";
4
- import "./router-B5hOtKSn.mjs";
2
+ import { g as getLogFormatAdapter, r as resolveLogFormat, a as getConversationId, c as cn, B as Badge, f as formatTokens } from "./ProxyViewerContainer--3K3o3Sm.mjs";
3
+ import { JsonViewerFromString } from "./json-viewer-B4c_WjXD.mjs";
4
+ import "./router-DVixpJO-.mjs";
5
5
  import "../_libs/modelcontextprotocol__server.mjs";
6
6
  import "../_libs/jszip.mjs";
7
- import { X, B as Rows3, H as Columns2, m as Minus, P as Plus, l as Pencil, f as ChevronRight, I as Equal, C as Check, c as Copy } from "../_libs/lucide-react.mjs";
7
+ import { X, H as Rows3, I as Columns2, m as Minus, P as Plus, l as Pencil, f as ChevronRight, J as Equal, C as Check, a as Copy } from "../_libs/lucide-react.mjs";
8
8
  import "../_libs/swr.mjs";
9
9
  import "../_libs/use-sync-external-store.mjs";
10
10
  import "../_libs/dequal.mjs";
@@ -57,9 +57,9 @@ import "../_libs/radix-ui__react-use-size.mjs";
57
57
  import "../_libs/radix-ui__react-use-previous.mjs";
58
58
  import "../_libs/@radix-ui/react-visually-hidden+[...].mjs";
59
59
  import "../_libs/zod.mjs";
60
+ import "../_libs/radix-ui__react-tooltip.mjs";
60
61
  import "../_libs/radix-ui__react-tabs.mjs";
61
62
  import "../_libs/radix-ui__react-roving-focus.mjs";
62
- import "../_libs/radix-ui__react-tooltip.mjs";
63
63
  import "../_libs/react-markdown.mjs";
64
64
  import "../_libs/devlop.mjs";
65
65
  import "../_libs/unified.mjs";
@@ -1,18 +1,18 @@
1
1
  import { r as reactExports, j as jsxRuntimeExports, a as React } from "../_libs/react.mjs";
2
- import { C as CapturedLogSchema, D as DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS, a as RuntimeConfigSchema, r as requestFormatForPath, c as createPendingProviderTestResults, P as ProviderTestResultsSchema, d as createFailedProviderTestResults, M as MAX_SLOW_RESPONSE_THRESHOLD_SECONDS, e as ProviderConfigSchema, s as stripClaudeCodeBillingHeader, p as parseOpenAIResponse, O as OpenAIRequestSchema, A as AnthropicResponseSchema$1, b as AnthropicRequestSchema } from "./router-B5hOtKSn.mjs";
2
+ import { C as CapturedLogSchema, D as DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS, a as RuntimeConfigSchema, r as requestFormatForPath, c as createPendingProviderTestResults, P as ProviderTestResultsSchema, d as createFailedProviderTestResults, M as MAX_SLOW_RESPONSE_THRESHOLD_SECONDS, g as getSessionPath, e as ProviderConfigSchema, s as stripClaudeCodeBillingHeader, p as parseOpenAIResponse, O as OpenAIRequestSchema, A as AnthropicResponseSchema$1, b as AnthropicRequestSchema } from "./router-DVixpJO-.mjs";
3
3
  import { u as useSWR, a as useSWRConfig } from "../_libs/swr.mjs";
4
4
  import { J as JSZip } from "../_libs/jszip.mjs";
5
5
  import { c as clsx } from "../_libs/clsx.mjs";
6
6
  import { t as twMerge } from "../_libs/tailwind-merge.mjs";
7
7
  import { c as cva } from "../_libs/class-variance-authority.mjs";
8
- 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";
8
+ import { R as Root, T as Trigger$2, C as Content, a as Close, b as Title, P as Portal$2, O as Overlay } from "../_libs/radix-ui__react-dialog.mjs";
9
9
  import { d as diffJson, a as diffLines } from "../_libs/diff.mjs";
10
10
  import { u as useVirtualizer } from "../_libs/tanstack__react-virtual.mjs";
11
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";
12
- import { C as Check, X, D as Download, S as Settings, a as ChevronDown, U as Upload, b as Scan, P as Plus, c as Copy, d as CircleAlert, e as ChevronUp, L as LoaderCircle, f as ChevronRight, g as User, h as Clock, M as MessageSquare, Z as Zap, E as ExternalLink, T as Trash2, i as TriangleAlert, j as EyeOff, k as Eye, R as RotateCw, l as Pencil, G as GitCompareArrows, m as Minus, n as CircleCheckBig, O as OctagonAlert, W as Wrench, o as Globe, F as FileTerminal, p as Radio, q as ChevronsUp, r as ChevronsDown, s as RotateCcw, t as CircleQuestionMark, u as Server, v as Gauge, w as Lock, x as Wifi, y as WifiOff, A as ArrowUp, z as ArrowDown, B as Rows3, H as Columns2 } from "../_libs/lucide-react.mjs";
12
+ import { C as Check, X, P as Plus, D as Download, S as Settings, A as ArrowLeft, a as Copy, b as ChevronDown, U as Upload, c as Scan, d as CircleAlert, e as ChevronUp, L as LoaderCircle, f as ChevronRight, g as User, h as Clock, M as MessageSquare, Z as Zap, E as ExternalLink, T as Trash2, i as TriangleAlert, j as EyeOff, k as Eye, R as RotateCw, l as Pencil, G as GitCompareArrows, m as Minus, n as CircleCheckBig, O as OctagonAlert, W as Wrench, o as Globe, F as FileTerminal, p as Radio, q as ChevronsUp, r as ChevronsDown, s as RotateCcw, t as CircleQuestionMark, u as Server, v as Gauge, w as Lock, x as Wifi, y as WifiOff, z as ArrowUp, B as ArrowDown, H as Rows3, I as Columns2 } from "../_libs/lucide-react.mjs";
13
13
  import { u as union, d as object, a as array, l as literal, b as string, n as number, c as boolean, _ as _enum } from "../_libs/zod.mjs";
14
- import { R as Root2$1, L as List, T as Trigger$2, C as Content$1 } from "../_libs/radix-ui__react-tabs.mjs";
15
- import { P as Provider, R as Root3, T as Trigger$3, a as Portal$2, C as Content2$1, A as Arrow2 } from "../_libs/radix-ui__react-tooltip.mjs";
14
+ import { P as Provider, R as Root3, T as Trigger$1, a as Portal$1, C as Content2$1, A as Arrow2 } from "../_libs/radix-ui__react-tooltip.mjs";
15
+ import { R as Root2$1, L as List, T as Trigger$3, C as Content$1 } from "../_libs/radix-ui__react-tabs.mjs";
16
16
  import { S as Slot } from "../_libs/radix-ui__react-slot.mjs";
17
17
  const ApiErrorSchema = object({
18
18
  error: string()
@@ -275,7 +275,7 @@ function getStatusCategory(status) {
275
275
  if (status >= 500) return "server_error";
276
276
  return "pending";
277
277
  }
278
- const version = "1.18.1";
278
+ const version = "1.18.2";
279
279
  const packageJson = {
280
280
  version
281
281
  };
@@ -322,12 +322,12 @@ function Dialog({
322
322
  function DialogTrigger({
323
323
  ...props
324
324
  }) {
325
- return /* @__PURE__ */ jsxRuntimeExports.jsx(Trigger$1, { "data-slot": "dialog-trigger", ...props });
325
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Trigger$2, { "data-slot": "dialog-trigger", ...props });
326
326
  }
327
327
  function DialogPortal({
328
328
  ...props
329
329
  }) {
330
- return /* @__PURE__ */ jsxRuntimeExports.jsx(Portal$1, { "data-slot": "dialog-portal", ...props });
330
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Portal$2, { "data-slot": "dialog-portal", ...props });
331
331
  }
332
332
  function DialogOverlay({
333
333
  className,
@@ -497,14 +497,7 @@ function ConversationHeader({
497
497
  const handleOpenInNewTab = reactExports.useCallback(
498
498
  (e) => {
499
499
  e.stopPropagation();
500
- let encoded;
501
- try {
502
- encoded = btoa(conversationId).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
503
- } catch {
504
- encoded = encodeURIComponent(conversationId);
505
- }
506
- const url = `/session/${encoded}`;
507
- window.open(url, "_blank", "noopener,noreferrer");
500
+ window.open(getSessionPath(conversationId), "_blank", "noopener,noreferrer");
508
501
  },
509
502
  [conversationId]
510
503
  );
@@ -537,7 +530,7 @@ function ConversationHeader({
537
530
  {
538
531
  className: "text-purple-400/90 font-mono text-xs font-semibold shrink-0",
539
532
  title: conversationId,
540
- children: conversationId.startsWith("PID:") || conversationId.includes("|") ? conversationId : conversationId.length > 24 ? conversationId.slice(0, 12) + "" + conversationId.slice(-12) : conversationId
533
+ children: conversationId.startsWith("PID:") || conversationId.includes("|") ? conversationId : conversationId.length > 24 ? conversationId.slice(0, 12) + "..." + conversationId.slice(-12) : conversationId
541
534
  }
542
535
  ),
543
536
  userAgent !== null && userAgent !== void 0 && userAgent !== "" && /* @__PURE__ */ jsxRuntimeExports.jsxs(
@@ -1163,7 +1156,7 @@ function Tooltip({ ...props }) {
1163
1156
  return /* @__PURE__ */ jsxRuntimeExports.jsx(Root3, { "data-slot": "tooltip", ...props });
1164
1157
  }
1165
1158
  function TooltipTrigger({ ...props }) {
1166
- return /* @__PURE__ */ jsxRuntimeExports.jsx(Trigger$3, { "data-slot": "tooltip-trigger", ...props });
1159
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Trigger$1, { "data-slot": "tooltip-trigger", ...props });
1167
1160
  }
1168
1161
  function TooltipContent({
1169
1162
  className,
@@ -1171,7 +1164,7 @@ function TooltipContent({
1171
1164
  children,
1172
1165
  ...props
1173
1166
  }) {
1174
- return /* @__PURE__ */ jsxRuntimeExports.jsx(Portal$2, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
1167
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Portal$1, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
1175
1168
  Content2$1,
1176
1169
  {
1177
1170
  "data-slot": "tooltip-content",
@@ -1330,7 +1323,7 @@ function TabsTrigger({
1330
1323
  ...props
1331
1324
  }) {
1332
1325
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
1333
- Trigger$2,
1326
+ Trigger$3,
1334
1327
  {
1335
1328
  "data-slot": "tabs-trigger",
1336
1329
  className: cn(
@@ -1358,27 +1351,27 @@ function TabsContent({
1358
1351
  );
1359
1352
  }
1360
1353
  const LazyCompareDrawer = reactExports.lazy(
1361
- () => import("./CompareDrawer-DajC3x7u.mjs").then((m) => ({ default: m.CompareDrawer }))
1354
+ () => import("./CompareDrawer-BGUgukJ8.mjs").then((m) => ({ default: m.CompareDrawer }))
1362
1355
  );
1363
1356
  const LazyReplayDialog = reactExports.lazy(
1364
- () => import("./ReplayDialog-BnCLuA5z.mjs").then((m) => ({ default: m.ReplayDialog }))
1357
+ () => import("./ReplayDialog-Bo86xZI4.mjs").then((m) => ({ default: m.ReplayDialog }))
1365
1358
  );
1366
1359
  const LazyRequestAnatomy = reactExports.lazy(
1367
- () => import("./RequestAnatomy-OHE3iT-f.mjs").then((m) => ({ default: m.RequestAnatomy }))
1360
+ () => import("./RequestAnatomy-jRU5qgwB.mjs").then((m) => ({ default: m.RequestAnatomy }))
1368
1361
  );
1369
1362
  const LazyResponseView = reactExports.lazy(
1370
- () => import("./ResponseView-NPshHwOv.mjs").then((m) => ({ default: m.ResponseView }))
1363
+ () => import("./ResponseView-DdO_-79a.mjs").then((m) => ({ default: m.ResponseView }))
1371
1364
  );
1372
1365
  const LazyStreamingChunkSequence = reactExports.lazy(
1373
- () => import("./StreamingChunkSequence-BfukoR7F.mjs").then((m) => ({
1366
+ () => import("./StreamingChunkSequence-BigLwhh4.mjs").then((m) => ({
1374
1367
  default: m.StreamingChunkSequence
1375
1368
  }))
1376
1369
  );
1377
1370
  const LazyJsonViewer = reactExports.lazy(
1378
- () => import("./json-viewer-CHBa-Oas.mjs").then((m) => ({ default: m.JsonViewer }))
1371
+ () => import("./json-viewer-B4c_WjXD.mjs").then((m) => ({ default: m.JsonViewer }))
1379
1372
  );
1380
1373
  const LazyJsonViewerFromString = reactExports.lazy(
1381
- () => import("./json-viewer-CHBa-Oas.mjs").then((m) => ({ default: m.JsonViewerFromString }))
1374
+ () => import("./json-viewer-B4c_WjXD.mjs").then((m) => ({ default: m.JsonViewerFromString }))
1382
1375
  );
1383
1376
  const HIGHLIGHT_DURATION_MS = 1200;
1384
1377
  const MAX_HIGHLIGHT_ATTEMPTS = 12;
@@ -3163,6 +3156,18 @@ function CrabLogo({ className }) {
3163
3156
  }
3164
3157
  );
3165
3158
  }
3159
+ const McpLogoPng = "data:image/png;base64,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";
3160
+ function McpLogo({ className }) {
3161
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
3162
+ "img",
3163
+ {
3164
+ src: McpLogoPng,
3165
+ alt: "Model Context Protocol",
3166
+ "aria-hidden": "true",
3167
+ className: cn("inline-block size-8 object-contain invert", className)
3168
+ }
3169
+ );
3170
+ }
3166
3171
  function Select({
3167
3172
  ...props
3168
3173
  }) {
@@ -5196,6 +5201,25 @@ function computeTokenSummary(logs) {
5196
5201
  }
5197
5202
  return { totalIn, totalOut };
5198
5203
  }
5204
+ function formatTimeRange(logs) {
5205
+ const first = logs[0];
5206
+ const last = logs[logs.length - 1];
5207
+ if (first === void 0 || last === void 0) return null;
5208
+ const format = (iso) => new Date(iso).toLocaleTimeString([], {
5209
+ hour: "2-digit",
5210
+ minute: "2-digit",
5211
+ second: "2-digit"
5212
+ });
5213
+ return `${format(first.timestamp)} - ${format(last.timestamp)}`;
5214
+ }
5215
+ function getFirstUserAgent(logs) {
5216
+ for (const log of logs) {
5217
+ if (log.userAgent !== null && log.userAgent !== void 0 && log.userAgent !== "") {
5218
+ return log.userAgent;
5219
+ }
5220
+ }
5221
+ return null;
5222
+ }
5199
5223
  function CopyableCommand({ command }) {
5200
5224
  const [copied, setCopied] = reactExports.useState(false);
5201
5225
  const handleCopy = reactExports.useCallback(() => {
@@ -5247,6 +5271,82 @@ function CopyableCommand({ command }) {
5247
5271
  )
5248
5272
  ] });
5249
5273
  }
5274
+ function McpReadyBadge() {
5275
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
5276
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex h-7 items-center gap-2 rounded-md border border-cyan-400/30 bg-cyan-500/10 px-2.5 font-mono text-[11px] font-medium text-cyan-300 shadow-[0_0_16px_rgba(34,211,238,0.08)]", children: [
5277
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "size-1.5 rounded-full bg-emerald-300 shadow-[0_0_8px_rgba(110,231,183,0.8)]" }),
5278
+ "MCP Ready",
5279
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "hidden text-cyan-200/70 sm:inline", children: "/api/mcp" })
5280
+ ] }) }),
5281
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { sideOffset: 8, className: "max-w-[320px] text-left leading-relaxed", children: "Coding agents can inspect logs, replay requests, test providers, and debug sessions through MCP at /api/mcp." })
5282
+ ] }) });
5283
+ }
5284
+ function SessionContextBar({
5285
+ sessionId,
5286
+ logs,
5287
+ totalIn,
5288
+ totalOut
5289
+ }) {
5290
+ const [copied, setCopied] = reactExports.useState(false);
5291
+ const timeRange = reactExports.useMemo(() => formatTimeRange(logs), [logs]);
5292
+ const userAgent = reactExports.useMemo(() => getFirstUserAgent(logs), [logs]);
5293
+ const handleCopyLink = reactExports.useCallback(() => {
5294
+ void window.navigator.clipboard.writeText(window.location.href).then(() => {
5295
+ setCopied(true);
5296
+ setTimeout(() => setCopied(false), 2e3);
5297
+ });
5298
+ }, []);
5299
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-4 flex items-center gap-3 border border-border rounded-md bg-muted/20 px-3 py-2 text-xs", children: [
5300
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
5301
+ "a",
5302
+ {
5303
+ href: "/",
5304
+ className: "inline-flex size-8 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
5305
+ "aria-label": "Back to all sessions",
5306
+ title: "Back to all sessions",
5307
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(ArrowLeft, { className: "size-3.5" })
5308
+ }
5309
+ ),
5310
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 flex-1", children: [
5311
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
5312
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono font-semibold text-purple-400/90 truncate", title: sessionId, children: truncateSessionId(sessionId) }),
5313
+ userAgent !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(
5314
+ "span",
5315
+ {
5316
+ className: "font-mono text-muted-foreground truncate max-w-[220px]",
5317
+ title: userAgent,
5318
+ children: userAgent
5319
+ }
5320
+ )
5321
+ ] }),
5322
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-1 flex flex-wrap items-center gap-x-3 gap-y-1 text-muted-foreground", children: [
5323
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
5324
+ logs.length,
5325
+ " request",
5326
+ logs.length !== 1 ? "s" : ""
5327
+ ] }),
5328
+ timeRange !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: timeRange }),
5329
+ (totalIn > 0 || totalOut > 0) && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono", children: [
5330
+ formatTokens(totalIn),
5331
+ " in / ",
5332
+ formatTokens(totalOut),
5333
+ " out"
5334
+ ] })
5335
+ ] })
5336
+ ] }),
5337
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
5338
+ "button",
5339
+ {
5340
+ type: "button",
5341
+ onClick: handleCopyLink,
5342
+ className: "inline-flex size-8 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
5343
+ "aria-label": copied ? "Copied session link" : "Copy session link",
5344
+ title: copied ? "Copied session link" : "Copy session link",
5345
+ children: copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-3.5" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-3.5" })
5346
+ }
5347
+ )
5348
+ ] });
5349
+ }
5250
5350
  function ProxyViewer({
5251
5351
  logs,
5252
5352
  sessions,
@@ -5261,7 +5361,8 @@ function ProxyViewer({
5261
5361
  onViewModeChange,
5262
5362
  strip,
5263
5363
  slowResponseThresholdSeconds,
5264
- hideSessionFilter = false
5364
+ hideSessionFilter = false,
5365
+ pinnedSessionId
5265
5366
  }) {
5266
5367
  const { totalIn, totalOut } = reactExports.useMemo(() => computeTokenSummary(logs), [logs]);
5267
5368
  const [exporting, setExporting] = reactExports.useState(false);
@@ -5283,6 +5384,14 @@ function ProxyViewer({
5283
5384
  clearTimeout(t2);
5284
5385
  };
5285
5386
  }, []);
5387
+ reactExports.useEffect(() => {
5388
+ if (pinnedSessionId === void 0) {
5389
+ document.title = "LLM Inspector";
5390
+ return;
5391
+ }
5392
+ const requestLabel = logs.length === 1 ? "1 req" : `${logs.length} req`;
5393
+ document.title = `${truncateSessionId(pinnedSessionId)} - ${requestLabel} - LLM Inspector`;
5394
+ }, [logs.length, pinnedSessionId]);
5286
5395
  const handleExport = reactExports.useCallback(async () => {
5287
5396
  setExporting(true);
5288
5397
  try {
@@ -5308,49 +5417,64 @@ function ProxyViewer({
5308
5417
  [comparisonPredecessors]
5309
5418
  );
5310
5419
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "max-w-[1400px] xl:max-w-[1600px] 2xl:max-w-[1800px] mx-auto px-6 pb-6", children: [
5311
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-end pt-6 pb-8 relative", children: [
5312
- /* @__PURE__ */ jsxRuntimeExports.jsxs("h1", { className: "text-lg font-bold flex items-end gap-2 absolute left-1/2 -translate-x-1/2 whitespace-nowrap", children: [
5313
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-end gap-1 group cursor-default", "aria-hidden": "true", children: [
5314
- /* @__PURE__ */ jsxRuntimeExports.jsx(CrabLogo, { className: "size-10 text-amber-500 transition-all duration-300 group-hover:scale-125 group-hover:-translate-y-1.5" }),
5315
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex items-end gap-0.5", children: crabVariants.map((Crab, i) => {
5316
- const color = [
5317
- "text-amber-500",
5318
- "text-rose-500",
5319
- "text-sky-500",
5320
- "text-emerald-500",
5321
- "text-violet-500",
5322
- "text-orange-500",
5323
- "text-cyan-500",
5324
- "text-pink-500",
5325
- "text-lime-500",
5326
- "text-blue-500",
5327
- "text-yellow-500",
5328
- "text-fuchsia-500"
5329
- ][i];
5330
- const entranceClass = crabEntrancePhase === "hidden" ? "opacity-0 scale-0" : crabEntrancePhase === "playing" ? "animate-crab-piano-pop" : "";
5331
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
5332
- Crab,
5333
- {
5334
- className: `size-5 ${color} transition-all duration-300 ease-out group-hover:scale-125 group-hover:-translate-y-1 ${entranceClass}`,
5335
- style: {
5336
- transitionDelay: `${i * 50}ms`,
5337
- ...crabEntrancePhase === "playing" ? { animationDelay: `${i * 400}ms` } : {}
5338
- }
5339
- },
5340
- i
5341
- );
5342
- }) })
5420
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-[1fr_auto_1fr] items-start gap-3 pt-6 pb-8", children: [
5421
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", {}),
5422
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("h1", { className: "flex min-w-0 flex-col items-center gap-2 text-center", children: [
5423
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex max-w-[calc(100vw-7rem)] items-end gap-2 whitespace-nowrap", children: [
5424
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex shrink-0 items-end gap-1 group cursor-default", "aria-hidden": "true", children: [
5425
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CrabLogo, { className: "size-10 text-amber-500 transition-all duration-300 group-hover:scale-125 group-hover:-translate-y-1.5" }),
5426
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "hidden items-end gap-0.5 sm:flex", children: crabVariants.map((Crab, i) => {
5427
+ const color = [
5428
+ "text-amber-500",
5429
+ "text-rose-500",
5430
+ "text-sky-500",
5431
+ "text-emerald-500",
5432
+ "text-violet-500",
5433
+ "text-orange-500",
5434
+ "text-cyan-500",
5435
+ "text-pink-500",
5436
+ "text-lime-500",
5437
+ "text-blue-500",
5438
+ "text-yellow-500",
5439
+ "text-fuchsia-500"
5440
+ ][i];
5441
+ const entranceClass = crabEntrancePhase === "hidden" ? "opacity-0 scale-0" : crabEntrancePhase === "playing" ? "animate-crab-piano-pop" : "";
5442
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
5443
+ Crab,
5444
+ {
5445
+ className: `size-5 ${color} transition-all duration-300 ease-out group-hover:scale-125 group-hover:-translate-y-1 ${entranceClass}`,
5446
+ style: {
5447
+ transitionDelay: `${i * 50}ms`,
5448
+ ...crabEntrancePhase === "playing" ? { animationDelay: `${i * 400}ms` } : {}
5449
+ }
5450
+ },
5451
+ i
5452
+ );
5453
+ }) })
5454
+ ] }),
5455
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 items-baseline gap-2 pl-1", children: [
5456
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate text-lg font-bold", children: "LLM Inspector" }),
5457
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "shrink-0 font-mono text-xs font-semibold text-muted-foreground", children: [
5458
+ "v",
5459
+ packageJson.version
5460
+ ] })
5461
+ ] }),
5462
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "size-4 shrink-0 text-muted-foreground/70", "aria-hidden": "true" }),
5463
+ /* @__PURE__ */ jsxRuntimeExports.jsx(McpLogo, { className: "size-10 shrink-0" })
5343
5464
  ] }),
5344
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-baseline gap-2", children: [
5345
- "LLM Inspector",
5346
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xs text-muted-foreground font-mono", children: [
5347
- "v",
5348
- packageJson.version
5349
- ] })
5350
- ] })
5465
+ /* @__PURE__ */ jsxRuntimeExports.jsx(McpReadyBadge, {})
5351
5466
  ] }),
5352
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ml-auto", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SettingsDialog, {}) })
5467
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "justify-self-end", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SettingsDialog, {}) })
5353
5468
  ] }),
5469
+ pinnedSessionId !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(
5470
+ SessionContextBar,
5471
+ {
5472
+ sessionId: pinnedSessionId,
5473
+ logs,
5474
+ totalIn,
5475
+ totalOut
5476
+ }
5477
+ ),
5354
5478
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3 mb-4", children: [
5355
5479
  !hideSessionFilter && /* @__PURE__ */ jsxRuntimeExports.jsxs(Select, { value: selectedSession, onValueChange: onSessionChange, children: [
5356
5480
  /* @__PURE__ */ jsxRuntimeExports.jsx(SelectTrigger, { className: "flex-1 max-w-[350px] text-xs", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue, { placeholder: "All sessions" }) }),
@@ -5426,7 +5550,7 @@ function ProxyViewer({
5426
5550
  /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-xs", children: [
5427
5551
  "This session may have been cleared or never existed.",
5428
5552
  " ",
5429
- /* @__PURE__ */ jsxRuntimeExports.jsx(
5553
+ hideSessionFilter ? /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "/", className: "underline hover:text-foreground transition-colors", children: "Back to all sessions" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
5430
5554
  "button",
5431
5555
  {
5432
5556
  type: "button",
@@ -5499,6 +5623,11 @@ function filterLogs(logs, selectedSession, selectedModel) {
5499
5623
  });
5500
5624
  }
5501
5625
  const DEBOUNCE_MS = 50;
5626
+ function buildLogsStreamUrl(sessionId) {
5627
+ if (sessionId === void 0) return "/api/logs/stream";
5628
+ const params = new URLSearchParams({ sessionId });
5629
+ return `/api/logs/stream?${params.toString()}`;
5630
+ }
5502
5631
  function ProxyViewerContainer({
5503
5632
  initialSessionId
5504
5633
  } = {}) {
@@ -5550,7 +5679,7 @@ function ProxyViewerContainer({
5550
5679
  if (eventSourceRef.current) {
5551
5680
  eventSourceRef.current.close();
5552
5681
  }
5553
- const es = new EventSource("/api/logs/stream");
5682
+ const es = new EventSource(buildLogsStreamUrl(initialSessionId));
5554
5683
  eventSourceRef.current = es;
5555
5684
  es.onmessage = (event) => {
5556
5685
  try {
@@ -5591,7 +5720,7 @@ function ProxyViewerContainer({
5591
5720
  }
5592
5721
  reconnectTimeoutRef.current = setTimeout(connectSSE, 3e3);
5593
5722
  };
5594
- }, [scheduleUpdate]);
5723
+ }, [initialSessionId, scheduleUpdate]);
5595
5724
  reactExports.useEffect(() => {
5596
5725
  connectSSE();
5597
5726
  return () => {
@@ -5610,9 +5739,17 @@ function ProxyViewerContainer({
5610
5739
  };
5611
5740
  }, [connectSSE]);
5612
5741
  const handleClearAll = reactExports.useCallback(() => {
5742
+ if (initialSessionId !== void 0 && allLogs.length === 0) return;
5613
5743
  void (async () => {
5614
5744
  try {
5615
- const res = await fetch("/api/logs", { method: "DELETE" });
5745
+ const body = initialSessionId === void 0 ? void 0 : JSON.stringify({ ids: allLogs.map((log) => log.id) });
5746
+ const res = await fetch("/api/logs", {
5747
+ method: "DELETE",
5748
+ ...body === void 0 ? {} : {
5749
+ headers: { "Content-Type": "application/json" },
5750
+ body
5751
+ }
5752
+ });
5616
5753
  if (!res.ok) {
5617
5754
  setError("Failed to clear logs");
5618
5755
  return;
@@ -5624,7 +5761,7 @@ function ProxyViewerContainer({
5624
5761
  setError(err instanceof Error ? err.message : "Unknown error clearing logs");
5625
5762
  }
5626
5763
  })();
5627
- }, []);
5764
+ }, [allLogs, initialSessionId]);
5628
5765
  const handleClearGroup = reactExports.useCallback((ids) => {
5629
5766
  if (ids.length === 0) return;
5630
5767
  void (async () => {
@@ -5675,7 +5812,8 @@ function ProxyViewerContainer({
5675
5812
  onViewModeChange: setViewMode,
5676
5813
  strip,
5677
5814
  slowResponseThresholdSeconds,
5678
- hideSessionFilter: initialSessionId !== void 0
5815
+ hideSessionFilter: initialSessionId !== void 0,
5816
+ pinnedSessionId: initialSessionId
5679
5817
  }
5680
5818
  )
5681
5819
  ] });
@@ -1,10 +1,10 @@
1
1
  import { r as reactExports, j as jsxRuntimeExports } from "../_libs/react.mjs";
2
- import { D as Dialog, b as DialogContent, d as DialogHeader, e as DialogTitle, T as Tabs, h as TabsList, i as TabsTrigger, j as TabsContent, k as TooltipProvider, l as Tooltip, m as TooltipTrigger, n as TooltipContent, o as Button } from "./ProxyViewerContainer-C2dnFXoC.mjs";
3
- import { ResponseView } from "./ResponseView-NPshHwOv.mjs";
4
- import "./router-B5hOtKSn.mjs";
2
+ import { D as Dialog, b as DialogContent, d as DialogHeader, e as DialogTitle, T as Tabs, h as TabsList, i as TabsTrigger, j as TabsContent, k as TooltipProvider, l as Tooltip, m as TooltipTrigger, n as TooltipContent, o as Button } from "./ProxyViewerContainer--3K3o3Sm.mjs";
3
+ import { ResponseView } from "./ResponseView-DdO_-79a.mjs";
4
+ import "./router-DVixpJO-.mjs";
5
5
  import "../_libs/modelcontextprotocol__server.mjs";
6
6
  import "../_libs/jszip.mjs";
7
- import "./json-viewer-CHBa-Oas.mjs";
7
+ import "./json-viewer-B4c_WjXD.mjs";
8
8
  import { s as RotateCcw } from "../_libs/lucide-react.mjs";
9
9
  import { d as object, c as boolean, n as number, b as string } from "../_libs/zod.mjs";
10
10
  import "../_libs/swr.mjs";
@@ -58,9 +58,9 @@ import "../_libs/radix-ui__react-arrow.mjs";
58
58
  import "../_libs/radix-ui__react-use-size.mjs";
59
59
  import "../_libs/radix-ui__react-use-previous.mjs";
60
60
  import "../_libs/@radix-ui/react-visually-hidden+[...].mjs";
61
+ import "../_libs/radix-ui__react-tooltip.mjs";
61
62
  import "../_libs/radix-ui__react-tabs.mjs";
62
63
  import "../_libs/radix-ui__react-roving-focus.mjs";
63
- import "../_libs/radix-ui__react-tooltip.mjs";
64
64
  import "../_libs/react-markdown.mjs";
65
65
  import "../_libs/devlop.mjs";
66
66
  import "../_libs/unified.mjs";