@tonyclaw/agent-inspector 3.0.14 → 3.0.15

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 (38) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/{CompareDrawer-DDfwHQUi.js → CompareDrawer-UaIxykqz.js} +1 -1
  3. package/.output/public/assets/ProxyViewerContainer-DlpfcX56.js +106 -0
  4. package/.output/public/assets/{ReplayDialog-D-26DMBt.js → ReplayDialog-BFFomU1m.js} +1 -1
  5. package/.output/public/assets/{RequestAnatomy-B6zNFqNX.js → RequestAnatomy-DKQJBt_c.js} +1 -1
  6. package/.output/public/assets/{ResponseView-Ccy95rWI.js → ResponseView-D7yotmne.js} +2 -2
  7. package/.output/public/assets/{StreamingChunkSequence-yIiscGuE.js → StreamingChunkSequence-Da-6WNFG.js} +1 -1
  8. package/.output/public/assets/{_sessionId-BnMB0zab.js → _sessionId-ByTXLS-w.js} +1 -1
  9. package/.output/public/assets/{index-BbtAIxbg.js → index-BrM8t5mc.js} +1 -1
  10. package/.output/public/assets/index-CGpPRty8.js +1 -0
  11. package/.output/public/assets/index-HRfrFVYw.css +1 -0
  12. package/.output/public/assets/{json-viewer-C838cVmD.js → json-viewer-DyjXQdVu.js} +1 -1
  13. package/.output/public/assets/{main-BfN4culo.js → main-Zv_gjZMb.js} +2 -2
  14. package/.output/server/_libs/lucide-react.mjs +215 -201
  15. package/.output/server/{_sessionId-DoprmwZV.mjs → _sessionId-GcFhWT0i.mjs} +2 -2
  16. package/.output/server/_ssr/{CompareDrawer-YMLJNxXR.mjs → CompareDrawer-BV7dw1TN.mjs} +3 -3
  17. package/.output/server/_ssr/{ProxyViewerContainer-C62eZnva.mjs → ProxyViewerContainer-CcgfvaS4.mjs} +725 -378
  18. package/.output/server/_ssr/{ReplayDialog-NmN7Ukjo.mjs → ReplayDialog-B7sBKxIO.mjs} +4 -4
  19. package/.output/server/_ssr/{RequestAnatomy-Dawm2qxe.mjs → RequestAnatomy-s_9Veje2.mjs} +3 -3
  20. package/.output/server/_ssr/{ResponseView-BHyAY83t.mjs → ResponseView-DsOFPCvF.mjs} +3 -3
  21. package/.output/server/_ssr/{StreamingChunkSequence-C4qgcJbg.mjs → StreamingChunkSequence-CyA1XtiF.mjs} +3 -3
  22. package/.output/server/_ssr/{index-B2Pf6W_T.mjs → index-CDDRt201.mjs} +2 -2
  23. package/.output/server/_ssr/index.mjs +2 -2
  24. package/.output/server/_ssr/{json-viewer-u67BASf8.mjs → json-viewer-BFV-xtRM.mjs} +3 -3
  25. package/.output/server/_ssr/{router-CZhFVMGN.mjs → router-B2Q7vHPM.mjs} +58 -14
  26. package/.output/server/{_tanstack-start-manifest_v-Dk2HfOoe.mjs → _tanstack-start-manifest_v-Dm_GmuRz.mjs} +1 -1
  27. package/.output/server/index.mjs +73 -73
  28. package/package.json +1 -1
  29. package/src/components/ProxyViewer.tsx +470 -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/proxy/formats/openai/codexMetadata.ts +61 -0
  34. package/src/proxy/formats/openai/handler.ts +8 -2
  35. package/styles/globals.css +54 -0
  36. package/.output/public/assets/ProxyViewerContainer-CbNsaoQw.js +0 -106
  37. package/.output/public/assets/index-49RC4dlD.js +0 -1
  38. 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-B2Q7vHPM.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-BV7dw1TN.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-B7sBKxIO.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-s_9Veje2.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-DsOFPCvF.mjs").then((m) => ({ default: m.ResponseView }))
