@tonyclaw/agent-inspector 3.0.14 → 3.0.16

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 (42) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/{CompareDrawer-DDfwHQUi.js → CompareDrawer-BJmxAiM0.js} +1 -1
  3. package/.output/public/assets/ProxyViewerContainer-C40Nig73.js +106 -0
  4. package/.output/public/assets/{ReplayDialog-D-26DMBt.js → ReplayDialog-CkLdOMJr.js} +1 -1
  5. package/.output/public/assets/{RequestAnatomy-B6zNFqNX.js → RequestAnatomy-DemOFfSc.js} +1 -1
  6. package/.output/public/assets/{ResponseView-Ccy95rWI.js → ResponseView-9LhpuDo7.js} +2 -2
  7. package/.output/public/assets/{StreamingChunkSequence-yIiscGuE.js → StreamingChunkSequence-RRWYBOdz.js} +1 -1
  8. package/.output/public/assets/{_sessionId-BnMB0zab.js → _sessionId-CWEh2Jsn.js} +1 -1
  9. package/.output/public/assets/index-HRfrFVYw.css +1 -0
  10. package/.output/public/assets/{index-BbtAIxbg.js → index-Lwir70Rs.js} +1 -1
  11. package/.output/public/assets/index-hjNWJZGE.js +1 -0
  12. package/.output/public/assets/{json-viewer-C838cVmD.js → json-viewer-D8gvbDlB.js} +1 -1
  13. package/.output/public/assets/{main-BfN4culo.js → main-ovrz0tyD.js} +7 -7
  14. package/.output/server/_libs/lucide-react.mjs +215 -201
  15. package/.output/server/{_sessionId-DoprmwZV.mjs → _sessionId-zI_GFX_7.mjs} +2 -2
  16. package/.output/server/_ssr/{CompareDrawer-YMLJNxXR.mjs → CompareDrawer-Ckcx1RVu.mjs} +3 -3
  17. package/.output/server/_ssr/{ProxyViewerContainer-C62eZnva.mjs → ProxyViewerContainer-BgXewlIr.mjs} +729 -378
  18. package/.output/server/_ssr/{ReplayDialog-NmN7Ukjo.mjs → ReplayDialog-wx3nDtZn.mjs} +4 -4
  19. package/.output/server/_ssr/{RequestAnatomy-Dawm2qxe.mjs → RequestAnatomy-DN80zt0G.mjs} +3 -3
  20. package/.output/server/_ssr/{ResponseView-BHyAY83t.mjs → ResponseView-DD7rTu_l.mjs} +3 -3
  21. package/.output/server/_ssr/{StreamingChunkSequence-C4qgcJbg.mjs → StreamingChunkSequence-DAgz6Vvw.mjs} +3 -3
  22. package/.output/server/_ssr/{index-B2Pf6W_T.mjs → index-dcTjp8du.mjs} +14 -5
  23. package/.output/server/_ssr/index.mjs +2 -2
  24. package/.output/server/_ssr/{json-viewer-u67BASf8.mjs → json-viewer-N2cuzGWR.mjs} +3 -3
  25. package/.output/server/_ssr/{router-CZhFVMGN.mjs → router-BfQ0QsD5.mjs} +132 -17
  26. package/.output/server/{_tanstack-start-manifest_v-Dk2HfOoe.mjs → _tanstack-start-manifest_v-BXnYrbcJ.mjs} +1 -1
  27. package/.output/server/index.mjs +75 -75
  28. package/package.json +1 -1
  29. package/src/components/ProxyViewer.tsx +475 -197
  30. package/src/components/ProxyViewerContainer.tsx +145 -17
  31. package/src/components/proxy-viewer/ToolTraceEvents.tsx +36 -10
  32. package/src/components/proxy-viewer/TurnGroup.tsx +4 -1
  33. package/src/lib/chunkLoadRecovery.ts +83 -0
  34. package/src/proxy/formats/openai/codexMetadata.ts +61 -0
  35. package/src/proxy/formats/openai/handler.ts +8 -2
  36. package/src/routes/__root.tsx +6 -3
  37. package/src/routes/index.tsx +25 -1
  38. package/src/routes/session/$sessionId.tsx +1 -0
  39. package/styles/globals.css +54 -0
  40. package/.output/public/assets/ProxyViewerContainer-CbNsaoQw.js +0 -106
  41. package/.output/public/assets/index-49RC4dlD.js +0 -1
  42. package/.output/public/assets/index-DXKupW0r.css +0 -1
@@ -1,5 +1,5 @@
1
1
  import { r as reactExports, j as jsxRuntimeExports, a as React } from "../_libs/react.mjs";
2
- import { 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, p as packageJson, P as ProviderConfigSchema, i as apiFormatForPath, n as DeleteInspectorGroupsResponseSchema, o as GroupEvidenceExportResultSchema, q as DeleteInspectorGroupResponseSchema, l as AlertSummarySchema, m as AlertListResponseSchema, I as InspectorGroupsListResponseSchema, G as GroupEvidenceReadResponseSchema, z as createPendingProviderTestResults, B as ProviderTestResultsSchema, E as createFailedProviderTestResults, M as MAX_SLOW_RESPONSE_THRESHOLD_SECONDS, F as MAX_PROVIDER_TEST_TIMEOUT_SECONDS, T as TimeDisplayFormatSchema, t as maskApiKey, v as PATH_V1_MESSAGES, w as PATH_V1_CHAT_COMPLETIONS, x as PATH_V1_RESPONSES, r as providerHasContextMetadata, f as parseOpenAIResponse, g as parseOpenAIResponsesResponse, O as OpenAIRequestSchema, h as OpenAIResponsesRequestSchema, A as AnthropicResponseSchema$1, e as AnthropicRequestSchema, s as safeGetOwnProperty, H as resolveProviderContextWindow, j as getSessionPath, u as findProviderModelMetadata, y as previewUpstreamUrl, K as KnowledgeCandidateSchema, J as isPlainRecord, k as stripClaudeCodeBillingHeader, L as LogBodyChunkSchema } from "./router-CZhFVMGN.mjs";
2
+ import { C as CapturedLogSchema, n as DeleteInspectorGroupsResponseSchema, 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, p as packageJson, P as ProviderConfigSchema, i as apiFormatForPath, o as GroupEvidenceExportResultSchema, q as DeleteInspectorGroupResponseSchema, l as AlertSummarySchema, m as AlertListResponseSchema, I as InspectorGroupsListResponseSchema, G as GroupEvidenceReadResponseSchema, z as createPendingProviderTestResults, B as ProviderTestResultsSchema, E as createFailedProviderTestResults, M as MAX_SLOW_RESPONSE_THRESHOLD_SECONDS, F as MAX_PROVIDER_TEST_TIMEOUT_SECONDS, T as TimeDisplayFormatSchema, t as maskApiKey, v as PATH_V1_MESSAGES, w as PATH_V1_CHAT_COMPLETIONS, x as PATH_V1_RESPONSES, r as providerHasContextMetadata, f as parseOpenAIResponse, g as parseOpenAIResponsesResponse, O as OpenAIRequestSchema, h as OpenAIResponsesRequestSchema, A as AnthropicResponseSchema$1, e as AnthropicRequestSchema, s as safeGetOwnProperty, H as resolveProviderContextWindow, j as getSessionPath, u as findProviderModelMetadata, y as previewUpstreamUrl, K as KnowledgeCandidateSchema, J as isPlainRecord, k as stripClaudeCodeBillingHeader, L as LogBodyChunkSchema } from "./router-BfQ0QsD5.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";
@@ -9,7 +9,7 @@ import { c as cva } from "../_libs/class-variance-authority.mjs";
9
9
  import { u as useWindowVirtualizer, a as useVirtualizer } from "../_libs/tanstack__react-virtual.mjs";
10
10
  import { d as diffJson, a as diffLines } from "../_libs/diff.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 { T as TriangleAlert, C as CircleCheck, X, I as Info, a as ChevronDown, b as Check, R as RefreshCw, c as Trash2, S as Search, U as Upload, D as Download, F as FileBraces, P as Plus, A as ArrowLeft, d as ChevronUp, e as Copy, f as ChevronsLeft, g as ChevronLeft, h as ChevronRight, i as ChevronsRight, j as Clapperboard, k as Flag, l as Siren, m as Timer, G as Gauge, L as LoaderCircle, n as Layers, o as FlaskConical, p as Sparkles, q as Activity, B as Beaker, N as Network, r as Terminal, s as Settings, M as Monitor, t as Rocket, u as PackageCheck, H as History, v as Scan, w as CircleAlert, x as ArrowUpRight, y as ArrowDownRight, z as Cpu, E as FolderOpen, J as Bell, K as Clock3, O as ShieldAlert, Q as EyeOff, V as Eye, W as ExternalLink, Y as Clock, Z as RotateCw, _ as Pencil, $ as MessageSquare, a0 as Zap, a1 as Wrench, a2 as Brain, a3 as CircleCheckBig, a4 as Minus, a5 as CircleQuestionMark, a6 as Server, a7 as Lock, a8 as Wifi, a9 as WifiOff, aa as CircleX, ab as ShieldCheck, ac as Save, ad as FileSearch, ae as CloudUpload, af as OctagonAlert, ag as Radio, ah as Globe, ai as FileTerminal, aj as ChevronsUp, ak as ChevronsDown, al as FileDiff, am as RotateCcw, an as GitCompareArrows, ao as ArrowUp, ap as ArrowDown, aq as Ellipsis, ar as CodeXml, as as Blocks, at as MousePointerClick, au as FileText, av as Rows3, aw as Columns2 } from "../_libs/lucide-react.mjs";
