@tonyclaw/agent-inspector 2.0.43 → 2.1.1

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 (44) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/{CompareDrawer-CxM1gCfL.js → CompareDrawer-DkDpl_Sg.js} +1 -1
  3. package/.output/public/assets/ProxyViewerContainer-D_-e1qn7.js +117 -0
  4. package/.output/public/assets/{ReplayDialog-UseUkucS.js → ReplayDialog-CKqYfD0A.js} +1 -1
  5. package/.output/public/assets/RequestAnatomy-CQZl-YIx.js +1 -0
  6. package/.output/public/assets/ResponseView-DW9tFPi0.js +1 -0
  7. package/.output/public/assets/{StreamingChunkSequence-JSQEPeNS.js → StreamingChunkSequence-m8zKc3L1.js} +1 -1
  8. package/.output/public/assets/_sessionId-DyfzgUXv.js +1 -0
  9. package/.output/public/assets/index-B6bobhTz.js +1 -0
  10. package/.output/public/assets/index-CLQKZ5A5.css +1 -0
  11. package/.output/public/assets/{main-BpGVJcpB.js → main-BjXd3DR-.js} +2 -2
  12. package/.output/server/_libs/lucide-react.mjs +219 -178
  13. package/.output/server/{_sessionId-DGn-TENM.mjs → _sessionId-LjzdyWF4.mjs} +3 -3
  14. package/.output/server/_ssr/{CompareDrawer-CFElCSYY.mjs → CompareDrawer-YX2uOwh9.mjs} +4 -4
  15. package/.output/server/_ssr/{ProxyViewerContainer-B7SR9mrD.mjs → ProxyViewerContainer-BcKHl2E3.mjs} +1016 -582
  16. package/.output/server/_ssr/{ReplayDialog-DfKapj0k.mjs → ReplayDialog-B9AxvV2j.mjs} +5 -5
  17. package/.output/server/_ssr/{RequestAnatomy-CUxTCg31.mjs → RequestAnatomy-DxmUOcz8.mjs} +4 -4
  18. package/.output/server/_ssr/{ResponseView-BXY0w197.mjs → ResponseView-B73PHDQ0.mjs} +4 -4
  19. package/.output/server/_ssr/{StreamingChunkSequence-CzMnES9H.mjs → StreamingChunkSequence-Bkwxu5Ev.mjs} +4 -4
  20. package/.output/server/_ssr/{index-CVlT-REW.mjs → index-Dfl6uxit.mjs} +3 -3
  21. package/.output/server/_ssr/index.mjs +2 -2
  22. package/.output/server/_ssr/{router-B2d1LUx6.mjs → router-B5cpU5Hi.mjs} +458 -10
  23. package/.output/server/{_tanstack-start-manifest_v-Drpi28BM.mjs → _tanstack-start-manifest_v-CHhxRQY_.mjs} +1 -1
  24. package/.output/server/index.mjs +62 -62
  25. package/package.json +1 -1
  26. package/src/components/OnboardingBanner.tsx +60 -70
  27. package/src/components/ProxyViewer.tsx +838 -366
  28. package/src/components/ProxyViewerContainer.tsx +136 -5
  29. package/src/components/providers/SettingsDialog.tsx +0 -13
  30. package/src/components/proxy-viewer/LogEntry.tsx +198 -89
  31. package/src/components/proxy-viewer/LogEntryHeader.tsx +23 -13
  32. package/src/components/proxy-viewer/RequestToolsPanel.tsx +8 -8
  33. package/src/components/ui/crab-logo.tsx +0 -50
  34. package/src/components/ui/json-viewer.tsx +6 -0
  35. package/src/proxy/logIndex.ts +188 -1
  36. package/src/proxy/store.ts +405 -3
  37. package/src/routes/api/logs.ts +36 -0
  38. package/styles/globals.css +53 -8
  39. package/.output/public/assets/ProxyViewerContainer-TtRG-0E7.js +0 -117
  40. package/.output/public/assets/RequestAnatomy-aPxgEJ2L.js +0 -1
  41. package/.output/public/assets/ResponseView-DA-F4F97.js +0 -1
  42. package/.output/public/assets/_sessionId-BEXuCWq5.js +0 -1
  43. package/.output/public/assets/index-Bhsa_2xX.js +0 -1
  44. package/.output/public/assets/index-DOWlRJ0W.css +0 -1
@@ -1,20 +1,20 @@
1
1
  import { r as reactExports, j as jsxRuntimeExports, a as React } from "../_libs/react.mjs";
2
- import { I as InspectorGroupsListResponseSchema, C as CapturedLogSchema, D as DEFAULT_CAPTURE_MODE, a as DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS, b as DEFAULT_PROVIDER_TEST_TIMEOUT_SECONDS, c as DEFAULT_TIME_DISPLAY_FORMAT, v as packageJson, i as GroupEvidenceExportResultSchema, j as DeleteInspectorGroupResponseSchema, d as RuntimeConfigSchema, P as ProviderConfigSchema, f as apiFormatForPath, n as createPendingProviderTestResults, o as ProviderTestResultsSchema, q as createFailedProviderTestResults, M as MAX_SLOW_RESPONSE_THRESHOLD_SECONDS, r as MAX_PROVIDER_TEST_TIMEOUT_SECONDS, T as TimeDisplayFormatSchema, m as maskApiKey, k as providerHasContextMetadata, l as findProviderModelMetadata, g as getSessionPath, p as parseOpenAIResponse, O as OpenAIRequestSchema, A as AnthropicResponseSchema$1, e as AnthropicRequestSchema, s as safeGetOwnProperty, t as resolveProviderContextWindow, K as KnowledgeCandidateSchema, h as stripClaudeCodeBillingHeader, u as isPlainRecord, G as GroupEvidenceReadResponseSchema } from "./router-B2d1LUx6.mjs";
2
+ import { I as InspectorGroupsListResponseSchema, C as CapturedLogSchema, D as DEFAULT_CAPTURE_MODE, a as DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS, b as DEFAULT_PROVIDER_TEST_TIMEOUT_SECONDS, c as DEFAULT_TIME_DISPLAY_FORMAT, d as RuntimeConfigSchema, v as packageJson, P as ProviderConfigSchema, f as apiFormatForPath, i as GroupEvidenceExportResultSchema, j as DeleteInspectorGroupResponseSchema, n as createPendingProviderTestResults, o as ProviderTestResultsSchema, q as createFailedProviderTestResults, M as MAX_SLOW_RESPONSE_THRESHOLD_SECONDS, r as MAX_PROVIDER_TEST_TIMEOUT_SECONDS, T as TimeDisplayFormatSchema, g as getSessionPath, p as parseOpenAIResponse, O as OpenAIRequestSchema, A as AnthropicResponseSchema$1, e as AnthropicRequestSchema, s as safeGetOwnProperty, t as resolveProviderContextWindow, m as maskApiKey, k as providerHasContextMetadata, l as findProviderModelMetadata, K as KnowledgeCandidateSchema, h as stripClaudeCodeBillingHeader, u as isPlainRecord, G as GroupEvidenceReadResponseSchema } from "./router-B5cpU5Hi.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$2, C as Content, a as Close, b as Title, P as Portal$2, O as Overlay } from "../_libs/radix-ui__react-dialog.mjs";
8
+ import { R as Root, T as Trigger$1, 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 useWindowVirtualizer, a 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, P as Plus, D as Download, F as FileBraces, T as Trash2, L as Layers, a as LoaderCircle, R as RefreshCw, S as Settings, A as ArrowLeft, b as Copy, c as ChevronDown, U as Upload, d as Scan, e as CircleAlert, f as Terminal, g as ChevronUp, E as EyeOff, h as Eye, i as ExternalLink, j as RotateCw, k as Clock, l as ChevronRight, m as Pencil, n as ArrowUpRight, o as ArrowDownRight, p as User, M as MessageSquare, Z as Zap, W as Wrench, q as TriangleAlert, B as Brain, r as Minus, s as CircleCheckBig, t as CircleX, u as ShieldCheck, v as Save, w as FileSearch, x as CircleCheck, y as CloudUpload, O as OctagonAlert, z as Radio, G as Gauge, H as Globe, I as FileTerminal, J as ChevronsUp, K as ChevronsDown, N as FileDiff, Q as History, V as RotateCcw, Y as Search, _ as GitCompareArrows, $ as CircleQuestionMark, a0 as Server, a1 as Lock, a2 as Wifi, a3 as WifiOff, a4 as ArrowUp, a5 as ArrowDown, a6 as Ellipsis, a7 as CodeXml, a8 as Blocks, a9 as MousePointerClick, aa as FileText, ab as Rows3, ac as Columns2 } from "../_libs/lucide-react.mjs";
12
+ import { I as Info, C as ChevronDown, a as Check, X, D as Download, F as FileBraces, T as Trash2, P as Plus, A as ArrowLeft, b as ChevronUp, c as Copy, d as ChevronsLeft, e as ChevronLeft, f as ChevronRight, g as ChevronsRight, h as Clapperboard, S as Siren, G as Gauge, L as Layers, i as LoaderCircle, R as RefreshCw, j as Settings, U as Upload, k as Scan, l as CircleAlert, m as Terminal, n as ArrowUpRight, o as ArrowDownRight, p as User, q as Clock, M as MessageSquare, Z as Zap, E as ExternalLink, W as Wrench, r as TriangleAlert, B as Brain, s as EyeOff, t as Eye, u as RotateCw, v as Pencil, w as CircleX, x as ShieldCheck, y as Save, z as FileSearch, H as CircleCheck, J as CloudUpload, O as OctagonAlert, K as Radio, N as Globe, Q as FileTerminal, V as ChevronsUp, Y as ChevronsDown, _ as FileDiff, $ as History, a0 as RotateCcw, a1 as Search, a2 as GitCompareArrows, a3 as Minus, a4 as CircleCheckBig, a5 as ArrowUp, a6 as ArrowDown, a7 as CircleQuestionMark, a8 as Server, a9 as Lock, aa as Wifi, ab as WifiOff, ac as Ellipsis, ad as CodeXml, ae as Blocks, af as MousePointerClick, ag as FileText, ah as Rows3, ai as Columns2 } from "../_libs/lucide-react.mjs";
13
13
  import { M as Markdown } from "../_libs/react-markdown.mjs";
14
14
  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";
15
- 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";
16
15
  import { S as Slot } from "../_libs/radix-ui__react-slot.mjs";
17
- import { R as Root2$1, L as List, T as Trigger$3, C as Content$1 } from "../_libs/radix-ui__react-tabs.mjs";
16
+ import { R as Root2$1, L as List, T as Trigger$2, C as Content$1 } from "../_libs/radix-ui__react-tabs.mjs";
17
+ import { P as Provider, R as Root3, T as Trigger$3, a as Portal$1, C as Content2$1, A as Arrow2 } from "../_libs/radix-ui__react-tooltip.mjs";
18
18
  import { R as Root$1, C as CollapsibleContent$1, a as CollapsibleTrigger$1 } from "../_libs/radix-ui__react-collapsible.mjs";
19
19
  import { R as Root$2, V as Viewport$1, C as Corner, S as ScrollAreaScrollbar, a as ScrollAreaThumb } from "../_libs/radix-ui__react-scroll-area.mjs";