2559
2559
  );
2560
2560
  const LazyStreamingChunkSequence = reactExports.lazy(
2561
- () => import("./StreamingChunkSequence-C4qgcJbg.mjs").then((m) => ({
2561
+ () => import("./StreamingChunkSequence-CyA1XtiF.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-BFV-xtRM.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-BFV-xtRM.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,10 @@ 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(
14819
+ readStoredDetailsPanelCollapsed
14820
+ );
14542
14821
  const [comparePair, setComparePair] = reactExports.useState(null);
14543
14822
  const [crabEntrancePhase, setCrabEntrancePhase] = reactExports.useState(
14544
14823
  "hidden"
@@ -14575,6 +14854,12 @@ function ProxyViewer({
14575
14854
  clearTimeout(t2);
14576
14855
  };
14577
14856
  }, []);
14857
+ reactExports.useEffect(() => {
14858
+ window.localStorage.setItem(
14859
+ DETAILS_PANEL_COLLAPSED_STORAGE_KEY,
14860
+ detailsPanelCollapsed ? "1" : "0"
14861
+ );
14862
+ }, [detailsPanelCollapsed]);
14578
14863
  reactExports.useEffect(() => {
14579
14864
  if (pinnedSessionId === void 0) {
14580
14865
  document.title = "Agent Inspector";
@@ -14656,7 +14941,6 @@ function ProxyViewer({
14656
14941
  onClearAll();
14657
14942
  }, [cancelTransientTasks, onClearAll]);
14658
14943
  const handleRequestDeleteCurrentView = reactExports.useCallback(() => {
14659
- setDeleteStoredData(false);
14660
14944
  setDeleteDialogOpen(true);
14661
14945
  }, []);
14662
14946
  const handleConfirmDeleteCurrentView = reactExports.useCallback(() => {
@@ -14664,13 +14948,9 @@ function ProxyViewer({
14664
14948
  setImportStatus(null);
14665
14949
  setImportError(null);
14666
14950
  setComparePair(null);
14667
- if (!deleteStoredData || onDeleteCurrentView === void 0) {
14668
- setDeleteDialogOpen(false);
14669
- onClearAll();
14670
- return;
14671
- }
14951
+ if (onDeleteCurrentView === void 0) return;
14672
14952
  setDeletingCurrentView(true);
14673
- void onDeleteCurrentView(logs.map((log) => log.id)).then(() => {
14953
+ void onDeleteCurrentView().then(() => {
14674
14954
  setDeleteDialogOpen(false);
14675
14955
  }).catch((err) => {
14676
14956
  const message = err instanceof Error ? err.message : "Failed to delete stored logs";
@@ -14682,7 +14962,7 @@ function ProxyViewer({
14682
14962
  }).finally(() => {
14683
14963
  setDeletingCurrentView(false);
14684
14964
  });
14685
- }, [cancelTransientTasks, deleteStoredData, logs, onClearAll, onDeleteCurrentView, onNotify]);
14965
+ }, [cancelTransientTasks, onDeleteCurrentView, onNotify]);
14686
14966
  const handleReloadCurrentSession = reactExports.useCallback(() => {
14687
14967
  if (onReloadSession === void 0) return;
14688
14968
  cancelTransientTasks();
@@ -14694,6 +14974,9 @@ function ProxyViewer({
14694
14974
  const closeCompare = reactExports.useCallback(() => {
14695
14975
  setComparePair(null);
14696
14976
  }, []);
14977
+ const toggleDetailsPanelCollapsed = reactExports.useCallback(() => {
14978
+ setDetailsPanelCollapsed((value) => !value);
14979
+ }, []);
14697
14980
  const groups = reactExports.useMemo(() => groupLogsByConversation(logs), [logs]);
14698
14981
  const displayNumberByLogId = reactExports.useMemo(() => buildDisplayNumberByLogId(groups), [groups]);
14699
14982
  const sessionContextScope = reactExports.useMemo(
@@ -14715,6 +14998,9 @@ function ProxyViewer({
14715
14998
  const exportActionVisibility = getExportActionVisibility(captureMode, logs.length);
14716
14999
  const isPinnedSessionPage = pinnedSessionId !== void 0;
14717
15000
  const canClearCurrentView = logs.length > 0;
15001
+ const canDeleteCurrentView = onDeleteCurrentView !== void 0 && (logs.length > 0 || selectedSession !== "__all__");
15002
+ const deleteTargetLabel = selectedSession === "__all__" ? "all sessions" : "this session";
15003
+ 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
15004
  const reloadSessionLabel = logs.length === 0 ? "Load" : "Reload";
14719
15005
  const sessionInputValue = selectedSession === "__all__" ? "" : selectedSession;
14720
15006
  const sessionSelectValue = selectedSession === "__all__" || sessions.includes(selectedSession) ? selectedSession : "__typed__";
@@ -14752,376 +15038,341 @@ function ProxyViewer({
14752
15038
  );
14753
15039
  const labSessionId = pinnedSessionId !== void 0 ? pinnedSessionId : selectedSession === "__all__" ? null : selectedSession;
14754
15040
  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
- }
15041
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
15042
+ "button",
15043
+ {
15044
+ type: "button",
15045
+ onClick: toggleDetailsPanelCollapsed,
15046
+ className: cn(
15047
+ "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",
15048
+ detailsPanelCollapsed ? "right-3" : "lg:right-[326px] xl:right-[346px]"
14765
15049
  ),
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
- ),
15050
+ "aria-label": detailsPanelCollapsed ? "Show details panel" : "Hide details panel",
15051
+ title: detailsPanelCollapsed ? "Show details panel" : "Hide details panel",
15052
+ children: [
15053
+ /* @__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]" }),
15054
+ detailsPanelCollapsed ? /* @__PURE__ */ jsxRuntimeExports.jsx(PanelRightOpen, { className: "size-3.5" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(PanelRightClose, { className: "size-3.5" })
15055
+ ]
15056
+ }
15057
+ ),
15058
+ detailsPanelCollapsed && /* @__PURE__ */ jsxRuntimeExports.jsx(FloatingInspectorLogo, {}),
15059
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
15060
+ "div",
15061
+ {
15062
+ className: cn(
15063
+ "grid min-h-screen w-full grid-cols-1",
15064
+ detailsPanelCollapsed ? "lg:grid-cols-[minmax(0,1fr)]" : "lg:grid-cols-[minmax(0,1fr)_340px] xl:grid-cols-[minmax(0,1fr)_360px]"
15065
+ ),
15066
+ children: [
15067
+ !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
15068
  /* @__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",
15069
+ BrandHeader,
14788
15070
  {
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
- ]
15071
+ compact: true,
15072
+ crabEntrancePhase,
15073
+ currentSessionId: labSessionId,
15074
+ logCount: logs.length
14798
15075
  }
14799
15076
  ),
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"
15077
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(SidebarPanel, { label: "Session", children: [
15078
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
15079
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SidebarMetric, { label: "Requests", value: logs.length }),
15080
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SidebarMetric, { label: "Sessions", value: sessions.length }),
15081
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
15082
+ SidebarMetric,
15083
+ {
15084
+ label: "Input",
15085
+ value: formatTokens(hasSessionContext ? sessionContextTotalIn : totalIn)
15086
+ }
14809
15087
  ),
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 })
15088
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
15089
+ SidebarMetric,
15090
+ {
15091
+ label: "Output",
15092
+ value: formatTokens(hasSessionContext ? sessionContextTotalOut : totalOut)
15093
+ }
15094
+ )
15095
+ ] }),
15096
+ 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
15097
  ] }),
14914
- onImportLogs !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
15098
+ /* @__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
15099
  /* @__PURE__ */ jsxRuntimeExports.jsx(
14916
- "input",
15100
+ "div",
14917
15101
  {
14918
- ref: importInputRef,
14919
- type: "file",
14920
- accept: ".zip,.json,.jsonl,application/zip,application/json",
14921
- className: "hidden",
14922
- onChange: handleImportFileChange
15102
+ className: "truncate font-mono text-xs font-semibold text-cyan-100",
15103
+ title: activeScopeLabel,
15104
+ children: activeScopeLabel
14923
15105
  }
14924
15106
  ),
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",
15107
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1 text-[11px] text-muted-foreground", children: isPinnedSessionPage ? "Session workspace" : "Live workspace" })
15108
+ ] }) }),
15109
+ hasSessionContext && sessionContextScope !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(
15110
+ SessionContextBar,
14942
15111
  {
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
- ] })
15112
+ label: sessionContextScope.label,
15113
+ logs: sessionContextLogs,
15114
+ totalIn: sessionContextTotalIn,
15115
+ totalOut: sessionContextTotalOut,
15116
+ timeDisplayFormat,
15117
+ contextSummary: sessionContextSummary,
15118
+ showBackLink: sessionContextScope.showBackLink
14954
15119
  }
14955
15120
  ),
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" })
15121
+ hasSessionContext && pinnedSessionId !== void 0 && sessionMemberships.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(SessionMembershipPanel, { memberships: sessionMemberships }),
15122
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SidebarPanel, { label: "Filters", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
15123
+ !hideSessionFilter && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
15124
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative", children: [
15125
+ /* @__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" }),
15126
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
15127
+ "input",
15128
+ {
15129
+ type: "search",
15130
+ value: sessionInputValue,
15131
+ onChange: handleSessionInputChange,
15132
+ placeholder: "Paste session ID",
15133
+ 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",
15134
+ "aria-label": "Filter by session ID",
15135
+ title: "Filter by exact session ID"
15136
+ }
15137
+ ),
15138
+ sessionInputValue !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx(
15139
+ "button",
15140
+ {
15141
+ type: "button",
15142
+ onClick: () => onSessionChange("__all__"),
15143
+ 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",
15144
+ "aria-label": "Clear session filter",
15145
+ title: "Clear session filter",
15146
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "size-3.5" })
15147
+ }
15148
+ )
15149
+ ] }),
15150
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Select, { value: sessionSelectValue, onValueChange: handleSessionSelectChange, children: [
15151
+ /* @__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" }) }),
15152
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(SelectContent, { children: [
15153
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: "__all__", children: "All sessions" }),
15154
+ sessionSelectValue === "__typed__" && /* @__PURE__ */ jsxRuntimeExports.jsxs(SelectItem, { value: "__typed__", children: [
15155
+ "Typed: ",
15156
+ truncateSessionId(selectedSession)
15157
+ ] }),
15158
+ sessions.map((s) => /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: s, children: truncateSessionId(s) }, s))
15159
+ ] })
14969
15160
  ] })
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: [
15161
+ ] }),
15162
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Select, { value: selectedModel, onValueChange: onModelChange, children: [
15163
+ /* @__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" }) }),
15164
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(SelectContent, { children: [
15165
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: "__all__", children: "All models" }),
15166
+ models.map((m) => /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: m, children: m }, m))
15167
+ ] })
15168
+ ] })
15169
+ ] }) })
15170
+ ] }) }),
15171
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("main", { className: "order-2 min-w-0 lg:order-1", children: [
15172
+ /* @__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: [
15173
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
15174
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-[180px] flex-1", children: [
15175
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm font-semibold text-foreground", children: "Logs" }),
15176
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-0.5 font-mono text-[11px] text-muted-foreground", children: activeScopeLabel })
15177
+ ] }),
15178
+ onImportLogs !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
15179
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
15180
+ "input",
15181
+ {
15182
+ ref: importInputRef,
15183
+ type: "file",
15184
+ accept: ".zip,.json,.jsonl,application/zip,application/json",
15185
+ className: "hidden",
15186
+ onChange: handleImportFileChange
15187
+ }
15188
+ ),
15189
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
15190
+ "button",
15191
+ {
15192
+ type: "button",
15193
+ onClick: handleImportClick,
15194
+ disabled: importing,
15195
+ 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",
15196
+ title: "Import Agent Inspector export",
15197
+ children: importing ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Importing..." }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
15198
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Upload, { className: "size-3.5" }),
15199
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Import" })
15200
+ ] })
15201
+ }
15202
+ )
15203
+ ] }),
15204
+ exportActionVisibility.redacted && /* @__PURE__ */ jsxRuntimeExports.jsx(
15205
+ "button",
15206
+ {
15207
+ type: "button",
15208
+ onClick: () => {
15209
+ void handleExport("redacted");
15210
+ },
15211
+ disabled: exporting !== null,
15212
+ 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",
15213
+ title: "Export redacted logs as JSON ZIP",
15214
+ children: exporting === "redacted" ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Exporting..." }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
15215
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Download, { className: "size-3.5" }),
15216
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Export" })
15217
+ ] })
15218
+ }
15219
+ ),
15220
+ exportActionVisibility.raw && /* @__PURE__ */ jsxRuntimeExports.jsx(
15221
+ "button",
15222
+ {
15223
+ type: "button",
15224
+ onClick: () => {
15225
+ void handleExport("raw");
15226
+ },
15227
+ disabled: exporting !== null,
15228
+ 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",
15229
+ title: "Export raw logs without redaction",
15230
+ children: exporting === "raw" ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Exporting..." }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
15231
+ /* @__PURE__ */ jsxRuntimeExports.jsx(FileBraces, { className: "size-3.5" }),
15232
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Raw" })
15233
+ ] })
15234
+ }
15235
+ ),
15031
15236
  onReloadSession !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