12
+ import { T as TriangleAlert, C as CircleCheck, X, I as Info, a as ChevronDown, b as Check, P as PanelRightOpen, c as PanelRightClose, S as Search, U as Upload, D as Download, F as FileBraces, R as RefreshCw, d as Trash2, e as Plus, A as ArrowLeft, f as ChevronUp, g as Copy, h as ChevronsLeft, i as ChevronLeft, j as ChevronRight, k as ChevronsRight, l as Clapperboard, m as Flag, n as Siren, o as Timer, G as Gauge, L as LoaderCircle, p as Layers, q as FlaskConical, r as Sparkles, s as Activity, B as Beaker, N as Network, t as Terminal, u as Settings, M as Monitor, v as Rocket, w as PackageCheck, H as History, x as Scan, y as CircleAlert, z as ArrowUpRight, E as ArrowDownRight, J as Cpu, K as FolderOpen, O as Bell, Q as Clock3, V as ShieldAlert, W as EyeOff, Y as Eye, Z as ExternalLink, _ as Clock, $ as RotateCw, a0 as Pencil, a1 as MessageSquare, a2 as Zap, a3 as Wrench, a4 as Brain, a5 as CircleCheckBig, a6 as Minus, a7 as CircleQuestionMark, a8 as Server, a9 as Lock, aa as Wifi, ab as WifiOff, ac as CircleX, ad as ShieldCheck, ae as Save, af as FileSearch, ag as CloudUpload, ah as OctagonAlert, ai as Radio, aj as Globe, ak as FileTerminal, al as ChevronsUp, am as ChevronsDown, an as FileDiff, ao as RotateCcw, ap as GitCompareArrows, aq as ArrowUp, ar as ArrowDown, as as Ellipsis, at as CodeXml, au as Blocks, av as MousePointerClick, aw as FileText, ax as Rows3, ay as Columns2 } from "../_libs/lucide-react.mjs";
13
13
  import { u as union, d as object, a as array, l as literal, n as number, c as boolean, b as string, _ as _enum } from "../_libs/zod.mjs";
14
14
  import { S as Slot } from "../_libs/radix-ui__react-slot.mjs";
15
15
  import { R as Root2$1, L as List, T as Trigger$2, C as Content$1 } from "../_libs/radix-ui__react-tabs.mjs";
@@ -2546,27 +2546,27 @@ function useCopyFeedback(text) {
2546
2546
  return { copied, copy };
2547
2547
  }
2548
2548
  const LazyCompareDrawer = reactExports.lazy(
2549
- () => import("./CompareDrawer-YMLJNxXR.mjs").then((m) => ({ default: m.CompareDrawer }))
2549
+ () => import("./CompareDrawer-Ckcx1RVu.mjs").then((m) => ({ default: m.CompareDrawer }))
2550
2550
  );
2551
2551
  const LazyReplayDialog = reactExports.lazy(
2552
- () => import("./ReplayDialog-NmN7Ukjo.mjs").then((m) => ({ default: m.ReplayDialog }))
2552
+ () => import("./ReplayDialog-wx3nDtZn.mjs").then((m) => ({ default: m.ReplayDialog }))
2553
2553
  );
2554
2554
  const LazyRequestAnatomy = reactExports.lazy(
2555
- () => import("./RequestAnatomy-Dawm2qxe.mjs").then((m) => ({ default: m.RequestAnatomy }))
2555
+ () => import("./RequestAnatomy-DN80zt0G.mjs").then((m) => ({ default: m.RequestAnatomy }))
2556
2556
  );
2557
2557
  const LazyResponseView = reactExports.lazy(
2558
- () => import("./ResponseView-BHyAY83t.mjs").then((m) => ({ default: m.ResponseView }))
2558
+ () => import("./ResponseView-DD7rTu_l.mjs").then((m) => ({ default: m.ResponseView }))
2559
2559
  );
2560
2560
  const LazyStreamingChunkSequence = reactExports.lazy(
2561
- () => import("./StreamingChunkSequence-C4qgcJbg.mjs").then((m) => ({
2561
+ () => import("./StreamingChunkSequence-DAgz6Vvw.mjs").then((m) => ({
2562
2562
  default: m.StreamingChunkSequence
2563
2563
  }))
2564
2564
  );
2565
2565
  const LazyJsonViewer = reactExports.lazy(
2566
- () => import("./json-viewer-u67BASf8.mjs").then((m) => ({ default: m.JsonViewer }))
2566
+ () => import("./json-viewer-N2cuzGWR.mjs").then((m) => ({ default: m.JsonViewer }))
2567
2567
  );
2568
2568
  const LazyJsonViewerFromString = reactExports.lazy(
2569
- () => import("./json-viewer-u67BASf8.mjs").then((m) => ({ default: m.JsonViewerFromString }))
2569
+ () => import("./json-viewer-N2cuzGWR.mjs").then((m) => ({ default: m.JsonViewerFromString }))
2570
2570
  );
2571
2571
  const HIGHLIGHT_DURATION_MS = 1200;
2572
2572
  const MAX_HIGHLIGHT_ATTEMPTS = 12;
@@ -4641,30 +4641,51 @@ function ThreadConnector({
4641
4641
  ) })
4642
4642
  ] });
4643
4643
  }
4644
+ const VISIBLE_TOOL_LIMIT = 4;
4644
4645
  function ToolTraceEventChip({ event }) {
4645
4646
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
4646
4647
  "button",
4647
4648
  {
4648
4649
  type: "button",
4649
- className: "inline-flex min-w-0 items-center gap-1.5 rounded-md bg-white/[0.035] px-2 py-1 text-xs text-muted-foreground transition-colors hover:bg-sky-400/[0.08] hover:text-sky-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
4650
+ className: "inline-flex h-6 max-w-[11rem] min-w-0 items-center gap-1 rounded-md bg-white/[0.028] px-1.5 text-[11px] text-muted-foreground transition-colors hover:bg-sky-400/[0.08] hover:text-sky-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
4650
4651
  onClick: () => dispatchLogFocusRequest({
4651
4652
  logId: event.logId,
4652
4653
  tab: "response",
4653
4654
  toolCallIndex: event.index
4654
4655
  }),
4655
4656
  "aria-label": `Open response tool call ${event.name}`,
4656
- title: `Open ${event.name} in Response`,
4657
4657
  children: [
4658
- /* @__PURE__ */ jsxRuntimeExports.jsx(Wrench, { className: "size-3.5 shrink-0 text-sky-400/70" }),
4658
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Wrench, { className: "size-3 shrink-0 text-sky-400/65" }),
4659
4659
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0 truncate font-mono font-semibold", children: event.name })
4660
4660
  ]
4661
4661
  },
4662
4662
  event.id
4663
4663
  );
4664
4664
  }
4665
- function ToolTraceEvents({ events }) {
4666
- if (events.length === 0) return null;
4667
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mx-3 mb-2 flex flex-wrap gap-1.5", children: events.map((event) => /* @__PURE__ */ jsxRuntimeExports.jsx(ToolTraceEventChip, { event }, event.id)) });
4665
+ function ToolTraceEvents({
4666
+ events,
4667
+ warnings = []
4668
+ }) {
4669
+ if (events.length === 0 && warnings.length === 0) return null;
4670
+ const visibleEvents = events.slice(0, VISIBLE_TOOL_LIMIT);
4671
+ const hiddenCount = Math.max(0, events.length - visibleEvents.length);
4672
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mx-3 mb-2 flex min-w-0 items-center gap-1.5 overflow-hidden rounded-md bg-black/[0.10] px-2 py-1 shadow-[inset_0_1px_0_rgba(255,255,255,0.025)]", children: [
4673
+ events.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex h-6 shrink-0 items-center gap-1 rounded-md px-1.5 font-mono text-[10px] font-semibold uppercase tracking-[0.12em] text-sky-300/70", children: [
4674
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Wrench, { className: "size-3" }),
4675
+ events.length
4676
+ ] }),
4677
+ warnings.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex h-6 shrink-0 items-center gap-1 rounded-md border border-amber-300/20 bg-amber-300/[0.08] px-1.5 font-mono text-[10px] font-semibold text-amber-100", children: [
4678
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TriangleAlert, { className: "size-3" }),
4679
+ warnings.length
4680
+ ] }),
4681
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-1 overflow-hidden", children: [
4682
+ visibleEvents.map((event) => /* @__PURE__ */ jsxRuntimeExports.jsx(ToolTraceEventChip, { event }, event.id)),
4683
+ hiddenCount > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex h-6 shrink-0 items-center rounded-md bg-white/[0.025] px-1.5 font-mono text-[11px] font-semibold text-muted-foreground", children: [
4684
+ "+",
4685
+ hiddenCount
4686
+ ] })
4687
+ ] })
4688
+ ] });
4668
4689
  }
4669
4690
  const PREVIEW_LIMIT = 180;
4670
4691
  const toolTraceCache = /* @__PURE__ */ new WeakMap();
@@ -5196,7 +5217,13 @@ const TurnGroup = reactExports.memo(function TurnGroup2({
5196
5217
  onCompareWithPrevious: comparisonPredecessors.has(log.id) ? onCompareWithPrevious : void 0
5197
5218
  }
5198
5219
  ),
5199
- /* @__PURE__ */ jsxRuntimeExports.jsx(ToolTraceEvents, { events: toolEventsByLogId.get(log.id) ?? [] })
5220
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
5221
+ ToolTraceEvents,
5222
+ {
5223
+ events: toolEventsByLogId.get(log.id) ?? [],
5224
+ warnings: log.warnings ?? []
5225
+ }
5226
+ )
5200
5227
  ] })
5201
5228
  ] }, log.id);
5202
5229
  })
@@ -14215,6 +14242,256 @@ function BrandHeader({
14215
14242
  ] })
14216
14243
  ] });
14217
14244
  }