20
20
  const ApiErrorSchema = object({
@@ -195,70 +195,59 @@ function useOnboarding() {
195
195
  };
196
196
  }
197
197
  function OnboardingBanner() {
198
- const { hasSeenOnboarding, captureMode, isLoading, markSeen } = useOnboarding();
198
+ const { hasSeenOnboarding, isLoading, markSeen } = useOnboarding();
199
+ const [expanded, setExpanded] = reactExports.useState(false);
199
200
  if (isLoading || hasSeenOnboarding) return null;
200
- const isFullMode = captureMode === "full";
201
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(
201
+ const detailClass = expanded ? "grid" : "hidden sm:grid";
202
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
202
203
  "div",
203
204
  {
204
205
  role: "note",
205
206
  "aria-label": "Onboarding tip",
206
- className: "mx-4 mt-2 mb-1 flex items-start gap-3 rounded-md border border-amber-500/30 bg-amber-500/5 px-4 py-3 text-sm",
207
- children: [
207
+ className: "mx-4 mt-2 mb-1 rounded-md border border-amber-500/30 bg-[#130d04] px-3 py-2 text-sm shadow-[0_12px_40px_rgba(0,0,0,0.16)]",
208
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-3", children: [
209
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Info, { className: "mt-0.5 size-4 shrink-0 text-amber-300", "aria-hidden": "true" }),
208
210
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 flex-1", children: [
209
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-1 font-medium text-amber-600 dark:text-amber-400", children: isFullMode ? "Agent Inspector is ready in Full mode" : "Agent Inspector is ready in Simple mode" }),
210
- /* @__PURE__ */ jsxRuntimeExports.jsxs("ol", { className: "space-y-0.5 text-xs leading-relaxed text-muted-foreground", children: [
211
- /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { children: [
212
- /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "1. Start in the right mode" }),
213
- ": this process is currently running in",
214
- " ",
215
- /* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: captureMode }),
216
- ". Mode is fixed at startup."
217
- ] }),
218
- isFullMode ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
219
- /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { children: [
220
- /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "2. Full diagnostics" }),
221
- ": raw headers, raw response, and SSE chunks are captured for deep investigations."
222
- ] }),
223
- /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { children: [
224
- /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "3. Daily work" }),
225
- ": restart with",
226
- " ",
227
- /* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: "agent-inspector --mode simple" }),
228
- " to reduce capture overhead."
229
- ] })
230
- ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
231
- /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { children: [
232
- /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "2. Simple capture" }),
233
- ": requests, responses, tools, timing, tokens, replay, and memory candidates are available with lower overhead."
234
- ] }),
235
- /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { children: [
236
- /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "3. Need raw diagnostics?" }),
237
- " Restart with",
238
- " ",
239
- /* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: "agent-inspector --mode full" }),
240
- " for raw headers, raw response, and SSE chunks."
241
- ] })
242
- ] }),
243
- /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { children: [
244
- /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Agent setup" }),
245
- ": run ",
246
- /* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: "agent-inspector onboard --status" }),
247
- ", then use ",
248
- /* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: "/agent-inspector:onboard" }),
249
- " in Claude Code or ask Codex to use",
250
- " ",
251
- /* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: "agent-inspector-onboard" }),
252
- "."
253
- ] }),
254
- /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { children: [
255
- /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Container networking" }),
256
- ": if the AI tool runs outside this Inspector container or host, replace ",
257
- /* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: "localhost" }),
258
- " with a reachable address."
259
- ] })
260
- ] })
211
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: [
212
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium text-amber-200", children: "Inspector ready" }),
213
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "hidden truncate text-xs text-muted-foreground sm:inline", children: "Request, response, tool, timing, token, replay, and memory signals are active." })
214
+ ] }),
215
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1 text-xs leading-relaxed text-muted-foreground sm:hidden", children: "Core capture is active." }),
216
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
217
+ "div",
218
+ {
219
+ className: `${detailClass} mt-2 gap-x-4 gap-y-1 text-xs leading-relaxed text-muted-foreground sm:grid-cols-2`,
220
+ children: [
221
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
222
+ /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Evidence" }),
223
+ ": logs, sessions, groups, and MCP exports are available."
224
+ ] }),
225
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
226
+ /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Network" }),
227
+ ": replace ",
228
+ /* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: "localhost" }),
229
+ " if containers differ."
230
+ ] })
231
+ ]
232
+ }
233
+ )
261
234
  ] }),
235
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
236
+ "button",
237
+ {
238
+ type: "button",
239
+ onClick: () => setExpanded((value) => !value),
240
+ className: "inline-flex h-8 shrink-0 items-center gap-1 rounded-md border border-amber-500/30 px-2 text-xs text-amber-200 transition-colors hover:bg-amber-500/10 sm:hidden",
241
+ "aria-expanded": expanded,
242
+ "aria-label": expanded ? "Hide onboarding details" : "Show onboarding details",
243
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(
244
+ ChevronDown,
245
+ {
246
+ className: `size-3.5 transition-transform ${expanded ? "rotate-180" : ""}`
247
+ }
248
+ )
249
+ }
250
+ ),
262
251
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
263
252
  "button",
264
253
  {
@@ -266,7 +255,7 @@ function OnboardingBanner() {
266
255
  onClick: () => {
267
256
  void markSeen();
268
257
  },
269
- className: "inline-flex h-8 shrink-0 items-center gap-1.5 rounded-md border border-amber-500/40 px-3 text-xs text-amber-700 transition-colors hover:bg-amber-500/10 dark:text-amber-300",
258
+ className: "hidden h-8 shrink-0 items-center gap-1.5 rounded-md border border-amber-500/40 px-3 text-xs text-amber-200 transition-colors hover:bg-amber-500/10 sm:inline-flex",
270
259
  "aria-label": "Dismiss onboarding tip",
271
260
  children: [
272
261
  /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-3.5" }),
@@ -286,7 +275,7 @@ function OnboardingBanner() {
286
275
  children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "size-3.5" })
287
276
  }
288
277
  )
289
- ]
278
+ ] })
290
279
  }
291
280
  );
292
281
  }
@@ -613,7 +602,7 @@ function Dialog({
613
602
  function DialogTrigger({
614
603
  ...props
615
604
  }) {
616
- return /* @__PURE__ */ jsxRuntimeExports.jsx(Trigger$2, { "data-slot": "dialog-trigger", ...props });
605
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Trigger$1, { "data-slot": "dialog-trigger", ...props });
617
606
  }
618
607
  function DialogPortal({
619
608
  ...props
@@ -1749,7 +1738,7 @@ function Tooltip({ ...props }) {
1749
1738
  return /* @__PURE__ */ jsxRuntimeExports.jsx(Root3, { "data-slot": "tooltip", ...props });
1750
1739
  }
1751
1740
  function TooltipTrigger({ ...props }) {
1752
- return /* @__PURE__ */ jsxRuntimeExports.jsx(Trigger$1, { "data-slot": "tooltip-trigger", ...props });
1741
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Trigger$3, { "data-slot": "tooltip-trigger", ...props });
1753
1742
  }
1754
1743
  function TooltipContent({
1755
1744
  className,
@@ -1885,7 +1874,7 @@ function TabsTrigger({
1885
1874
  ...props
1886
1875
  }) {
1887
1876
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
1888
- Trigger$3,
1877
+ Trigger$2,
1889
1878
  {
1890
1879
  "data-slot": "tabs-trigger",
1891
1880
  className: cn(
@@ -1937,19 +1926,19 @@ function useCopyFeedback(text) {
1937
1926
  return { copied, copy };
1938
1927
  }
1939
1928
  const LazyCompareDrawer = reactExports.lazy(
1940
- () => import("./CompareDrawer-CFElCSYY.mjs").then((m) => ({ default: m.CompareDrawer }))
1929
+ () => import("./CompareDrawer-YX2uOwh9.mjs").then((m) => ({ default: m.CompareDrawer }))
1941
1930
  );
1942
1931
  const LazyReplayDialog = reactExports.lazy(
1943
- () => import("./ReplayDialog-DfKapj0k.mjs").then((m) => ({ default: m.ReplayDialog }))
1932
+ () => import("./ReplayDialog-B9AxvV2j.mjs").then((m) => ({ default: m.ReplayDialog }))
1944
1933
  );
1945
1934
  const LazyRequestAnatomy = reactExports.lazy(
1946
- () => import("./RequestAnatomy-CUxTCg31.mjs").then((m) => ({ default: m.RequestAnatomy }))
1935
+ () => import("./RequestAnatomy-DxmUOcz8.mjs").then((m) => ({ default: m.RequestAnatomy }))
1947
1936
  );
1948
1937
  const LazyResponseView = reactExports.lazy(
1949
- () => import("./ResponseView-BXY0w197.mjs").then((m) => ({ default: m.ResponseView }))
1938
+ () => import("./ResponseView-B73PHDQ0.mjs").then((m) => ({ default: m.ResponseView }))
1950
1939
  );
1951
1940
  const LazyStreamingChunkSequence = reactExports.lazy(
1952
- () => import("./StreamingChunkSequence-CzMnES9H.mjs").then((m) => ({
1941
+ () => import("./StreamingChunkSequence-Bkwxu5Ev.mjs").then((m) => ({
1953
1942
  default: m.StreamingChunkSequence
1954
1943
  }))
1955
1944
  );
@@ -2351,6 +2340,7 @@ const STATUS_BADGE_CLASSES = {
2351
2340
  server_error: "bg-rose-500/15 text-rose-400 border-rose-500/25",
2352
2341
  pending: "bg-muted text-muted-foreground border-border"
2353
2342
  };
2343
+ const HEADER_ACTION_BUTTON_CLASS = "size-8 border-white/10 bg-[#0a0d11] text-muted-foreground shadow-none hover:border-cyan-300/30 hover:bg-cyan-400/10 hover:text-cyan-100";
2354
2344
  function formatElapsed$3(ms) {
2355
2345
  if (ms < 1e3) return `${ms}ms`;
2356
2346
  return `${(ms / 1e3).toFixed(1)}s`;
@@ -2402,8 +2392,8 @@ const LogEntryHeader = reactExports.memo(function({
2402
2392
  "data-nav-id": `log-${log.id}`,
2403
2393
  "data-nav-action": expanded ? "collapse" : "expand",
2404
2394
  className: cn(
2405
- "flex items-center gap-2 px-3 py-1 cursor-pointer transition-colors",
2406
- "hover:bg-muted/50",
2395
+ "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1 px-3 py-1.5 cursor-pointer transition-colors",
2396
+ expanded ? "bg-[#0c1015]" : "hover:bg-muted/30",
2407
2397
  "select-none",
2408
2398
  "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:outline-none"
2409
2399
  ),
@@ -2491,24 +2481,30 @@ const LogEntryHeader = reactExports.memo(function({
2491
2481
  ] }) }),
2492
2482
  /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Output token throughput after first chunk" })
2493
2483
  ] }),
2494
- hasTokens && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1 text-xs shrink-0", children: [
2484
+ hasTokens && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 items-center gap-1 text-xs sm:shrink-0", children: [
2495
2485
  /* @__PURE__ */ jsxRuntimeExports.jsx(Zap, { className: "size-3 text-muted-foreground" }),
2496
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono tabular-nums", children: [
2486
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 flex-wrap items-center gap-x-1 font-mono tabular-nums", children: [
2497
2487
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
2498
2488
  "span",
2499
2489
  {
2500
- className: log.inputTokens !== null ? "text-blue-400" : "text-muted-foreground",
2490
+ className: cn(
2491
+ "whitespace-nowrap",
2492
+ log.inputTokens !== null ? "text-blue-400" : "text-muted-foreground"
2493
+ ),
2501
2494
  children: [
2502
2495
  "IN ",
2503
2496
  log.inputTokens !== null ? formatTokens(log.inputTokens) : "—"
2504
2497
  ]
2505
2498
  }
2506
2499
  ),
2507
- " / ",
2500
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground", children: "/" }),
2508
2501
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
2509
2502
  "span",
2510
2503
  {
2511
- className: log.outputTokens !== null ? "text-amber-400" : "text-muted-foreground",
2504
+ className: cn(
2505
+ "whitespace-nowrap",
2506
+ log.outputTokens !== null ? "text-amber-400" : "text-muted-foreground"
2507
+ ),
2512
2508
  children: [
2513
2509
  "OUT ",
2514
2510
  log.outputTokens !== null ? formatTokens(log.outputTokens) : "—"
@@ -2582,7 +2578,7 @@ const LogEntryHeader = reactExports.memo(function({
2582
2578
  {
2583
2579
  variant: "outline",
2584
2580
  size: "icon",
2585
- className: "size-8",
2581
+ className: HEADER_ACTION_BUTTON_CLASS,
2586
2582
  onClick: action.expansion.onToggle,
2587
2583
  disabled: action.expansion.isPending,
2588
2584
  "aria-pressed": action.expansion.isExpanded,
@@ -2599,8 +2595,8 @@ const LogEntryHeader = reactExports.memo(function({
2599
2595
  variant: "outline",
2600
2596
  size: "icon",
2601
2597
  className: cn(
2602
- "size-8",
2603
- action.diffWithRaw.active && "bg-accent text-accent-foreground"
2598
+ HEADER_ACTION_BUTTON_CLASS,
2599
+ action.diffWithRaw.active && "border-cyan-300/35 bg-cyan-400/15 text-cyan-100"
2604
2600
  ),
2605
2601
  onClick: action.diffWithRaw.onToggle,
2606
2602
  "aria-pressed": action.diffWithRaw.active,
@@ -2616,7 +2612,7 @@ const LogEntryHeader = reactExports.memo(function({
2616
2612
  {
2617
2613
  variant: "outline",
2618
2614
  size: "icon",
2619
- className: "size-8",
2615
+ className: HEADER_ACTION_BUTTON_CLASS,
2620
2616
  onClick: action.diffWithPrevious,
2621
2617
  "aria-label": "Diff with previous",
2622
2618
  children: /* @__PURE__ */ jsxRuntimeExports.jsx(History, { className: "size-3.5" })
@@ -2630,7 +2626,7 @@ const LogEntryHeader = reactExports.memo(function({
2630
2626
  {
2631
2627
  variant: "outline",
2632
2628
  size: "icon",
2633
- className: "size-8",
2629
+ className: HEADER_ACTION_BUTTON_CLASS,
2634
2630
  onClick: action.onCopy,
2635
2631
  "aria-label": action.copyCopied ? "Copied" : action.copyLabel,
2636
2632
  children: action.copyCopied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-3.5 text-emerald-500" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-3.5" })
@@ -2646,7 +2642,7 @@ const LogEntryHeader = reactExports.memo(function({
2646
2642
  {
2647
2643
  variant: "outline",
2648
2644
  size: "icon",
2649
- className: "size-8",
2645
+ className: HEADER_ACTION_BUTTON_CLASS,
2650
2646
  onClick: onReplay,
2651
2647
  "aria-label": "Replay request",
2652
2648
  children: /* @__PURE__ */ jsxRuntimeExports.jsx(RotateCcw, { className: "size-3.5" })
@@ -2989,6 +2985,10 @@ function JsonViewer({
2989
2985
  const isArray = dataType === "array";
2990
2986
  return /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cn("font-mono text-xs leading-relaxed", className), children: [
2991
2987
  showCopy && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-2 flex items-center justify-end gap-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(CopyValueButton, { value: data }) }),
2988
+ entries.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-md border border-white/10 bg-black/20 px-3 py-2 text-muted-foreground", children: [
2989
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-cyan-300", children: isArray ? "[]" : "{}" }),
2990
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ml-2 text-[10px] uppercase", children: "0 items" })
2991
+ ] }),
2992
2992
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: entries.map(([key, childValue]) => /* @__PURE__ */ jsxRuntimeExports.jsx(
2993
2993
  JsonNode,
2994
2994
  {
@@ -3144,7 +3144,7 @@ function ToolRow({ tool, called }) {
3144
3144
  const [open, setOpen] = reactExports.useState(false);
3145
3145
  const nameCopy = useCopyFeedback(tool.name);
3146
3146
  const hasDetails = tool.description !== null || tool.requiredParameters.length > 0 || tool.schema !== null;
3147
- return /* @__PURE__ */ jsxRuntimeExports.jsx(Collapsible, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-md border border-border/60 bg-background/40", children: [
3147
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Collapsible, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-md border border-white/10 bg-black/20 shadow-[inset_0_1px_0_rgba(255,255,255,0.03)]", children: [
3148
3148
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center gap-2 px-2.5 py-2", children: [
3149
3149
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
3150
3150
  "button",
@@ -3186,10 +3186,10 @@ function ToolRow({ tool, called }) {
3186
3186
  }
3187
3187
  )
3188
3188
  ] }),
3189
- /* @__PURE__ */ jsxRuntimeExports.jsx(CollapsibleContent, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2 border-t border-border/60 px-2.5 py-2", children: [
3189
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CollapsibleContent, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2 border-t border-white/10 bg-white/[0.02] px-2.5 py-2", children: [
3190
3190
  tool.description !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs leading-relaxed text-muted-foreground", children: tool.description }),
3191
3191
  /* @__PURE__ */ jsxRuntimeExports.jsx(RequiredParameters, { names: tool.requiredParameters }),
3192
- tool.schema !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(ScrollArea, { className: "max-h-64 rounded-md border border-border/60 bg-muted/20 p-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(JsonViewer, { data: safeJsonValue(tool.schema), defaultExpandDepth: 0 }) })
3192
+ tool.schema !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(ScrollArea, { className: "max-h-64 rounded-md border border-white/10 bg-[#06080b] p-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(JsonViewer, { data: safeJsonValue(tool.schema), defaultExpandDepth: 0 }) })
3193
3193
  ] }) })
3194
3194
  ] }) });
3195
3195
  }
@@ -3213,7 +3213,7 @@ const RequestTools = reactExports.memo(function RequestTools2({
3213
3213
  if (summary === null) return null;
3214
3214
  const previewTools = summary.tools.slice(0, 6);
3215
3215
  const hiddenPreviewCount = summary.tools.length - previewTools.length;
3216
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "mb-3 rounded-lg border border-border/70 bg-muted/20", children: [
3216
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "mb-3 overflow-hidden rounded-md border border-white/10 bg-[#080b0f] shadow-[inset_0_1px_0_rgba(255,255,255,0.04)]", children: [
3217
3217
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-2 px-3 py-2", children: [
3218
3218
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
3219
3219
  /* @__PURE__ */ jsxRuntimeExports.jsx(Wrench, { className: "size-4 shrink-0 text-sky-300/80" }),
@@ -3257,7 +3257,7 @@ const RequestTools = reactExports.memo(function RequestTools2({
3257
3257
  type: "button",
3258
3258
  variant: "ghost",
3259
3259
  size: "sm",
3260
- className: "h-7 px-2",
3260
+ className: "h-7 border border-white/10 bg-black/20 px-2 text-muted-foreground hover:border-cyan-300/30 hover:bg-cyan-400/10 hover:text-cyan-100",
3261
3261
  onClick: () => setExpanded((value) => !value),
3262
3262
  "aria-expanded": expanded,
3263
3263
  children: [
@@ -3267,7 +3267,7 @@ const RequestTools = reactExports.memo(function RequestTools2({
3267
3267
  }
3268
3268
  )
3269
3269
  ] }),
3270
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-wrap gap-1.5 border-t border-border/60 px-3 py-2", children: [
3270
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-wrap gap-1.5 border-t border-white/10 bg-black/10 px-3 py-2", children: [
3271
3271
  previewTools.map((tool) => /* @__PURE__ */ jsxRuntimeExports.jsx(
3272
3272
  Badge,
3273
3273
  {
@@ -3285,8 +3285,8 @@ const RequestTools = reactExports.memo(function RequestTools2({
3285
3285
  hiddenPreviewCount
3286
3286
  ] })
3287
3287
  ] }),
3288
- expanded && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2 border-t border-border/60 px-3 py-3", children: [
3289
- /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "flex h-8 items-center gap-2 rounded-md border border-border/70 bg-background/50 px-2 text-xs", children: [
3288
+ expanded && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2 border-t border-white/10 bg-black/15 px-3 py-3", children: [
3289
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "flex h-8 items-center gap-2 rounded-md border border-white/10 bg-[#06080b] px-2 text-xs", children: [
3290
3290
  /* @__PURE__ */ jsxRuntimeExports.jsx(Search, { className: "size-3.5 shrink-0 text-muted-foreground" }),
3291
3291
  /* @__PURE__ */ jsxRuntimeExports.jsx(
3292
3292
  "input",
@@ -3505,9 +3505,73 @@ function resolveFocusedTab(tab, anatomySegments) {
3505
3505
  return "request";
3506
3506
  }
3507
3507
  }
3508
+ const TAB_TRIGGER_CLASS = "h-9 flex-none rounded-none border-0 border-b-2 border-transparent bg-transparent px-3 text-xs font-semibold text-muted-foreground shadow-none hover:bg-cyan-400/[0.04] hover:text-foreground data-[state=active]:border-cyan-300 data-[state=active]:bg-transparent data-[state=active]:text-cyan-100 data-[state=active]:shadow-none";
3508
3509
  function shouldHydrateLogBody(log) {
3509
3510
  return log.bodyContentMode === "compact" || log.bodyContentMode === "truncated";
3510
3511
  }
3512
+ function ExpandedPanel({
3513
+ children,
3514
+ className
3515
+ }) {
3516
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
3517
+ "div",
3518
+ {
3519
+ className: cn(
3520
+ "inspector-scrollbar mx-3 mb-3 max-h-[72vh] overflow-auto rounded-md border border-white/10 bg-[#06080b] p-3 shadow-[inset_0_1px_0_rgba(255,255,255,0.04)]",
3521
+ className
3522
+ ),
3523
+ children
3524
+ }
3525
+ );
3526
+ }
3527
+ function EmptyState({ children }) {
3528
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "rounded-md border border-dashed border-white/10 bg-white/[0.02] px-3 py-5 text-center text-xs italic text-muted-foreground", children });
3529
+ }
3530
+ function RawTextBlock({ children }) {
3531
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "inspector-scrollbar max-h-[64vh] overflow-auto whitespace-pre-wrap break-words rounded-md border border-white/10 bg-black/30 p-3 font-mono text-xs leading-relaxed text-muted-foreground", children });
3532
+ }
3533
+ const NOTICE_TONE_CLASSES = {
3534
+ loading: "border-cyan-400/25 bg-cyan-400/[0.06] text-cyan-100",
3535
+ warning: "border-amber-400/25 bg-amber-400/[0.08] text-amber-100",
3536
+ danger: "border-rose-400/25 bg-rose-400/[0.08] text-rose-100"
3537
+ };
3538
+ function NoticeBlock({
3539
+ tone,
3540
+ title,
3541
+ children
3542
+ }) {
3543
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
3544
+ "div",
3545
+ {
3546
+ className: cn(
3547
+ "mb-3 rounded-md border px-3 py-2 text-xs shadow-[inset_0_1px_0_rgba(255,255,255,0.04)]",
3548
+ NOTICE_TONE_CLASSES[tone]
3549
+ ),
3550
+ children: [
3551
+ title !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-1 font-semibold", children: title }),
3552
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "leading-relaxed text-muted-foreground", children })
3553
+ ]
3554
+ }
3555
+ );
3556
+ }
3557
+ function HeaderRows({
3558
+ headers,
3559
+ emptyLabel
3560
+ }) {
3561
+ const entries = headers === void 0 ? [] : Object.entries(headers).sort(([left], [right]) => left.localeCompare(right));
3562
+ if (entries.length === 0) return /* @__PURE__ */ jsxRuntimeExports.jsx(EmptyState, { children: emptyLabel });
3563
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "overflow-hidden rounded-md border border-white/10 bg-black/20 font-mono text-xs", children: entries.map(([key, value]) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
3564
+ "div",
3565
+ {
3566
+ className: "grid min-w-0 grid-cols-[minmax(140px,0.32fr)_minmax(0,1fr)] border-b border-white/5 last:border-b-0",
3567
+ children: [
3568
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "min-w-0 truncate border-r border-white/5 bg-white/[0.03] px-2.5 py-2 font-semibold text-cyan-200", children: key }),
3569
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "min-w-0 truncate px-2.5 py-2 text-muted-foreground", title: value, children: value })
3570
+ ]
3571
+ },
3572
+ key
3573
+ )) });
3574
+ }
3511
3575
  function DiffToggleButton({
3512
3576
  active,
3513
3577
  onClick
@@ -3518,7 +3582,10 @@ function DiffToggleButton({
3518
3582
  {
3519
3583
  variant: active ? "default" : "outline",
3520
3584
  size: "sm",
3521
- className: "h-8 text-xs",
3585
+ className: cn(
3586
+ "h-8 border-white/10 text-xs shadow-none",
3587
+ active ? "bg-cyan-300 text-black hover:bg-cyan-200" : "bg-[#0a0d11] text-muted-foreground hover:border-cyan-300/30 hover:bg-cyan-400/10 hover:text-cyan-100"
3588
+ ),
3522
3589
  onClick,
3523
3590
  "aria-pressed": active,
3524
3591
  children: [
@@ -3749,162 +3816,177 @@ const LogEntry = reactExports.memo(function({
3749
3816
  };
3750
3817
  }, [anatomySegments, log.id]);
3751
3818
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(TooltipProvider, { children: [
3752
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border border-border rounded-lg mb-1 overflow-hidden", children: [
3753
- /* @__PURE__ */ jsxRuntimeExports.jsx(
3754
- LogEntryHeader,
3755
- {
3756
- log: displayLog,
3757
- messageCount: requestAnalysis.messageCount,
3758
- toolCount: requestAnalysis.toolCount,
3759
- expanded,
3760
- onToggle: handleToggleExpanded,
3761
- cacheTrend,
3762
- slowResponseThresholdSeconds,
3763
- timeDisplayFormat,
3764
- activeTab,
3765
- tabActions,
3766
- onReplay: onCompareWithPrevious === void 0 ? void 0 : () => {
3767
- setReplayOpen(true);
3768
- }
3769
- }
3770
- ),
3771
- expanded && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { onClick: (e) => e.stopPropagation(), onKeyDown: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tabs, { value: activeTab, onValueChange: setActiveTab, children: [
3772
- /* @__PURE__ */ jsxRuntimeExports.jsxs(TabsList, { className: "mx-4 mt-2", children: [
3773
- viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "raw-headers", children: "Raw Headers" }),
3774
- viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "headers", children: "Headers" }),
3775
- anatomySegments !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "anatomy", children: "Context" }),
3776
- shouldShowRawRequestTab(resolvedFormat, viewMode, strip) && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "raw-request", children: "Raw Request" }),
3777
- /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "request", children: "Request" }),
3778
- viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "raw", children: "Raw Response" }),
3779
- /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "parsed", children: "Response" })
3780
- ] }),
3781
- shouldShowRawRequestTab(resolvedFormat, viewMode, strip) && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "raw-request", children: activeTab === "raw-request" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-4 pt-1 pb-3", children: displayLog.rawRequestBody === null ? /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground italic", children: "No request body" }) : rawRequestExpansion.parsedData !== null ? /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
3782
- LazyJsonViewer,
3783
- {
3784
- data: rawRequestExpansion.parsedData,
3785
- bulkDepth: rawRequestExpansion.bulkDepth,
3786
- bulkRevision: rawRequestExpansion.bulkRevision
3787
- }
3788
- ) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "font-mono text-xs whitespace-pre-wrap break-words", children: displayLog.rawRequestBody }) }) }),
3789
- /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "request", children: activeTab === "request" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 pt-1 pb-3", children: [
3790
- bodyHydrationState === "loading" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-3 rounded border border-border bg-muted/30 p-3 text-xs text-muted-foreground", children: "Loading full request and response bodies..." }),
3791
- bodyHydrationState === "failed" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-3 rounded border border-amber-500/30 bg-amber-500/10 p-3 text-xs text-amber-200", children: "Full request and response bodies could not be loaded. Compact metadata is still available." }),
3792
- warnings.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-3 rounded border border-amber-500/30 bg-amber-500/10 p-3 text-xs", children: [
3793
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 font-semibold text-amber-300", children: [
3794
- /* @__PURE__ */ jsxRuntimeExports.jsx(TriangleAlert, { className: "size-3.5" }),
3795
- "Tool schema warnings"
3796
- ] }),
3797
- /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { className: "mt-2 space-y-1 text-muted-foreground", children: warnings.map((warning) => /* @__PURE__ */ jsxRuntimeExports.jsx("li", { children: warning }, warning)) })
3798
- ] }),
3819
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
3820
+ "div",
3821
+ {
3822
+ className: cn(
3823
+ "mb-2 overflow-hidden rounded-md border bg-[#090a0d] transition-[background-color,border-color,box-shadow]",
3824
+ expanded ? "border-cyan-300/20 shadow-[0_18px_60px_rgba(0,0,0,0.28),inset_0_1px_0_rgba(255,255,255,0.05)]" : "border-border/70 hover:border-border"
3825
+ ),
3826
+ children: [
3799
3827
  /* @__PURE__ */ jsxRuntimeExports.jsx(
3800
- RequestTools,
3801
- {
3802
- summary: requestTools,
3803
- calledToolNames: responseAnalysis.toolNames ?? []
3804
- }
3805
- ),
3806
- requestDiff ? /* @__PURE__ */ jsxRuntimeExports.jsx(
3807
- RequestDiffContent,
3808
- {
3809
- rawBody: displayLog.rawRequestBody,
3810
- displayedBody: displayedRequestBody,
3811
- emptyLabel: "No transformation applied; raw and sent request bodies are identical."
3812
- }
3813
- ) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: requestJsonRef, children: displayedRequestBody === null ? /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground italic", children: "No request body" }) : requestExpansion.parsedData !== null ? /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
3814
- LazyJsonViewer,
3828
+ LogEntryHeader,
3815
3829
  {
3816
- data: requestExpansion.parsedData,
3817
- bulkDepth: requestExpansion.bulkDepth,
3818
- bulkRevision: requestExpansion.bulkRevision,
3819
- anatomyPaths,
3820
- expandToPath
3821
- }
3822
- ) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "font-mono text-xs whitespace-pre-wrap break-words", children: displayedRequestBody }) })
3823
- ] }) }),
3824
- anatomySegments !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "anatomy", children: activeTab === "anatomy" && /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
3825
- LazyRequestAnatomy,
3826
- {
3827
- parsed: requestExpansion.parsedData,
3828
- inputTokens: displayLog.inputTokens ?? null,
3829
- model: displayLog.model,
3830
- segments: anatomySegments,
3831
- onSegmentActivate: jumpToAnatomySegment
3832
- }
3833
- ) }) }),
3834
- viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "headers", children: activeTab === "headers" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 pt-1 pb-3", children: [
3835
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex justify-end gap-2 mb-2", children: shouldShowHeadersDiffButton(
3836
- viewMode,
3837
- displayLog.rawHeaders !== void 0 && Object.keys(displayLog.rawHeaders).length > 0
3838
- ) && /* @__PURE__ */ jsxRuntimeExports.jsx(
3839
- DiffToggleButton,
3840
- {
3841
- active: headersDiff,
3842
- onClick: (e) => {
3843
- e.stopPropagation();
3844
- setHeadersDiff(!headersDiff);
3830
+ log: displayLog,
3831
+ messageCount: requestAnalysis.messageCount,
3832
+ toolCount: requestAnalysis.toolCount,
3833
+ expanded,
3834
+ onToggle: handleToggleExpanded,
3835
+ cacheTrend,
3836
+ slowResponseThresholdSeconds,
3837
+ timeDisplayFormat,
3838
+ activeTab,
3839
+ tabActions,
3840
+ onReplay: onCompareWithPrevious === void 0 ? void 0 : () => {
3841
+ setReplayOpen(true);
3845
3842
  }
3846
3843
  }
3847
- ) }),
3848
- headersDiff ? /* @__PURE__ */ jsxRuntimeExports.jsx(
3849
- HeadersDiffContent,
3850
- {
3851
- rawHeaders: displayLog.rawHeaders,
3852
- headers: displayLog.headers,
3853
- emptyLabel: "No transformation applied; raw and processed headers are identical."
3854
- }
3855
- ) : displayLog.headers && Object.keys(displayLog.headers).length > 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1 font-mono text-xs", children: Object.entries(displayLog.headers).sort(([a], [b]) => a.localeCompare(b)).map(([key, value]) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
3856
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-blue-600 dark:text-blue-400 font-semibold shrink-0", children: [
3857
- key,
3858
- ":"
3859
- ] }),
3860
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground truncate", title: value, children: value })
3861
- ] }, key)) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground italic", children: "No headers captured" })
3862
- ] }) }),
3863
- viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "raw-headers", children: activeTab === "raw-headers" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-4 pt-1 pb-3", children: displayLog.rawHeaders && Object.keys(displayLog.rawHeaders).length > 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1 font-mono text-xs", children: Object.entries(displayLog.rawHeaders).sort(([a], [b]) => a.localeCompare(b)).map(([key, value]) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
3864
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-blue-600 dark:text-blue-400 font-semibold shrink-0", children: [
3865
- key,
3866
- ":"
3867
- ] }),
3868
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground truncate", title: value, children: value })
3869
- ] }, key)) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground italic", children: "No raw headers captured" }) }) }),
3870
- /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "raw", children: activeTab === "raw" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 pt-1 pb-3 space-y-3", children: [
3871
- displayLog.error !== void 0 && displayLog.error !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded border border-destructive/50 bg-destructive/10 p-3 text-xs", children: [
3872
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-semibold text-destructive mb-1", children: "SSE Error" }),
3873
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-muted-foreground font-mono", children: displayLog.error })
3874
- ] }),
3875
- displayLog.responseText !== null ? /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
3876
- LazyJsonViewerFromString,
3877
- {
3878
- text: displayLog.responseText,
3879
- defaultExpandDepth: 0,
3880
- bulkDepth: responseExpansion.bulkDepth,
3881
- bulkRevision: responseExpansion.bulkRevision
3882
- }
3883
- ) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground italic", children: "No response" }),
3884
- displayLog.streaming === true && /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
3885
- LazyStreamingChunkSequence,
3844
+ ),
3845
+ expanded && /* @__PURE__ */ jsxRuntimeExports.jsx(
3846
+ "div",
3886
3847
  {
3887
- logId: displayLog.id,
3888
- truncated: displayLog.streamingChunksPath !== null
3848
+ className: "border-t border-white/10 bg-[#050607]/80 pt-2",
3849
+ onClick: (e) => e.stopPropagation(),
3850
+ onKeyDown: (e) => e.stopPropagation(),
3851
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tabs, { value: activeTab, onValueChange: setActiveTab, className: "gap-2", children: [
3852
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
3853
+ TabsList,
3854
+ {
3855
+ variant: "line",
3856
+ className: "inspector-scrollbar mx-3 h-auto w-[calc(100%-1.5rem)] justify-start overflow-x-auto rounded-none border-b border-white/10 bg-transparent p-0",
3857
+ children: [
3858
+ viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { className: TAB_TRIGGER_CLASS, value: "raw-headers", children: "Raw Headers" }),
3859
+ viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { className: TAB_TRIGGER_CLASS, value: "headers", children: "Headers" }),
3860
+ anatomySegments !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { className: TAB_TRIGGER_CLASS, value: "anatomy", children: "Context" }),
3861
+ shouldShowRawRequestTab(resolvedFormat, viewMode, strip) && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { className: TAB_TRIGGER_CLASS, value: "raw-request", children: "Raw Request" }),
3862
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { className: TAB_TRIGGER_CLASS, value: "request", children: "Request" }),
3863
+ viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { className: TAB_TRIGGER_CLASS, value: "raw", children: "Raw Response" }),
3864
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { className: TAB_TRIGGER_CLASS, value: "parsed", children: "Response" })
3865
+ ]
3866
+ }
3867
+ ),
3868
+ shouldShowRawRequestTab(resolvedFormat, viewMode, strip) && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "raw-request", children: activeTab === "raw-request" && /* @__PURE__ */ jsxRuntimeExports.jsx(ExpandedPanel, { children: displayLog.rawRequestBody === null ? /* @__PURE__ */ jsxRuntimeExports.jsx(EmptyState, { children: "No request body" }) : rawRequestExpansion.parsedData !== null ? /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
3869
+ LazyJsonViewer,
3870
+ {
3871
+ data: rawRequestExpansion.parsedData,
3872
+ bulkDepth: rawRequestExpansion.bulkDepth,
3873
+ bulkRevision: rawRequestExpansion.bulkRevision
3874
+ }
3875
+ ) }) : /* @__PURE__ */ jsxRuntimeExports.jsx(RawTextBlock, { children: displayLog.rawRequestBody }) }) }),
3876
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "request", children: activeTab === "request" && /* @__PURE__ */ jsxRuntimeExports.jsxs(ExpandedPanel, { children: [
3877
+ bodyHydrationState === "loading" && /* @__PURE__ */ jsxRuntimeExports.jsx(NoticeBlock, { tone: "loading", children: "Loading full request and response bodies..." }),
3878
+ bodyHydrationState === "failed" && /* @__PURE__ */ jsxRuntimeExports.jsx(NoticeBlock, { tone: "warning", children: "Full request and response bodies could not be loaded. Compact metadata is still available." }),
3879
+ warnings.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(NoticeBlock, { tone: "warning", children: [
3880
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 font-semibold text-amber-300", children: [
3881
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TriangleAlert, { className: "size-3.5" }),
3882
+ "Tool schema warnings"
3883
+ ] }),
3884
+ /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { className: "mt-2 space-y-1 text-muted-foreground", children: warnings.map((warning) => /* @__PURE__ */ jsxRuntimeExports.jsx("li", { children: warning }, warning)) })
3885
+ ] }),
3886
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
3887
+ RequestTools,
3888
+ {
3889
+ summary: requestTools,
3890
+ calledToolNames: responseAnalysis.toolNames ?? []
3891
+ }
3892
+ ),
3893
+ requestDiff ? /* @__PURE__ */ jsxRuntimeExports.jsx(
3894
+ RequestDiffContent,
3895
+ {
3896
+ rawBody: displayLog.rawRequestBody,
3897
+ displayedBody: displayedRequestBody,
3898
+ emptyLabel: "No transformation applied; raw and sent request bodies are identical."
3899
+ }
3900
+ ) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: requestJsonRef, children: displayedRequestBody === null ? /* @__PURE__ */ jsxRuntimeExports.jsx(EmptyState, { children: "No request body" }) : requestExpansion.parsedData !== null ? /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
3901
+ LazyJsonViewer,
3902
+ {
3903
+ data: requestExpansion.parsedData,
3904
+ bulkDepth: requestExpansion.bulkDepth,
3905
+ bulkRevision: requestExpansion.bulkRevision,
3906
+ anatomyPaths,
3907
+ expandToPath
3908
+ }
3909
+ ) }) : /* @__PURE__ */ jsxRuntimeExports.jsx(RawTextBlock, { children: displayedRequestBody }) })
3910
+ ] }) }),
3911
+ anatomySegments !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "anatomy", children: activeTab === "anatomy" && /* @__PURE__ */ jsxRuntimeExports.jsx(ExpandedPanel, { className: "p-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
3912
+ LazyRequestAnatomy,
3913
+ {
3914
+ parsed: requestExpansion.parsedData,
3915
+ inputTokens: displayLog.inputTokens ?? null,
3916
+ model: displayLog.model,
3917
+ segments: anatomySegments,
3918
+ onSegmentActivate: jumpToAnatomySegment
3919
+ }
3920
+ ) }) }) }),
3921
+ viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "headers", children: activeTab === "headers" && /* @__PURE__ */ jsxRuntimeExports.jsxs(ExpandedPanel, { children: [
3922
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex justify-end gap-2 mb-2", children: shouldShowHeadersDiffButton(
3923
+ viewMode,
3924
+ displayLog.rawHeaders !== void 0 && Object.keys(displayLog.rawHeaders).length > 0
3925
+ ) && /* @__PURE__ */ jsxRuntimeExports.jsx(
3926
+ DiffToggleButton,
3927
+ {
3928
+ active: headersDiff,
3929
+ onClick: (e) => {
3930
+ e.stopPropagation();
3931
+ setHeadersDiff(!headersDiff);
3932
+ }
3933
+ }
3934
+ ) }),
3935
+ headersDiff ? /* @__PURE__ */ jsxRuntimeExports.jsx(
3936
+ HeadersDiffContent,
3937
+ {
3938
+ rawHeaders: displayLog.rawHeaders,
3939
+ headers: displayLog.headers,
3940
+ emptyLabel: "No transformation applied; raw and processed headers are identical."
3941
+ }
3942
+ ) : /* @__PURE__ */ jsxRuntimeExports.jsx(HeaderRows, { headers: displayLog.headers, emptyLabel: "No headers captured" })
3943
+ ] }) }),
3944
+ viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "raw-headers", children: activeTab === "raw-headers" && /* @__PURE__ */ jsxRuntimeExports.jsx(ExpandedPanel, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(
3945
+ HeaderRows,
3946
+ {
3947
+ headers: displayLog.rawHeaders,
3948
+ emptyLabel: "No raw headers captured"
3949
+ }
3950
+ ) }) }),
3951
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "raw", children: activeTab === "raw" && /* @__PURE__ */ jsxRuntimeExports.jsxs(ExpandedPanel, { className: "space-y-3", children: [
3952
+ displayLog.error !== void 0 && displayLog.error !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(NoticeBlock, { tone: "danger", title: "SSE Error", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono", children: displayLog.error }) }),
3953
+ displayLog.responseText !== null ? /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
3954
+ LazyJsonViewerFromString,
3955
+ {
3956
+ text: displayLog.responseText,
3957
+ defaultExpandDepth: 0,
3958
+ bulkDepth: responseExpansion.bulkDepth,
3959
+ bulkRevision: responseExpansion.bulkRevision
3960
+ }
3961
+ ) }) : /* @__PURE__ */ jsxRuntimeExports.jsx(EmptyState, { children: "No response" }),
3962
+ displayLog.streaming === true && /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
3963
+ LazyStreamingChunkSequence,
3964
+ {
3965
+ logId: displayLog.id,
3966
+ truncated: displayLog.streamingChunksPath !== null
3967
+ }
3968
+ ) })
3969
+ ] }) }),
3970
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "parsed", children: activeTab === "parsed" && /* @__PURE__ */ jsxRuntimeExports.jsx(ExpandedPanel, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
3971
+ LazyResponseView,
3972
+ {
3973
+ responseText: displayLog.responseText,
3974
+ responseStatus: displayLog.responseStatus,
3975
+ streaming: displayLog.streaming,
3976
+ inputTokens: displayLog.inputTokens,
3977
+ outputTokens: displayLog.outputTokens,
3978
+ cacheCreationInputTokens: displayLog.cacheCreationInputTokens,
3979
+ cacheReadInputTokens: displayLog.cacheReadInputTokens,
3980
+ apiFormat: resolvedFormat,
3981
+ error: displayLog.error
3982
+ }
3983
+ ) }) }) })
3984
+ ] })
3889
3985
  }