15032
15237
  "button",
15033
15238
  {
15034
15239
  type: "button",
15035
15240
  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",
15241
+ disabled: isLoading,
15242
+ 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",
15243
+ title: "Reload this session from stored logs",
15037
15244
  children: [
15038
- /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: "size-3.5" }),
15039
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Load session" })
15245
+ /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: cn("size-3.5", isLoading && "animate-spin") }),
15246
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: reloadSessionLabel })
15040
15247
  ]
15041
15248
  }
15042
15249
  ),
15043
- hideSessionFilter ? /* @__PURE__ */ jsxRuntimeExports.jsx(
15044
- "a",
15250
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
15251
+ "button",
15045
15252
  {
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"
15253
+ type: "button",
15254
+ onClick: handleClearCurrentView,
15255
+ disabled: !canClearCurrentView,
15256
+ 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",
15257
+ title: "Clear the current view. Stored logs remain reloadable.",
15258
+ children: [
15259
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" }),
15260
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Clear" })
15261
+ ]
15049
15262
  }
15050
- ) : /* @__PURE__ */ jsxRuntimeExports.jsx(
15263
+ ),
15264
+ onDeleteCurrentView !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
15051
15265
  "button",
15052
15266
  {
15053
15267
  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"
15268
+ onClick: handleRequestDeleteCurrentView,
15269
+ disabled: !canDeleteCurrentView || deletingCurrentView,
15270
+ 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",
15271
+ title: "Delete persisted history for the selected session.",
15272
+ children: [
15273
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" }),
15274
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Delete" })
15275
+ ]
15057
15276
  }