14245
+ const FLOATING_LOGO_SIZE = 56;
14246
+ const FLOATING_LOGO_MARGIN = 14;
14247
+ const FLOATING_LOGO_MIN_DRIFT_MS = 5200;
14248
+ const FLOATING_LOGO_DRIFT_WINDOW_MS = 2400;
14249
+ const FLOATING_LOGO_MIN_STEP = 72;
14250
+ const FLOATING_LOGO_MAX_STEP = 156;
14251
+ const DETAILS_PANEL_COLLAPSED_STORAGE_KEY = "agent-inspector.detailsPanelCollapsed";
14252
+ function readStoredDetailsPanelCollapsed() {
14253
+ if (typeof window === "undefined") return true;
14254
+ const stored = window.localStorage.getItem(DETAILS_PANEL_COLLAPSED_STORAGE_KEY);
14255
+ return stored === null || stored === "1";
14256
+ }
14257
+ function clampFloatingLogoPosition(position) {
14258
+ const maxX = Math.max(
14259
+ FLOATING_LOGO_MARGIN,
14260
+ window.innerWidth - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
14261
+ );
14262
+ const maxY = Math.max(
14263
+ FLOATING_LOGO_MARGIN,
14264
+ window.innerHeight - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
14265
+ );
14266
+ return {
14267
+ x: Math.min(Math.max(position.x, FLOATING_LOGO_MARGIN), maxX),
14268
+ y: Math.min(Math.max(position.y, FLOATING_LOGO_MARGIN), maxY)
14269
+ };
14270
+ }
14271
+ function snapFloatingLogoToEdge(position) {
14272
+ const clamped = clampFloatingLogoPosition(position);
14273
+ const maxX = Math.max(
14274
+ FLOATING_LOGO_MARGIN,
14275
+ window.innerWidth - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
14276
+ );
14277
+ const maxY = Math.max(
14278
+ FLOATING_LOGO_MARGIN,
14279
+ window.innerHeight - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
14280
+ );
14281
+ const leftDistance = clamped.x - FLOATING_LOGO_MARGIN;
14282
+ const rightDistance = maxX - clamped.x;
14283
+ const topDistance = clamped.y - FLOATING_LOGO_MARGIN;
14284
+ const bottomDistance = maxY - clamped.y;
14285
+ const nearestDistance = Math.min(leftDistance, rightDistance, topDistance, bottomDistance);
14286
+ if (nearestDistance === leftDistance) return { x: FLOATING_LOGO_MARGIN, y: clamped.y };
14287
+ if (nearestDistance === rightDistance) return { x: maxX, y: clamped.y };
14288
+ if (nearestDistance === topDistance) return { x: clamped.x, y: FLOATING_LOGO_MARGIN };
14289
+ return { x: clamped.x, y: maxY };
14290
+ }
14291
+ function randomFloatingLogoEdgePosition() {
14292
+ const maxX = Math.max(
14293
+ FLOATING_LOGO_MARGIN,
14294
+ window.innerWidth - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
14295
+ );
14296
+ const maxY = Math.max(
14297
+ FLOATING_LOGO_MARGIN,
14298
+ window.innerHeight - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
14299
+ );
14300
+ const randomX = FLOATING_LOGO_MARGIN + Math.random() * (maxX - FLOATING_LOGO_MARGIN);
14301
+ const randomY = FLOATING_LOGO_MARGIN + Math.random() * (maxY - FLOATING_LOGO_MARGIN);
14302
+ const edgeIndex = Math.floor(Math.random() * 4);
14303
+ switch (edgeIndex) {
14304
+ case 0:
14305
+ return { x: FLOATING_LOGO_MARGIN, y: randomY };
14306
+ case 1:
14307
+ return { x: maxX, y: randomY };
14308
+ case 2:
14309
+ return { x: randomX, y: FLOATING_LOGO_MARGIN };
14310
+ case 3:
14311
+ return { x: randomX, y: maxY };
14312
+ default:
14313
+ return { x: maxX, y: FLOATING_LOGO_MARGIN };
14314
+ }
14315
+ }
14316
+ function nearestFloatingLogoEdge(position) {
14317
+ const clamped = clampFloatingLogoPosition(position);
14318
+ const maxX = Math.max(
14319
+ FLOATING_LOGO_MARGIN,
14320
+ window.innerWidth - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
14321
+ );
14322
+ const maxY = Math.max(
14323
+ FLOATING_LOGO_MARGIN,
14324
+ window.innerHeight - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
14325
+ );
14326
+ const distances = [
14327
+ { edge: "left", distance: clamped.x - FLOATING_LOGO_MARGIN },
14328
+ { edge: "right", distance: maxX - clamped.x },
14329
+ { edge: "top", distance: clamped.y - FLOATING_LOGO_MARGIN },
14330
+ { edge: "bottom", distance: maxY - clamped.y }
14331
+ ];
14332
+ return distances.reduce((best, current) => current.distance < best.distance ? current : best).edge;
14333
+ }
14334
+ function nextFloatingLogoWalkingPosition(position) {
14335
+ const clamped = snapFloatingLogoToEdge(position);
14336
+ const maxX = Math.max(
14337
+ FLOATING_LOGO_MARGIN,
14338
+ window.innerWidth - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
14339
+ );
14340
+ const maxY = Math.max(
14341
+ FLOATING_LOGO_MARGIN,
14342
+ window.innerHeight - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
14343
+ );
14344
+ const step = FLOATING_LOGO_MIN_STEP + Math.random() * (FLOATING_LOGO_MAX_STEP - FLOATING_LOGO_MIN_STEP);
14345
+ const direction = Math.random() > 0.5 ? 1 : -1;
14346
+ const edge = nearestFloatingLogoEdge(clamped);
14347
+ switch (edge) {
14348
+ case "left": {
14349
+ const nextY = clamped.y + step * direction;
14350
+ if (nextY <= FLOATING_LOGO_MARGIN)
14351
+ return { x: FLOATING_LOGO_MARGIN, y: FLOATING_LOGO_MARGIN };
14352
+ if (nextY >= maxY) return { x: FLOATING_LOGO_MARGIN, y: maxY };
14353
+ return { x: FLOATING_LOGO_MARGIN, y: nextY };
14354
+ }
14355
+ case "right": {
14356
+ const nextY = clamped.y + step * direction;
14357
+ if (nextY <= FLOATING_LOGO_MARGIN) return { x: maxX, y: FLOATING_LOGO_MARGIN };
14358
+ if (nextY >= maxY) return { x: maxX, y: maxY };
14359
+ return { x: maxX, y: nextY };
14360
+ }
14361
+ case "top": {
14362
+ const nextX = clamped.x + step * direction;
14363
+ if (nextX <= FLOATING_LOGO_MARGIN)
14364
+ return { x: FLOATING_LOGO_MARGIN, y: FLOATING_LOGO_MARGIN };
14365
+ if (nextX >= maxX) return { x: maxX, y: FLOATING_LOGO_MARGIN };
14366
+ return { x: nextX, y: FLOATING_LOGO_MARGIN };
14367
+ }
14368
+ case "bottom": {
14369
+ const nextX = clamped.x + step * direction;
14370
+ if (nextX <= FLOATING_LOGO_MARGIN) return { x: FLOATING_LOGO_MARGIN, y: maxY };
14371
+ if (nextX >= maxX) return { x: maxX, y: maxY };
14372
+ return { x: nextX, y: maxY };
14373
+ }
14374
+ }
14375
+ }
14376
+ function FloatingInspectorLogo() {
14377
+ const [position, setPosition] = reactExports.useState({
14378
+ x: FLOATING_LOGO_MARGIN,
14379
+ y: FLOATING_LOGO_MARGIN
14380
+ });
14381
+ const [motionTick, setMotionTick] = reactExports.useState(0);
14382
+ const [dragging, setDragging] = reactExports.useState(false);
14383
+ const dragStateRef = reactExports.useRef(null);
14384
+ reactExports.useEffect(() => {
14385
+ setPosition(randomFloatingLogoEdgePosition());
14386
+ }, []);
14387
+ reactExports.useEffect(() => {
14388
+ if (dragging) return void 0;
14389
+ let timeoutId = null;
14390
+ const scheduleDrift = () => {
14391
+ const delay = FLOATING_LOGO_MIN_DRIFT_MS + Math.random() * FLOATING_LOGO_DRIFT_WINDOW_MS;
14392
+ timeoutId = window.setTimeout(() => {
14393
+ setMotionTick((current) => current + 1);
14394
+ setPosition((current) => nextFloatingLogoWalkingPosition(current));
14395
+ scheduleDrift();
14396
+ }, delay);
14397
+ };
14398
+ scheduleDrift();
14399
+ return () => {
14400
+ if (timeoutId !== null) {
14401
+ window.clearTimeout(timeoutId);
14402
+ }
14403
+ };
14404
+ }, [dragging]);
14405
+ reactExports.useEffect(() => {
14406
+ const handleResize = () => {
14407
+ setPosition((current) => snapFloatingLogoToEdge(current));
14408
+ };
14409
+ window.addEventListener("resize", handleResize);
14410
+ return () => window.removeEventListener("resize", handleResize);
14411
+ }, []);
14412
+ const handlePointerDown = reactExports.useCallback((event) => {
14413
+ const rect = event.currentTarget.getBoundingClientRect();
14414
+ dragStateRef.current = {
14415
+ pointerId: event.pointerId,
14416
+ offsetX: event.clientX - rect.left,
14417
+ offsetY: event.clientY - rect.top
14418
+ };
14419
+ event.currentTarget.setPointerCapture(event.pointerId);
14420
+ setDragging(true);
14421
+ }, []);
14422
+ const handlePointerMove = reactExports.useCallback((event) => {
14423
+ const dragState = dragStateRef.current;
14424
+ if (dragState === null || dragState.pointerId !== event.pointerId) return;
14425
+ setPosition(
14426
+ clampFloatingLogoPosition({
14427
+ x: event.clientX - dragState.offsetX,
14428
+ y: event.clientY - dragState.offsetY
14429
+ })
14430
+ );
14431
+ }, []);
14432
+ const handlePointerUp = reactExports.useCallback((event) => {
14433
+ const dragState = dragStateRef.current;
14434
+ if (dragState === null || dragState.pointerId !== event.pointerId) return;
14435
+ if (event.currentTarget.hasPointerCapture(event.pointerId)) {
14436
+ event.currentTarget.releasePointerCapture(event.pointerId);
14437
+ }
14438
+ dragStateRef.current = null;
14439
+ setDragging(false);
14440
+ setPosition((current) => snapFloatingLogoToEdge(current));
14441
+ }, []);
14442
+ const style = reactExports.useMemo(
14443
+ () => ({
14444
+ transform: `translate3d(${position.x}px, ${position.y}px, 0) rotate(${motionTick % 2 === 0 ? "-4deg" : "5deg"}) scale(${dragging ? "1.08" : "1"})`,
14445
+ transition: dragging ? "none" : "transform 4800ms cubic-bezier(0.33, 1, 0.68, 1)",
14446
+ touchAction: "none"
14447
+ }),
14448
+ [dragging, motionTick, position.x, position.y]
14449
+ );
14450
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
14451
+ "button",
14452
+ {
14453
+ type: "button",
14454
+ className: cn(
14455
+ "fixed left-0 top-0 z-40 flex size-14 items-center justify-center rounded-full bg-transparent text-foreground outline-none transition-[filter,opacity] duration-200 hover:opacity-95 hover:drop-shadow-[0_0_24px_rgba(245,158,11,0.36)] focus-visible:ring-1 focus-visible:ring-amber-300/55",
14456
+ dragging ? "cursor-grabbing" : "cursor-grab"
14457
+ ),
14458
+ style,
14459
+ onPointerDown: handlePointerDown,
14460
+ onPointerMove: handlePointerMove,
14461
+ onPointerUp: handlePointerUp,
14462
+ onPointerCancel: handlePointerUp,
14463
+ "aria-label": "Floating Inspector logo",
14464
+ title: "Drag Inspector logo",
14465
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
14466
+ "span",
14467
+ {
14468
+ className: cn(
14469
+ "relative flex size-12 items-center justify-center",
14470
+ !dragging && "floating-crab-body"
14471
+ ),
14472
+ "aria-hidden": "true",
14473
+ children: [
14474
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CrabLogo, { className: "relative z-10 size-11 text-amber-500 drop-shadow-[0_0_15px_rgba(245,158,11,0.30)]" }),
14475
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "pointer-events-none absolute inset-x-0 bottom-0 z-0 flex items-end justify-center gap-1 text-amber-400/80", children: [0, 1, 2, 3, 4, 5].map((leg) => /* @__PURE__ */ jsxRuntimeExports.jsx(
14476
+ "span",
14477
+ {
14478
+ className: cn(
14479
+ "floating-crab-leg h-2 w-0.5 rounded-full bg-current shadow-[0_0_7px_rgba(245,158,11,0.24)]",
14480
+ leg < 3 ? "floating-crab-leg-left" : "floating-crab-leg-right",
14481
+ dragging && "animate-none"
14482
+ ),
14483
+ style: {
14484
+ animationDelay: `${leg % 2 === 0 ? 0 : 180}ms`
14485
+ }
14486
+ },
14487
+ leg
14488
+ )) })
14489
+ ]
14490
+ }
14491
+ )
14492
+ }
14493
+ );
14494
+ }
14218
14495
  function SessionContextLogButton({ label, logId }) {
14219
14496
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
14220
14497
  "button",
@@ -14537,8 +14814,9 @@ function ProxyViewer({
14537
14814
  const [importStatus, setImportStatus] = reactExports.useState(null);
14538
14815
  const [importError, setImportError] = reactExports.useState(null);
14539
14816
  const [deleteDialogOpen, setDeleteDialogOpen] = reactExports.useState(false);
14540
- const [deleteStoredData, setDeleteStoredData] = reactExports.useState(false);
14541
14817
  const [deletingCurrentView, setDeletingCurrentView] = reactExports.useState(false);
14818
+ const [detailsPanelCollapsed, setDetailsPanelCollapsed] = reactExports.useState(true);
14819
+ const [detailsPanelStorageLoaded, setDetailsPanelStorageLoaded] = reactExports.useState(false);
14542
14820
  const [comparePair, setComparePair] = reactExports.useState(null);
14543
14821
  const [crabEntrancePhase, setCrabEntrancePhase] = reactExports.useState(
14544
14822
  "hidden"
@@ -14575,6 +14853,17 @@ function ProxyViewer({
14575
14853
  clearTimeout(t2);
14576
14854
  };
14577
14855
  }, []);
14856
+ reactExports.useEffect(() => {
14857
+ setDetailsPanelCollapsed(readStoredDetailsPanelCollapsed());
14858
+ setDetailsPanelStorageLoaded(true);
14859
+ }, []);
14860
+ reactExports.useEffect(() => {
14861
+ if (!detailsPanelStorageLoaded) return;
14862
+ window.localStorage.setItem(
14863
+ DETAILS_PANEL_COLLAPSED_STORAGE_KEY,
14864
+ detailsPanelCollapsed ? "1" : "0"
14865
+ );
14866
+ }, [detailsPanelCollapsed, detailsPanelStorageLoaded]);
14578
14867
  reactExports.useEffect(() => {
14579
14868
  if (pinnedSessionId === void 0) {
14580
14869
  document.title = "Agent Inspector";
@@ -14656,7 +14945,6 @@ function ProxyViewer({
14656
14945
  onClearAll();
14657
14946
  }, [cancelTransientTasks, onClearAll]);
14658
14947
  const handleRequestDeleteCurrentView = reactExports.useCallback(() => {
14659
- setDeleteStoredData(false);
14660
14948
  setDeleteDialogOpen(true);
14661
14949
  }, []);
14662
14950
  const handleConfirmDeleteCurrentView = reactExports.useCallback(() => {
@@ -14664,13 +14952,9 @@ function ProxyViewer({
14664
14952
  setImportStatus(null);
14665
14953
  setImportError(null);
14666
14954
  setComparePair(null);
14667
- if (!deleteStoredData || onDeleteCurrentView === void 0) {
14668
- setDeleteDialogOpen(false);
14669
- onClearAll();
14670
- return;
14671
- }
14955
+ if (onDeleteCurrentView === void 0) return;
14672
14956
  setDeletingCurrentView(true);
14673
- void onDeleteCurrentView(logs.map((log) => log.id)).then(() => {
14957
+ void onDeleteCurrentView().then(() => {
14674
14958
  setDeleteDialogOpen(false);
14675
14959
  }).catch((err) => {
14676
14960
  const message = err instanceof Error ? err.message : "Failed to delete stored logs";
@@ -14682,7 +14966,7 @@ function ProxyViewer({
14682
14966
  }).finally(() => {
14683
14967
  setDeletingCurrentView(false);
14684
14968
  });
14685
- }, [cancelTransientTasks, deleteStoredData, logs, onClearAll, onDeleteCurrentView, onNotify]);
14969
+ }, [cancelTransientTasks, onDeleteCurrentView, onNotify]);
14686
14970
  const handleReloadCurrentSession = reactExports.useCallback(() => {
14687
14971
  if (onReloadSession === void 0) return;
14688
14972
  cancelTransientTasks();
@@ -14694,6 +14978,9 @@ function ProxyViewer({
14694
14978
  const closeCompare = reactExports.useCallback(() => {
14695
14979
  setComparePair(null);
14696
14980
  }, []);
14981
+ const toggleDetailsPanelCollapsed = reactExports.useCallback(() => {
14982
+ setDetailsPanelCollapsed((value) => !value);
14983
+ }, []);
14697
14984
  const groups = reactExports.useMemo(() => groupLogsByConversation(logs), [logs]);
14698
14985
  const displayNumberByLogId = reactExports.useMemo(() => buildDisplayNumberByLogId(groups), [groups]);
14699
14986
  const sessionContextScope = reactExports.useMemo(
@@ -14715,6 +15002,9 @@ function ProxyViewer({
14715
15002
  const exportActionVisibility = getExportActionVisibility(captureMode, logs.length);
14716
15003
  const isPinnedSessionPage = pinnedSessionId !== void 0;
14717
15004
  const canClearCurrentView = logs.length > 0;
15005
+ const canDeleteCurrentView = onDeleteCurrentView !== void 0 && (logs.length > 0 || selectedSession !== "__all__");
15006
+ const deleteTargetLabel = selectedSession === "__all__" ? "all sessions" : "this session";
15007
+ const deleteTargetDescription = selectedSession === "__all__" ? "Deletes every stored log, streaming chunk, and session archive entry across all sessions." : "Deletes every stored log, streaming chunk, and session archive entry for this session, including history that is not currently loaded.";
14718
15008
  const reloadSessionLabel = logs.length === 0 ? "Load" : "Reload";
14719
15009
  const sessionInputValue = selectedSession === "__all__" ? "" : selectedSession;
14720
15010
  const sessionSelectValue = selectedSession === "__all__" || sessions.includes(selectedSession) ? selectedSession : "__typed__";
@@ -14752,376 +15042,341 @@ function ProxyViewer({
14752
15042
  );
14753
15043
  const labSessionId = pinnedSessionId !== void 0 ? pinnedSessionId : selectedSession === "__all__" ? null : selectedSession;
14754
15044
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-background min-h-screen w-full text-foreground", children: [
14755
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid min-h-screen w-full grid-cols-1 lg:grid-cols-[minmax(0,1fr)_340px] xl:grid-cols-[minmax(0,1fr)_360px]", children: [
14756
- /* @__PURE__ */ jsxRuntimeExports.jsx("aside", { className: "bg-background/95 order-1 border-b border-white/[0.045] lg:sticky lg:top-0 lg:order-2 lg:h-screen lg:overflow-y-auto lg:border-b-0 lg:border-l lg:border-white/[0.055]", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4 p-4", children: [
14757
- /* @__PURE__ */ jsxRuntimeExports.jsx(
14758
- BrandHeader,
14759
- {
14760
- compact: true,
14761
- crabEntrancePhase,
14762
- currentSessionId: labSessionId,
14763
- logCount: logs.length
14764
- }
15045
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
15046
+ "button",
15047
+ {
15048
+ type: "button",
15049
+ onClick: toggleDetailsPanelCollapsed,
15050
+ className: cn(
15051
+ "group fixed top-1/2 right-3 z-40 inline-flex h-14 w-7 -translate-y-1/2 items-center justify-center rounded-l-md border border-white/[0.08] bg-background/90 text-muted-foreground shadow-[0_12px_34px_rgba(0,0,0,0.26),inset_0_1px_0_rgba(255,255,255,0.06)] backdrop-blur transition-[right,background-color,color,border-color] duration-200 hover:border-white/[0.16] hover:bg-white/[0.07] hover:text-foreground focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none",
15052
+ detailsPanelCollapsed ? "right-3" : "lg:right-[326px] xl:right-[346px]"
14765
15053
  ),
14766
- /* @__PURE__ */ jsxRuntimeExports.jsxs(SidebarPanel, { label: "Session", children: [
14767
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
14768
- /* @__PURE__ */ jsxRuntimeExports.jsx(SidebarMetric, { label: "Requests", value: logs.length }),
14769
- /* @__PURE__ */ jsxRuntimeExports.jsx(SidebarMetric, { label: "Sessions", value: sessions.length }),
14770
- /* @__PURE__ */ jsxRuntimeExports.jsx(
14771
- SidebarMetric,
14772
- {
14773
- label: "Input",
14774
- value: formatTokens(hasSessionContext ? sessionContextTotalIn : totalIn)
14775
- }
14776
- ),
15054
+ "aria-label": detailsPanelCollapsed ? "Show details panel" : "Hide details panel",
15055
+ title: detailsPanelCollapsed ? "Show details panel" : "Hide details panel",
15056
+ children: [
15057
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "absolute left-1 top-2 bottom-2 w-px rounded-full bg-white/[0.16] transition-colors group-hover:bg-white/[0.28]" }),
15058
+ detailsPanelCollapsed ? /* @__PURE__ */ jsxRuntimeExports.jsx(PanelRightOpen, { className: "size-3.5" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(PanelRightClose, { className: "size-3.5" })
15059
+ ]
15060
+ }
15061
+ ),
15062
+ detailsPanelCollapsed && /* @__PURE__ */ jsxRuntimeExports.jsx(FloatingInspectorLogo, {}),
15063
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
15064
+ "div",
15065
+ {
15066
+ className: cn(
15067
+ "grid min-h-screen w-full grid-cols-1",
15068
+ detailsPanelCollapsed ? "lg:grid-cols-[minmax(0,1fr)]" : "lg:grid-cols-[minmax(0,1fr)_340px] xl:grid-cols-[minmax(0,1fr)_360px]"
15069
+ ),
15070
+ children: [
15071
+ !detailsPanelCollapsed && /* @__PURE__ */ jsxRuntimeExports.jsx("aside", { className: "bg-background/95 order-1 border-b border-white/[0.045] lg:sticky lg:top-0 lg:order-2 lg:h-screen lg:overflow-y-auto lg:border-b-0 lg:border-l lg:border-white/[0.055]", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4 p-4", children: [
14777
15072
  /* @__PURE__ */ jsxRuntimeExports.jsx(
14778
- SidebarMetric,
14779
- {
14780
- label: "Output",
14781
- value: formatTokens(hasSessionContext ? sessionContextTotalOut : totalOut)
14782
- }
14783
- )
14784
- ] }),
14785
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-2 grid grid-cols-2 gap-2", children: [
14786
- onReloadSession !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
14787
- "button",
15073
+ BrandHeader,
14788
15074
  {
14789
- type: "button",
14790
- onClick: handleReloadCurrentSession,
14791
- disabled: isLoading,
14792
- className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 min-w-0 items-center justify-center gap-1.5 rounded-md px-2 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
14793
- title: "Load stored logs for this session",
14794
- children: [
14795
- /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: cn("size-3.5", isLoading && "animate-spin") }),
14796
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: reloadSessionLabel })
14797
- ]
15075
+ compact: true,
15076
+ crabEntrancePhase,
15077
+ currentSessionId: labSessionId,
15078
+ logCount: logs.length
14798
15079
  }
14799
15080
  ),
14800
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
14801
- "button",
14802
- {
14803
- type: "button",
14804
- onClick: handleClearCurrentView,
14805
- disabled: !canClearCurrentView,
14806
- className: cn(
14807
- "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 min-w-0 items-center justify-center gap-1.5 rounded-md px-2 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
14808
- onReloadSession === void 0 && onDeleteCurrentView === void 0 && "col-span-2"
15081
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(SidebarPanel, { label: "Session", children: [
15082
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
15083
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SidebarMetric, { label: "Requests", value: logs.length }),
15084
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SidebarMetric, { label: "Sessions", value: sessions.length }),
15085
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
15086
+ SidebarMetric,
15087
+ {
15088
+ label: "Input",
15089
+ value: formatTokens(hasSessionContext ? sessionContextTotalIn : totalIn)
15090
+ }
14809
15091
  ),
14810
- title: "Clear the current view. Stored logs remain reloadable.",
14811
- children: [
14812
- /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" }),
14813
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Clear" })
14814
- ]
14815
- }
14816
- ),
14817
- onDeleteCurrentView !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
14818
- "button",
14819
- {
14820
- type: "button",
14821
- onClick: handleRequestDeleteCurrentView,
14822
- disabled: !canClearCurrentView || deletingCurrentView,
14823
- className: "bg-red-500/[0.07] hover:bg-red-500/[0.12] inline-flex h-8 min-w-0 items-center justify-center gap-1.5 rounded-md px-2 text-xs text-red-200 shadow-[inset_0_0_0_1px_rgba(248,113,113,0.14)] transition-colors hover:text-red-100 disabled:cursor-not-allowed disabled:opacity-50",
14824
- title: "Choose whether to delete stored data for the current view.",
14825
- children: [
14826
- /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" }),
14827
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Delete" })
14828
- ]
14829
- }
14830
- )
14831
- ] }),
14832
- sessionLoadProgress !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 rounded-md bg-black/20 px-2 py-2 shadow-[inset_0_0_0_1px_rgba(255,255,255,0.045)]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SessionLoadProgressBar, { progress: sessionLoadProgress }) })
14833
- ] }),
14834
- /* @__PURE__ */ jsxRuntimeExports.jsx(SidebarPanel, { label: "Workspace", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-black/20 rounded-md px-3 py-2 shadow-[inset_0_1px_0_rgba(255,255,255,0.035)]", children: [
14835
- /* @__PURE__ */ jsxRuntimeExports.jsx(
14836
- "div",
14837
- {
14838
- className: "truncate font-mono text-xs font-semibold text-cyan-100",
14839
- title: activeScopeLabel,
14840
- children: activeScopeLabel
14841
- }
14842
- ),
14843
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1 text-[11px] text-muted-foreground", children: isPinnedSessionPage ? "Session workspace" : "Live workspace" })
14844
- ] }) }),
14845
- hasSessionContext && sessionContextScope !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(
14846
- SessionContextBar,
14847
- {
14848
- label: sessionContextScope.label,
14849
- logs: sessionContextLogs,
14850
- totalIn: sessionContextTotalIn,
14851
- totalOut: sessionContextTotalOut,
14852
- timeDisplayFormat,
14853
- contextSummary: sessionContextSummary,
14854
- showBackLink: sessionContextScope.showBackLink
14855
- }
14856
- ),
14857
- hasSessionContext && pinnedSessionId !== void 0 && sessionMemberships.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(SessionMembershipPanel, { memberships: sessionMemberships }),
14858
- /* @__PURE__ */ jsxRuntimeExports.jsx(SidebarPanel, { label: "Filters", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
14859
- !hideSessionFilter && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
14860
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative", children: [
14861
- /* @__PURE__ */ jsxRuntimeExports.jsx(Search, { className: "pointer-events-none absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground" }),
14862
- /* @__PURE__ */ jsxRuntimeExports.jsx(
14863
- "input",
14864
- {
14865
- type: "search",
14866
- value: sessionInputValue,
14867
- onChange: handleSessionInputChange,
14868
- placeholder: "Paste session ID",
14869
- className: "bg-black/25 hover:bg-white/[0.045] focus-visible:ring-ring h-9 w-full rounded-md px-8 font-mono text-xs text-foreground outline-none shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors placeholder:font-sans placeholder:text-muted-foreground focus-visible:ring-1",
14870
- "aria-label": "Filter by session ID",
14871
- title: "Filter by exact session ID"
14872
- }
14873
- ),
14874
- sessionInputValue !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx(
14875
- "button",
14876
- {
14877
- type: "button",
14878
- onClick: () => onSessionChange("__all__"),
14879
- className: "absolute right-1.5 top-1/2 inline-flex size-6 -translate-y-1/2 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-white/[0.06] hover:text-foreground",
14880
- "aria-label": "Clear session filter",
14881
- title: "Clear session filter",
14882
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "size-3.5" })
14883
- }
14884
- )
14885
- ] }),
14886
- /* @__PURE__ */ jsxRuntimeExports.jsxs(Select, { value: sessionSelectValue, onValueChange: handleSessionSelectChange, children: [
14887
- /* @__PURE__ */ jsxRuntimeExports.jsx(SelectTrigger, { className: "bg-black/25 hover:bg-white/[0.045] h-9 w-full border-0 text-xs text-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue, { placeholder: "All sessions" }) }),
14888
- /* @__PURE__ */ jsxRuntimeExports.jsxs(SelectContent, { children: [
14889
- /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: "__all__", children: "All sessions" }),
14890
- sessionSelectValue === "__typed__" && /* @__PURE__ */ jsxRuntimeExports.jsxs(SelectItem, { value: "__typed__", children: [
14891
- "Typed: ",
14892
- truncateSessionId(selectedSession)
14893
- ] }),
14894
- sessions.map((s) => /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: s, children: truncateSessionId(s) }, s))
14895
- ] })
14896
- ] })
14897
- ] }),
14898
- /* @__PURE__ */ jsxRuntimeExports.jsxs(Select, { value: selectedModel, onValueChange: onModelChange, children: [
14899
- /* @__PURE__ */ jsxRuntimeExports.jsx(SelectTrigger, { className: "bg-black/25 hover:bg-white/[0.045] h-9 w-full border-0 text-xs text-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue, { placeholder: "All models" }) }),
14900
- /* @__PURE__ */ jsxRuntimeExports.jsxs(SelectContent, { children: [
14901
- /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: "__all__", children: "All models" }),
14902
- models.map((m) => /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: m, children: m }, m))
14903
- ] })
14904
- ] })
14905
- ] }) })
14906
- ] }) }),
14907
- /* @__PURE__ */ jsxRuntimeExports.jsxs("main", { className: "order-2 min-w-0 lg:order-1", children: [
14908
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-background/95 shadow-[0_12px_36px_rgba(0,0,0,0.18),inset_0_-1px_0_rgba(255,255,255,0.045)] sticky top-0 z-30 px-4 py-3 lg:px-5", children: [
14909
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
14910
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-[180px] flex-1", children: [
14911
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm font-semibold text-foreground", children: "Logs" }),
14912
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-0.5 font-mono text-[11px] text-muted-foreground", children: activeScopeLabel })
15092
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
15093
+ SidebarMetric,
15094
+ {
15095
+ label: "Output",
15096
+ value: formatTokens(hasSessionContext ? sessionContextTotalOut : totalOut)
15097
+ }
15098
+ )
15099
+ ] }),
15100
+ sessionLoadProgress !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 rounded-md bg-black/20 px-2 py-2 shadow-[inset_0_0_0_1px_rgba(255,255,255,0.045)]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SessionLoadProgressBar, { progress: sessionLoadProgress }) })
14913
15101
  ] }),