3890
- ) })
3891
- ] }) }),
3892
- /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "parsed", children: activeTab === "parsed" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-4 pt-1 pb-3", children: /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
3893
- LazyResponseView,
3894
- {
3895
- responseText: displayLog.responseText,
3896
- responseStatus: displayLog.responseStatus,
3897
- streaming: displayLog.streaming,
3898
- inputTokens: displayLog.inputTokens,
3899
- outputTokens: displayLog.outputTokens,
3900
- cacheCreationInputTokens: displayLog.cacheCreationInputTokens,
3901
- cacheReadInputTokens: displayLog.cacheReadInputTokens,
3902
- apiFormat: resolvedFormat,
3903
- error: displayLog.error
3904
- }
3905
- ) }) }) })
3906
- ] }) })
3907
- ] }),
3986
+ )
3987
+ ]
3988
+ }
3989
+ ),
3908
3990
  /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntimeExports.jsx(LazyReplayDialog, { log: displayLog, open: replayOpen, onOpenChange: setReplayOpen }) })
3909
3991
  ] });
3910
3992
  });
@@ -5345,74 +5427,7 @@ function CrabLogo({ className }) {
5345
5427
  /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "6.5", y1: "16", x2: "4.5", y2: "19.5" }),
5346
5428
  /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "9", y1: "17.5", x2: "8", y2: "20.5" }),
