@tonyclaw/agent-inspector 2.0.3 → 2.0.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.
Files changed (53) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/{CompareDrawer-D5A4bTfV.js → CompareDrawer-BCH_fsLm.js} +1 -1
  3. package/.output/public/assets/ProxyViewerContainer-D85_UANk.js +101 -0
  4. package/.output/public/assets/{ReplayDialog-CxUk_TF0.js → ReplayDialog-DTeaHHit.js} +1 -1
  5. package/.output/public/assets/RequestAnatomy-DZ8grAih.js +1 -0
  6. package/.output/public/assets/ResponseView-Cldm6RCi.js +1 -0
  7. package/.output/public/assets/{StreamingChunkSequence-DHk4SGGL.js → StreamingChunkSequence-3x4p-yT7.js} +1 -1
  8. package/.output/public/assets/_sessionId-YqWFBu6d.js +1 -0
  9. package/.output/public/assets/index-BIw2H6jO.js +1 -0
  10. package/.output/public/assets/index-CobXD0yH.css +1 -0
  11. package/.output/public/assets/{json-viewer-BbU0n8eM.js → json-viewer-BrzjD7qI.js} +1 -1
  12. package/.output/public/assets/{main-CZT_F-gu.js → main-mgxeUdZQ.js} +2 -2
  13. package/.output/server/{_sessionId-B-s9P7fJ.mjs → _sessionId-C4xsxIWm.mjs} +2 -2
  14. package/.output/server/_ssr/{CompareDrawer-C08L3UOO.mjs → CompareDrawer-DuWEpqQ7.mjs} +3 -3
  15. package/.output/server/_ssr/{ProxyViewerContainer-CMWl3Ijy.mjs → ProxyViewerContainer-Cckz5qKu.mjs} +167 -87
  16. package/.output/server/_ssr/{ReplayDialog-CPDo9_G5.mjs → ReplayDialog-BDRcr8E5.mjs} +4 -4
  17. package/.output/server/_ssr/{RequestAnatomy-D9wt_K1E.mjs → RequestAnatomy-BoO2_Ij0.mjs} +4 -4
  18. package/.output/server/_ssr/{ResponseView-DXaL7nY3.mjs → ResponseView-DZiPBxvO.mjs} +20 -16
  19. package/.output/server/_ssr/{StreamingChunkSequence-B_hudZyb.mjs → StreamingChunkSequence-D-be7KEL.mjs} +3 -3
  20. package/.output/server/_ssr/{index-CuE_BN86.mjs → index-5RImHKfu.mjs} +2 -2
  21. package/.output/server/_ssr/index.mjs +2 -2
  22. package/.output/server/_ssr/{json-viewer-Ci6kkjde.mjs → json-viewer-aJhb93ZK.mjs} +2 -2
  23. package/.output/server/_ssr/{router-BemxgIg7.mjs → router-Dgkv5nKP.mjs} +22 -14
  24. package/.output/server/{_tanstack-start-manifest_v--L1_b4sd.mjs → _tanstack-start-manifest_v-B8rrWXjr.mjs} +1 -1
  25. package/.output/server/index.mjs +61 -61
  26. package/package.json +1 -1
  27. package/src/components/ProxyViewer.tsx +25 -15
  28. package/src/components/ProxyViewerContainer.tsx +2 -1
  29. package/src/components/providers/SettingsDialog.tsx +45 -1
  30. package/src/components/proxy-viewer/AgentTraceSummary.tsx +103 -45
  31. package/src/components/proxy-viewer/AnswerMarkdown.tsx +16 -0
  32. package/src/components/proxy-viewer/ConversationGroup.tsx +12 -0
  33. package/src/components/proxy-viewer/ConversationHeader.tsx +6 -6
  34. package/src/components/proxy-viewer/LogEntry.tsx +5 -5
  35. package/src/components/proxy-viewer/LogEntryHeader.tsx +9 -14
  36. package/src/components/proxy-viewer/ResponseView.tsx +2 -6
  37. package/src/components/proxy-viewer/ToolTraceEvents.tsx +3 -4
  38. package/src/components/proxy-viewer/TurnGroup.tsx +4 -0
  39. package/src/components/proxy-viewer/anatomy/SegmentBar.tsx +2 -2
  40. package/src/components/proxy-viewer/formats/anthropic/ContentBlocks.tsx +6 -12
  41. package/src/components/proxy-viewer/formats/openai/ResponseView.tsx +10 -14
  42. package/src/lib/runtimeConfig.ts +6 -0
  43. package/src/lib/timeDisplay.ts +22 -0
  44. package/src/lib/useOnboarding.ts +2 -0
  45. package/src/lib/useStripConfig.ts +16 -0
  46. package/src/proxy/config.ts +3 -0
  47. package/src/routes/api/config.ts +5 -1
  48. package/.output/public/assets/ProxyViewerContainer-Da0jpBkp.js +0 -101
  49. package/.output/public/assets/RequestAnatomy-DIlzjgjJ.js +0 -1
  50. package/.output/public/assets/ResponseView-DQCuKJ1G.js +0 -1
  51. package/.output/public/assets/_sessionId-dY1TTl7N.js +0 -1
  52. package/.output/public/assets/index-D7wwbwly.css +0 -1
  53. package/.output/public/assets/index-FqQZbfl2.js +0 -1
@@ -1,6 +1,6 @@
1
1
  import { r as reactExports, j as jsxRuntimeExports } from "../_libs/react.mjs";
2
- import { k as TooltipProvider, f as formatTokens, c as cn, l as Tooltip, m as TooltipTrigger, n as TooltipContent } from "./ProxyViewerContainer-CMWl3Ijy.mjs";
3
- import "./router-BemxgIg7.mjs";
2
+ import { k as TooltipProvider, f as formatTokens, c as cn, l as Tooltip, m as TooltipTrigger, n as TooltipContent } from "./ProxyViewerContainer-Cckz5qKu.mjs";
3
+ import "./router-Dgkv5nKP.mjs";
4
4
  import "../_libs/modelcontextprotocol__server.mjs";
5
5
  import "../_libs/jszip.mjs";
6
6
  import { V as Info } from "../_libs/lucide-react.mjs";
@@ -116,14 +116,14 @@ const ROLE_COLOR_CLASSES = {
116
116
  system: "bg-sky-500/70",
117
117
  user: "bg-emerald-500/70",
118
118
  assistant: "bg-violet-500/70",
119
- tool: "bg-amber-500/70",
119
+ tool: "bg-sky-400/55",
120
120
  tools: "bg-slate-500/70"
121
121
  };