15058
15277
  )
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>" })
15278
+ ] }),
15279
+ 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 }) }),
15280
+ /* @__PURE__ */ jsxRuntimeExports.jsx(LogPaginationBar, { logs, pagination, embedded: true }),
15281
+ 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 }),
15282
+ 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 }),
15283
+ 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
15284
  ] }),
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
- ] }),
15285
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-4 lg:px-5", children: [
15286
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SessionOpeningSlate, { stats: slateStats }),
15287
+ 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: [
15288
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-medium", children: isLoading ? "Loading session data..." : "No logs loaded for this session" }),
15289
+ /* @__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) }),
15290
+ 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 }) }),
15291
+ sessionMemberships.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-left", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SessionMembershipPanel, { memberships: sessionMemberships }) }),
15292
+ !isLoading && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center gap-3 text-xs", children: [
15293
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Stored logs may still be available." }),
15294
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center justify-center gap-2", children: [
15295
+ onReloadSession !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
15296
+ "button",
15297
+ {
15298
+ type: "button",
15299
+ onClick: handleReloadCurrentSession,
15300
+ 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",
15301
+ children: [
15302
+ /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: "size-3.5" }),
15303
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Load session" })
15304
+ ]
15305
+ }
15306
+ ),
15307
+ hideSessionFilter ? /* @__PURE__ */ jsxRuntimeExports.jsx(
15308
+ "a",
15309
+ {
15310
+ href: "/",
15311
+ className: "inline-flex h-8 items-center rounded-md px-3 text-xs text-muted-foreground underline transition-colors hover:text-foreground",
15312
+ children: "Back to all sessions"
15313
+ }
15314
+ ) : /* @__PURE__ */ jsxRuntimeExports.jsx(
15315
+ "button",
15316
+ {
15317
+ type: "button",
15318
+ onClick: () => onSessionChange("__all__"),
15319
+ className: "inline-flex h-8 items-center rounded-md px-3 text-xs text-muted-foreground underline transition-colors hover:text-foreground",
15320
+ children: "Show all sessions"
15321
+ }
15322
+ )
15323
+ ] })
15324
+ ] })
15325
+ ] }) }) : /* @__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: [
15326
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm", children: "No logs loaded in the current view." }),
15327
+ 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." }),
15328
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center gap-2", children: [
15329
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CopyableCommand, { command: "ANTHROPIC_BASE_URL=http://localhost:9527/proxy <your-tool>" }),
15330
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CopyableCommand, { command: "OPENAI_BASE_URL=http://localhost:9527/proxy <your-tool>" })
15331
+ ] }),
15332
+ /* @__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." })
15333
+ ] }) }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(
15334
+ "div",
15335
+ {
15336
+ ref: logListWrapperRef,
15337
+ tabIndex: 0,
15338
+ className: "flex flex-col gap-2 focus:outline-none",
15339
+ children: [
15340
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: logListRef, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
15341
+ ConversationGroupList,
15342
+ {
15343
+ groups,
15344
+ viewMode,
15345
+ strip,
15346
+ slowResponseThresholdSeconds,
15347
+ cacheTrends,
15348
+ onCompareWithPrevious: handleCompareWithPrevious,
15349
+ comparisonPredecessors,
15350
+ onClearGroup,
15351
+ defaultExpanded: groups.length === 1,
15352
+ timeDisplayFormat
15353
+ }
15354
+ ) }),
15355
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-3", children: /* @__PURE__ */ jsxRuntimeExports.jsx(LogPaginationBar, { logs, pagination }) })
15356
+ ]
15357
+ }
15358
+ )
15359
+ ] })
15360
+ ] })
15361
+ ]
15362
+ }
15363
+ ),
15098
15364
  /* @__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
15365
  /* @__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." })
15366
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogTitle, { children: [
15367
+ "Delete ",
15368
+ deleteTargetLabel,
15369
+ " history?"
15370
+ ] }),
15371
+ /* @__PURE__ */ jsxRuntimeExports.jsx(DialogDescription, { children: "Clear only hides logs from the UI. Delete removes stored history from disk." })
15102
15372
  ] }),
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
- ] })
15373
+ /* @__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: [
15374
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "block font-medium", children: "This is a full history delete." }),
15375
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "mt-1 block text-xs text-red-200/80", children: deleteTargetDescription })
15125
15376
  ] }),
15126
15377
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-end gap-2", children: [
15127
15378
  /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -15139,11 +15390,11 @@ function ProxyViewer({
15139
15390
  Button,
15140
15391
  {
15141
15392
  type: "button",
15142
- variant: deleteStoredData ? "destructive" : "secondary",
15393
+ variant: "destructive",
15143
15394
  size: "sm",
15144
15395
  disabled: deletingCurrentView,
15145
15396
  onClick: handleConfirmDeleteCurrentView,
15146
- children: deletingCurrentView ? "Deleting..." : deleteStoredData ? "Delete data" : "Clear only"
15397
+ children: deletingCurrentView ? "Deleting..." : "Delete history"
15147
15398
  }
15148
15399
  )
15149
15400
  ] })
@@ -15280,6 +15531,38 @@ function fetchSessionLogsPage(sessionId, request, limit = SESSION_PAGE_LIMIT) {
15280
15531
  SESSION_LOGS_FETCH_TIMEOUT_MS
15281
15532
  );
15282
15533
  }
15534
+ async function collectSessionLogIds(sessionId, onProgress) {
15535
+ const ids = /* @__PURE__ */ new Set();
15536
+ let page = await fetchSessionLogsPage(sessionId, { kind: "oldest" }, SESSION_RELOAD_PAGE_LIMIT);
15537
+ for (const log of page.logs) {
15538
+ ids.add(log.id);
15539
+ }
15540
+ onProgress(ids.size, 1);
15541
+ let loadedPages = 1;
15542
+ while (page.hasNewer && page.newestLogId !== null && loadedPages < MAX_SESSION_RELOAD_PAGES) {
15543
+ page = await fetchSessionLogsPage(
15544
+ sessionId,
15545
+ { kind: "newer", afterLogId: page.newestLogId },
15546
+ SESSION_RELOAD_PAGE_LIMIT
15547
+ );
15548
+ for (const log of page.logs) {
15549
+ ids.add(log.id);
15550
+ }
15551
+ loadedPages += 1;
15552
+ onProgress(ids.size, loadedPages);
15553
+ }
15554
+ return { ids: [...ids], truncated: page.hasNewer };
15555
+ }
15556
+ async function deleteAllGroupsForFullHistoryDelete() {
15557
+ try {
15558
+ const result = await fetchJson("/api/groups", DeleteInspectorGroupsResponseSchema, {
15559
+ method: "DELETE"
15560
+ });
15561
+ return { deleted: result.deleted, ok: true };
15562
+ } catch {
15563
+ return { deleted: 0, ok: false };
15564
+ }
15565
+ }
15283
15566
  function mergeLogsById(previousLogs, incomingLogs) {
15284
15567
  if (incomingLogs.length === 0) return [...previousLogs];
15285
15568
  const byId = /* @__PURE__ */ new Map();
@@ -15696,43 +15979,107 @@ function ProxyViewerContainer({
15696
15979
  },
15697
15980
  [showToast]
15698
15981
  );
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);
15982
+ const handleDeleteCurrentView = reactExports.useCallback(async () => {
15983
+ const deleteRequestId = sessionPageRequestIdRef.current + 1;
15984
+ sessionPageRequestIdRef.current = deleteRequestId;
15985
+ setSessionPageLoading(true);
15986
+ stopSessionLoadProgress();
15987
+ dismissToast();
15988
+ try {
15989
+ if (selectedSession === "__all__") {
15990
+ startSessionLoadProgress("Deleting stored history", deleteRequestId);
15991
+ const result2 = await fetchJson("/api/logs", DeleteLogsResponseSchema, {
15992
+ method: "DELETE"
15993
+ });
15994
+ const groupCleanup = await deleteAllGroupsForFullHistoryDelete();
15995
+ if (sessionPageRequestIdRef.current !== deleteRequestId) return;
15996
+ setAllLogs([]);
15997
+ logIndexRef.current.clear();
15998
+ setLogPage(null);
15999
+ setKnownSessions([]);
16000
+ setSessionMemberships([]);
16001
+ setSessionPageLoading(false);
16002
+ stopSessionLoadProgress();
16003
+ const groupMessage = groupCleanup.ok ? ` Cleared ${groupCleanup.deleted.toString()} group${groupCleanup.deleted === 1 ? "" : "s"}.` : " Group cleanup failed; open Groups to retry Clear.";
16004
+ showToast({
16005
+ message: `Deleted ${result2.cleared.toString()} stored log${result2.cleared === 1 ? "" : "s"} across all sessions.${groupMessage}`,
16006
+ tone: groupCleanup.ok ? "success" : "error"
16007
+ });
16008
+ return;
16009
+ }
16010
+ const sessionId = selectedSession;
16011
+ startSessionLoadProgress("Deleting session history", deleteRequestId);
16012
+ const collected = await collectSessionLogIds(sessionId, (logCount, pageCount) => {
16013
+ updateSessionLoadProgress("Deleting session history", deleteRequestId, logCount, pageCount);
16014
+ });
16015
+ const idSet = new Set(collected.ids);
16016
+ for (const log of allLogs) {
16017
+ if (log.sessionId === sessionId) {
16018
+ idSet.add(log.id);
16019
+ }
16020
+ }
16021
+ const persistedIds = [...idSet].filter((id) => Number.isInteger(id) && id >= 0);
15703
16022
  if (persistedIds.length === 0) {
16023
+ if (sessionPageRequestIdRef.current !== deleteRequestId) return;
16024
+ setAllLogs((prev) => {
16025
+ const remaining = prev.filter((log) => log.sessionId !== sessionId);
16026
+ logIndexRef.current = buildLogIndex(remaining);
16027
+ return remaining;
16028
+ });
16029
+ setLogPage(
16030
+ (prev) => prev === null ? null : {
16031
+ ...prev,
16032
+ logs: prev.logs.filter((log) => log.sessionId !== sessionId)
16033
+ }
16034
+ );
16035
+ setKnownSessions((prev) => prev.filter((session) => session !== sessionId));
16036
+ setSessionPageLoading(false);
16037
+ stopSessionLoadProgress();
15704
16038
  showToast({
15705
- message: "No persisted log records were found for this view.",
15706
- tone: "error"
16039
+ message: "No stored log records were found for this session.",
16040
+ tone: "success"
15707
16041
  });
15708
16042
  return;
15709
16043
  }
15710
- const idSet = new Set(persistedIds);
15711
- const removed = allLogs.filter((log) => idSet.has(log.id));
15712
16044
  const result = await fetchJson("/api/logs", DeleteLogsResponseSchema, {
15713
16045
  method: "DELETE",
15714
16046
  headers: { "content-type": "application/json" },
15715
16047
  body: JSON.stringify({ ids: persistedIds })
15716
16048
  });
16049
+ if (sessionPageRequestIdRef.current !== deleteRequestId) return;
15717
16050
  setAllLogs((prev) => {
15718
- const remaining = prev.filter((log) => !idSet.has(log.id));
16051
+ const remaining = prev.filter((log) => log.sessionId !== sessionId);
15719
16052
  logIndexRef.current = buildLogIndex(remaining);
15720
16053
  return remaining;
15721
16054
  });
15722
16055
  setLogPage(
15723
16056
  (prev) => prev === null ? null : {
15724
16057
  ...prev,
15725
- logs: prev.logs.filter((log) => !idSet.has(log.id))
16058
+ logs: prev.logs.filter((log) => log.sessionId !== sessionId)
15726
16059
  }
15727
16060
  );
15728
- setKnownSessions((prev) => mergeSessionIds(prev, extractSessions(removed)));
16061
+ setKnownSessions((prev) => prev.filter((session) => session !== sessionId));
16062
+ setSessionPageLoading(false);
16063
+ stopSessionLoadProgress();
15729
16064
  showToast({
15730
- message: `Deleted ${result.cleared.toString()} stored log${result.cleared === 1 ? "" : "s"} from the current view.`,
15731
- tone: "success"
16065
+ message: `Deleted ${result.cleared.toString()} stored log${result.cleared === 1 ? "" : "s"} for this session${collected.truncated ? ". More history may remain." : "."}`,
16066
+ tone: collected.truncated ? "error" : "success"
15732
16067
  });
15733
- },
15734
- [allLogs, showToast]
15735
- );
16068
+ } finally {
16069
+ if (sessionPageRequestIdRef.current === deleteRequestId) {
16070
+ setSessionPageLoading(false);
16071
+ stopSessionLoadProgress();
16072
+ }
16073
+ }
16074
+ }, [
16075
+ allLogs,
16076
+ dismissToast,
16077
+ selectedSession,
16078
+ showToast,
16079
+ startSessionLoadProgress,
16080
+ stopSessionLoadProgress,
16081
+ updateSessionLoadProgress
16082
+ ]);
15736
16083
  const handleReloadSession = reactExports.useCallback(() => {
15737
16084
  if (initialSessionId !== void 0) {
15738
16085
  loadSessionPage({ kind: "newest" });