5347
5429
  /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "15", y1: "17.5", x2: "16", y2: "20.5" }),
5348
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "17.5", y1: "16", x2: "19.5", y2: "19.5" }),
5349
- /* @__PURE__ */ jsxRuntimeExports.jsxs("g", { children: [
5350
- /* @__PURE__ */ jsxRuntimeExports.jsx(
5351
- "path",
5352
- {
5353
- d: "M5.6 17.7 L8.4 15.4 L10.8 18 C9.1 18.9 7.2 18.8 5.6 17.7 Z",
5354
- fill: "#2f6b3f",
5355
- stroke: "none",
5356
- opacity: "0.95"
5357
- }
5358
- ),
5359
- /* @__PURE__ */ jsxRuntimeExports.jsx(
5360
- "path",
5361
- {
5362
- d: "M6.9 17.5 L8.4 16 L9.8 17.7 C8.9 18.1 7.8 18.1 6.9 17.5 Z",
5363
- fill: "#6fb36f",
5364
- stroke: "none",
5365
- opacity: "0.95"
5366
- }
5367
- ),
5368
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M8.4 16 L8.4 18.4", stroke: "#d6b45f", strokeWidth: "0.34" }),
5369
- /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "10.6", cy: "17.75", r: "0.36", fill: "#c2412d", stroke: "none" })
5370
- ] }),
5371
- /* @__PURE__ */ jsxRuntimeExports.jsxs("g", { children: [
5372
- /* @__PURE__ */ jsxRuntimeExports.jsx(
5373
- "path",
5374
- {
5375
- d: "M8 16.5 L11.9 13.6 L15.8 16.8 C13.3 18.4 10.4 18.3 8 16.5 Z",
5376
- fill: "#2f6b3f",
5377
- stroke: "none",
5378
- opacity: "0.97"
5379
- }
5380
- ),
5381
- /* @__PURE__ */ jsxRuntimeExports.jsx(
5382
- "path",
5383
- {
5384
- d: "M9.8 16.3 L11.9 14.4 L14.3 16.5 C12.8 17.4 11.3 17.4 9.8 16.3 Z",
5385
- fill: "#6fb36f",
5386
- stroke: "none",
5387
- opacity: "0.95"
5388
- }
5389
- ),
5390
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M11.9 14.3 L11.9 17.8", stroke: "#d6b45f", strokeWidth: "0.42" }),
5391
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M9.8 16.3 C11.2 15.8 12.9 15.9 14.3 16.5", stroke: "#9fca78", strokeWidth: "0.36" }),
5392
- /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "15.6", cy: "16.75", r: "0.43", fill: "#c2412d", stroke: "none" })
5393
- ] }),
5394
- /* @__PURE__ */ jsxRuntimeExports.jsxs("g", { children: [
5395
- /* @__PURE__ */ jsxRuntimeExports.jsx(
5396
- "path",
5397
- {
5398
- d: "M13.6 18.1 L16.2 15.7 L18.5 18.2 C17.1 19.1 15.2 19 13.6 18.1 Z",
5399
- fill: "#2f6b3f",
5400
- stroke: "none",
5401
- opacity: "0.95"
5402
- }
5403
- ),
5404
- /* @__PURE__ */ jsxRuntimeExports.jsx(
5405
- "path",
5406
- {
5407
- d: "M14.8 17.9 L16.2 16.3 L17.5 18 C16.6 18.4 15.7 18.4 14.8 17.9 Z",
5408
- fill: "#6fb36f",
5409
- stroke: "none",
5410
- opacity: "0.95"
5411
- }
5412
- ),
5413
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M16.2 16.3 L16.2 18.6", stroke: "#d6b45f", strokeWidth: "0.34" }),
5414
- /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "18.35", cy: "18.15", r: "0.36", fill: "#c2412d", stroke: "none" })
5415
- ] })
5430
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "17.5", y1: "16", x2: "19.5", y2: "19.5" })
5416
5431
  ]
5417
5432
  }
5418
5433
  );