14914
- onImportLogs !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
15102
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SidebarPanel, { label: "Workspace", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-black/20 rounded-md px-3 py-2 shadow-[inset_0_1px_0_rgba(255,255,255,0.035)]", children: [
14915
15103
  /* @__PURE__ */ jsxRuntimeExports.jsx(
14916
- "input",
15104
+ "div",
14917
15105
  {
14918
- ref: importInputRef,
14919
- type: "file",
14920
- accept: ".zip,.json,.jsonl,application/zip,application/json",
14921
- className: "hidden",
14922
- onChange: handleImportFileChange
15106
+ className: "truncate font-mono text-xs font-semibold text-cyan-100",
15107
+ title: activeScopeLabel,
15108
+ children: activeScopeLabel
14923
15109
  }
14924
15110
  ),
14925
- /* @__PURE__ */ jsxRuntimeExports.jsx(
14926
- "button",
14927
- {
14928
- type: "button",
14929
- onClick: handleImportClick,
14930
- disabled: importing,
14931
- className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
14932
- title: "Import Agent Inspector export",
14933
- children: importing ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Importing..." }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
14934
- /* @__PURE__ */ jsxRuntimeExports.jsx(Upload, { className: "size-3.5" }),
14935
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Import" })
14936
- ] })
14937
- }
14938
- )
14939
- ] }),
14940
- exportActionVisibility.redacted && /* @__PURE__ */ jsxRuntimeExports.jsx(
14941
- "button",
15111
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1 text-[11px] text-muted-foreground", children: isPinnedSessionPage ? "Session workspace" : "Live workspace" })
15112
+ ] }) }),
15113
+ hasSessionContext && sessionContextScope !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(
15114
+ SessionContextBar,
14942
15115
  {
14943
- type: "button",
14944
- onClick: () => {
14945
- void handleExport("redacted");
14946
- },
14947
- disabled: exporting !== null,
14948
- className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
14949
- title: "Export redacted logs as JSON ZIP",
14950
- children: exporting === "redacted" ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Exporting..." }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
14951
- /* @__PURE__ */ jsxRuntimeExports.jsx(Download, { className: "size-3.5" }),
14952
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Export" })
14953
- ] })
15116
+ label: sessionContextScope.label,
15117
+ logs: sessionContextLogs,
15118
+ totalIn: sessionContextTotalIn,
15119
+ totalOut: sessionContextTotalOut,
15120
+ timeDisplayFormat,
15121
+ contextSummary: sessionContextSummary,
15122
+ showBackLink: sessionContextScope.showBackLink
14954
15123
  }