122
122
  const ROLE_FOCUS_RING = {
123
123
  system: "focus-visible:ring-sky-300",
124
124
  user: "focus-visible:ring-emerald-300",
125
125
  assistant: "focus-visible:ring-violet-300",
126
- tool: "focus-visible:ring-amber-300",
126
+ tool: "focus-visible:ring-sky-300",
127
127
  tools: "focus-visible:ring-slate-300"
128
128
  };
129
129
  const MAX_VISIBLE_SEGMENTS = 12;
@@ -1,7 +1,7 @@
1
1
  import { r as reactExports, j as jsxRuntimeExports } from "../_libs/react.mjs";
2
- import { g as getLogFormatAdapter, f as formatTokens, c as cn, p as getStatusCategory, B as Badge, s as safeJsonValue } from "./ProxyViewerContainer-CMWl3Ijy.mjs";
3
- import { JsonViewer } from "./json-viewer-Ci6kkjde.mjs";
4
- import "./router-BemxgIg7.mjs";
2
+ import { g as getLogFormatAdapter, f as formatTokens, c as cn, p as getStatusCategory, B as Badge, s as safeJsonValue } from "./ProxyViewerContainer-Cckz5qKu.mjs";
3
+ import { JsonViewer } from "./json-viewer-aJhb93ZK.mjs";
4
+ import "./router-Dgkv5nKP.mjs";
5
5
  import "../_libs/modelcontextprotocol__server.mjs";
6
6
  import "../_libs/jszip.mjs";
7
7
  import { Z as Zap, i as TriangleAlert, Y as CircleStop, B as Brain, b as ChevronDown, f as ChevronRight, _ as Terminal } from "../_libs/lucide-react.mjs";
@@ -167,6 +167,10 @@ import "../_libs/inline-style-parser.mjs";
167
167
  import "../_libs/hast-util-whitespace.mjs";
168
168
  import "../_libs/estree-util-is-identifier-name.mjs";
169
169
  import "../_libs/html-url-attributes.mjs";
170
+ const ANSWER_MARKDOWN_CLASS = "prose prose-sm dark:prose-invert max-w-none text-[13px] leading-[1.65] [&_pre]:bg-muted [&_pre]:text-foreground [&_code]:text-[0.8em] [&_p]:my-1 [&_p]:leading-[1.65] [&_ul]:my-1 [&_ol]:my-1 [&_li]:my-0.5 [&_li]:leading-[1.6]";
171
+ function AnswerMarkdown({ text }) {
172
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: ANSWER_MARKDOWN_CLASS, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Markdown, { children: text }) });
173
+ }
170
174
  function Separator({
171
175
  className,
172
176
  orientation = "horizontal",
@@ -276,7 +280,7 @@ function SystemReminderBlock({ text }) {
276
280
  open ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-3 text-muted-foreground" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-3 text-muted-foreground" }),
277
281
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground text-xs italic select-none opacity-60", children: "[system-reminder]" })
278
282
  ] }),
279
- /* @__PURE__ */ jsxRuntimeExports.jsx(CollapsibleContent, { children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "pl-4 pt-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "prose prose-sm dark:prose-invert max-w-none [&_pre]:bg-muted [&_pre]:text-foreground [&_code]:text-[0.8em] [&_p]:my-1 [&_ul]:my-1 [&_ol]:my-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Markdown, { children: text }) }) }) })
283
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CollapsibleContent, { children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "pl-4 pt-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx(AnswerMarkdown, { text }) }) })
280
284
  ] });
281
285
  }
282
286
  const TextBlock = reactExports.memo(function TextBlock2({ text }) {
@@ -286,7 +290,7 @@ const TextBlock = reactExports.memo(function TextBlock2({ text }) {
286
290
  const { thinking, remainingText } = extractThinkingFromContent(text);
287
291
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
288
292
  thinking !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(ThinkingBlock, { thinking }),
289
- remainingText.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "prose prose-sm dark:prose-invert max-w-none [&_pre]:bg-muted [&_pre]:text-foreground [&_code]:text-[0.8em] [&_p]:my-1 [&_ul]:my-1 [&_ol]:my-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Markdown, { children: remainingText }) }),
293
+ remainingText.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(AnswerMarkdown, { text: remainingText }),
290
294
  thinking === null && remainingText.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground italic", children: "Empty text block" })
291
295
  ] });
292
296
  });