@@ -8882,7 +8897,6 @@ args = ["stdio", "--url", "${endpoint}"]`
8882
8897
  function ProxySettingsTab() {
8883
8898
  const {
8884
8899
  strip,
8885
- captureMode,
8886
8900
  slowResponseThresholdSeconds,
8887
8901
  providerTestTimeoutSeconds,
8888
8902
  timeDisplayFormat,
@@ -8894,7 +8908,6 @@ function ProxySettingsTab() {
8894
8908
  } = useStripConfig();
8895
8909
  const [error, setError] = reactExports.useState(null);
8896
8910
  const [pending, setPending] = reactExports.useState(false);
8897
- const alternateCaptureMode = captureMode === "full" ? "simple" : "full";
8898
8911
  const handleToggle = reactExports.useCallback(
8899
8912
  async (next) => {
8900
8913
  setError(null);
@@ -8952,21 +8965,6 @@ function ProxySettingsTab() {
8952
8965
  [setTimeDisplayFormat]
8953
8966
  );
8954
8967
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
8955
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1", children: [
8956
- /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-sm font-semibold", children: "Capture mode" }),
8957
- /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-xs text-muted-foreground", children: [
8958
- "This process is running in ",
8959
- /* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: captureMode }),
8960
- " mode. Restart with",
8961
- " ",
8962
- /* @__PURE__ */ jsxRuntimeExports.jsxs("code", { children: [
8963
- "agent-inspector --mode ",
8964
- alternateCaptureMode
8965
- ] }),
8966
- " to change it.",
8967
- captureMode === "simple" ? " Simple mode keeps replay, parsed requests, responses, timing, tools, and token usage while skipping raw headers, raw response retention, and detailed SSE chunk retention." : " Full mode retains raw headers, raw responses, and SSE chunks for diagnostics; use simple mode for everyday lower-overhead capture."
8968
- ] })
8969
- ] }),
8970
8968
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1", children: [
8971
8969
  /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-sm font-semibold", children: "Claude Code billing header" }),
8972
8970
  /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-xs text-muted-foreground", children: [
@@ -10260,6 +10258,114 @@ function getFirstUserAgent(logs) {
10260
10258
  }
10261
10259
  return null;
10262
10260
  }
10261
+ function hasLogFailure(log) {
10262
+ if (log.error !== null && log.error !== void 0 && log.error.length > 0) return true;
10263
+ return log.responseStatus !== null && log.responseStatus >= 400;
10264
+ }
10265
+ function getModelLabel(logs) {
10266
+ const models = /* @__PURE__ */ new Set();
10267
+ for (const log of logs) {
10268
+ if (log.model !== null && log.model.length > 0) {
10269
+ models.add(log.model);
10270
+ }
10271
+ }
10272
+ const sorted = [...models].sort();
10273
+ if (sorted.length === 0) return "Model unknown";
10274
+ if (sorted.length === 1) return sorted[0] ?? "Model unknown";
10275
+ return `${sorted.length} models`;
10276
+ }
10277
+ function buildSessionSlateStats({
10278
+ logs,
10279
+ isLoading,
10280
+ timeDisplayFormat,
10281
+ slowResponseThresholdSeconds
10282
+ }) {
10283
+ let failures = 0;
10284
+ let slow = 0;
10285
+ let totalIn = 0;
10286
+ let totalOut = 0;
10287
+ const slowThresholdMs = slowResponseThresholdSeconds * 1e3;
10288
+ for (const log of logs) {
10289
+ if (hasLogFailure(log)) failures += 1;
10290
+ if (slowResponseThresholdSeconds > 0 && log.elapsedMs !== null && log.elapsedMs >= slowThresholdMs) {
10291
+ slow += 1;
10292
+ }
10293
+ if (log.inputTokens !== null) totalIn += log.inputTokens;
10294
+ if (log.outputTokens !== null) totalOut += log.outputTokens;
10295
+ }
10296
+ const status = isLoading ? "rolling" : failures > 0 ? "failed" : slow > 0 ? "watch" : "clear";
10297
+ const statusLabel2 = status === "rolling" ? "Rolling" : status === "failed" ? "Failure" : status === "watch" ? "Watch" : "Clear";
10298
+ return {
10299
+ status,
10300
+ statusLabel: statusLabel2,
10301
+ modelLabel: getModelLabel(logs),
10302
+ requests: logs.length,
10303
+ failures,
10304
+ slow,
10305
+ timeRange: formatTimeRange(logs, timeDisplayFormat),
10306
+ tokenLabel: `${formatTokens(totalIn)} in / ${formatTokens(totalOut)} out`
10307
+ };
10308
+ }
10309
+ function slateStatusClass(status) {
10310
+ switch (status) {
10311
+ case "rolling":
10312
+ return "border-cyan-400/35 bg-cyan-500/10 text-cyan-200";
10313
+ case "failed":
10314
+ return "border-red-400/35 bg-red-500/10 text-red-100";
10315
+ case "watch":
10316
+ return "border-amber-300/35 bg-amber-400/10 text-amber-100";
10317
+ case "clear":
10318
+ return "border-emerald-400/30 bg-emerald-500/10 text-emerald-100";
10319
+ }
10320
+ }
10321
+ function SessionOpeningSlate({ stats }) {
10322
+ if (stats.requests === 0) return null;
10323
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-4 rounded-md border border-border bg-[#0c0d0f] shadow-[0_14px_50px_rgba(0,0,0,0.25)]", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-0 md:grid-cols-[minmax(220px,1.2fr)_repeat(4,minmax(120px,1fr))]", children: [
10324
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "col-span-2 border-b border-border/70 px-4 py-3 md:col-span-1 md:border-b-0 md:border-r", children: [
10325
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-[10px] font-semibold uppercase text-muted-foreground", children: [
10326
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Clapperboard, { className: "size-3.5 text-cyan-300" }),
10327
+ "Opening Slate"
10328
+ ] }),
10329
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 min-w-0 truncate font-mono text-sm font-semibold text-foreground", children: stats.modelLabel }),
10330
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1 truncate font-mono text-[11px] text-muted-foreground", children: stats.timeRange ?? "Timeline pending" })
10331
+ ] }),
10332
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-r border-b border-border/70 px-4 py-3 md:border-b-0", children: [
10333
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[10px] uppercase text-muted-foreground", children: "Status" }),
10334
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
10335
+ "div",
10336
+ {
10337
+ className: cn(
10338
+ "mt-2 inline-flex h-7 items-center rounded-md border px-2.5 font-mono text-xs font-semibold",
10339
+ slateStatusClass(stats.status)
10340
+ ),
10341
+ children: stats.statusLabel
10342
+ }
10343
+ )
10344
+ ] }),
10345
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-b border-border/70 px-4 py-3 md:border-b-0 md:border-r", children: [
10346
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[10px] uppercase text-muted-foreground", children: "Requests" }),
10347
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 font-mono text-xl font-semibold text-foreground", children: stats.requests })
10348
+ ] }),
10349
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-r border-border/70 px-4 py-3 md:border-r", children: [
10350
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 text-[10px] uppercase text-muted-foreground", children: [
10351
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Siren, { className: "size-3 text-red-300" }),
10352
+ "Failure"
10353
+ ] }),
10354
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 font-mono text-xl font-semibold text-red-100", children: stats.failures })
10355
+ ] }),
10356
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-3", children: [
10357
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 text-[10px] uppercase text-muted-foreground", children: [
10358
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Gauge, { className: "size-3 text-amber-200" }),
10359
+ "Tempo"
10360
+ ] }),
10361
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-2 font-mono text-sm font-semibold text-foreground", children: [
10362
+ stats.slow,
10363
+ " slow"
10364
+ ] }),
10365
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1 truncate font-mono text-[11px] text-muted-foreground", children: stats.tokenLabel })
10366
+ ] })
10367
+ ] }) });
10368
+ }
10263
10369
  function resolveSessionContextScope({
10264
10370
  pinnedSessionId,
10265
10371
  selectedSession,
@@ -10351,6 +10457,25 @@ function formatMetadataValue(value) {
10351
10457
  if (value === null) return null;
10352
10458
  return JSON.stringify(value);
10353
10459
  }
10460
+ function formatMemberMetadata(member, key) {
10461
+ if (member === null) return null;
10462
+ const value = member.metadata[key];
10463
+ if (value === void 0) return null;
10464
+ return formatMetadataValue(value);
10465
+ }
10466
+ function evidenceChipClass(value) {
10467
+ const normalized = value.toLowerCase();
10468
+ if (normalized.includes("reject") || normalized.includes("fail") || normalized.includes("error")) {
10469
+ return "border-red-400/35 bg-red-500/10 text-red-100";
10470
+ }
10471
+ if (normalized.includes("partial") || normalized.includes("pending") || normalized.includes("slow")) {
10472
+ return "border-amber-300/35 bg-amber-400/10 text-amber-100";
10473
+ }
10474
+ if (normalized.includes("pass") || normalized.includes("complete") || normalized.includes("accept")) {
10475
+ return "border-emerald-400/30 bg-emerald-500/10 text-emerald-100";
10476
+ }
10477
+ return "border-border/70 bg-background/70 text-muted-foreground";
10478
+ }
10354
10479
  function getMemberMetadataRows(member) {
10355
10480
  const rows = [];
10356
10481
  for (const key of MEMBER_METADATA_KEYS) {
@@ -10362,19 +10487,60 @@ function getMemberMetadataRows(member) {
10362
10487
  return rows;
10363
10488
  }
10364
10489
  function SessionMembershipPanel({
10365
- memberships
10490
+ memberships,
10491
+ defaultOpen = false
10366
10492
  }) {
10493
+ const [open, setOpen] = reactExports.useState(defaultOpen);
10367
10494
  if (memberships.length === 0) return null;
10368
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-4 rounded-md border border-border bg-muted/10 px-3 py-2 text-xs", children: [
10369
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-2 flex items-center justify-between gap-2", children: [
10370
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-semibold text-foreground", children: "Group Member Evidence" }),
10371
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "font-mono text-[10px] text-muted-foreground", children: [
10372
- memberships.length,
10373
- " group",
10374
- memberships.length === 1 ? "" : "s"
10375
- ] })
10376
- ] }),
10377
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-2", children: memberships.map((membership) => {
10495
+ const primary = memberships[0];
10496
+ const primaryMember = primary?.member ?? null;
10497
+ const score = formatMemberMetadata(primaryMember, "score");
10498
+ const decision = formatMemberMetadata(primaryMember, "decision");
10499
+ const finalStatus = formatMemberMetadata(primaryMember, "final_status");
10500
+ const summaryChips = [
10501
+ score === null ? null : { label: `score ${score}`, value: score },
10502
+ decision === null ? null : { label: decision, value: decision },
10503
+ finalStatus === null ? null : { label: finalStatus, value: finalStatus },
10504
+ primaryMember?.model === null || primaryMember?.model === void 0 ? null : { label: primaryMember.model, value: primaryMember.model }
10505
+ ].filter(
10506
+ (value) => value !== null && value.label.length > 0 && value.value.length > 0
10507
+ );
10508
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-3 overflow-hidden rounded-md border border-border bg-[#0c0d0f] text-xs", children: [
10509
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
10510
+ "button",
10511
+ {
10512
+ type: "button",
10513
+ onClick: () => setOpen((value) => !value),
10514
+ className: "flex w-full items-center gap-3 px-3 py-2 text-left transition-colors hover:bg-muted/30",
10515
+ "aria-expanded": open,
10516
+ children: [
10517
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 flex-1", children: [
10518
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: [
10519
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-semibold text-foreground", children: "Case File" }),
10520
+ primary !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate text-muted-foreground", title: primary.groupTitle, children: primary.groupTitle }),
10521
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono text-[10px] uppercase text-muted-foreground", children: [
10522
+ memberships.length,
10523
+ " group",
10524
+ memberships.length === 1 ? "" : "s"
10525
+ ] })
10526
+ ] }),
10527
+ summaryChips.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1 flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: summaryChips.slice(0, 4).map((chip) => /* @__PURE__ */ jsxRuntimeExports.jsx(
10528
+ "span",
10529
+ {
10530
+ className: cn(
10531
+ "rounded border px-1.5 py-0.5 font-mono text-[10px]",
10532
+ evidenceChipClass(chip.value)
10533
+ ),
10534
+ children: chip.label
10535
+ },
10536
+ chip.label
10537
+ )) })
10538
+ ] }),
10539
+ open ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronUp, { className: "size-4 shrink-0 text-muted-foreground" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-4 shrink-0 text-muted-foreground" })
10540
+ ]
10541
+ }
10542
+ ),
10543
+ open && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-2 border-t border-border/70 px-3 py-2", children: memberships.map((membership) => {
10378
10544
  const member = membership.member;
10379
10545
  const metadataRows = getMemberMetadataRows(member);
10380
10546
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0", children: [
@@ -10425,6 +10591,105 @@ function SessionMembershipPanel({
10425
10591
  }) })
10426
10592
  ] });
10427
10593
  }
10594
+ function formatPaginationStatus({
10595
+ logs,
10596
+ pagination
10597
+ }) {
10598
+ if (pagination.isLoading && logs.length === 0) return "Loading logs...";
10599
+ if (logs.length === 0) return "No logs on this page";
10600
+ const first = logs[0];
10601
+ const last = logs[logs.length - 1];
10602
+ const range = first === void 0 || last === void 0 ? "Current page" : `#${first.id}-#${last.id}`;
10603
+ const total = pagination.total === null ? "logs" : `${pagination.total} logs`;
10604
+ return `Showing ${range} of ${total}`;
10605
+ }
10606
+ function LogPaginationButton({
10607
+ label,
10608
+ title,
10609
+ icon,
10610
+ disabled,
10611
+ onClick
10612
+ }) {
10613
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
10614
+ "button",
10615
+ {
10616
+ type: "button",
10617
+ onClick,
10618
+ disabled,
10619
+ className: "inline-flex h-8 items-center gap-1.5 rounded-md px-2.5 text-xs text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:cursor-not-allowed disabled:opacity-45",
10620
+ title,
10621
+ children: [
10622
+ icon,
10623
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: label })
10624
+ ]
10625
+ }
10626
+ );
10627
+ }
10628
+ function LogPaginationBar({
10629
+ logs,
10630
+ pagination,
10631
+ embedded = false
10632
+ }) {
10633
+ if (pagination === void 0) return null;
10634
+ const disabled = pagination.isLoading;
10635
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
10636
+ "div",
10637
+ {
10638
+ className: cn(
10639
+ "flex min-h-9 flex-col gap-2 px-1 py-1 sm:flex-row sm:items-center",
10640
+ embedded ? "border-t border-border/70 pt-2" : "mb-3 rounded-md border border-border bg-muted/10 px-2"
10641
+ ),
10642
+ children: [
10643
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full min-w-0 px-1 font-mono text-[11px] text-muted-foreground sm:flex-1", children: [
10644
+ formatPaginationStatus({ logs, pagination }),
10645
+ pagination.isLoading && logs.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ml-2", children: "Loading..." })
10646
+ ] }),
10647
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex w-full items-center gap-1 overflow-x-auto sm:w-auto", children: [
10648
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
10649
+ LogPaginationButton,
10650
+ {
10651
+ label: "Oldest",
10652
+ title: "Load the oldest logs in this session",
10653
+ icon: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronsLeft, { className: "size-3.5" }),
10654
+ disabled: disabled || !pagination.hasOlder,
10655
+ onClick: pagination.onOldest
10656
+ }
10657
+ ),
10658
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
10659
+ LogPaginationButton,
10660
+ {
10661
+ label: "Older",
10662
+ title: "Load older logs",
10663
+ icon: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronLeft, { className: "size-3.5" }),
10664
+ disabled: disabled || !pagination.hasOlder,
10665
+ onClick: pagination.onOlder
10666
+ }
10667
+ ),
10668
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
10669
+ LogPaginationButton,
10670
+ {
10671
+ label: "Newer",
10672
+ title: "Load newer logs",
10673
+ icon: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-3.5" }),
10674
+ disabled: disabled || !pagination.hasNewer,
10675
+ onClick: pagination.onNewer
10676
+ }
10677
+ ),
10678
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
10679
+ LogPaginationButton,
10680
+ {
10681
+ label: "Newest",
10682
+ title: "Load the newest logs in this session",
10683
+ icon: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronsRight, { className: "size-3.5" }),
10684
+ disabled: disabled || !pagination.hasNewer,
10685
+ onClick: pagination.onNewest
10686
+ }
10687
+ )
10688
+ ] })
10689
+ ]
10690
+ }
10691
+ );
10692
+ }
10428
10693
  function formatRequestCount(count) {
10429
10694
  return `${count} ${count === 1 ? "request" : "requests"}`;
10430
10695
  }