14955
15124
  ),
14956
- exportActionVisibility.raw && /* @__PURE__ */ jsxRuntimeExports.jsx(
14957
- "button",
14958
- {
14959
- type: "button",
14960
- onClick: () => {
14961
- void handleExport("raw");
14962
- },
14963
- disabled: exporting !== null,
14964
- className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-2.5 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
14965
- title: "Export raw logs without redaction",
14966
- children: exporting === "raw" ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Exporting..." }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
14967
- /* @__PURE__ */ jsxRuntimeExports.jsx(FileBraces, { className: "size-3.5" }),
14968
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Raw" })
15125
+ hasSessionContext && pinnedSessionId !== void 0 && sessionMemberships.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(SessionMembershipPanel, { memberships: sessionMemberships }),
15126
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SidebarPanel, { label: "Filters", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
15127
+ !hideSessionFilter && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
15128
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative", children: [
15129
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Search, { className: "pointer-events-none absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground" }),
15130
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
15131
+ "input",
15132
+ {
15133
+ type: "search",
15134
+ value: sessionInputValue,
15135
+ onChange: handleSessionInputChange,
15136
+ placeholder: "Paste session ID",
15137
+ className: "bg-black/25 hover:bg-white/[0.045] focus-visible:ring-ring h-9 w-full rounded-md px-8 font-mono text-xs text-foreground outline-none shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors placeholder:font-sans placeholder:text-muted-foreground focus-visible:ring-1",
15138
+ "aria-label": "Filter by session ID",
15139
+ title: "Filter by exact session ID"
15140
+ }
15141
+ ),
15142
+ sessionInputValue !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx(
15143
+ "button",
15144
+ {
15145
+ type: "button",
15146
+ onClick: () => onSessionChange("__all__"),
15147
+ className: "absolute right-1.5 top-1/2 inline-flex size-6 -translate-y-1/2 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-white/[0.06] hover:text-foreground",
15148
+ "aria-label": "Clear session filter",
15149
+ title: "Clear session filter",
15150
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "size-3.5" })
15151
+ }
15152
+ )
15153
+ ] }),
15154
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Select, { value: sessionSelectValue, onValueChange: handleSessionSelectChange, children: [
15155
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SelectTrigger, { className: "bg-black/25 hover:bg-white/[0.045] h-9 w-full border-0 text-xs text-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue, { placeholder: "All sessions" }) }),
15156
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(SelectContent, { children: [
15157
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: "__all__", children: "All sessions" }),
15158
+ sessionSelectValue === "__typed__" && /* @__PURE__ */ jsxRuntimeExports.jsxs(SelectItem, { value: "__typed__", children: [
15159
+ "Typed: ",
15160
+ truncateSessionId(selectedSession)
15161
+ ] }),
15162
+ sessions.map((s) => /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: s, children: truncateSessionId(s) }, s))
15163
+ ] })
14969
15164
  ] })