@@ -320,9 +324,9 @@ const ToolUseBlock = reactExports.memo(function ToolUseBlock2({
320
324
  input
321
325
  }) {
322
326
  const [open, setOpen] = reactExports.useState(false);
323
- return /* @__PURE__ */ jsxRuntimeExports.jsx(Collapsible, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-l-2 border-blue-500/40 my-1", children: [
324
- /* @__PURE__ */ jsxRuntimeExports.jsxs(CollapsibleTrigger, { className: "flex items-center gap-1.5 px-3 py-1 w-full text-left cursor-pointer hover:bg-blue-500/5 transition-colors rounded-r-sm group", children: [
325
- /* @__PURE__ */ jsxRuntimeExports.jsx(Terminal, { className: "size-3.5 text-blue-400 shrink-0" }),
327
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Collapsible, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-l-2 border-sky-400/25 my-1", children: [
328
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(CollapsibleTrigger, { className: "flex items-center gap-1.5 px-3 py-1 w-full text-left cursor-pointer hover:bg-sky-400/[0.04] transition-colors rounded-r-sm group", children: [
329
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Terminal, { className: "size-3.5 text-sky-400/70 shrink-0" }),
326
330
  /* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { variant: "outline", className: "text-[10px] font-mono px-1.5 py-0 h-4", children: name }),
327
331
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1" }),
328
332
  open ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-3 text-muted-foreground" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-3 text-muted-foreground" })
@@ -400,9 +404,9 @@ function OpenAIToolCallBlock({ call }) {
400
404
  const [open, setOpen] = reactExports.useState(false);
401
405
  const name = call.function.name ?? "(unnamed tool)";
402
406
  const parsed = parseToolArguments(call.function.arguments);
403
- return /* @__PURE__ */ jsxRuntimeExports.jsx(Collapsible, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-l-2 border-blue-500/40 my-1", children: [
404
- /* @__PURE__ */ jsxRuntimeExports.jsxs(CollapsibleTrigger, { className: "flex items-center gap-1.5 px-3 py-1 w-full text-left cursor-pointer hover:bg-blue-500/5 transition-colors rounded-r-sm group", children: [
405
- /* @__PURE__ */ jsxRuntimeExports.jsx(Terminal, { className: "size-3.5 text-blue-400 shrink-0" }),
407
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Collapsible, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-l-2 border-sky-400/25 my-1", children: [
408
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(CollapsibleTrigger, { className: "flex items-center gap-1.5 px-3 py-1 w-full text-left cursor-pointer hover:bg-sky-400/[0.04] transition-colors rounded-r-sm group", children: [
409
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Terminal, { className: "size-3.5 text-sky-400/70 shrink-0" }),
406
410
  /* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { variant: "outline", className: "text-[10px] font-mono px-1.5 py-0 h-4", children: name }),
407
411
  call.id !== void 0 && call.id !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] font-mono text-muted-foreground/60 truncate", children: call.id }),
408
412
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1" }),
@@ -454,17 +458,17 @@ const OpenAIResponseView = reactExports.memo(function OpenAIResponseView2({
454
458
  const { thinking, remainingText } = extractThinkingFromContent(message.content);
455
459
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
456
460
  thinking !== null && !hasReasoningField && /* @__PURE__ */ jsxRuntimeExports.jsx(ThinkingBlock, { thinking }),
457
- remainingText.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "prose prose-sm dark:prose-invert max-w-none [&_pre]:bg-muted [&_pre]:text-foreground [&_code]:text-[0.8em] [&_p]:my-1 [&_ul]:my-1 [&_ol]:my-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Markdown, { children: remainingText }) })
461
+ remainingText.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(AnswerMarkdown, { text: remainingText })
458
462
  ] });
459
463
  })(),
460
464
  toolCalls.map((call, i) => (
461
465
  // biome-ignore lint/suspicious/noArrayIndexKey: tool_calls is the positionally stable list from the response
462
466
  /* @__PURE__ */ jsxRuntimeExports.jsx(OpenAIToolCallBlock, { call }, call.id ?? `tc-${i}`)
463
467
  )),
464
- message?.function_call !== null && message?.function_call !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border border-blue-500/30 rounded-md p-3 bg-blue-500/5", children: [
465
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-blue-400 font-mono mb-1", children: "function_call" }),
468
+ message?.function_call !== null && message?.function_call !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border border-sky-400/20 rounded-md p-3 bg-muted/20", children: [
469
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-sky-400/80 font-mono mb-1", children: "function_call" }),
466
470
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "font-mono text-xs", children: [
467
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-blue-300", children: message.function_call.name }),
471
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-foreground/80", children: message.function_call.name }),
468
472
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground", children: [
469
473
  "(",
470
474
  message.function_call.arguments,
@@ -521,7 +525,7 @@ function ErrorResponseView({ text }) {
521
525
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "rounded-md border border-red-500/30 bg-red-500/5 p-3", children: /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "text-xs text-red-300 whitespace-pre-wrap font-mono leading-relaxed overflow-auto max-h-[60vh]", children: text }) });
522
526
  }
523
527
  function MarkdownFallbackView({ text }) {
524
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "prose prose-sm dark:prose-invert max-w-none [&_pre]:bg-muted [&_pre]:text-foreground [&_code]:text-[0.8em] [&_p]:my-1 [&_ul]:my-1 [&_ol]:my-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Markdown, { children: text }) });
528
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(AnswerMarkdown, { text });
525
529
  }
526
530
  const ResponseView = reactExports.memo(function ResponseView2({
527
531
  responseText,
@@ -1,7 +1,7 @@
1
1
  import { r as reactExports, j as jsxRuntimeExports } from "../_libs/react.mjs";
2
- import { k as TooltipProvider, l as Tooltip, m as TooltipTrigger, B as Badge, n as TooltipContent } from "./ProxyViewerContainer-CMWl3Ijy.mjs";
3
- import { JsonViewer } from "./json-viewer-Ci6kkjde.mjs";
4
- import "./router-BemxgIg7.mjs";
2
+ import { k as TooltipProvider, l as Tooltip, m as TooltipTrigger, B as Badge, n as TooltipContent } from "./ProxyViewerContainer-Cckz5qKu.mjs";
3
+ import { JsonViewer } from "./json-viewer-aJhb93ZK.mjs";
4
+ import "./router-Dgkv5nKP.mjs";
5
5
  import "../_libs/modelcontextprotocol__server.mjs";
6
6
  import "../_libs/jszip.mjs";
7
7
  import { b as ChevronDown, f as ChevronRight, L as LoaderCircle } from "../_libs/lucide-react.mjs";
@@ -1,6 +1,6 @@
1
- import { P as ProxyViewerContainer } from "./ProxyViewerContainer-CMWl3Ijy.mjs";
1
+ import { P as ProxyViewerContainer } from "./ProxyViewerContainer-Cckz5qKu.mjs";
2
2
  import "../_libs/react.mjs";
3
- import "./router-BemxgIg7.mjs";
3
+ import "./router-Dgkv5nKP.mjs";
4
4
  import "../_libs/modelcontextprotocol__server.mjs";
5
5
  import "../_libs/jszip.mjs";
6
6
  import "../_libs/swr.mjs";
@@ -198,7 +198,7 @@ function getResponse() {
198
198
  return event.res;
199
199
  }
200
200
  async function getStartManifest(matchedRoutes) {
201
- const { tsrStartManifest } = await import("../_tanstack-start-manifest_v--L1_b4sd.mjs");
201
+ const { tsrStartManifest } = await import("../_tanstack-start-manifest_v-B8rrWXjr.mjs");
202
202
  const startManifest = tsrStartManifest();
203
203
  const rootRoute = startManifest.routes[rootRouteId] = startManifest.routes[rootRouteId] || {};
204
204
  rootRoute.assets = rootRoute.assets || [];
@@ -767,7 +767,7 @@ let entriesPromise;
767
767
  let baseManifestPromise;
768
768
  let cachedFinalManifestPromise;
769
769
  async function loadEntries() {
770
- const routerEntry = await import("./router-BemxgIg7.mjs").then((n) => n.h);
770
+ const routerEntry = await import("./router-Dgkv5nKP.mjs").then((n) => n.i);
771
771
  const startEntry = await import("./start-HYkvq4Ni.mjs");
772
772
  return { startEntry, routerEntry };
773
773
  }
@@ -1,6 +1,6 @@
1
1
  import { r as reactExports, j as jsxRuntimeExports } from "../_libs/react.mjs";
2
- import { q as parseJsonText, c as cn, k as TooltipProvider, l as Tooltip, m as TooltipTrigger, n as TooltipContent } from "./ProxyViewerContainer-CMWl3Ijy.mjs";
3
- import "./router-BemxgIg7.mjs";
2
+ import { q as parseJsonText, c as cn, k as TooltipProvider, l as Tooltip, m as TooltipTrigger, n as TooltipContent } from "./ProxyViewerContainer-Cckz5qKu.mjs";
3
+ import "./router-Dgkv5nKP.mjs";
4
4
  import "../_libs/modelcontextprotocol__server.mjs";
5
5
  import "../_libs/jszip.mjs";
6
6
  import { C as Check, a as Copy, b as ChevronDown, f as ChevronRight, q as ChevronsDown } from "../_libs/lucide-react.mjs";
@@ -49,7 +49,7 @@ import "../_libs/mimic-function.mjs";
49
49
  import "../_libs/semver.mjs";
50
50
  import "../_libs/uint8array-extras.mjs";
51
51
  const faviconSvg = "data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2064%2064'%20role='img'%20aria-label='Agent%20Inspector'%3e%3crect%20width='64'%20height='64'%20rx='14'%20fill='%23111827'%20/%3e%3cg%20fill='none'%20stroke='%23f59e0b'%20stroke-width='4.2'%20stroke-linecap='round'%20stroke-linejoin='round'%3e%3cpath%20fill='%23f59e0b'%20d='M15%2036c0-11%207-18%2017-18s17%207%2017%2018c0%208-7%2013-17%2013s-17-5-17-13z'%20/%3e%3cpath%20d='M16%2031c-6-5-12-3-12%204%200%205%206%206%2011%202'%20/%3e%3cpath%20d='M48%2031c6-5%2012-3%2012%204%200%205-6%206-11%202'%20/%3e%3cpath%20d='M27%2019l-3-7'%20/%3e%3cpath%20d='M37%2019l3-7'%20/%3e%3cpath%20d='M19%2045l-6%209'%20/%3e%3cpath%20d='M27%2048l-3%209'%20/%3e%3cpath%20d='M37%2048l3%209'%20/%3e%3cpath%20d='M45%2045l6%209'%20/%3e%3c/g%3e%3cpath%20d='M14%2047l9-8%208%209c-5%203.5-12%203-17-1z'%20fill='%232f6b3f'%20opacity='.95'%20/%3e%3cpath%20d='M18%2046l5-5%205%206c-3%201.6-7%201.4-10-1z'%20fill='%236fb36f'%20opacity='.95'%20/%3e%3cpath%20d='M23%2041v10'%20fill='none'%20stroke='%23d6b45f'%20stroke-width='1.6'%20stroke-linecap='round'%20/%3e%3ccircle%20cx='31'%20cy='48'%20r='1.8'%20fill='%23c2412d'%20/%3e%3cpath%20d='M24%2044l13-11%2014%2013c-8%205.8-18%205.3-27-2z'%20fill='%232f6b3f'%20opacity='.97'%20/%3e%3cpath%20d='M30%2043l7-7%209%209c-5%202.7-11%202.5-16-2z'%20fill='%236fb36f'%20opacity='.95'%20/%3e%3cpath%20d='M37%2036v14'%20fill='none'%20stroke='%23d6b45f'%20stroke-width='2'%20stroke-linecap='round'%20/%3e%3cpath%20d='M30%2043c5-2%2011-1.5%2016%202'%20fill='none'%20stroke='%239fca78'%20stroke-width='1.8'%20stroke-linecap='round'%20/%3e%3ccircle%20cx='51'%20cy='46'%20r='2'%20fill='%23c2412d'%20/%3e%3cpath%20d='M40%2050l8-8%207%208c-4.2%203.2-10%203-15%200z'%20fill='%232f6b3f'%20opacity='.95'%20/%3e%3cpath%20d='M43%2049l5-5%204.5%205.5c-3%201.5-6%201.2-9.5-.5z'%20fill='%236fb36f'%20opacity='.95'%20/%3e%3cpath%20d='M48%2044v9'%20fill='none'%20stroke='%23d6b45f'%20stroke-width='1.5'%20stroke-linecap='round'%20/%3e%3ccircle%20cx='55'%20cy='50'%20r='1.7'%20fill='%23c2412d'%20/%3e%3ccircle%20cx='24'%20cy='11'%20r='3.2'%20fill='%23f59e0b'%20/%3e%3ccircle%20cx='40'%20cy='11'%20r='3.2'%20fill='%23f59e0b'%20/%3e%3ccircle%20cx='25'%20cy='34'%20r='2.1'%20fill='%23111827'%20/%3e%3ccircle%20cx='39'%20cy='34'%20r='2.1'%20fill='%23111827'%20/%3e%3c/svg%3e";
52
- const appCss = "/assets/index-D7wwbwly.css";
52
+ const appCss = "/assets/index-CobXD0yH.css";
53
53
  const Route$q = createRootRoute({
54
54
  head: () => ({
55
55
  meta: [
@@ -76,7 +76,7 @@ function RootDocument({ children }) {
76
76
  ] })
77
77
  ] });
78
78
  }
79
- const $$splitComponentImporter$1 = () => import("./index-CuE_BN86.mjs");
79
+ const $$splitComponentImporter$1 = () => import("./index-5RImHKfu.mjs");
80
80
  const Route$p = createFileRoute("/")({
81
81
  component: lazyRouteComponent($$splitComponentImporter$1, "component")
82
82
  });
@@ -119,7 +119,7 @@ function decodeSessionIdFromPath(encoded) {
119
119
  function getSessionPath(sessionId) {
120
120
  return `/session/${encodeSessionIdForPath(sessionId)}`;
121
121
  }
122
- const $$splitComponentImporter = () => import("../_sessionId-B-s9P7fJ.mjs");
122
+ const $$splitComponentImporter = () => import("../_sessionId-C4xsxIWm.mjs");
123
123
  const Route$o = createFileRoute("/session/$sessionId")({
124
124
  component: lazyRouteComponent($$splitComponentImporter, "component"),
125
125
  parseParams: (params) => ({
@@ -2634,10 +2634,13 @@ async function getClientInfo(request) {
2634
2634
  }
2635
2635
  const DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS = 10;
2636
2636
  const MAX_SLOW_RESPONSE_THRESHOLD_SECONDS = 600;
2637
+ const DEFAULT_TIME_DISPLAY_FORMAT = "time";
2638
+ const TimeDisplayFormatSchema = _enum(["time", "full"]);
2637
2639
  const RuntimeConfigSchema = object({
2638
2640
  stripClaudeCodeBillingHeader: boolean(),
2639
2641
  hasSeenOnboarding: boolean().default(false),
2640
- slowResponseThresholdSeconds: number().int().min(0).max(MAX_SLOW_RESPONSE_THRESHOLD_SECONDS).default(DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS)
2642
+ slowResponseThresholdSeconds: number().int().min(0).max(MAX_SLOW_RESPONSE_THRESHOLD_SECONDS).default(DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS),
2643
+ timeDisplayFormat: TimeDisplayFormatSchema.default(DEFAULT_TIME_DISPLAY_FORMAT)
2641
2644
  });
2642
2645
  function getConfigFilePath() {
2643
2646
  return join(getDataDir(), "config.json");
@@ -2670,13 +2673,15 @@ function resolveInitialConfig() {
2670
2673
  return {
2671
2674
  stripClaudeCodeBillingHeader: true,
2672
2675
  hasSeenOnboarding: false,
2673
- slowResponseThresholdSeconds: DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS
2676
+ slowResponseThresholdSeconds: DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS,
2677
+ timeDisplayFormat: DEFAULT_TIME_DISPLAY_FORMAT
2674
2678
  };
2675
2679
  }
2676
2680
  return {
2677
2681
  stripClaudeCodeBillingHeader: false,
2678
2682
  hasSeenOnboarding: false,
2679
- slowResponseThresholdSeconds: DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS
2683
+ slowResponseThresholdSeconds: DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS,
2684
+ timeDisplayFormat: DEFAULT_TIME_DISPLAY_FORMAT
2680
2685
  };
2681
2686
  }
2682
2687
  function getConfig() {
@@ -4095,7 +4100,8 @@ const Route$h = createFileRoute("/api/health")({
4095
4100
  const RuntimeConfigPatchSchema = object({
4096
4101
  stripClaudeCodeBillingHeader: boolean().optional(),
4097
4102
  hasSeenOnboarding: boolean().optional(),
4098
- slowResponseThresholdSeconds: number().int().min(0).max(MAX_SLOW_RESPONSE_THRESHOLD_SECONDS).optional()
4103
+ slowResponseThresholdSeconds: number().int().min(0).max(MAX_SLOW_RESPONSE_THRESHOLD_SECONDS).optional(),
4104
+ timeDisplayFormat: TimeDisplayFormatSchema.optional()
4099
4105
  }).strict().refine((v) => Object.keys(v).length > 0, {
4100
4106
  message: "At least one field must be provided"
4101
4107
  });
@@ -6574,14 +6580,16 @@ export {
6574
6580
  OpenAIRequestSchema as O,
6575
6581
  ProviderTestResultsSchema as P,
6576
6582
  Route$o as R,
6577
- RuntimeConfigSchema as a,
6578
- AnthropicRequestSchema as b,
6579
- safeGetOwnProperty as c,
6580
- createPendingProviderTestResults as d,
6581
- createFailedProviderTestResults as e,
6582
- ProviderConfigSchema as f,
6583
+ TimeDisplayFormatSchema as T,
6584
+ DEFAULT_TIME_DISPLAY_FORMAT as a,
6585
+ RuntimeConfigSchema as b,
6586
+ AnthropicRequestSchema as c,
6587
+ safeGetOwnProperty as d,
6588
+ createPendingProviderTestResults as e,
6589
+ createFailedProviderTestResults as f,
6583
6590
  getSessionPath as g,
6584
- router as h,
6591
+ ProviderConfigSchema as h,
6592
+ router as i,
6585
6593
  parseOpenAIResponse as p,
6586
6594
  requestFormatForPath as r,
6587
6595
  stripClaudeCodeBillingHeader as s
@@ -1,4 +1,4 @@
1
- const tsrStartManifest = () => ({ "routes": { "__root__": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/__root.tsx", "children": ["/", "/api/config", "/api/health", "/api/logs", "/api/mcp", "/api/models", "/api/providers", "/api/sessions", "/proxy/$", "/session/$sessionId", "/api/knowledge/candidates", "/api/knowledge/project-context", "/api/knowledge/search", "/api/knowledge/sessions/$sessionId/candidates"], "preloads": ["/assets/main-CZT_F-gu.js"], "assets": [] }, "/": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/index.tsx", "assets": [], "preloads": ["/assets/index-FqQZbfl2.js", "/assets/ProxyViewerContainer-Da0jpBkp.js"] }, "/api/config": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/config.ts", "children": ["/api/config/paths"] }, "/api/health": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/health.ts" }, "/api/logs": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.ts", "children": ["/api/logs/$id", "/api/logs/stream"] }, "/api/mcp": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/mcp.ts" }, "/api/models": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/models.ts" }, "/api/providers": { "filePath": "C:/Users/claw/workspace/agent-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/agent-inspector/src/routes/api/sessions.ts" }, "/proxy/$": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/proxy/$.ts" }, "/session/$sessionId": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/session/$sessionId.tsx", "assets": [], "preloads": ["/assets/_sessionId-dY1TTl7N.js", "/assets/ProxyViewerContainer-Da0jpBkp.js"] }, "/api/config/paths": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/config.paths.ts" }, "/api/knowledge/candidates": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.candidates.ts", "children": ["/api/knowledge/candidates/$candidateId/promote"] }, "/api/knowledge/project-context": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.project-context.ts" }, "/api/knowledge/search": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.search.ts" }, "/api/logs/$id": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.$id.ts", "children": ["/api/logs/$id/chunks", "/api/logs/$id/replay"] }, "/api/logs/stream": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.stream.ts" }, "/api/providers/$providerId": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.$providerId.ts", "children": ["/api/providers/$providerId/test"] }, "/api/providers/export": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.export.ts" }, "/api/providers/import": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.import.ts" }, "/api/providers/scan": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.scan.ts" }, "/api/logs/$id/chunks": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.$id.chunks.ts" }, "/api/logs/$id/replay": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.$id.replay.ts" }, "/api/providers/$providerId/test": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.$providerId.test.ts", "children": ["/api/providers/$providerId/test/log"] }, "/api/knowledge/candidates/$candidateId/promote": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.candidates.$candidateId.promote.ts" }, "/api/knowledge/sessions/$sessionId/candidates": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.sessions.$sessionId.candidates.ts" }, "/api/providers/$providerId/test/log": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.$providerId.test.log.ts" } }, "clientEntry": "/assets/main-CZT_F-gu.js" });
1
+ const tsrStartManifest = () => ({ "routes": { "__root__": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/__root.tsx", "children": ["/", "/api/config", "/api/health", "/api/logs", "/api/mcp", "/api/models", "/api/providers", "/api/sessions", "/proxy/$", "/session/$sessionId", "/api/knowledge/candidates", "/api/knowledge/project-context", "/api/knowledge/search", "/api/knowledge/sessions/$sessionId/candidates"], "preloads": ["/assets/main-mgxeUdZQ.js"], "assets": [] }, "/": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/index.tsx", "assets": [], "preloads": ["/assets/index-BIw2H6jO.js", "/assets/ProxyViewerContainer-D85_UANk.js"] }, "/api/config": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/config.ts", "children": ["/api/config/paths"] }, "/api/health": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/health.ts" }, "/api/logs": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.ts", "children": ["/api/logs/$id", "/api/logs/stream"] }, "/api/mcp": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/mcp.ts" }, "/api/models": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/models.ts" }, "/api/providers": { "filePath": "C:/Users/claw/workspace/agent-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/agent-inspector/src/routes/api/sessions.ts" }, "/proxy/$": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/proxy/$.ts" }, "/session/$sessionId": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/session/$sessionId.tsx", "assets": [], "preloads": ["/assets/_sessionId-YqWFBu6d.js", "/assets/ProxyViewerContainer-D85_UANk.js"] }, "/api/config/paths": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/config.paths.ts" }, "/api/knowledge/candidates": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.candidates.ts", "children": ["/api/knowledge/candidates/$candidateId/promote"] }, "/api/knowledge/project-context": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.project-context.ts" }, "/api/knowledge/search": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.search.ts" }, "/api/logs/$id": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.$id.ts", "children": ["/api/logs/$id/chunks", "/api/logs/$id/replay"] }, "/api/logs/stream": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.stream.ts" }, "/api/providers/$providerId": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.$providerId.ts", "children": ["/api/providers/$providerId/test"] }, "/api/providers/export": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.export.ts" }, "/api/providers/import": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.import.ts" }, "/api/providers/scan": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.scan.ts" }, "/api/logs/$id/chunks": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.$id.chunks.ts" }, "/api/logs/$id/replay": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.$id.replay.ts" }, "/api/providers/$providerId/test": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.$providerId.test.ts", "children": ["/api/providers/$providerId/test/log"] }, "/api/knowledge/candidates/$candidateId/promote": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.candidates.$candidateId.promote.ts" }, "/api/knowledge/sessions/$sessionId/candidates": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.sessions.$sessionId.candidates.ts" }, "/api/providers/$providerId/test/log": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.$providerId.test.log.ts" } }, "clientEntry": "/assets/main-mgxeUdZQ.js" });
2
2
  export {
3
3
  tsrStartManifest
4
4
  };