@@ -10510,36 +10775,7 @@ function CopyableCommand({ command }) {
10510
10775
  onClick: handleCopy,
10511
10776
  className: "text-muted-foreground hover:text-foreground transition-colors shrink-0 cursor-pointer",
10512
10777
  "aria-label": "Copy command",
10513
- children: copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(
10514
- "svg",
10515
- {
10516
- width: "16",
10517
- height: "16",
10518
- viewBox: "0 0 24 24",
10519
- fill: "none",
10520
- stroke: "currentColor",
10521
- strokeWidth: "2",
10522
- strokeLinecap: "round",
10523
- strokeLinejoin: "round",
10524
- children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M20 6 9 17l-5-5" })
10525
- }
10526
- ) : /* @__PURE__ */ jsxRuntimeExports.jsxs(
10527
- "svg",
10528
- {
10529
- width: "16",
10530
- height: "16",
10531
- viewBox: "0 0 24 24",
10532
- fill: "none",
10533
- stroke: "currentColor",
10534
- strokeWidth: "2",
10535
- strokeLinecap: "round",
10536
- strokeLinejoin: "round",
10537
- children: [
10538
- /* @__PURE__ */ jsxRuntimeExports.jsx("rect", { width: "14", height: "14", x: "8", y: "8", rx: "2", ry: "2" }),
10539
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" })
10540
- ]
10541
- }
10542
- )
10778
+ children: copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-4" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-4" })
10543
10779
  }
10544
10780
  )
10545
10781
  ] });
@@ -10554,6 +10790,98 @@ function McpReadyBadge() {
10554
10790
  /* @__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." })
10555
10791
  ] }) });
10556
10792
  }
10793
+ const CRAB_VARIANT_COLORS = [
10794
+ "text-amber-500",
10795
+ "text-rose-500",
10796
+ "text-sky-500",
10797
+ "text-emerald-500",
10798
+ "text-violet-500",
10799
+ "text-orange-500",
10800
+ "text-cyan-500",
10801
+ "text-pink-500",
10802
+ "text-lime-500",
10803
+ "text-blue-500",
10804
+ "text-yellow-500",
10805
+ "text-fuchsia-500"
10806
+ ];
10807
+ function CrabFamily({
10808
+ compact,
10809
+ entrancePhase
10810
+ }) {
10811
+ if (compact) {
10812
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(CrabLogo, { className: "size-7 text-amber-500" });
10813
+ }
10814
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex shrink-0 items-end gap-1 group cursor-default", "aria-hidden": "true", children: [
10815
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CrabLogo, { className: "size-10 text-amber-500 transition-all duration-300 group-hover:scale-125 group-hover:-translate-y-1.5" }),
10816
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "hidden items-end gap-0.5 sm:flex", children: crabVariants.map((Crab, i) => {
10817
+ const color = CRAB_VARIANT_COLORS[i] ?? "text-amber-500";
10818
+ const entranceClass = entrancePhase === "hidden" ? "opacity-0 scale-0" : entrancePhase === "playing" ? "animate-crab-piano-pop" : "";
10819
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
10820
+ Crab,
10821
+ {
10822
+ className: `size-5 ${color} transition-all duration-300 ease-out group-hover:scale-125 group-hover:-translate-y-1 ${entranceClass}`,
10823
+ style: {
10824
+ transitionDelay: `${i * 50}ms`,
10825
+ ...entrancePhase === "playing" ? { animationDelay: `${i * 400}ms` } : {}
10826
+ }
10827
+ },
10828
+ i
10829
+ );
10830
+ }) })
10831
+ ] });
10832
+ }
10833
+ function BrandHeader({
10834
+ compact,
10835
+ crabEntrancePhase
10836
+ }) {
10837
+ if (compact) {
10838
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "pb-3", children: [
10839
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
10840
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-start gap-2", children: [
10841
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CrabFamily, { compact: true, entrancePhase: crabEntrancePhase }),
10842
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0", children: [
10843
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-baseline gap-2", children: [
10844
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate text-base font-bold", children: "Inspector" }),
10845
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "hidden shrink-0 font-mono text-[11px] font-semibold text-muted-foreground sm:inline", children: [
10846
+ "v",
10847
+ packageJson.version
10848
+ ] })
10849
+ ] }),
10850
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "hidden text-[11px] font-semibold text-muted-foreground sm:block", children: "Local First. Evidence First." })
10851
+ ] })
10852
+ ] }),
10853
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [
10854
+ /* @__PURE__ */ jsxRuntimeExports.jsx(GroupsDialog, {}),
10855
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SettingsDialog, {})
10856
+ ] })
10857
+ ] }),
10858
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 hidden sm:block", children: /* @__PURE__ */ jsxRuntimeExports.jsx(McpReadyBadge, {}) })
10859
+ ] });
10860
+ }
10861
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-[1fr_auto_1fr] items-start gap-3 pb-6", children: [
10862
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", {}),
10863
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("h1", { className: "flex min-w-0 flex-col items-center gap-2 text-center", children: [
10864
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex max-w-[calc(100vw-7rem)] items-end gap-2 whitespace-nowrap", children: [
10865
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CrabFamily, { compact: false, entrancePhase: crabEntrancePhase }),
10866
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 items-baseline gap-2 pl-1", children: [
10867
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate text-lg font-bold", children: "Agent Inspector" }),
10868
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "shrink-0 font-mono text-xs font-semibold text-muted-foreground", children: [
10869
+ "v",
10870
+ packageJson.version
10871
+ ] })
10872
+ ] }),
10873
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "size-4 shrink-0 text-muted-foreground/70", "aria-hidden": "true" }),
10874
+ /* @__PURE__ */ jsxRuntimeExports.jsx(McpLogo, { className: "size-10 shrink-0" })
10875
+ ] }),
10876
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "max-w-[calc(100vw-7rem)] text-sm font-semibold text-muted-foreground", children: "Local First. Evidence First." }),
10877
+ /* @__PURE__ */ jsxRuntimeExports.jsx(McpReadyBadge, {})
10878
+ ] }),
10879
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "justify-self-end flex items-center gap-1", children: [
10880
+ /* @__PURE__ */ jsxRuntimeExports.jsx(GroupsDialog, {}),
10881
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SettingsDialog, {})
10882
+ ] })
10883
+ ] });
10884
+ }
10557
10885
  function SessionContextLogButton({ label, logId }) {
10558
10886
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
10559
10887
  "button",
@@ -10738,6 +11066,15 @@ function SessionContextSummaryPanel({
10738
11066
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "max-h-52 overflow-y-auto pr-1", children: summary.models.map((modelSummary) => /* @__PURE__ */ jsxRuntimeExports.jsx(SessionModelContextRow, { summary: modelSummary }, modelSummary.model)) })
10739
11067
  ] });
10740
11068
  }
11069
+ function formatSessionContextOverview(summary) {
11070
+ const riskCount = summary.models.filter((model) => model.latest.health.level === "risk").length;
11071
+ if (riskCount > 0) return `${riskCount} risk`;
11072
+ const optimizableCount = summary.models.filter(
11073
+ (model) => model.latest.health.level === "optimizable"
11074
+ ).length;
11075
+ if (optimizableCount > 0) return `${optimizableCount} optimizable`;
11076
+ return `${summary.models.length} model${summary.models.length === 1 ? "" : "s"}`;
11077
+ }
10741
11078
  function SessionContextBar({
10742
11079
  label,
10743
11080
  logs,
@@ -10748,11 +11085,16 @@ function SessionContextBar({
10748
11085
  showBackLink
10749
11086
  }) {
10750
11087
  const [copied, setCopied] = reactExports.useState(false);
11088
+ const [detailsOpen, setDetailsOpen] = reactExports.useState(false);
10751
11089
  const timeRange = reactExports.useMemo(
10752
11090
  () => formatTimeRange(logs, timeDisplayFormat),
10753
11091
  [logs, timeDisplayFormat]
10754
11092
  );
10755
11093
  const userAgent = reactExports.useMemo(() => getFirstUserAgent(logs), [logs]);
11094
+ const contextOverview = reactExports.useMemo(
11095
+ () => formatSessionContextOverview(contextSummary),
11096
+ [contextSummary]
11097
+ );
10756
11098
  const handleCopyLink = reactExports.useCallback(() => {
10757
11099
  void copyTextToClipboard(window.location.href).then((success) => {
10758
11100
  if (!success) return;
@@ -10760,8 +11102,8 @@ function SessionContextBar({
10760
11102
  setTimeout(() => setCopied(false), 2e3);
10761
11103
  });
10762
11104
  }, []);
10763
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-4 border border-border rounded-md bg-muted/20 px-3 py-2 text-xs", children: [
10764
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
11105
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-3 rounded-md border border-border bg-muted/15 px-3 py-2 text-xs", children: [
11106
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
10765
11107
  showBackLink && /* @__PURE__ */ jsxRuntimeExports.jsx(
10766
11108
  "a",
10767
11109
  {
@@ -10772,7 +11114,7 @@ function SessionContextBar({
10772
11114
  children: /* @__PURE__ */ jsxRuntimeExports.jsx(ArrowLeft, { className: "size-3.5" })
10773
11115
  }
10774
11116
  ),
10775
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 flex-1", children: [
11117
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-[180px] flex-1", children: [
10776
11118
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
10777
11119
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono font-semibold text-purple-400/90 truncate", title: label, children: truncateSessionId(label) }),
10778
11120
  userAgent !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -10799,6 +11141,20 @@ function SessionContextBar({
10799
11141
  ] })
10800
11142
  ] })
10801
11143
  ] }),
11144
+ contextSummary.models.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
11145
+ "button",
11146
+ {
11147
+ type: "button",
11148
+ onClick: () => setDetailsOpen((value) => !value),
11149
+ className: "inline-flex h-8 shrink-0 items-center gap-1.5 rounded-md border border-border bg-background/60 px-2.5 font-mono text-[11px] text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
11150
+ "aria-expanded": detailsOpen,
11151
+ title: detailsOpen ? "Hide context details" : "Show context details",
11152
+ children: [
11153
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: contextOverview }),
11154
+ detailsOpen ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronUp, { className: "size-3.5" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-3.5" })
11155
+ ]
11156
+ }
11157
+ ),
10802
11158
  /* @__PURE__ */ jsxRuntimeExports.jsx(
10803
11159
  "button",
10804
11160
  {
@@ -10811,7 +11167,7 @@ function SessionContextBar({
10811
11167
  }
10812
11168
  )
10813
11169
  ] }),
10814
- /* @__PURE__ */ jsxRuntimeExports.jsx(SessionContextSummaryPanel, { summary: contextSummary })
11170
+ detailsOpen && /* @__PURE__ */ jsxRuntimeExports.jsx(SessionContextSummaryPanel, { summary: contextSummary })
10815
11171
  ] });
10816
11172
  }