14970
- }
14971
- ),
14972
- onReloadSession !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
14973
- "button",
14974
- {
14975
- type: "button",
14976
- onClick: handleReloadCurrentSession,
14977
- disabled: isLoading,
14978
- className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
14979
- title: "Reload this session from stored logs",
14980
- children: [
14981
- /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: cn("size-3.5", isLoading && "animate-spin") }),
14982
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: reloadSessionLabel })
14983
- ]
14984
- }
14985
- ),
14986
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
14987
- "button",
14988
- {
14989
- type: "button",
14990
- onClick: handleClearCurrentView,
14991
- disabled: !canClearCurrentView,
14992
- className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
14993
- title: "Clear the current view. Stored logs remain reloadable.",
14994
- children: [
14995
- /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" }),
14996
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Clear" })
14997
- ]
14998
- }
14999
- ),
15000
- onDeleteCurrentView !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
15001
- "button",
15002
- {
15003
- type: "button",
15004
- onClick: handleRequestDeleteCurrentView,
15005
- disabled: !canClearCurrentView || deletingCurrentView,
15006
- className: "bg-red-500/[0.07] hover:bg-red-500/[0.12] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-red-200 shadow-[inset_0_0_0_1px_rgba(248,113,113,0.14)] transition-colors hover:text-red-100 disabled:cursor-not-allowed disabled:opacity-50",
15007
- title: "Choose whether to delete stored data for the current view.",
15008
- children: [
15009
- /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" }),
15010
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Delete" })
15011
- ]
15012
- }
15013
- )
15014
- ] }),
15015
- pagination === void 0 && sessionLoadProgress !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 rounded-md bg-black/20 px-2 py-2 shadow-[inset_0_0_0_1px_rgba(255,255,255,0.045)]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SessionLoadProgressBar, { progress: sessionLoadProgress }) }),
15016
- /* @__PURE__ */ jsxRuntimeExports.jsx(LogPaginationBar, { logs, pagination, embedded: true }),
15017
- onNotify === void 0 && 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 }),
15018
- onNotify === void 0 && importError !== 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: importError }),
15019
- onNotify === void 0 && importStatus !== null && importError === null && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 rounded-md border border-cyan-400/25 bg-cyan-500/10 px-3 py-2 text-xs text-cyan-100", children: importStatus })
15020
- ] }),
15021
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-4 lg:px-5", children: [
15022
- /* @__PURE__ */ jsxRuntimeExports.jsx(SessionOpeningSlate, { stats: slateStats }),
15023
- logs.length === 0 ? selectedSession !== "__all__" ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "py-16 text-center text-muted-foreground", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-white/[0.035] shadow-[inset_0_1px_0_rgba(255,255,255,0.045),0_18px_52px_rgba(0,0,0,0.18)] mx-auto max-w-xl space-y-4 rounded-[8px] px-4 py-8", children: [
15024
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-medium", children: isLoading ? "Loading session data..." : "No logs loaded for this session" }),
15025
- /* @__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) }),
15026
- sessionLoadProgress !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mx-auto max-w-md rounded-md bg-black/20 px-2 py-2 text-left shadow-[inset_0_0_0_1px_rgba(255,255,255,0.045)]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SessionLoadProgressBar, { progress: sessionLoadProgress }) }),
15027
- sessionMemberships.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-left", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SessionMembershipPanel, { memberships: sessionMemberships }) }),
15028
- !isLoading && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center gap-3 text-xs", children: [
15029
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Stored logs may still be available." }),
15030
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center justify-center gap-2", children: [
15165
+ ] }),
15166
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Select, { value: selectedModel, onValueChange: onModelChange, children: [
15167
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SelectTrigger, { className: "bg-black/25 hover:bg-white/[0.045] h-9 w-full border-0 text-xs text-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue, { placeholder: "All models" }) }),
15168
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(SelectContent, { children: [
15169
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: "__all__", children: "All models" }),
15170
+ models.map((m) => /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: m, children: m }, m))
15171
+ ] })
15172
+ ] })
15173
+ ] }) })
15174
+ ] }) }),
15175
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("main", { className: "order-2 min-w-0 lg:order-1", children: [
15176
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-background/95 shadow-[0_12px_36px_rgba(0,0,0,0.18),inset_0_-1px_0_rgba(255,255,255,0.045)] sticky top-0 z-30 px-4 py-3 lg:px-5", children: [
15177
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
15178
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-[180px] flex-1", children: [
15179
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm font-semibold text-foreground", children: "Logs" }),
15180
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-0.5 font-mono text-[11px] text-muted-foreground", children: activeScopeLabel })
15181
+ ] }),
15182
+ onImportLogs !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
15183
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
15184
+ "input",
15185
+ {
15186
+ ref: importInputRef,
15187
+ type: "file",
15188
+ accept: ".zip,.json,.jsonl,application/zip,application/json",
15189
+ className: "hidden",
15190
+ onChange: handleImportFileChange
15191
+ }
15192
+ ),
15193
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
15194
+ "button",
15195
+ {
15196
+ type: "button",
15197
+ onClick: handleImportClick,
15198
+ disabled: importing,
15199
+ className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
15200
+ title: "Import Agent Inspector export",
15201
+ children: importing ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Importing..." }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
15202
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Upload, { className: "size-3.5" }),
15203
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Import" })
15204
+ ] })
15205
+ }
15206
+ )
15207
+ ] }),
15208
+ exportActionVisibility.redacted && /* @__PURE__ */ jsxRuntimeExports.jsx(
15209
+ "button",
15210
+ {
15211
+ type: "button",
15212
+ onClick: () => {
15213
+ void handleExport("redacted");
15214
+ },
15215
+ disabled: exporting !== null,
15216
+ className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
15217
+ title: "Export redacted logs as JSON ZIP",
15218
+ children: exporting === "redacted" ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Exporting..." }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
15219
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Download, { className: "size-3.5" }),
15220
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Export" })
15221
+ ] })
15222
+ }
15223
+ ),
15224
+ exportActionVisibility.raw && /* @__PURE__ */ jsxRuntimeExports.jsx(
15225
+ "button",
15226
+ {
15227
+ type: "button",
15228
+ onClick: () => {
15229
+ void handleExport("raw");
15230
+ },
15231
+ disabled: exporting !== null,
15232
+ className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-2.5 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
15233
+ title: "Export raw logs without redaction",
15234
+ children: exporting === "raw" ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Exporting..." }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
15235
+ /* @__PURE__ */ jsxRuntimeExports.jsx(FileBraces, { className: "size-3.5" }),
15236
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Raw" })
15237
+ ] })
15238
+ }
15239
+ ),
15031
15240
  onReloadSession !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