@@ -38,107 +38,107 @@ const assets = {
38
38
  "/assets/alibaba-TTwafVwX.svg": {
39
39
  "type": "image/svg+xml",
40
40
  "etag": '"171b-6dyV5K8QjiaY35sN9qNprh9zDIs"',
41
- "mtime": "2026-06-20T07:49:57.206Z",
41
+ "mtime": "2026-06-20T09:50:40.188Z",
42
42
  "size": 5915,
43
43
  "path": "../public/assets/alibaba-TTwafVwX.svg"
44
44
  },
45
- "/assets/CompareDrawer-D5A4bTfV.js": {
45
+ "/assets/index-BIw2H6jO.js": {
46
46
  "type": "text/javascript; charset=utf-8",
47
- "etag": '"4a1f-mEPVKgxEcmIrRzyfYSrf+TEFNes"',
48
- "mtime": "2026-06-20T07:49:57.206Z",
49
- "size": 18975,
50
- "path": "../public/assets/CompareDrawer-D5A4bTfV.js"
51
- },
52
- "/assets/index-FqQZbfl2.js": {
53
- "type": "text/javascript; charset=utf-8",
54
- "etag": '"74-el2/zDM0d+yANqsiilX18eIScpc"',
55
- "mtime": "2026-06-20T07:49:57.206Z",
47
+ "etag": '"74-4Z3U3XPh22QGtEz8rgtC6KUxxBk"',
48
+ "mtime": "2026-06-20T09:50:40.189Z",
56
49
  "size": 116,
57
- "path": "../public/assets/index-FqQZbfl2.js"
50
+ "path": "../public/assets/index-BIw2H6jO.js"
58
51
  },
59
- "/assets/index-D7wwbwly.css": {
52
+ "/assets/index-CobXD0yH.css": {
60
53
  "type": "text/css; charset=utf-8",
61
- "etag": '"17293-5C6kMCq9PaxOjrbr7Or2ITIT6Lo"',
62
- "mtime": "2026-06-20T07:49:57.206Z",
63
- "size": 94867,
64
- "path": "../public/assets/index-D7wwbwly.css"
54
+ "etag": '"17587-wM3UwOtYjpQy81oA4sjkIdizScg"',
55
+ "mtime": "2026-06-20T09:50:40.188Z",
56
+ "size": 95623,
57
+ "path": "../public/assets/index-CobXD0yH.css"
65
58
  },
66
59
  "/assets/minimax-BPMzvuL-.jpeg": {
67
60
  "type": "image/jpeg",
68
61
  "etag": '"1b06-IwivU89ko5UTMUM1/t7hn4sQK9A"',
69
- "mtime": "2026-06-20T07:49:57.206Z",
62
+ "mtime": "2026-06-20T09:50:40.188Z",
70
63
  "size": 6918,
71
64
  "path": "../public/assets/minimax-BPMzvuL-.jpeg"
72
65
  },
73
- "/assets/json-viewer-BbU0n8eM.js": {
66
+ "/assets/json-viewer-BrzjD7qI.js": {
74
67
  "type": "text/javascript; charset=utf-8",
75
- "etag": '"1e652-M43x58m2bH0hBJMNDpGZ/fDfT5s"',
76
- "mtime": "2026-06-20T07:49:57.207Z",
68
+ "etag": '"1e652-kToNy9EOWKlmvVVK2ggoK6Yj4is"',
69
+ "mtime": "2026-06-20T09:50:40.189Z",
77
70
  "size": 124498,
78
- "path": "../public/assets/json-viewer-BbU0n8eM.js"
71
+ "path": "../public/assets/json-viewer-BrzjD7qI.js"
79
72
  },
80
- "/assets/main-CZT_F-gu.js": {
73
+ "/assets/main-mgxeUdZQ.js": {
81
74
  "type": "text/javascript; charset=utf-8",
82
- "etag": '"5138c-VrHslavJjlr9YgDZ13bVuWsHMqQ"',
83
- "mtime": "2026-06-20T07:49:57.207Z",
75
+ "etag": '"5138c-8pFfB8xlDwdi154QNl3icGhbrO0"',
76
+ "mtime": "2026-06-20T09:50:40.189Z",
84
77
  "size": 332684,
85
- "path": "../public/assets/main-CZT_F-gu.js"
78
+ "path": "../public/assets/main-mgxeUdZQ.js"
79
+ },
80
+ "/assets/RequestAnatomy-DZ8grAih.js": {
81
+ "type": "text/javascript; charset=utf-8",
82
+ "etag": '"1426-KgPrtOak3tXSA1eBiDgPYDF0NzY"',
83
+ "mtime": "2026-06-20T09:50:40.189Z",
84
+ "size": 5158,
85
+ "path": "../public/assets/RequestAnatomy-DZ8grAih.js"
86
86
  },
87
- "/assets/ReplayDialog-CxUk_TF0.js": {
87
+ "/assets/ReplayDialog-DTeaHHit.js": {
88
88
  "type": "text/javascript; charset=utf-8",
89
- "etag": '"11c0-esa6w7Upc98DpnzYsJtOduS9W7w"',
90
- "mtime": "2026-06-20T07:49:57.207Z",
89
+ "etag": '"11c0-vzfqRFtK58XnhNRimd5URd22Gcs"',
90
+ "mtime": "2026-06-20T09:50:40.189Z",
91
91
  "size": 4544,
92
- "path": "../public/assets/ReplayDialog-CxUk_TF0.js"
92
+ "path": "../public/assets/ReplayDialog-DTeaHHit.js"
93
93
  },
94
- "/assets/RequestAnatomy-DIlzjgjJ.js": {
94
+ "/assets/ResponseView-Cldm6RCi.js": {
95
95
  "type": "text/javascript; charset=utf-8",
96
- "etag": '"142a-Say/U0wBSXeJXbMdzIFCiD2Yq8o"',
97
- "mtime": "2026-06-20T07:49:57.207Z",
98
- "size": 5162,
99
- "path": "../public/assets/RequestAnatomy-DIlzjgjJ.js"
96
+ "etag": '"6b01-Qix5qsvqjrCTAlqfCJ+Pp8h1e9I"',
97
+ "mtime": "2026-06-20T09:50:40.189Z",
98
+ "size": 27393,
99
+ "path": "../public/assets/ResponseView-Cldm6RCi.js"
100
100
  },
101
- "/assets/ResponseView-DQCuKJ1G.js": {
101
+ "/assets/StreamingChunkSequence-3x4p-yT7.js": {
102
102
  "type": "text/javascript; charset=utf-8",
103
- "etag": '"6c88-pdMfEcfub7CjHnge4PzxOHEcbPE"',
104
- "mtime": "2026-06-20T07:49:57.207Z",
105
- "size": 27784,
106
- "path": "../public/assets/ResponseView-DQCuKJ1G.js"
103
+ "etag": '"d81-mHjIspQgaAOB4LmN6Cfnz+NcWOM"',
104
+ "mtime": "2026-06-20T09:50:40.189Z",
105
+ "size": 3457,
106
+ "path": "../public/assets/StreamingChunkSequence-3x4p-yT7.js"
107
107
  },
108
108
  "/assets/zhipuai-BPNAnxo-.svg": {
109
109
  "type": "image/svg+xml",
110
110
  "etag": '"2bf8-hNaLCTi89nOFCsIIfWpP/jrfo0s"',
111
- "mtime": "2026-06-20T07:49:57.206Z",
111
+ "mtime": "2026-06-20T09:50:40.188Z",
112
112
  "size": 11256,
113
113
  "path": "../public/assets/zhipuai-BPNAnxo-.svg"
114
114
  },
115
+ "/assets/CompareDrawer-BCH_fsLm.js": {
116
+ "type": "text/javascript; charset=utf-8",
117
+ "etag": '"4a1f-Y215Tlm1TY2GPfXfX4DX86bgJPU"',
118
+ "mtime": "2026-06-20T09:50:40.189Z",
119
+ "size": 18975,
120
+ "path": "../public/assets/CompareDrawer-BCH_fsLm.js"
121
+ },
122
+ "/assets/_sessionId-YqWFBu6d.js": {
123
+ "type": "text/javascript; charset=utf-8",
124
+ "etag": '"d2-hOIbwqwgtPs0H/vPSZ1gDPz5pFU"',
125
+ "mtime": "2026-06-20T09:50:40.189Z",
126
+ "size": 210,
127
+ "path": "../public/assets/_sessionId-YqWFBu6d.js"
128
+ },
115
129
  "/assets/qwen-CONDcHqt.png": {
116
130
  "type": "image/png",
117
131
  "etag": '"572c3-cdJAPaHdOvFCGzuaQjagdgOu6XE"',
118
- "mtime": "2026-06-20T07:49:57.206Z",
132
+ "mtime": "2026-06-20T09:50:40.188Z",
119
133
  "size": 357059,
120
134
  "path": "../public/assets/qwen-CONDcHqt.png"
121
135
  },
122
- "/assets/_sessionId-dY1TTl7N.js": {
136
+ "/assets/ProxyViewerContainer-D85_UANk.js": {
123
137
  "type": "text/javascript; charset=utf-8",
124
- "etag": '"d2-gUdCO5tW0loAHOM6KOFd73K/+Es"',
125
- "mtime": "2026-06-20T07:49:57.206Z",
126
- "size": 210,
127
- "path": "../public/assets/_sessionId-dY1TTl7N.js"
128
- },
129
- "/assets/ProxyViewerContainer-Da0jpBkp.js": {
130
- "type": "text/javascript; charset=utf-8",
131
- "etag": '"79801-1JDGhvSsOIGys3Enbh6ed4oyMoE"',
132
- "mtime": "2026-06-20T07:49:57.207Z",
133
- "size": 497665,
134
- "path": "../public/assets/ProxyViewerContainer-Da0jpBkp.js"
135
- },
136
- "/assets/StreamingChunkSequence-DHk4SGGL.js": {
137
- "type": "text/javascript; charset=utf-8",
138
- "etag": '"d81-q+WustPR2MRDE/q2wIQ/H/VHcAc"',
139
- "mtime": "2026-06-20T07:49:57.207Z",
140
- "size": 3457,
141
- "path": "../public/assets/StreamingChunkSequence-DHk4SGGL.js"
138
+ "etag": '"79ec4-8t+BfQ9tY8ia35/KlmoU69wDlc8"',
139
+ "mtime": "2026-06-20T09:50:40.189Z",
140
+ "size": 499396,
141
+ "path": "../public/assets/ProxyViewerContainer-D85_UANk.js"
142
142
  }
143
143
  };
144
144
  function readAsset(id) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tonyclaw/agent-inspector",
3
- "version": "2.0.3",
3
+ "version": "2.0.4",
4
4
  "type": "module",
5
5
  "description": "Agent observability and knowledge capture layer for AI coding tools.",
6
6
  "license": "MIT",
@@ -3,6 +3,8 @@ import { ArrowLeft, Check, Copy, Download, Plus } from "lucide-react";
3
3
 
4
4
  import type { CapturedLog } from "../proxy/schemas";
5
5
  import { exportLogsAsZip } from "../lib/export-logs";
6
+ import type { TimeDisplayFormat } from "../lib/runtimeConfig";
7
+ import { formatTimestampRange } from "../lib/timeDisplay";
6
8
  import { formatTokens } from "../lib/utils";
7
9
  import packageJson from "../../package.json";
8
10
  import { ConversationGroup, groupLogsByConversation } from "./proxy-viewer";
@@ -33,17 +35,11 @@ function computeTokenSummary(logs: CapturedLog[]): { totalIn: number; totalOut:
33
35
  return { totalIn, totalOut };
34
36
  }
35
37
 
36
- function formatTimeRange(logs: CapturedLog[]): string | null {
38
+ function formatTimeRange(logs: CapturedLog[], timeDisplayFormat: TimeDisplayFormat): string | null {
37
39
  const first = logs[0];
38
40
  const last = logs[logs.length - 1];
39
41
  if (first === undefined || last === undefined) return null;
40
- const format = (iso: string): string =>
41
- new Date(iso).toLocaleTimeString([], {
42
- hour: "2-digit",
43
- minute: "2-digit",
44
- second: "2-digit",
45
- });
46
- return `${format(first.timestamp)} - ${format(last.timestamp)}`;
42
+ return formatTimestampRange(first.timestamp, last.timestamp, timeDisplayFormat);
47
43
  }
48
44
 
49
45
  function getFirstUserAgent(logs: CapturedLog[]): string | null {
@@ -132,14 +128,19 @@ function SessionContextBar({
132
128
  logs,
133
129
  totalIn,
134
130
  totalOut,
131
+ timeDisplayFormat,
135
132
  }: {
136
133
  sessionId: string;
137
134
  logs: CapturedLog[];
138
135
  totalIn: number;
139
136
  totalOut: number;
137
+ timeDisplayFormat: TimeDisplayFormat;
140
138
  }): JSX.Element {
141
139
  const [copied, setCopied] = useState(false);
142
- const timeRange = useMemo(() => formatTimeRange(logs), [logs]);
140
+ const timeRange = useMemo(
141
+ () => formatTimeRange(logs, timeDisplayFormat),
142
+ [logs, timeDisplayFormat],
143
+ );
143
144
  const userAgent = useMemo(() => getFirstUserAgent(logs), [logs]);
144
145
 
145
146
  const handleCopyLink = useCallback(() => {
@@ -216,6 +217,8 @@ export type ProxyViewerProps = {
216
217
  strip: boolean;
217
218
  /** Slow-response threshold in seconds. `0` disables the warning indicator. */
218
219
  slowResponseThresholdSeconds: number;
220
+ /** Controls whether timestamps render as compact local time or full ISO strings. */
221
+ timeDisplayFormat: TimeDisplayFormat;
219
222
  /** Hide the session filter dropdown. Used on `/session/$id` routes where
220
223
  * the session is already pinned by the URL and the dropdown would just
221
224
  * fight the URL state. */
@@ -238,6 +241,7 @@ export function ProxyViewer({
238
241
  onViewModeChange,
239
242
  strip,
240
243
  slowResponseThresholdSeconds,
244
+ timeDisplayFormat,
241
245
  hideSessionFilter = false,
242
246
  pinnedSessionId,
243
247
  }: ProxyViewerProps): JSX.Element {
@@ -291,6 +295,7 @@ export function ProxyViewer({
291
295
  }, []);
292
296
 
293
297
  const groups = useMemo(() => groupLogsByConversation(logs), [logs]);
298
+ const hasPinnedSessionContext = pinnedSessionId !== undefined;
294
299
  const cacheTrends = useMemo(() => computeCacheTrends(groups), [groups]);
295
300
  const comparisonPredecessors = useMemo(() => buildValidPredecessors(groups), [groups]);
296
301
  const handleCompareWithPrevious = useCallback(
@@ -380,6 +385,7 @@ export function ProxyViewer({
380
385
  logs={logs}
381
386
  totalIn={totalIn}
382
387
  totalOut={totalOut}
388
+ timeDisplayFormat={timeDisplayFormat}
383
389
  />
384
390
  )}
385
391
 
@@ -438,12 +444,14 @@ export function ProxyViewer({
438
444
  </button>
439
445
  </div>
440
446
  <div className="flex-1" />
441
- <span className="text-muted-foreground text-xs font-mono">
442
- {logs.length} request{logs.length !== 1 ? "s" : ""}
443
- {totalIn > 0 || totalOut > 0
444
- ? ` · ${formatTokens(totalIn)} in / ${formatTokens(totalOut)} out`
445
- : ""}
446
- </span>
447
+ {!hasPinnedSessionContext && (
448
+ <span className="text-muted-foreground text-xs font-mono">
449
+ {logs.length} request{logs.length !== 1 ? "s" : ""}
450
+ {totalIn > 0 || totalOut > 0
451
+ ? ` · ${formatTokens(totalIn)} in / ${formatTokens(totalOut)} out`
452
+ : ""}
453
+ </span>
454
+ )}
447
455
  {logs.length > 0 && (
448
456
  <button
449
457
  type="button"
@@ -527,6 +535,8 @@ export function ProxyViewer({
527
535
  comparisonPredecessors={comparisonPredecessors}
528
536
  onClearGroup={onClearGroup}
529
537
  standalone={groups.length === 1}
538
+ hasPinnedSessionContext={hasPinnedSessionContext}
539
+ timeDisplayFormat={timeDisplayFormat}
530
540
  />
531
541
  ))}
532
542
  </div>
@@ -330,7 +330,7 @@ export function ProxyViewerContainer({
330
330
 
331
331
  // Read the strip config once at the container so the virtualized list does
332
332
  // not need N independent SWR subscriptions per row.
333
- const { strip, slowResponseThresholdSeconds } = useStripConfig();
333
+ const { strip, slowResponseThresholdSeconds, timeDisplayFormat } = useStripConfig();
334
334
 
335
335
  return (
336
336
  <>
@@ -354,6 +354,7 @@ export function ProxyViewerContainer({
354
354
  onViewModeChange={setViewMode}
355
355
  strip={strip}
356
356
  slowResponseThresholdSeconds={slowResponseThresholdSeconds}
357
+ timeDisplayFormat={timeDisplayFormat}
357
358
  // Session filter is the URL's job when `initialSessionId` was given.
358
359
  hideSessionFilter={initialSessionId !== undefined}
359
360
  pinnedSessionId={initialSessionId}