10817
11173
  function ProxyViewer({
@@ -10825,12 +11181,12 @@ function ProxyViewer({
10825
11181
  onClearAll,
10826
11182
  onClearGroup,
10827
11183
  viewMode,
10828
- onViewModeChange,
10829
11184
  captureMode,
10830
11185
  strip,
10831
11186
  slowResponseThresholdSeconds,
10832
11187
  timeDisplayFormat,
10833
11188
  isLoading = false,
11189
+ pagination,
10834
11190
  sessionMemberships = [],
10835
11191
  hideSessionFilter = false,
10836
11192
  pinnedSessionId
@@ -10904,6 +11260,17 @@ function ProxyViewer({
10904
11260
  const cacheTrends = reactExports.useMemo(() => computeCacheTrends(groups), [groups]);
10905
11261
  const comparisonPredecessors = reactExports.useMemo(() => buildValidPredecessors(groups), [groups]);
10906
11262
  const exportActionVisibility = getExportActionVisibility(captureMode, logs.length);
11263
+ const isPinnedSessionPage = pinnedSessionId !== void 0;
11264
+ const activeScopeLabel = hasSessionContext && sessionContextScope !== null ? truncateSessionId(sessionContextScope.label) : selectedSession === "__all__" ? "All sessions" : truncateSessionId(selectedSession);
11265
+ const slateStats = reactExports.useMemo(
11266
+ () => buildSessionSlateStats({
11267
+ logs,
11268
+ isLoading,
11269
+ timeDisplayFormat,
11270
+ slowResponseThresholdSeconds
11271
+ }),
11272
+ [isLoading, logs, slowResponseThresholdSeconds, timeDisplayFormat]
11273
+ );
10907
11274
  const handleCompareWithPrevious = reactExports.useCallback(
10908
11275
  (log) => {
10909
11276
  const predecessor = comparisonPredecessors.get(log.id);
@@ -10911,220 +11278,181 @@ function ProxyViewer({
10911
11278
  },
10912
11279
  [comparisonPredecessors]
10913
11280
  );
10914
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "max-w-[1400px] xl:max-w-[1600px] 2xl:max-w-[1800px] mx-auto px-6 pb-6", children: [
10915
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sticky top-0 z-30 bg-background pt-6", children: [
10916
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-[1fr_auto_1fr] items-start gap-3 pb-8", children: [
10917
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", {}),
10918
- /* @__PURE__ */ jsxRuntimeExports.jsxs("h1", { className: "flex min-w-0 flex-col items-center gap-2 text-center", children: [
10919
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex max-w-[calc(100vw-7rem)] items-end gap-2 whitespace-nowrap", children: [
10920
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
10921
- "span",
11281
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-h-screen bg-[#070809] text-foreground", children: [
11282
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mx-auto grid min-h-screen max-w-[1920px] grid-cols-1 lg:grid-cols-[340px_minmax(0,1fr)] xl:grid-cols-[360px_minmax(0,1fr)]", children: [
11283
+ /* @__PURE__ */ jsxRuntimeExports.jsx("aside", { className: "border-b border-border bg-[#090a0c] lg:sticky lg:top-0 lg:h-screen lg:overflow-y-auto lg:border-b-0 lg:border-r", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4 p-4", children: [
11284
+ /* @__PURE__ */ jsxRuntimeExports.jsx(BrandHeader, { compact: true, crabEntrancePhase }),
11285
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-3 gap-2 border-y border-border/70 py-3", children: [
11286
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0", children: [
11287
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-mono text-lg font-semibold text-foreground", children: logs.length }),
11288
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[10px] uppercase text-muted-foreground", children: "Requests" })
11289
+ ] }),
11290
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0", children: [
11291
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-mono text-lg font-semibold text-foreground", children: formatTokens(hasSessionContext ? sessionContextTotalIn : totalIn) }),
11292
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[10px] uppercase text-muted-foreground", children: "Input" })
11293
+ ] }),
11294
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0", children: [
11295
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-mono text-lg font-semibold text-foreground", children: formatTokens(hasSessionContext ? sessionContextTotalOut : totalOut) }),
11296
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[10px] uppercase text-muted-foreground", children: "Output" })
11297
+ ] })
11298
+ ] }),
11299
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
11300
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[10px] font-semibold uppercase tracking-normal text-muted-foreground", children: "Workspace" }),
11301
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-md border border-border bg-[#0c0d0f] px-3 py-2", children: [
11302
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
11303
+ "div",
10922
11304
  {
10923
- className: "flex shrink-0 items-end gap-1 group cursor-default",
10924
- "aria-hidden": "true",
10925
- children: [
10926
- /* @__PURE__ */ jsxRuntimeExports.jsx(CrabLogo, { className: "size-10 text-amber-500 transition-all duration-300 group-hover:scale-125 group-hover:-translate-y-1.5" }),
10927
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "hidden items-end gap-0.5 sm:flex", children: crabVariants.map((Crab, i) => {
10928
- const color = [
10929
- "text-amber-500",
10930
- "text-rose-500",
10931
- "text-sky-500",
10932
- "text-emerald-500",
10933
- "text-violet-500",
10934
- "text-orange-500",
10935
- "text-cyan-500",
10936
- "text-pink-500",
10937
- "text-lime-500",
10938
- "text-blue-500",
10939
- "text-yellow-500",
10940
- "text-fuchsia-500"
10941
- ][i];
10942
- const entranceClass = crabEntrancePhase === "hidden" ? "opacity-0 scale-0" : crabEntrancePhase === "playing" ? "animate-crab-piano-pop" : "";
10943
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
10944
- Crab,
10945
- {
10946
- className: `size-5 ${color} transition-all duration-300 ease-out group-hover:scale-125 group-hover:-translate-y-1 ${entranceClass}`,
10947
- style: {
10948
- transitionDelay: `${i * 50}ms`,
10949
- ...crabEntrancePhase === "playing" ? { animationDelay: `${i * 400}ms` } : {}
10950
- }
10951
- },
10952
- i
10953
- );
10954
- }) })
10955
- ]
11305
+ className: "font-mono text-xs font-semibold text-purple-300",
11306
+ title: activeScopeLabel,
11307
+ children: activeScopeLabel
10956
11308
  }
10957
11309
  ),
10958
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 items-baseline gap-2 pl-1", children: [
10959
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate text-lg font-bold", children: "Agent Inspector" }),
10960
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "shrink-0 font-mono text-xs font-semibold text-muted-foreground", children: [
10961
- "v",
10962
- packageJson.version
10963
- ] })
10964
- ] }),
10965
- /* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "size-4 shrink-0 text-muted-foreground/70", "aria-hidden": "true" }),
10966
- /* @__PURE__ */ jsxRuntimeExports.jsx(McpLogo, { className: "size-10 shrink-0" })
10967
- ] }),
10968
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "max-w-[calc(100vw-7rem)] text-sm font-semibold text-muted-foreground", children: "Local First. Evidence First." }),
10969
- /* @__PURE__ */ jsxRuntimeExports.jsx(McpReadyBadge, {})
10970
- ] }),
10971
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "justify-self-end flex items-center gap-1", children: [
10972
- /* @__PURE__ */ jsxRuntimeExports.jsx(GroupsDialog, {}),
10973
- /* @__PURE__ */ jsxRuntimeExports.jsx(SettingsDialog, {})
10974
- ] })
10975
- ] }),
10976
- hasSessionContext && sessionContextScope !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(
10977
- SessionContextBar,
10978
- {
10979
- label: sessionContextScope.label,
10980
- logs: sessionContextLogs,
10981
- totalIn: sessionContextTotalIn,
10982
- totalOut: sessionContextTotalOut,
10983
- timeDisplayFormat,
10984
- contextSummary: sessionContextSummary,
10985
- showBackLink: sessionContextScope.showBackLink
10986
- }
10987
- ),
10988
- hasSessionContext && pinnedSessionId !== void 0 && sessionMemberships.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(SessionMembershipPanel, { memberships: sessionMemberships }),
10989
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3 mb-4", children: [
10990
- !hideSessionFilter && /* @__PURE__ */ jsxRuntimeExports.jsxs(Select, { value: selectedSession, onValueChange: onSessionChange, children: [
10991
- /* @__PURE__ */ jsxRuntimeExports.jsx(SelectTrigger, { className: "flex-1 max-w-[350px] text-xs", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue, { placeholder: "All sessions" }) }),
10992
- /* @__PURE__ */ jsxRuntimeExports.jsxs(SelectContent, { children: [
10993
- /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: "__all__", children: "All sessions" }),
10994
- sessions.map((s) => /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: s, children: truncateSessionId(s) }, s))
11310
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1 text-[11px] text-muted-foreground", children: isPinnedSessionPage ? "Session workspace" : "Live workspace" })
10995
11311
  ] })
10996
11312
  ] }),
10997
- /* @__PURE__ */ jsxRuntimeExports.jsxs(Select, { value: selectedModel, onValueChange: onModelChange, children: [
10998
- /* @__PURE__ */ jsxRuntimeExports.jsx(SelectTrigger, { className: "flex-1 max-w-[250px] text-xs", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue, { placeholder: "All models" }) }),
10999
- /* @__PURE__ */ jsxRuntimeExports.jsxs(SelectContent, { children: [
11000
- /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: "__all__", children: "All models" }),
11001
- models.map((m) => /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: m, children: m }, m))
11313
+ hasSessionContext && sessionContextScope !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(
11314
+ SessionContextBar,
11315
+ {
11316
+ label: sessionContextScope.label,
11317
+ logs: sessionContextLogs,
11318
+ totalIn: sessionContextTotalIn,
11319
+ totalOut: sessionContextTotalOut,
11320
+ timeDisplayFormat,
11321
+ contextSummary: sessionContextSummary,
11322
+ showBackLink: sessionContextScope.showBackLink
11323
+ }
11324
+ ),
11325
+ hasSessionContext && pinnedSessionId !== void 0 && sessionMemberships.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(SessionMembershipPanel, { memberships: sessionMemberships }),
11326
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
11327
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[10px] font-semibold uppercase tracking-normal text-muted-foreground", children: "Filters" }),
11328
+ !hideSessionFilter && /* @__PURE__ */ jsxRuntimeExports.jsxs(Select, { value: selectedSession, onValueChange: onSessionChange, children: [
11329
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SelectTrigger, { className: "h-9 w-full text-xs", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue, { placeholder: "All sessions" }) }),
11330
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(SelectContent, { children: [
11331
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: "__all__", children: "All sessions" }),
11332
+ sessions.map((s) => /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: s, children: truncateSessionId(s) }, s))
11333
+ ] })
11334
+ ] }),
11335
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Select, { value: selectedModel, onValueChange: onModelChange, children: [
11336
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SelectTrigger, { className: "h-9 w-full text-xs", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue, { placeholder: "All models" }) }),
11337
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(SelectContent, { children: [
11338
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: "__all__", children: "All models" }),
11339
+ models.map((m) => /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: m, children: m }, m))
11340
+ ] })
11002
11341
  ] })
11342
+ ] })
11343
+ ] }) }),
11344
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("main", { className: "min-w-0", children: [
11345
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sticky top-0 z-30 border-b border-border bg-[#08090b]/95 px-4 py-3 shadow-[0_12px_40px_rgba(0,0,0,0.24)] backdrop-blur lg:px-5", children: [
11346
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
11347
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-[180px] flex-1", children: [
11348
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm font-semibold text-foreground", children: "Logs" }),
11349
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-0.5 font-mono text-[11px] text-muted-foreground", children: activeScopeLabel })
11350
+ ] }),
11351
+ exportActionVisibility.redacted && /* @__PURE__ */ jsxRuntimeExports.jsx(
11352
+ "button",
11353
+ {
11354
+ type: "button",
11355
+ onClick: () => {
11356
+ void handleExport("redacted");
11357
+ },
11358
+ disabled: exporting !== null,
11359
+ className: "inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
11360
+ title: "Export redacted logs as JSON ZIP",
11361
+ children: exporting === "redacted" ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Exporting..." }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
11362
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Download, { className: "size-3.5" }),
11363
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Export" })
11364
+ ] })
11365
+ }
11366
+ ),
11367
+ exportActionVisibility.raw && /* @__PURE__ */ jsxRuntimeExports.jsx(
11368
+ "button",
11369
+ {
11370
+ type: "button",
11371
+ onClick: () => {
11372
+ void handleExport("raw");
11373
+ },
11374
+ disabled: exporting !== null,
11375
+ className: "inline-flex h-8 items-center gap-1.5 rounded-md px-2.5 text-xs text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
11376
+ title: "Export raw logs without redaction",
11377
+ children: exporting === "raw" ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Exporting..." }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
11378
+ /* @__PURE__ */ jsxRuntimeExports.jsx(FileBraces, { className: "size-3.5" }),
11379
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Raw" })
11380
+ ] })
11381
+ }
11382
+ ),
11383
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
11384
+ "button",
11385
+ {
11386
+ type: "button",
11387
+ onClick: onClearAll,
11388
+ className: "inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
11389
+ title: "Clear all logs",
11390
+ children: [
11391
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" }),
11392
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Clear" })
11393
+ ]
11394
+ }
11395
+ )
11396
+ ] }),
11397
+ /* @__PURE__ */ jsxRuntimeExports.jsx(LogPaginationBar, { logs, pagination, embedded: true }),
11398
+ exportError !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-xs text-destructive", children: exportError })
11003
11399
  ] }),
11004
- captureMode === "full" ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center border border-border rounded-md overflow-hidden", children: [
11005
- /* @__PURE__ */ jsxRuntimeExports.jsx(
11006
- "button",
11007
- {
11008
- type: "button",
11009
- onClick: () => onViewModeChange("simple"),
11010
- className: `h-8 px-3 cursor-pointer transition-colors text-xs ${viewMode === "simple" ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted/50"}`,
11011
- children: "Simple"
11012
- }
11013
- ),
11014
- /* @__PURE__ */ jsxRuntimeExports.jsx(
11015
- "button",
11400
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-4 lg:px-5", children: [
11401
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SessionOpeningSlate, { stats: slateStats }),
11402
+ logs.length === 0 ? selectedSession !== "__all__" ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "py-16 text-center text-muted-foreground", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mx-auto max-w-xl space-y-4 rounded-md border border-border bg-muted/10 px-4 py-8", children: [
11403
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-medium", children: isLoading ? "Loading session data..." : "Session not found" }),
11404
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "inline-block max-w-full rounded bg-muted px-3 py-1 font-mono text-xs break-all", children: truncateSessionId(selectedSession) }),
11405
+ sessionMemberships.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-left", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SessionMembershipPanel, { memberships: sessionMemberships }) }),
11406
+ !isLoading && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-xs", children: [
11407
+ "This session may have been cleared or never existed.",
11408
+ " ",
11409
+ hideSessionFilter ? /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "/", className: "underline transition-colors hover:text-foreground", children: "Back to all sessions" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
11410
+ "button",
11411
+ {
11412
+ type: "button",
11413
+ onClick: () => onSessionChange("__all__"),
11414
+ className: "underline transition-colors hover:text-foreground",
11415
+ children: "Show all sessions"
11416
+ }
11417
+ )
11418
+ ] })
11419
+ ] }) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "py-16 text-center text-muted-foreground", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mx-auto max-w-2xl space-y-4 rounded-md border border-border bg-muted/10 px-4 py-8", children: [
11420
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm", children: "No requests captured yet." }),
11421
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center gap-2", children: [
11422
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CopyableCommand, { command: "ANTHROPIC_BASE_URL=http://localhost:25947/proxy <your-tool>" }),
11423
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CopyableCommand, { command: "OPENAI_BASE_URL=http://localhost:25947/proxy <your-tool>" })
11424
+ ] }),
11425
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mx-auto max-w-xl text-xs leading-relaxed text-muted-foreground", children: "Container note: if your AI tool runs in a different container or host than Agent Inspector, replace localhost with an address reachable from that tool and verify the network/firewall path." })
11426
+ ] }) }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(
11427
+ "div",
11016
11428
  {
11017
- type: "button",
11018
- onClick: () => onViewModeChange("full"),
11019
- className: `h-8 px-3 cursor-pointer transition-colors text-xs ${viewMode === "full" ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted/50"}`,
11020
- children: "Full"
11429
+ ref: logListWrapperRef,
11430
+ tabIndex: 0,
11431
+ className: "flex flex-col gap-2 focus:outline-none",
11432
+ children: [
11433
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: logListRef, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
11434
+ ConversationGroupList,
11435
+ {
11436
+ groups,
11437
+ viewMode,
11438
+ strip,
11439
+ slowResponseThresholdSeconds,
11440
+ cacheTrends,
11441
+ onCompareWithPrevious: handleCompareWithPrevious,
11442
+ comparisonPredecessors,
11443
+ onClearGroup,
11444
+ standalone: groups.length === 1,
11445
+ hasPinnedSessionContext: hasSessionContext,
11446
+ timeDisplayFormat
11447
+ }
11448
+ ) }),
11449
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-3", children: /* @__PURE__ */ jsxRuntimeExports.jsx(LogPaginationBar, { logs, pagination }) })
11450
+ ]
11021
11451
  }
11022
11452
  )