15032
15241
  "button",
15033
15242
  {
15034
15243
  type: "button",
15035
15244
  onClick: handleReloadCurrentSession,
15036
- className: "bg-white/[0.045] hover:bg-white/[0.075] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground",
15245
+ disabled: isLoading,
15246
+ className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
15247
+ title: "Reload this session from stored logs",
15037
15248
  children: [
15038
- /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: "size-3.5" }),
15039
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Load session" })
15249
+ /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: cn("size-3.5", isLoading && "animate-spin") }),
15250
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: reloadSessionLabel })
15040
15251
  ]
15041
15252
  }
15042
15253
  ),
15043
- hideSessionFilter ? /* @__PURE__ */ jsxRuntimeExports.jsx(
15044
- "a",
15254
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
15255
+ "button",
15045
15256
  {
15046
- href: "/",
15047
- className: "inline-flex h-8 items-center rounded-md px-3 text-xs text-muted-foreground underline transition-colors hover:text-foreground",
15048
- children: "Back to all sessions"
15257
+ type: "button",
15258
+ onClick: handleClearCurrentView,
15259
+ disabled: !canClearCurrentView,
15260
+ className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
15261
+ title: "Clear the current view. Stored logs remain reloadable.",
15262
+ children: [
15263
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" }),
15264
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Clear" })
15265
+ ]
15049
15266
  }
15050
- ) : /* @__PURE__ */ jsxRuntimeExports.jsx(
15267
+ ),
15268
+ onDeleteCurrentView !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
15051
15269
  "button",
15052
15270
  {
15053
15271
  type: "button",
15054
- onClick: () => onSessionChange("__all__"),
15055
- className: "inline-flex h-8 items-center rounded-md px-3 text-xs text-muted-foreground underline transition-colors hover:text-foreground",
15056
- children: "Show all sessions"
15272
+ onClick: handleRequestDeleteCurrentView,
15273
+ disabled: !canDeleteCurrentView || deletingCurrentView,
15274
+ className: "bg-red-500/[0.07] hover:bg-red-500/[0.12] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-red-200 shadow-[inset_0_0_0_1px_rgba(248,113,113,0.14)] transition-colors hover:text-red-100 disabled:cursor-not-allowed disabled:opacity-50",
15275
+ title: "Delete persisted history for the selected session.",
15276
+ children: [
15277
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" }),
15278
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Delete" })
15279
+ ]
15057
15280
  }
15058
15281
  )
15059
- ] })
15060
- ] })
15061
- ] }) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "py-16 text-center text-muted-foreground", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-white/[0.035] shadow-[inset_0_1px_0_rgba(255,255,255,0.045),0_18px_52px_rgba(0,0,0,0.18)] mx-auto max-w-2xl space-y-4 rounded-[8px] px-4 py-8", children: [
15062
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm", children: "No logs loaded in the current view." }),
15063
- sessions.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mx-auto max-w-xl text-xs leading-relaxed text-muted-foreground", children: "Pick a session from the filter panel to load stored logs on demand." }),
15064
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center gap-2", children: [
15065
- /* @__PURE__ */ jsxRuntimeExports.jsx(CopyableCommand, { command: "ANTHROPIC_BASE_URL=http://localhost:9527/proxy <your-tool>" }),
15066
- /* @__PURE__ */ jsxRuntimeExports.jsx(CopyableCommand, { command: "OPENAI_BASE_URL=http://localhost:9527/proxy <your-tool>" })
15282
+ ] }),
15283
+ pagination === void 0 && sessionLoadProgress !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 rounded-md bg-black/20 px-2 py-2 shadow-[inset_0_0_0_1px_rgba(255,255,255,0.045)]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SessionLoadProgressBar, { progress: sessionLoadProgress }) }),
15284
+ /* @__PURE__ */ jsxRuntimeExports.jsx(LogPaginationBar, { logs, pagination, embedded: true }),
15285
+ onNotify === void 0 && 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 }),
15286
+ onNotify === void 0 && importError !== 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: importError }),
15287
+ onNotify === void 0 && importStatus !== null && importError === null && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 rounded-md border border-cyan-400/25 bg-cyan-500/10 px-3 py-2 text-xs text-cyan-100", children: importStatus })
15067
15288
  ] }),
15068
- /* @__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." })
15069
- ] }) }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(
15070
- "div",
15071
- {
15072
- ref: logListWrapperRef,
15073
- tabIndex: 0,
15074
- className: "flex flex-col gap-2 focus:outline-none",
15075
- children: [
15076
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: logListRef, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
15077
- ConversationGroupList,
15078
- {
15079
- groups,
15080
- viewMode,
15081
- strip,
15082
- slowResponseThresholdSeconds,
15083
- cacheTrends,
15084
- onCompareWithPrevious: handleCompareWithPrevious,
15085
- comparisonPredecessors,
15086
- onClearGroup,
15087
- defaultExpanded: groups.length === 1,
15088
- timeDisplayFormat
15089
- }
15090
- ) }),
15091
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-3", children: /* @__PURE__ */ jsxRuntimeExports.jsx(LogPaginationBar, { logs, pagination }) })
15092
- ]
15093
- }
15094
- )
15095
- ] })
15096
- ] })
15097
- ] }),
15289
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-4 lg:px-5", children: [
15290
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SessionOpeningSlate, { stats: slateStats }),
15291
+ logs.length === 0 ? selectedSession !== "__all__" ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "py-16 text-center text-muted-foreground", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-white/[0.035] shadow-[inset_0_1px_0_rgba(255,255,255,0.045),0_18px_52px_rgba(0,0,0,0.18)] mx-auto max-w-xl space-y-4 rounded-[8px] px-4 py-8", children: [
15292
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-medium", children: isLoading ? "Loading session data..." : "No logs loaded for this session" }),
15293
+ /* @__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) }),
15294
+ sessionLoadProgress !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mx-auto max-w-md rounded-md bg-black/20 px-2 py-2 text-left shadow-[inset_0_0_0_1px_rgba(255,255,255,0.045)]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SessionLoadProgressBar, { progress: sessionLoadProgress }) }),
15295
+ sessionMemberships.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-left", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SessionMembershipPanel, { memberships: sessionMemberships }) }),
15296
+ !isLoading && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center gap-3 text-xs", children: [
15297
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Stored logs may still be available." }),
15298
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center justify-center gap-2", children: [
15299
+ onReloadSession !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
15300
+ "button",
15301
+ {
15302
+ type: "button",
15303
+ onClick: handleReloadCurrentSession,
15304
+ className: "bg-white/[0.045] hover:bg-white/[0.075] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground",
15305
+ children: [
15306
+ /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: "size-3.5" }),
15307
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Load session" })
15308
+ ]
15309
+ }
15310
+ ),
15311
+ hideSessionFilter ? /* @__PURE__ */ jsxRuntimeExports.jsx(
15312
+ "a",
15313
+ {
15314
+ href: "/",
15315
+ className: "inline-flex h-8 items-center rounded-md px-3 text-xs text-muted-foreground underline transition-colors hover:text-foreground",
15316
+ children: "Back to all sessions"
15317
+ }
15318
+ ) : /* @__PURE__ */ jsxRuntimeExports.jsx(
15319
+ "button",
15320
+ {
15321
+ type: "button",
15322
+ onClick: () => onSessionChange("__all__"),
15323
+ className: "inline-flex h-8 items-center rounded-md px-3 text-xs text-muted-foreground underline transition-colors hover:text-foreground",
15324
+ children: "Show all sessions"
15325
+ }
15326
+ )
15327
+ ] })
15328
+ ] })
15329
+ ] }) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "py-16 text-center text-muted-foreground", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-white/[0.035] shadow-[inset_0_1px_0_rgba(255,255,255,0.045),0_18px_52px_rgba(0,0,0,0.18)] mx-auto max-w-2xl space-y-4 rounded-[8px] px-4 py-8", children: [
15330
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm", children: "No logs loaded in the current view." }),
15331
+ sessions.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mx-auto max-w-xl text-xs leading-relaxed text-muted-foreground", children: "Pick a session from the filter panel to load stored logs on demand." }),
15332
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center gap-2", children: [
15333
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CopyableCommand, { command: "ANTHROPIC_BASE_URL=http://localhost:9527/proxy <your-tool>" }),
15334
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CopyableCommand, { command: "OPENAI_BASE_URL=http://localhost:9527/proxy <your-tool>" })
15335
+ ] }),
15336
+ /* @__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." })
15337
+ ] }) }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(
15338
+ "div",
15339
+ {
15340
+ ref: logListWrapperRef,
15341
+ tabIndex: 0,
15342
+ className: "flex flex-col gap-2 focus:outline-none",
15343
+ children: [
15344
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: logListRef, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
15345
+ ConversationGroupList,
15346
+ {
15347
+ groups,
15348
+ viewMode,
15349
+ strip,
15350
+ slowResponseThresholdSeconds,
15351
+ cacheTrends,
15352
+ onCompareWithPrevious: handleCompareWithPrevious,
15353
+ comparisonPredecessors,
15354
+ onClearGroup,
15355
+ defaultExpanded: groups.length === 1,
15356
+ timeDisplayFormat
15357
+ }
15358
+ ) }),
15359
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-3", children: /* @__PURE__ */ jsxRuntimeExports.jsx(LogPaginationBar, { logs, pagination }) })
15360
+ ]
15361
+ }
15362
+ )
15363
+ ] })
15364
+ ] })
15365
+ ]
15366
+ }
15367
+ ),
15098
15368
  /* @__PURE__ */ jsxRuntimeExports.jsx(Dialog, { open: deleteDialogOpen, onOpenChange: setDeleteDialogOpen, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogContent, { className: "border-red-500/20 bg-zinc-950 text-zinc-100 sm:max-w-md", children: [
15099
15369
  /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogHeader, { children: [
15100
- /* @__PURE__ */ jsxRuntimeExports.jsx(DialogTitle, { children: "Delete current logs?" }),
15101
- /* @__PURE__ */ jsxRuntimeExports.jsx(DialogDescription, { children: "Choose whether this only clears the UI or also deletes the stored log data for the current view." })
15370
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogTitle, { children: [
15371
+ "Delete ",
15372
+ deleteTargetLabel,
15373
+ " history?"
15374
+ ] }),
15375
+ /* @__PURE__ */ jsxRuntimeExports.jsx(DialogDescription, { children: "Clear only hides logs from the UI. Delete removes stored history from disk." })
15102
15376
  ] }),
15103
- /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "flex items-start gap-3 rounded-md bg-red-500/[0.08] px-3 py-3 text-sm text-red-100 shadow-[inset_0_0_0_1px_rgba(248,113,113,0.16)]", children: [
15104
- /* @__PURE__ */ jsxRuntimeExports.jsx(
15105
- "input",
15106
- {
15107
- type: "checkbox",
15108
- className: "mt-0.5 size-4 shrink-0",
15109
- checked: deleteStoredData,
15110
- disabled: deletingCurrentView,
15111
- onChange: (event) => setDeleteStoredData(event.currentTarget.checked)
15112
- }
15113
- ),
15114
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "min-w-0", children: [
15115
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "block font-medium", children: "Also delete stored data" }),
15116
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "mt-1 block text-xs text-red-200/80", children: [
15117
- "Removes persisted log rows, streaming chunks, and session archive entries for these",
15118
- " ",
15119
- logs.length.toString(),
15120
- " visible request",
15121
- logs.length === 1 ? "" : "s",
15122
- "."
15123
- ] })
15124
- ] })
15377
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-md bg-red-500/[0.08] px-3 py-3 text-sm text-red-100 shadow-[inset_0_0_0_1px_rgba(248,113,113,0.16)]", children: [
15378
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "block font-medium", children: "This is a full history delete." }),
15379
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "mt-1 block text-xs text-red-200/80", children: deleteTargetDescription })
15125
15380
  ] }),