11023
- ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex h-8 items-center rounded-md border border-border bg-muted px-3 text-xs text-foreground", children: "Simple" }),
11024
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1" }),
11025
- !hasSessionContext && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground text-xs font-mono", children: [
11026
- logs.length,
11027
- " request",
11028
- logs.length !== 1 ? "s" : "",
11029
- totalIn > 0 || totalOut > 0 ? ` - ${formatTokens(totalIn)} in / ${formatTokens(totalOut)} out` : ""
11030
- ] }),
11031
- exportActionVisibility.redacted && /* @__PURE__ */ jsxRuntimeExports.jsx(
11032
- "button",
11033
- {
11034
- type: "button",
11035
- onClick: () => {
11036
- void handleExport("redacted");
11037
- },
11038
- disabled: exporting !== null,
11039
- className: "h-8 px-3 text-xs text-muted-foreground hover:text-foreground transition-colors cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed inline-flex items-center gap-1.5 rounded-md hover:bg-muted",
11040
- title: "Export redacted logs as JSON ZIP",
11041
- children: exporting === "redacted" ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Exporting..." }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
11042
- /* @__PURE__ */ jsxRuntimeExports.jsx(Download, { className: "size-3.5" }),
11043
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Export" })
11044
- ] })
11045
- }
11046
- ),
11047
- exportActionVisibility.raw && /* @__PURE__ */ jsxRuntimeExports.jsx(
11048
- "button",
11049
- {
11050
- type: "button",
11051
- onClick: () => {
11052
- void handleExport("raw");
11053
- },
11054
- disabled: exporting !== null,
11055
- className: "h-8 px-2.5 text-xs text-muted-foreground hover:text-foreground transition-colors cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed inline-flex items-center gap-1.5 rounded-md hover:bg-muted",
11056
- title: "Export raw logs without redaction",
11057
- children: exporting === "raw" ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Exporting..." }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
11058
- /* @__PURE__ */ jsxRuntimeExports.jsx(FileBraces, { className: "size-3.5" }),
11059
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Raw" })
11060
- ] })
11061
- }
11062
- ),
11063
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
11064
- "button",
11065
- {
11066
- type: "button",
11067
- onClick: onClearAll,
11068
- className: "h-8 px-3 text-xs text-muted-foreground hover:text-foreground transition-colors cursor-pointer inline-flex items-center gap-1.5 rounded-md hover:bg-muted",
11069
- title: "Clear all logs",
11070
- children: [
11071
- /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" }),
11072
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Clear" })
11073
- ]
11074
- }
11075
- )
11076
- ] }),
11077
- exportError !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-4 rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-xs text-destructive", children: exportError })
11078
- ] }),
11079
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: logs.length === 0 ? selectedSession !== "__all__" ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center text-muted-foreground py-16 space-y-4", children: [
11080
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-medium", children: isLoading ? "Loading session data..." : "Session not found" }),
11081
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs font-mono bg-muted px-3 py-1 rounded inline-block max-w-[500px] break-all", children: truncateSessionId(selectedSession) }),
11082
- sessionMemberships.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mx-auto max-w-3xl text-left", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SessionMembershipPanel, { memberships: sessionMemberships }) }),
11083
- !isLoading && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-xs", children: [
11084
- "This session may have been cleared or never existed.",
11085
- " ",
11086
- hideSessionFilter ? /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "/", className: "underline hover:text-foreground transition-colors", children: "Back to all sessions" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
11087
- "button",
11088
- {
11089
- type: "button",
11090
- onClick: () => onSessionChange("__all__"),
11091
- className: "underline hover:text-foreground transition-colors",
11092
- children: "Show all sessions"
11093
- }
11094
- )
11453
+ ] })
11095
11454
  ] })
11096
- ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center text-muted-foreground py-16 space-y-4", children: [
11097
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm", children: "No requests captured yet." }),
11098
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs", children: "Route AI coding tools through the proxy:" }),
11099
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center gap-2", children: [
11100
- /* @__PURE__ */ jsxRuntimeExports.jsx(CopyableCommand, { command: "ANTHROPIC_BASE_URL=http://localhost:25947/proxy <your-tool>" }),
11101
- /* @__PURE__ */ jsxRuntimeExports.jsx(CopyableCommand, { command: "OPENAI_BASE_URL=http://localhost:25947/proxy <your-tool>" })
11102
- ] }),
11103
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mx-auto max-w-xl text-xs leading-relaxed text-muted-foreground", children: "Container note: if your AI tool runs in a different container or host than Agent Inspector, replace localhost with an address reachable from that tool and verify the network/firewall path." })
11104
- ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
11105
- "div",
11106
- {
11107
- ref: logListWrapperRef,
11108
- tabIndex: 0,
11109
- className: "flex flex-col gap-2 focus:outline-none",
11110
- children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: logListRef, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
11111
- ConversationGroupList,
11112
- {
11113
- groups,
11114
- viewMode,
11115
- strip,
11116
- slowResponseThresholdSeconds,
11117
- cacheTrends,
11118
- onCompareWithPrevious: handleCompareWithPrevious,
11119
- comparisonPredecessors,
11120
- onClearGroup,
11121
- standalone: groups.length === 1,
11122
- hasPinnedSessionContext: hasSessionContext,
11123
- timeDisplayFormat
11124
- }
11125
- ) })
11126
- }
11127
- ) }),
11455
+ ] }),
11128
11456
  comparePair !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntimeExports.jsx(LazyCompareDrawer, { left: comparePair[0], right: comparePair[1], onClose: closeCompare }) })
11129
11457
  ] });
11130
11458
  }
@@ -11138,6 +11466,15 @@ const SSEUpdateSchema = union([
11138
11466
  log: CapturedLogSchema
11139
11467
  })
11140
11468
  ]);
11469
+ const LogCursorPageSchema = object({
11470
+ logs: array(CapturedLogSchema),
11471
+ total: number().int().nonnegative(),
11472
+ limit: number().int().positive(),
11473
+ hasOlder: boolean(),
11474
+ hasNewer: boolean(),
11475
+ oldestLogId: number().int().positive().nullable(),
11476
+ newestLogId: number().int().positive().nullable()
11477
+ });
11141
11478
  function buildSessionMembershipEvidence(groups, sessionId) {
11142
11479
  const memberships = [];
11143
11480
  for (const group of groups) {
@@ -11183,6 +11520,7 @@ const DEBOUNCE_MS = 50;
11183
11520
  const HASH_SCROLL_ATTEMPTS = 12;
11184
11521
  const HASH_HIGHLIGHT_MS = 1800;
11185
11522
  const MAX_CLIENT_LOGS = 500;
11523
+ const SESSION_PAGE_LIMIT = 100;
11186
11524
  function buildLogsStreamUrl(sessionId) {
11187
11525
  const params = new URLSearchParams();
11188
11526
  if (sessionId !== void 0) {
@@ -11192,6 +11530,26 @@ function buildLogsStreamUrl(sessionId) {
11192
11530
  const query = params.toString();
11193
11531
  return query.length > 0 ? `/api/logs/stream?${query}` : "/api/logs/stream";
11194
11532
  }
11533
+ function buildSessionLogsPageUrl(sessionId, request) {
11534
+ const params = new URLSearchParams({
11535
+ cursor: "1",
11536
+ compact: "1",
11537
+ limit: String(SESSION_PAGE_LIMIT),
11538
+ sessionId
11539
+ });
11540
+ switch (request.kind) {
11541
+ case "oldest":
11542
+ params.set("anchor", "oldest");
11543
+ break;
11544
+ case "older":
11545
+ params.set("beforeLogId", String(request.beforeLogId));
11546
+ break;
11547
+ case "newer":
11548
+ params.set("afterLogId", String(request.afterLogId));
11549
+ break;
11550
+ }
11551
+ return `/api/logs?${params.toString()}`;
11552
+ }
11195
11553
  function buildLogIndex(logs) {
11196
11554
  const idx = /* @__PURE__ */ new Map();
11197
11555
  for (let i = 0; i < logs.length; i++) {
@@ -11210,13 +11568,15 @@ function ProxyViewerContainer({
11210
11568
  const [allLogs, setAllLogs] = reactExports.useState([]);
11211
11569
  const [selectedSession, setSelectedSession] = reactExports.useState(initialSessionId ?? "__all__");
11212
11570
  const [selectedModel, setSelectedModel] = reactExports.useState("__all__");
11213
- const [viewMode, setViewMode] = reactExports.useState("simple");
11214
11571
  const [error, setError] = reactExports.useState(null);
11215
11572
  const [streamInitialized, setStreamInitialized] = reactExports.useState(initialSessionId === void 0);
11573
+ const [logPage, setLogPage] = reactExports.useState(null);
11574
+ const [sessionPageLoading, setSessionPageLoading] = reactExports.useState(initialSessionId !== void 0);
11216
11575
  const [sessionMemberships, setSessionMemberships] = reactExports.useState([]);
11217
11576
  const eventSourceRef = reactExports.useRef(null);
11218
11577
  const reconnectTimeoutRef = reactExports.useRef(null);
11219
11578
  const handledHashRef = reactExports.useRef(null);
11579
+ const sessionPageRequestIdRef = reactExports.useRef(0);
11220
11580
  const logIndexRef = reactExports.useRef(/* @__PURE__ */ new Map());
11221
11581
  const pendingUpdatesRef = reactExports.useRef([]);
11222
11582
  const flushTimerRef = reactExports.useRef(null);
@@ -11301,6 +11661,32 @@ function ProxyViewerContainer({
11301
11661
  reconnectTimeoutRef.current = setTimeout(connectSSE, 3e3);
11302
11662
  };
11303
11663
  }, [initialSessionId, scheduleUpdate]);
11664
+ const loadSessionPage = reactExports.useCallback(
11665
+ (request) => {
11666
+ if (initialSessionId === void 0) return;
11667
+ const requestId = sessionPageRequestIdRef.current + 1;
11668
+ sessionPageRequestIdRef.current = requestId;
11669
+ setSessionPageLoading(true);
11670
+ setError(null);
11671
+ void fetchJson(buildSessionLogsPageUrl(initialSessionId, request), LogCursorPageSchema).then((page) => {
11672
+ if (sessionPageRequestIdRef.current !== requestId) return;
11673
+ const nextLogs = page.logs;
11674
+ logIndexRef.current = buildLogIndex(nextLogs);
11675
+ setAllLogs(nextLogs);
11676
+ setLogPage(page);
11677
+ setSelectedSession(initialSessionId);
11678
+ setSessionPageLoading(false);
11679
+ setError(null);
11680
+ }).catch((err) => {
11681
+ if (sessionPageRequestIdRef.current !== requestId) return;
11682
+ setAllLogs([]);
11683
+ setLogPage(null);
11684
+ setSessionPageLoading(false);
11685
+ setError(err instanceof Error ? err.message : "Failed to load session logs");
11686
+ });
11687
+ },
11688
+ [initialSessionId]
11689
+ );
11304
11690
  reactExports.useEffect(() => {
11305
11691
  if (initialSessionId === void 0) {
11306
11692
  setSessionMemberships([]);
@@ -11323,6 +11709,11 @@ function ProxyViewerContainer({
11323
11709
  };
11324
11710
  }, [initialSessionId]);
11325
11711
  reactExports.useEffect(() => {
11712
+ if (initialSessionId === void 0) return;
11713
+ loadSessionPage({ kind: "newest" });
11714
+ }, [initialSessionId, loadSessionPage]);
11715
+ reactExports.useEffect(() => {
11716
+ if (initialSessionId !== void 0) return void 0;
11326
11717
  connectSSE();
11327
11718
  return () => {
11328
11719
  if (eventSourceRef.current) {
@@ -11338,7 +11729,7 @@ function ProxyViewerContainer({
11338
11729
  flushTimerRef.current = null;
11339
11730
  }
11340
11731
  };
11341
- }, [connectSSE]);
11732
+ }, [connectSSE, initialSessionId]);
11342
11733
  reactExports.useEffect(() => {
11343
11734
  const hash = window.location.hash;
11344
11735
  if (!hash.startsWith("#log-")) return;
@@ -11437,6 +11828,49 @@ function ProxyViewerContainer({
11437
11828
  })();
11438
11829
  }, []);
11439
11830
  const { strip, captureMode, slowResponseThresholdSeconds, timeDisplayFormat } = useStripConfig();
11831
+ const viewMode = captureMode;
11832
+ const loadOldestPage = reactExports.useCallback(() => {
11833
+ loadSessionPage({ kind: "oldest" });
11834
+ }, [loadSessionPage]);
11835
+ const loadNewestPage = reactExports.useCallback(() => {
11836
+ loadSessionPage({ kind: "newest" });
11837
+ }, [loadSessionPage]);
11838
+ const loadOlderPage = reactExports.useCallback(() => {
11839
+ const firstLog = allLogs[0];
11840
+ const beforeLogId = logPage?.oldestLogId ?? firstLog?.id ?? null;
11841
+ if (beforeLogId === null) return;
11842
+ loadSessionPage({ kind: "older", beforeLogId });
11843
+ }, [allLogs, loadSessionPage, logPage]);
11844
+ const loadNewerPage = reactExports.useCallback(() => {
11845
+ const lastLog = allLogs[allLogs.length - 1];
11846
+ const afterLogId = logPage?.newestLogId ?? lastLog?.id ?? null;
11847
+ if (afterLogId === null) return;
11848
+ loadSessionPage({ kind: "newer", afterLogId });
11849
+ }, [allLogs, loadSessionPage, logPage]);
11850
+ const pagination = reactExports.useMemo(() => {
11851
+ if (initialSessionId === void 0) return void 0;
11852
+ return {
11853
+ isLoading: sessionPageLoading,
11854
+ total: logPage?.total ?? null,
11855
+ pageSize: logPage?.limit ?? SESSION_PAGE_LIMIT,
11856
+ hasOlder: logPage?.hasOlder ?? false,
11857
+ hasNewer: logPage?.hasNewer ?? false,
11858
+ oldestLogId: logPage?.oldestLogId ?? null,
11859
+ newestLogId: logPage?.newestLogId ?? null,
11860
+ onOldest: loadOldestPage,
11861
+ onOlder: loadOlderPage,
11862
+ onNewer: loadNewerPage,
11863
+ onNewest: loadNewestPage
11864
+ };
11865
+ }, [
11866
+ initialSessionId,
11867
+ loadNewestPage,
11868
+ loadNewerPage,
11869
+ loadOlderPage,
11870
+ loadOldestPage,
11871
+ logPage,
11872
+ sessionPageLoading
11873
+ ]);
11440
11874
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
11441
11875
  error !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fixed top-4 right-4 bg-destructive text-destructive-foreground px-4 py-2 rounded-md text-sm z-50", children: error }),
11442
11876
  /* @__PURE__ */ jsxRuntimeExports.jsx(OnboardingBanner, {}),
@@ -11452,10 +11886,10 @@ function ProxyViewerContainer({
11452
11886
  onModelChange: setSelectedModel,
11453
11887
  onClearAll: handleClearAll,
11454
11888
  onClearGroup: handleClearGroup,
11455
- isLoading: initialSessionId !== void 0 && !streamInitialized,
11889
+ isLoading: initialSessionId === void 0 ? !streamInitialized : sessionPageLoading,
11890
+ pagination,
11456
11891
  sessionMemberships,
11457
11892
  viewMode,
11458
- onViewModeChange: setViewMode,
11459
11893
  captureMode,
11460
11894
  strip,
11461
11895
  slowResponseThresholdSeconds,