15126
15381
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-end gap-2", children: [
15127
15382
  /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -15139,11 +15394,11 @@ function ProxyViewer({
15139
15394
  Button,
15140
15395
  {
15141
15396
  type: "button",
15142
- variant: deleteStoredData ? "destructive" : "secondary",
15397
+ variant: "destructive",
15143
15398
  size: "sm",
15144
15399
  disabled: deletingCurrentView,
15145
15400
  onClick: handleConfirmDeleteCurrentView,
15146
- children: deletingCurrentView ? "Deleting..." : deleteStoredData ? "Delete data" : "Clear only"
15401
+ children: deletingCurrentView ? "Deleting..." : "Delete history"
15147
15402
  }
15148
15403
  )
15149
15404
  ] })
@@ -15280,6 +15535,38 @@ function fetchSessionLogsPage(sessionId, request, limit = SESSION_PAGE_LIMIT) {
15280
15535
  SESSION_LOGS_FETCH_TIMEOUT_MS
15281
15536
  );
15282
15537
  }
15538
+ async function collectSessionLogIds(sessionId, onProgress) {
15539
+ const ids = /* @__PURE__ */ new Set();
15540
+ let page = await fetchSessionLogsPage(sessionId, { kind: "oldest" }, SESSION_RELOAD_PAGE_LIMIT);
15541
+ for (const log of page.logs) {
15542
+ ids.add(log.id);
15543
+ }
15544
+ onProgress(ids.size, 1);
15545
+ let loadedPages = 1;
15546
+ while (page.hasNewer && page.newestLogId !== null && loadedPages < MAX_SESSION_RELOAD_PAGES) {
15547
+ page = await fetchSessionLogsPage(
15548
+ sessionId,
15549
+ { kind: "newer", afterLogId: page.newestLogId },
15550
+ SESSION_RELOAD_PAGE_LIMIT
15551
+ );
15552
+ for (const log of page.logs) {
15553
+ ids.add(log.id);
15554
+ }
15555
+ loadedPages += 1;
15556
+ onProgress(ids.size, loadedPages);
15557
+ }
15558
+ return { ids: [...ids], truncated: page.hasNewer };
15559
+ }
15560
+ async function deleteAllGroupsForFullHistoryDelete() {
15561
+ try {
15562
+ const result = await fetchJson("/api/groups", DeleteInspectorGroupsResponseSchema, {
15563
+ method: "DELETE"
15564
+ });
15565
+ return { deleted: result.deleted, ok: true };
15566
+ } catch {
15567
+ return { deleted: 0, ok: false };
15568
+ }
15569
+ }
15283
15570
  function mergeLogsById(previousLogs, incomingLogs) {
15284
15571
  if (incomingLogs.length === 0) return [...previousLogs];
15285
15572
  const byId = /* @__PURE__ */ new Map();
@@ -15696,43 +15983,107 @@ function ProxyViewerContainer({
15696
15983
  },
15697
15984
  [showToast]
15698
15985
  );
15699
- const handleDeleteCurrentView = reactExports.useCallback(
15700
- async (ids) => {
15701
- if (ids.length === 0) return;
15702
- const persistedIds = ids.filter((id) => Number.isInteger(id) && id >= 0);
15986
+ const handleDeleteCurrentView = reactExports.useCallback(async () => {
15987
+ const deleteRequestId = sessionPageRequestIdRef.current + 1;
15988
+ sessionPageRequestIdRef.current = deleteRequestId;
15989
+ setSessionPageLoading(true);
15990
+ stopSessionLoadProgress();
15991
+ dismissToast();
15992
+ try {
15993
+ if (selectedSession === "__all__") {
15994
+ startSessionLoadProgress("Deleting stored history", deleteRequestId);
15995
+ const result2 = await fetchJson("/api/logs", DeleteLogsResponseSchema, {
15996
+ method: "DELETE"
15997
+ });
15998
+ const groupCleanup = await deleteAllGroupsForFullHistoryDelete();
15999
+ if (sessionPageRequestIdRef.current !== deleteRequestId) return;
16000
+ setAllLogs([]);
16001
+ logIndexRef.current.clear();
16002
+ setLogPage(null);
16003
+ setKnownSessions([]);
16004
+ setSessionMemberships([]);
16005
+ setSessionPageLoading(false);
16006
+ stopSessionLoadProgress();
16007
+ const groupMessage = groupCleanup.ok ? ` Cleared ${groupCleanup.deleted.toString()} group${groupCleanup.deleted === 1 ? "" : "s"}.` : " Group cleanup failed; open Groups to retry Clear.";
16008
+ showToast({
16009
+ message: `Deleted ${result2.cleared.toString()} stored log${result2.cleared === 1 ? "" : "s"} across all sessions.${groupMessage}`,
16010
+ tone: groupCleanup.ok ? "success" : "error"
16011
+ });
16012
+ return;
16013
+ }
16014
+ const sessionId = selectedSession;
16015
+ startSessionLoadProgress("Deleting session history", deleteRequestId);
16016
+ const collected = await collectSessionLogIds(sessionId, (logCount, pageCount) => {
16017
+ updateSessionLoadProgress("Deleting session history", deleteRequestId, logCount, pageCount);
16018
+ });
16019
+ const idSet = new Set(collected.ids);
16020
+ for (const log of allLogs) {
16021
+ if (log.sessionId === sessionId) {
16022
+ idSet.add(log.id);
16023
+ }
16024
+ }
16025
+ const persistedIds = [...idSet].filter((id) => Number.isInteger(id) && id >= 0);
15703
16026
  if (persistedIds.length === 0) {
16027
+ if (sessionPageRequestIdRef.current !== deleteRequestId) return;
16028
+ setAllLogs((prev) => {
16029
+ const remaining = prev.filter((log) => log.sessionId !== sessionId);
16030
+ logIndexRef.current = buildLogIndex(remaining);
16031
+ return remaining;
16032
+ });
16033
+ setLogPage(
16034
+ (prev) => prev === null ? null : {
16035
+ ...prev,
16036
+ logs: prev.logs.filter((log) => log.sessionId !== sessionId)
16037
+ }
16038
+ );
16039
+ setKnownSessions((prev) => prev.filter((session) => session !== sessionId));
16040
+ setSessionPageLoading(false);
16041
+ stopSessionLoadProgress();
15704
16042
  showToast({
15705
- message: "No persisted log records were found for this view.",
15706
- tone: "error"
16043
+ message: "No stored log records were found for this session.",
16044
+ tone: "success"
15707
16045
  });
15708
16046
  return;
15709
16047
  }
15710
- const idSet = new Set(persistedIds);
15711
- const removed = allLogs.filter((log) => idSet.has(log.id));
15712
16048
  const result = await fetchJson("/api/logs", DeleteLogsResponseSchema, {
15713
16049
  method: "DELETE",
15714
16050
  headers: { "content-type": "application/json" },
15715
16051
  body: JSON.stringify({ ids: persistedIds })
15716
16052
  });
16053
+ if (sessionPageRequestIdRef.current !== deleteRequestId) return;
15717
16054
  setAllLogs((prev) => {
15718
- const remaining = prev.filter((log) => !idSet.has(log.id));
16055
+ const remaining = prev.filter((log) => log.sessionId !== sessionId);
15719
16056
  logIndexRef.current = buildLogIndex(remaining);
15720
16057
  return remaining;
15721
16058
  });
15722
16059
  setLogPage(
15723
16060
  (prev) => prev === null ? null : {
15724
16061
  ...prev,
15725
- logs: prev.logs.filter((log) => !idSet.has(log.id))
16062
+ logs: prev.logs.filter((log) => log.sessionId !== sessionId)
15726
16063
  }
15727
16064
  );
15728
- setKnownSessions((prev) => mergeSessionIds(prev, extractSessions(removed)));
16065
+ setKnownSessions((prev) => prev.filter((session) => session !== sessionId));
16066
+ setSessionPageLoading(false);
16067
+ stopSessionLoadProgress();
15729
16068
  showToast({
15730
- message: `Deleted ${result.cleared.toString()} stored log${result.cleared === 1 ? "" : "s"} from the current view.`,
15731
- tone: "success"
16069
+ message: `Deleted ${result.cleared.toString()} stored log${result.cleared === 1 ? "" : "s"} for this session${collected.truncated ? ". More history may remain." : "."}`,
16070
+ tone: collected.truncated ? "error" : "success"
15732
16071
  });
15733
- },
15734
- [allLogs, showToast]
15735
- );
16072
+ } finally {
16073
+ if (sessionPageRequestIdRef.current === deleteRequestId) {
16074
+ setSessionPageLoading(false);
16075
+ stopSessionLoadProgress();
16076
+ }
16077
+ }
16078
+ }, [
16079
+ allLogs,
16080
+ dismissToast,
16081
+ selectedSession,
16082
+ showToast,
16083
+ startSessionLoadProgress,
16084
+ stopSessionLoadProgress,
16085
+ updateSessionLoadProgress
16086
+ ]);
15736
16087
  const handleReloadSession = reactExports.useCallback(() => {
15737
16088
  if (initialSessionId !== void 0) {
15738
16089
  loadSessionPage({ kind: "newest" });