@tonyclaw/agent-inspector 3.0.27 → 3.0.29

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 (43) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/{CompareDrawer-BVCAAbbu.js → CompareDrawer-Cb5ccPeX.js} +1 -1
  3. package/.output/public/assets/{ProxyViewerContainer-CYOXB81n.js → ProxyViewerContainer-COBe5GTT.js} +198 -198
  4. package/.output/public/assets/{ReplayDialog-DMX23O5G.js → ReplayDialog-CctnITbt.js} +1 -1
  5. package/.output/public/assets/{RequestAnatomy-S17pYDRc.js → RequestAnatomy-BrN0RBbL.js} +1 -1
  6. package/.output/public/assets/{ResponseView-Cf1XrawD.js → ResponseView-Cqq87lX_.js} +2 -2
  7. package/.output/public/assets/{StreamingChunkSequence-BdOrVlCi.js → StreamingChunkSequence-CnTa9mCr.js} +1 -1
  8. package/.output/public/assets/{_sessionId-BnKGmJrR.js → _sessionId-DKM91udC.js} +1 -1
  9. package/.output/public/assets/{index-gY3I-7-D.js → index-Bq-nqolG.js} +1 -1
  10. package/.output/public/assets/{index-9fMLCU4d.js → index-DPiESBo2.js} +1 -1
  11. package/.output/public/assets/{index-B1atk19i.js → index-DTLNVcgc.js} +7 -7
  12. package/.output/public/assets/index-DliqmwUw.css +1 -0
  13. package/.output/public/assets/{json-viewer-CpyYpPjx.js → json-viewer-CfaDJwx8.js} +1 -1
  14. package/.output/server/_libs/lucide-react.mjs +39 -39
  15. package/.output/server/{_sessionId-eA_h2_s6.mjs → _sessionId-CwGXPD4C.mjs} +2 -2
  16. package/.output/server/_ssr/{CompareDrawer-K2k9G7r1.mjs → CompareDrawer-R_P1-VNr.mjs} +3 -3
  17. package/.output/server/_ssr/{ProxyViewerContainer-CbyBpCAj.mjs → ProxyViewerContainer-DUgxRNbj.mjs} +344 -191
  18. package/.output/server/_ssr/{ReplayDialog-DacI2Iv0.mjs → ReplayDialog-De9wKKzS.mjs} +4 -4
  19. package/.output/server/_ssr/{RequestAnatomy-gh-pAdkO.mjs → RequestAnatomy-Db4MxUYo.mjs} +2 -2
  20. package/.output/server/_ssr/{ResponseView-BRJKN50-.mjs → ResponseView-8rDXOiNB.mjs} +3 -3
  21. package/.output/server/_ssr/{StreamingChunkSequence-BQLVEuWY.mjs → StreamingChunkSequence-N9teZHkA.mjs} +2 -2
  22. package/.output/server/_ssr/{index-DuSWrjbH.mjs → index-D4DvByuW.mjs} +2 -2
  23. package/.output/server/_ssr/index.mjs +2 -2
  24. package/.output/server/_ssr/{json-viewer-DNs1ZjKI.mjs → json-viewer-BjoHRbjS.mjs} +3 -3
  25. package/.output/server/_ssr/{router-Dgx6-ot3.mjs → router-BYlePDj8.mjs} +138 -162
  26. package/.output/server/{_tanstack-start-manifest_v-CoGjnkQD.mjs → _tanstack-start-manifest_v-DMCA8KK3.mjs} +1 -1
  27. package/.output/server/index.mjs +68 -68
  28. package/package.json +1 -1
  29. package/src/components/ProxyViewer.tsx +57 -1
  30. package/src/components/clients/ClientLogo.tsx +51 -9
  31. package/src/components/inspector-pet/InspectorPet.tsx +0 -7
  32. package/src/components/proxy-viewer/ConversationGroup.tsx +1 -1
  33. package/src/components/proxy-viewer/ConversationGroupList.tsx +251 -155
  34. package/src/components/proxy-viewer/ConversationHeader.tsx +43 -23
  35. package/src/lib/jsonFile.ts +46 -0
  36. package/src/lib/utils.ts +5 -1
  37. package/src/proxy/evidenceAnalysis.ts +116 -117
  38. package/src/proxy/groupEvidenceExporter.ts +4 -8
  39. package/src/proxy/groupStore.ts +3 -10
  40. package/src/proxy/providerSecretStore.ts +4 -8
  41. package/src/proxy/runFailures.ts +4 -10
  42. package/src/proxy/runStore.ts +4 -11
  43. package/.output/public/assets/index-CmeF5XXS.css +0 -1
@@ -1,5 +1,5 @@
1
1
  import { r as reactExports, j as jsxRuntimeExports, R as React } from "../_libs/react.mjs";
2
- import { C as CapturedLogSchema, B 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, g as readStoredUiScalePreference, h as persistUiScalePreference, j as applyUiScalePreference, x as extractStopReason, p as packageJson, P as ProviderConfigSchema, U as UI_SCALE_STORAGE_KEY, k as normalizeUiScalePreference, t as apiFormatForPath, E as GroupEvidenceExportResultSchema, F as DeleteInspectorGroupResponseSchema, $ as PiAgentResponseSchema, w as isTurnBoundary, r as readStoredThemeMode, e as applyThemeMode, f as persistThemeMode, a2 as formatUiScale, y as AlertSummarySchema, z as AlertListResponseSchema, I as InspectorGroupsListResponseSchema, G as GroupEvidenceReadResponseSchema, V as createPendingProviderTestResults, W as ProviderTestResultsSchema, X as createFailedProviderTestResults, Y as MAX_SLOW_RESPONSE_THRESHOLD_SECONDS, Z as MAX_PROVIDER_TEST_TIMEOUT_SECONDS, _ as TimeDisplayFormatSchema, i as isRecord, T as THEME_MODE_STORAGE_KEY, n as normalizeThemeMode, M as PATH_V1_MESSAGES, N as PATH_V1_CHAT_COMPLETIONS, Q as PATH_V1_RESPONSES, H as providerHasContextMetadata, m as parseOpenAIResponse, o as parseOpenAIResponsesResponse, O as OpenAIRequestSchema, q as OpenAIResponsesRequestSchema, A as AnthropicResponseSchema$1, l as AnthropicRequestSchema, s as safeGetOwnProperty, a0 as resolveProviderContextWindow, u as getSessionPath, J as findProviderModelMetadata, S as previewUpstreamUrl, K as KnowledgeCandidateSchema, a1 as isPlainRecord, v as stripClaudeCodeBillingHeader, L as LogBodyChunkSchema } from "./router-Dgx6-ot3.mjs";
2
+ import { C as CapturedLogSchema, B 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, g as readStoredUiScalePreference, h as persistUiScalePreference, j as applyUiScalePreference, x as extractStopReason, p as packageJson, P as ProviderConfigSchema, U as UI_SCALE_STORAGE_KEY, k as normalizeUiScalePreference, t as apiFormatForPath, E as GroupEvidenceExportResultSchema, F as DeleteInspectorGroupResponseSchema, $ as PiAgentResponseSchema, w as isTurnBoundary, r as readStoredThemeMode, e as applyThemeMode, f as persistThemeMode, a2 as formatUiScale, y as AlertSummarySchema, z as AlertListResponseSchema, I as InspectorGroupsListResponseSchema, G as GroupEvidenceReadResponseSchema, V as createPendingProviderTestResults, W as ProviderTestResultsSchema, X as createFailedProviderTestResults, Y as MAX_SLOW_RESPONSE_THRESHOLD_SECONDS, Z as MAX_PROVIDER_TEST_TIMEOUT_SECONDS, _ as TimeDisplayFormatSchema, i as isRecord, T as THEME_MODE_STORAGE_KEY, n as normalizeThemeMode, M as PATH_V1_MESSAGES, N as PATH_V1_CHAT_COMPLETIONS, Q as PATH_V1_RESPONSES, H as providerHasContextMetadata, m as parseOpenAIResponse, o as parseOpenAIResponsesResponse, O as OpenAIRequestSchema, q as OpenAIResponsesRequestSchema, A as AnthropicResponseSchema$1, l as AnthropicRequestSchema, s as safeGetOwnProperty, a0 as resolveProviderContextWindow, u as getSessionPath, J as findProviderModelMetadata, S as previewUpstreamUrl, K as KnowledgeCandidateSchema, a1 as isPlainRecord, v as stripClaudeCodeBillingHeader, L as LogBodyChunkSchema } from "./router-BYlePDj8.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 { u as useWindowVirtualizer, a as useVirtualizer } from "../_libs/tanstac
9
9
  import { d as diffJson, a as diffLines } from "../_libs/diff.mjs";
10
10
  import { r as reactDomExports } from "../_libs/react-dom.mjs";
11
11
  import { W as WebGLRenderer, S as SRGBColorSpace, A as ACESFilmicToneMapping, a as Scene, O as OrthographicCamera, M as MeshPhysicalMaterial, C as Color, G as Group, b as Mesh, c as CircleGeometry, d as MeshBasicMaterial, e as SphereGeometry, f as AmbientLight, H as HemisphereLight, D as DirectionalLight, P as PointLight, V as Vector3, g as CylinderGeometry } from "../_libs/three.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, H as Heart, e as Pause, f as Play, g as Plus, B as BrainCircuit, L as LoaderCircle, h as Send, A as ArrowLeft, i as ChevronUp, j as Copy, k as ChevronsLeft, l as ChevronLeft, m as ChevronRight, n as ChevronsRight, o as Clapperboard, p as Flag, q as Siren, r as Timer, G as Gauge, s as Sun, E as Eye, M as Moon, t as ALargeSmall, u as Layers, v as FlaskConical, w as Sparkles, x as Activity, y as Beaker, N as Network, z as Terminal, J as Settings, K as Monitor, O as Rocket, Q as PackageCheck, V as History, W as Scan, Y as CircleAlert, Z as ArrowUpRight, _ as ArrowDownRight, $ as Cpu, a0 as FolderOpen, a1 as Bell, a2 as Clock3, a3 as ShieldAlert, a4 as EyeOff, a5 as ExternalLink, a6 as Clock, a7 as RotateCw, a8 as CircleCheckBig, a9 as Pencil, aa as MessageSquare, ab as Zap, ac as Wrench, ad as Brain, ae as Minus, af as CircleX, ag as ShieldCheck, ah as Save, ai as FileSearch, aj as CloudUpload, ak as CircleQuestionMark, al as Server, am as Lock, an as Wifi, ao as WifiOff, ap as OctagonAlert, aq as Radio, ar as Globe, as as FileTerminal, at as ChevronsUp, au as ChevronsDown, av as FileDiff, aw as RotateCcw, ax as GitCompareArrows, ay as ArrowUp, az as ArrowDown, aA as Ellipsis, aB as CodeXml, aC as Blocks, aD as MousePointerClick, aE as FileText, aF as Rows3, aG 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, H as Heart, e as Pause, f as Play, g as Plus, B as BrainCircuit, L as LoaderCircle, h as Send, A as ArrowLeft, i as ChevronUp, j as Copy, k as ChevronsLeft, l as ChevronLeft, m as ChevronRight, n as ChevronsRight, o as Clapperboard, p as Flag, q as Siren, r as Timer, G as Gauge, s as Sun, E as Eye, M as Moon, t as ALargeSmall, u as Layers, v as FlaskConical, w as Sparkles, x as Activity, y as Beaker, N as Network, z as Terminal, J as Settings, K as Monitor, O as Rocket, Q as PackageCheck, V as History, W as Scan, Y as CircleAlert, Z as ArrowUpRight, _ as ArrowDownRight, $ as CodeXml, a0 as Cpu, a1 as FolderOpen, a2 as Bell, a3 as Clock3, a4 as ShieldAlert, a5 as EyeOff, a6 as ExternalLink, a7 as Clock, a8 as RotateCw, a9 as CircleCheckBig, aa as Pencil, ab as MessageSquare, ac as Zap, ad as Wrench, ae as Brain, af as Minus, ag as CircleX, ah as ShieldCheck, ai as Save, aj as FileSearch, ak as CloudUpload, al as CircleQuestionMark, am as Server, an as Lock, ao as Wifi, ap as WifiOff, aq as OctagonAlert, ar as Radio, as as Globe, at as FileTerminal, au as ChevronsUp, av as ChevronsDown, aw as FileDiff, ax as RotateCcw, ay as GitCompareArrows, az as ArrowUp, aA as ArrowDown, aB as Ellipsis, aC as Blocks, aD as MousePointerClick, aE as FileText, aF as Rows3, aG as Columns2 } from "../_libs/lucide-react.mjs";
13
13
  import { u as union, o as object, e as array, l as literal, n as number, d as boolean, b as string, _ as _enum } from "../_libs/zod.mjs";
14
14
  import { S as Select$1, a as SelectTrigger$1, b as SelectIcon, c as SelectValue$1, d as SelectPortal, e as SelectContent$1, f as SelectViewport, g as SelectItem$1, h as SelectItemIndicator, i as SelectItemText, j as SelectScrollUpButton$1, k as SelectScrollDownButton$1 } from "../_libs/radix-ui__react-select.mjs";
15
15
  import { D as Dialog$1, a as DialogContent$1, b as DialogClose, c as DialogTitle$1, d as DialogDescription$1, e as DialogPortal$1, f as DialogOverlay$1, g as DialogTrigger$1 } from "../_libs/radix-ui__react-dialog.mjs";
@@ -566,7 +566,11 @@ function cn(...inputs) {
566
566
  return twMerge(clsx(inputs));
567
567
  }
568
568
  function formatTokens(count) {
569
- if (count >= 1e6) return (count / 1e6).toFixed(1).replace(/\.0$/, "") + "M";
569
+ const absoluteCount = Math.abs(count);
570
+ if (absoluteCount < 1e3) return String(count);
571
+ if (absoluteCount >= 1e6) {
572
+ return (count / 1e6).toFixed(1).replace(/\.0$/, "") + "M";
573
+ }
570
574
  return (count / 1e3).toFixed(1).replace(/\.0$/, "") + "K";
571
575
  }
572
576
  function formatContextWindowTokens(count) {
@@ -874,7 +878,8 @@ const CLIENT_LABELS = {
874
878
  codex: "Codex",
875
879
  opencode: "OpenCode",
876
880
  "mimo-code": "MiMo Code",
877
- "claude-code": "Claude Code"
881
+ "claude-code": "Claude Code",
882
+ "ai-sdk": "AI SDK"
878
883
  };
879
884
  function normalize(value) {
880
885
  return value?.toLowerCase() ?? "";
@@ -902,6 +907,7 @@ function detectClientApp(input) {
902
907
  if (matchesAny(haystack, ["codex desktop", "codex-cli", "openai-codex", "codex"])) {
903
908
  return "codex";
904
909
  }
910
+ if (matchesAny(normalize(input.userAgent), ["ai-sdk", "ai/"])) return "ai-sdk";
905
911
  return "unknown";
906
912
  }
907
913
  function clientAppLabel(client) {
@@ -911,11 +917,25 @@ function clientAppLabel(client) {
911
917
  case "opencode":
912
918
  case "mimo-code":
913
919
  case "claude-code":
920
+ case "ai-sdk":
914
921
  return CLIENT_LABELS[client];
915
922
  case "unknown":
916
923
  return null;
917
924
  }
918
925
  }
926
+ function clientAppTypeLabel(client) {
927
+ switch (client) {
928
+ case "codex":
929
+ case "opencode":
930
+ case "mimo-code":
931
+ case "claude-code":
932
+ return "IDE";
933
+ case "agent-inspector":
934
+ case "ai-sdk":
935
+ case "unknown":
936
+ return "CLIENT";
937
+ }
938
+ }
919
939
  const CLIENT_LOGOS = {
920
940
  "agent-inspector": AgentInspectorLogo,
921
941
  codex: CodexLogoSvg,
@@ -924,11 +944,11 @@ const CLIENT_LOGOS = {
924
944
  "claude-code": ClaudeCodeLogoSvg
925
945
  };
926
946
  const CLIENT_LOGO_FRAMES = {
927
- "agent-inspector": "border-orange-200/25 bg-orange-300/[0.12]",
928
- codex: "border-cyan-200/20 bg-cyan-300/[0.08]",
929
- opencode: "border-sky-200/25 bg-sky-300/[0.12]",
930
- "mimo-code": "border-orange-200/25 bg-orange-400/[0.12]",
931
- "claude-code": "border-amber-100/20 bg-amber-300/[0.09]"
947
+ "agent-inspector": "border-orange-700/15 bg-orange-500/[0.08] dark:border-orange-200/25 dark:bg-orange-300/[0.12]",
948
+ codex: "border-cyan-700/15 bg-cyan-500/[0.08] dark:border-cyan-200/20 dark:bg-cyan-300/[0.08]",
949
+ opencode: "border-sky-700/15 bg-sky-500/[0.09] dark:border-sky-200/25 dark:bg-sky-300/[0.12]",
950
+ "mimo-code": "border-orange-700/15 bg-orange-500/[0.09] dark:border-orange-200/25 dark:bg-orange-400/[0.12]",
951
+ "claude-code": "border-amber-700/15 bg-amber-500/[0.08] dark:border-amber-100/20 dark:bg-amber-300/[0.09]"
932
952
  };
933
953
  const CLIENT_LOGO_IMAGES = {
934
954
  "agent-inspector": "p-0.5 drop-shadow-[0_0_8px_rgba(251,146,60,0.35)]",
@@ -939,11 +959,27 @@ const CLIENT_LOGO_IMAGES = {
939
959
  };
940
960
  function ClientLogo({
941
961
  client,
942
- className
962
+ className,
963
+ decorative = false
943
964
  }) {
944
965
  if (client === "unknown") return null;
945
966
  const label = clientAppLabel(client);
946
967
  if (label === null) return null;
968
+ if (client === "ai-sdk") {
969
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
970
+ "span",
971
+ {
972
+ className: cn(
973
+ "inline-flex size-6 shrink-0 items-center justify-center rounded-md border border-cyan-700/15 bg-cyan-500/[0.08] text-[var(--inspector-status-cool)] shadow-sm dark:border-cyan-200/20 dark:bg-cyan-300/[0.08]",
974
+ className
975
+ ),
976
+ "aria-label": decorative ? void 0 : label,
977
+ "aria-hidden": decorative ? true : void 0,
978
+ title: label,
979
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(CodeXml, { className: "size-1/2", "aria-hidden": "true" })
980
+ }
981
+ );
982
+ }
947
983
  const logoSrc = CLIENT_LOGOS[client];
948
984
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
949
985
  "span",
@@ -953,7 +989,8 @@ function ClientLogo({
953
989
  CLIENT_LOGO_FRAMES[client],
954
990
  className
955
991
  ),
956
- "aria-label": label,
992
+ "aria-label": decorative ? void 0 : label,
993
+ "aria-hidden": decorative ? true : void 0,
957
994
  title: label,
958
995
  children: /* @__PURE__ */ jsxRuntimeExports.jsx(
959
996
  "img",
@@ -1669,7 +1706,14 @@ function resolveLogFormat(log) {
1669
1706
  const pathFormat = apiFormatForPath(log.path);
1670
1707
  return pathFormat === "unknown" ? log.apiFormat : pathFormat;
1671
1708
  }
1672
- const HEADER_ACTION_BUTTON_CLASS$1 = "bg-white/[0.045] hover:bg-white/[0.075] inline-flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-md text-muted-foreground transition-colors hover:text-foreground";
1709
+ const HEADER_ACTION_BUTTON_CLASS$1 = "inline-flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-md bg-[var(--inspector-surface-low)] text-muted-foreground transition-colors hover:bg-[var(--inspector-surface-medium)] hover:text-foreground";
1710
+ function isSyntheticSessionId(conversationId) {
1711
+ return conversationId.startsWith("PID:") || conversationId.startsWith("process:") || conversationId.startsWith("connection:") || conversationId.includes("|");
1712
+ }
1713
+ function compactSessionLabel(conversationId) {
1714
+ if (isSyntheticSessionId(conversationId)) return "No session ID";
1715
+ return conversationId.length > 24 ? `${conversationId.slice(0, 12)}...${conversationId.slice(-12)}` : conversationId;
1716
+ }
1673
1717
  function HeaderMetric({
1674
1718
  icon,
1675
1719
  children,
@@ -1680,7 +1724,7 @@ function HeaderMetric({
1680
1724
  "span",
1681
1725
  {
1682
1726
  className: cn(
1683
- "bg-white/[0.045] inline-flex h-7 min-w-0 items-center gap-1.5 rounded-md px-2 text-xs text-muted-foreground",
1727
+ "inline-flex h-7 min-w-0 items-center gap-1.5 rounded-md bg-[var(--inspector-surface-low)] px-2 text-xs text-muted-foreground",
1684
1728
  className
1685
1729
  ),
1686
1730
  title,
@@ -1691,11 +1735,11 @@ function HeaderMetric({
1691
1735
  }
1692
1736
  );
1693
1737
  }
1694
- function PendingTurnBadge$1() {
1738
+ function PendingTurnBadge() {
1695
1739
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
1696
1740
  "span",
1697
1741
  {
1698
- className: "inline-flex h-6 shrink-0 items-center gap-1.5 rounded-md bg-amber-300/[0.10] px-1.5 font-mono text-[10px] uppercase tracking-[0.14em] text-amber-100/90 ring-1 ring-amber-200/10",
1742
+ className: "inline-flex h-6 shrink-0 items-center gap-1.5 rounded-md bg-[var(--inspector-surface-medium)] px-1.5 font-mono text-[10px] uppercase text-[var(--inspector-status-watch)] ring-1 ring-border/50",
1699
1743
  title: "This session has a turn that has not finished yet",
1700
1744
  children: [
1701
1745
  /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-3 animate-spin" }),
@@ -1745,8 +1789,8 @@ function ConversationHeader({
1745
1789
  const hasUserAgent = userAgent !== null && userAgent !== void 0 && userAgent !== "";
1746
1790
  const clientDisplayLabel = detectedClientLabel ?? userAgent ?? null;
1747
1791
  const clientTooltip = detectedClientLabel !== null && hasUserAgent ? `${detectedClientLabel} - ${userAgent}` : null;
1748
- const isFallbackConversation = conversationId.startsWith("PID:") || conversationId.includes("|");
1749
- const compactSessionLabel = conversationId.length > 24 ? conversationId.slice(0, 12) + "..." + conversationId.slice(-12) : conversationId;
1792
+ const isFallbackConversation = isSyntheticSessionId(conversationId);
1793
+ const sessionLabel = compactSessionLabel(conversationId);
1750
1794
  const timeLabel = formatTimestampRange(startTime, endTime, timeDisplayFormat);
1751
1795
  const callsLabel = `${totalCalls} call${totalCalls !== 1 ? "s" : ""}`;
1752
1796
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
@@ -1757,11 +1801,11 @@ function ConversationHeader({
1757
1801
  "data-nav-id": `conv-${conversationId}`,
1758
1802
  "data-nav-action": expanded ? "collapse" : "expand",
1759
1803
  className: cn(
1760
- "bg-card/80 shadow-sm relative flex cursor-pointer items-start gap-3 overflow-hidden rounded-[8px] px-3 py-2.5 transition-colors",
1761
- "hover:bg-card",
1804
+ "relative flex cursor-pointer items-start gap-2.5 overflow-hidden rounded-md bg-[var(--inspector-surface-low)] px-3 py-2.5 transition-colors",
1805
+ "hover:bg-[var(--inspector-surface-medium)]",
1762
1806
  "select-none",
1763
1807
  "sticky top-0 z-10 mb-2",
1764
- "focus-visible:ring-1 focus-visible:ring-cyan-300/35 focus-visible:outline-none"
1808
+ "focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none"
1765
1809
  ),
1766
1810
  onClick: onToggle,
1767
1811
  onKeyDown: (e) => {
@@ -1782,10 +1826,11 @@ function ConversationHeader({
1782
1826
  ),
1783
1827
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "min-w-0 flex-1", children: [
1784
1828
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: [
1829
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0 rounded bg-[var(--inspector-surface-medium)] px-1.5 py-0.5 font-mono text-[9px] uppercase text-muted-foreground", children: "Session" }),
1785
1830
  isFallbackConversation && showProcessMetadata ? clientPid !== null && clientPid !== void 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs(
1786
1831
  "span",
1787
1832
  {
1788
- className: "min-w-0 max-w-full truncate font-mono text-xs font-semibold text-violet-200",
1833
+ className: "min-w-0 max-w-full truncate font-mono text-xs font-semibold text-foreground",
1789
1834
  title: `PID ${clientPid}`,
1790
1835
  children: [
1791
1836
  "PID ",
@@ -1795,22 +1840,22 @@ function ConversationHeader({
1795
1840
  ) : /* @__PURE__ */ jsxRuntimeExports.jsx(
1796
1841
  "span",
1797
1842
  {
1798
- className: "min-w-0 max-w-full truncate font-mono text-xs font-semibold text-violet-200",
1843
+ className: "min-w-0 max-w-full truncate font-mono text-xs font-semibold text-foreground",
1799
1844
  title: conversationId,
1800
1845
  children: conversationId
1801
1846
  }
1802
1847
  ) : /* @__PURE__ */ jsxRuntimeExports.jsx(
1803
1848
  "span",
1804
1849
  {
1805
- className: "min-w-0 max-w-full truncate font-mono text-xs font-semibold text-violet-200",
1850
+ className: "min-w-0 max-w-full truncate font-mono text-xs font-semibold text-foreground",
1806
1851
  title: conversationId,
1807
- children: isFallbackConversation ? "sessionless" : compactSessionLabel
1852
+ children: sessionLabel
1808
1853
  }
1809
1854
  ),
1810
1855
  !isFallbackConversation && showProcessMetadata && clientPid !== null && clientPid !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
1811
1856
  "span",
1812
1857
  {
1813
- className: "bg-white/[0.045] shrink-0 rounded px-1.5 py-0.5 font-mono text-xs tabular-nums text-muted-foreground",
1858
+ className: "shrink-0 rounded bg-[var(--inspector-surface-medium)] px-1.5 py-0.5 font-mono text-xs tabular-nums text-muted-foreground",
1814
1859
  title: `Client process ID ${clientPid}`,
1815
1860
  children: [
1816
1861
  "PID ",
@@ -1829,23 +1874,23 @@ function ConversationHeader({
1829
1874
  showClientIdentity && clientDisplayLabel !== null && clientDisplayLabel !== "" && /* @__PURE__ */ jsxRuntimeExports.jsxs(
1830
1875
  "span",
1831
1876
  {
1832
- className: "bg-white/[0.045] inline-flex min-h-6 shrink-0 flex-wrap items-center gap-1 rounded-md px-1.5 py-0.5 text-xs text-muted-foreground",
1877
+ className: "inline-flex min-h-6 shrink-0 flex-wrap items-center gap-1 rounded-md bg-[var(--inspector-surface-medium)] px-1.5 py-0.5 text-xs text-muted-foreground",
1833
1878
  title: clientTooltip ?? clientDisplayLabel,
1834
1879
  children: [
1835
- /* @__PURE__ */ jsxRuntimeExports.jsx(ClientLogo, { client: clientApp, className: "size-4 shrink-0" }),
1880
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ClientLogo, { client: clientApp, className: "size-4 shrink-0", decorative: true }),
1836
1881
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono leading-snug tabular-nums", children: clientDisplayLabel })
1837
1882
  ]
1838
1883
  }
1839
1884
  ),
1840
- isLoading && /* @__PURE__ */ jsxRuntimeExports.jsx(PendingTurnBadge$1, {})
1885
+ isLoading && /* @__PURE__ */ jsxRuntimeExports.jsx(PendingTurnBadge, {})
1841
1886
  ] }),
1842
1887
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "mt-1.5 flex min-w-0 flex-wrap items-center gap-1.5", children: [
1843
1888
  /* @__PURE__ */ jsxRuntimeExports.jsx(HeaderMetric, { icon: /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "size-3 shrink-0" }), title: timeLabel, children: timeLabel }),
1844
1889
  /* @__PURE__ */ jsxRuntimeExports.jsx(HeaderMetric, { icon: /* @__PURE__ */ jsxRuntimeExports.jsx(MessageSquare, { className: "size-3 shrink-0" }), children: callsLabel }),
1845
1890
  /* @__PURE__ */ jsxRuntimeExports.jsxs(HeaderMetric, { icon: /* @__PURE__ */ jsxRuntimeExports.jsx(Zap, { className: "size-3 shrink-0" }), className: "max-w-full", children: [
1846
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-blue-400", children: formatTokens(totalInputTokens) }),
1891
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[var(--inspector-status-info)]", children: formatTokens(totalInputTokens) }),
1847
1892
  " / ",
1848
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-amber-400", children: formatTokens(totalOutputTokens) })
1893
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[var(--inspector-status-watch)]", children: formatTokens(totalOutputTokens) })
1849
1894
  ] })
1850
1895
  ] })
1851
1896
  ] }),
@@ -1880,7 +1925,7 @@ function ConversationHeader({
1880
1925
  /* @__PURE__ */ jsxRuntimeExports.jsx(
1881
1926
  "span",
1882
1927
  {
1883
- className: "bg-white/[0.045] hover:bg-white/[0.075] inline-flex size-8 shrink-0 items-center justify-center rounded-md text-slate-200",
1928
+ className: "inline-flex size-8 shrink-0 items-center justify-center rounded-md bg-[var(--inspector-surface-low)] text-muted-foreground transition-colors hover:bg-[var(--inspector-surface-medium)] hover:text-foreground",
1884
1929
  "aria-hidden": "true",
1885
1930
  children: expanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-4 shrink-0" }) : isLoading ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-4 shrink-0 animate-spin" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-4 shrink-0" })
1886
1931
  }
@@ -1889,9 +1934,9 @@ function ConversationHeader({
1889
1934
  isLoading && /* @__PURE__ */ jsxRuntimeExports.jsx(
1890
1935
  "span",
1891
1936
  {
1892
- className: "pointer-events-none absolute inset-x-3 bottom-0 h-px overflow-hidden rounded-full bg-white/[0.06]",
1937
+ className: "pointer-events-none absolute inset-x-3 bottom-0 h-px overflow-hidden rounded-full bg-[var(--inspector-surface-medium)]",
1893
1938
  "aria-hidden": "true",
1894
- children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "absolute inset-y-0 left-0 w-1/3 animate-pulse rounded-full bg-amber-200/65 shadow-[0_0_14px_rgba(252,211,77,0.32)]" })
1939
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "absolute inset-y-0 left-0 w-1/3 animate-pulse rounded-full bg-[var(--inspector-status-watch)] opacity-70" })
1895
1940
  }
1896
1941
  ),
1897
1942
  /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -2524,27 +2569,27 @@ function useCopyFeedback(text) {
2524
2569
  return { copied, copy };
2525
2570
  }
2526
2571
  const LazyCompareDrawer = reactExports.lazy(
2527
- () => import("./CompareDrawer-K2k9G7r1.mjs").then((m) => ({ default: m.CompareDrawer }))
2572
+ () => import("./CompareDrawer-R_P1-VNr.mjs").then((m) => ({ default: m.CompareDrawer }))
2528
2573
  );
2529
2574
  const LazyReplayDialog = reactExports.lazy(
2530
- () => import("./ReplayDialog-DacI2Iv0.mjs").then((m) => ({ default: m.ReplayDialog }))
2575
+ () => import("./ReplayDialog-De9wKKzS.mjs").then((m) => ({ default: m.ReplayDialog }))
2531
2576
  );
2532
2577
  const LazyRequestAnatomy = reactExports.lazy(
2533
- () => import("./RequestAnatomy-gh-pAdkO.mjs").then((m) => ({ default: m.RequestAnatomy }))
2578
+ () => import("./RequestAnatomy-Db4MxUYo.mjs").then((m) => ({ default: m.RequestAnatomy }))
2534
2579
  );
2535
2580
  const LazyResponseView = reactExports.lazy(
2536
- () => import("./ResponseView-BRJKN50-.mjs").then((m) => ({ default: m.ResponseView }))
2581
+ () => import("./ResponseView-8rDXOiNB.mjs").then((m) => ({ default: m.ResponseView }))
2537
2582
  );
2538
2583
  const LazyStreamingChunkSequence = reactExports.lazy(
2539
- () => import("./StreamingChunkSequence-BQLVEuWY.mjs").then((m) => ({
2584
+ () => import("./StreamingChunkSequence-N9teZHkA.mjs").then((m) => ({
2540
2585
  default: m.StreamingChunkSequence
2541
2586
  }))
2542
2587
  );
2543
2588
  const LazyJsonViewer = reactExports.lazy(
2544
- () => import("./json-viewer-DNs1ZjKI.mjs").then((m) => ({ default: m.JsonViewer }))
2589
+ () => import("./json-viewer-BjoHRbjS.mjs").then((m) => ({ default: m.JsonViewer }))
2545
2590
  );
2546
2591
  const LazyJsonViewerFromString = reactExports.lazy(
2547
- () => import("./json-viewer-DNs1ZjKI.mjs").then((m) => ({ default: m.JsonViewerFromString }))
2592
+ () => import("./json-viewer-BjoHRbjS.mjs").then((m) => ({ default: m.JsonViewerFromString }))
2548
2593
  );
2549
2594
  const HIGHLIGHT_DURATION_MS = 1200;
2550
2595
  const MAX_HIGHLIGHT_ATTEMPTS = 12;
@@ -6170,7 +6215,7 @@ const ConversationGroup = reactExports.memo(function({
6170
6215
  window.removeEventListener(LOG_FOCUS_REQUEST_EVENT, handleLogFocusRequest);
6171
6216
  };
6172
6217
  }, [group.logs, setExpanded]);
6173
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-2", children: [
6218
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-1.5", children: [
6174
6219
  /* @__PURE__ */ jsxRuntimeExports.jsx(
6175
6220
  ConversationHeader,
6176
6221
  {
@@ -12416,8 +12461,8 @@ function resolveInspectorPetStatus(logs, nowMs) {
12416
12461
  capturedCount
12417
12462
  };
12418
12463
  }
12419
- const latestTimestamp = Date.parse(latest.timestamp);
12420
- if (Number.isFinite(latestTimestamp) && nowMs - latestTimestamp >= INSPECTOR_PET_SLEEP_AFTER_MS) {
12464
+ const latestTimestamp2 = Date.parse(latest.timestamp);
12465
+ if (Number.isFinite(latestTimestamp2) && nowMs - latestTimestamp2 >= INSPECTOR_PET_SLEEP_AFTER_MS) {
12421
12466
  return {
12422
12467
  mood: "sleeping",
12423
12468
  label: "All quiet",
@@ -13043,16 +13088,6 @@ function InspectorPet({ logs }) {
13043
13088
  ) })
13044
13089
  }
13045
13090
  ),
13046
- /* @__PURE__ */ jsxRuntimeExports.jsx(
13047
- "span",
13048
- {
13049
- className: cn(
13050
- "absolute right-0 top-2 size-3 rounded-full border border-background/90",
13051
- moodDotClass(status.mood),
13052
- status.mood === "active" && !reduceMotion && "animate-pulse"
13053
- )
13054
- }
13055
- ),
13056
13091
  reactionVisible && /* @__PURE__ */ jsxRuntimeExports.jsx(
13057
13092
  Heart,
13058
13093
  {
@@ -13268,6 +13303,11 @@ function compareField(previous, current) {
13268
13303
  if (current < previous) return { direction: "down", delta: previous - current };
13269
13304
  return null;
13270
13305
  }
13306
+ const COLLAPSED_CLIENTS_STORAGE_KEY = "agent-inspector.hierarchy.collapsedClients";
13307
+ const COLLAPSED_PROCESSES_STORAGE_KEY = "agent-inspector.hierarchy.collapsedProcesses";
13308
+ function hasPendingLogs(logs) {
13309
+ return logs.some((log) => log.responseStatus === null);
13310
+ }
13271
13311
  function countPendingTurns(logs) {
13272
13312
  return logs.filter((log) => log.responseStatus === null).length;
13273
13313
  }
@@ -13302,9 +13342,9 @@ function groupClient(group) {
13302
13342
  });
13303
13343
  }
13304
13344
  function fallbackClientLabel(userAgent) {
13305
- if (userAgent === null || userAgent === "") return "Unknown IDE";
13345
+ if (userAgent === null || userAgent === "") return "Unknown client";
13306
13346
  const firstToken = userAgent.split(/[ /;]/)[0] ?? "";
13307
- if (firstToken === "") return "Unknown IDE";
13347
+ if (firstToken === "") return "Unknown client";
13308
13348
  return firstToken;
13309
13349
  }
13310
13350
  function clientLabel(client, userAgent) {
@@ -13326,22 +13366,41 @@ function processKey(clientPid, projectFolder) {
13326
13366
  function sortLogsByTimestamp(logs) {
13327
13367
  return [...logs].sort((a, b) => a.timestamp.localeCompare(b.timestamp));
13328
13368
  }
13329
- function firstTimestamp(logs) {
13330
- return sortLogsByTimestamp(logs)[0]?.timestamp ?? "";
13369
+ function latestTimestamp(logs) {
13370
+ let latest = "";
13371
+ for (const log of logs) {
13372
+ if (log.timestamp > latest) latest = log.timestamp;
13373
+ }
13374
+ return latest;
13331
13375
  }
13332
- function sortByFirstLogTime(items) {
13333
- return [...items].sort((a, b) => firstTimestamp(a.logs).localeCompare(firstTimestamp(b.logs)));
13376
+ function operationalPriority(logs) {
13377
+ if (hasPendingLogs(logs)) return 0;
13378
+ if (logs.some(
13379
+ (log) => log.error !== null && log.error !== void 0 || log.responseStatus !== null && log.responseStatus !== void 0 && log.responseStatus >= 400
13380
+ )) {
13381
+ return 1;
13382
+ }
13383
+ return 2;
13384
+ }
13385
+ function sortByOperationalPriority(items) {
13386
+ return [...items].sort((left, right) => {
13387
+ const priorityDifference = operationalPriority(left.logs) - operationalPriority(right.logs);
13388
+ if (priorityDifference !== 0) return priorityDifference;
13389
+ const recencyDifference = latestTimestamp(right.logs).localeCompare(latestTimestamp(left.logs));
13390
+ if (recencyDifference !== 0) return recencyDifference;
13391
+ return left.id.localeCompare(right.id);
13392
+ });
13334
13393
  }
13335
13394
  function buildConversationHierarchy(groups) {
13336
- const ideGroups = /* @__PURE__ */ new Map();
13395
+ const clientGroups = /* @__PURE__ */ new Map();
13337
13396
  for (const group of groups) {
13338
13397
  const userAgent = firstUserAgent(group.logs);
13339
13398
  const projectFolder = firstClientProjectFolder(group.logs);
13340
13399
  const client = groupClient(group);
13341
13400
  const currentIdeKey = ideKey(client, userAgent, projectFolder);
13342
- let ideGroup = ideGroups.get(currentIdeKey);
13343
- if (ideGroup === void 0) {
13344
- ideGroup = {
13401
+ let clientGroup = clientGroups.get(currentIdeKey);
13402
+ if (clientGroup === void 0) {
13403
+ clientGroup = {
13345
13404
  id: currentIdeKey,
13346
13405
  client,
13347
13406
  label: clientLabel(client, userAgent),
@@ -13349,12 +13408,12 @@ function buildConversationHierarchy(groups) {
13349
13408
  processes: /* @__PURE__ */ new Map(),
13350
13409
  logs: []
13351
13410
  };
13352
- ideGroups.set(currentIdeKey, ideGroup);
13411
+ clientGroups.set(currentIdeKey, clientGroup);
13353
13412
  }
13354
- ideGroup.logs.push(...group.logs);
13413
+ clientGroup.logs.push(...group.logs);
13355
13414
  const clientPid = firstClientPid(group.logs);
13356
13415
  const currentProcessKey = `${currentIdeKey}:${processKey(clientPid, projectFolder)}`;
13357
- let processGroup = ideGroup.processes.get(currentProcessKey);
13416
+ let processGroup = clientGroup.processes.get(currentProcessKey);
13358
13417
  if (processGroup === void 0) {
13359
13418
  processGroup = {
13360
13419
  id: currentProcessKey,
@@ -13363,32 +13422,32 @@ function buildConversationHierarchy(groups) {
13363
13422
  sessions: [],
13364
13423
  logs: []
13365
13424
  };
13366
- ideGroup.processes.set(currentProcessKey, processGroup);
13425
+ clientGroup.processes.set(currentProcessKey, processGroup);
13367
13426
  }
13368
13427
  processGroup.sessions.push(group);
13369
13428
  processGroup.logs.push(...group.logs);
13370
13429
  }
13371
13430
  const hierarchy = [];
13372
- for (const ideGroup of ideGroups.values()) {
13373
- const processes = sortByFirstLogTime(
13374
- [...ideGroup.processes.values()].map((processGroup) => ({
13431
+ for (const clientGroup of clientGroups.values()) {
13432
+ const processes = sortByOperationalPriority(
13433
+ [...clientGroup.processes.values()].map((processGroup) => ({
13375
13434
  id: processGroup.id,
13376
13435
  clientPid: processGroup.clientPid,
13377
13436
  clientProjectFolder: processGroup.clientProjectFolder,
13378
- sessions: sortByFirstLogTime(processGroup.sessions),
13437
+ sessions: sortByOperationalPriority(processGroup.sessions),
13379
13438
  logs: sortLogsByTimestamp(processGroup.logs)
13380
13439
  }))
13381
13440
  );
13382
13441
  hierarchy.push({
13383
- id: ideGroup.id,
13384
- client: ideGroup.client,
13385
- label: ideGroup.label,
13386
- userAgent: ideGroup.userAgent,
13442
+ id: clientGroup.id,
13443
+ client: clientGroup.client,
13444
+ label: clientGroup.label,
13445
+ userAgent: clientGroup.userAgent,
13387
13446
  processes,
13388
- logs: sortLogsByTimestamp(ideGroup.logs)
13447
+ logs: sortLogsByTimestamp(clientGroup.logs)
13389
13448
  });
13390
13449
  }
13391
- return sortByFirstLogTime(hierarchy);
13450
+ return sortByOperationalPriority(hierarchy);
13392
13451
  }
13393
13452
  function formatTokenCount(count) {
13394
13453
  if (count <= 0) return "0";
@@ -13412,6 +13471,44 @@ function countSessions(processes) {
13412
13471
  }
13413
13472
  return sessions;
13414
13473
  }
13474
+ function readStoredIdSet(storageKey) {
13475
+ if (typeof window === "undefined") return null;
13476
+ try {
13477
+ const storedValue = window.localStorage.getItem(storageKey);
13478
+ if (storedValue === null) return null;
13479
+ const parsed = JSON.parse(storedValue);
13480
+ if (!Array.isArray(parsed)) return null;
13481
+ return new Set(parsed.filter((value) => typeof value === "string"));
13482
+ } catch {
13483
+ return null;
13484
+ }
13485
+ }
13486
+ function persistIdSet(storageKey, values) {
13487
+ try {
13488
+ window.localStorage.setItem(storageKey, JSON.stringify([...values]));
13489
+ } catch {
13490
+ }
13491
+ }
13492
+ function removeIds(values, ids) {
13493
+ let changed = false;
13494
+ const next = new Set(values);
13495
+ for (const id of ids) {
13496
+ if (next.delete(id)) changed = true;
13497
+ }
13498
+ return changed ? next : values;
13499
+ }
13500
+ function buildDefaultCollapsedProcessIds(hierarchy) {
13501
+ const collapsedIds = /* @__PURE__ */ new Set();
13502
+ for (const clientGroup of hierarchy) {
13503
+ for (let index = 1; index < clientGroup.processes.length; index++) {
13504
+ const processGroup = clientGroup.processes[index];
13505
+ if (processGroup !== void 0 && !hasPendingLogs(processGroup.logs)) {
13506
+ collapsedIds.add(processGroup.id);
13507
+ }
13508
+ }
13509
+ }
13510
+ return collapsedIds;
13511
+ }
13415
13512
  function shortProjectPath(projectFolder) {
13416
13513
  if (projectFolder === null || projectFolder === "") return null;
13417
13514
  const parts = projectFolder.replaceAll("\\", "/").split("/").filter((part) => part !== "");
@@ -13430,57 +13527,69 @@ function SummaryChip({
13430
13527
  "span",
13431
13528
  {
13432
13529
  className: cn(
13433
- "bg-white/[0.045] inline-flex h-7 items-center gap-1 rounded-md px-2 text-xs text-muted-foreground",
13530
+ "inline-flex h-7 items-center gap-1 rounded-md bg-[var(--inspector-surface-low)] px-2 text-xs text-muted-foreground",
13434
13531
  className
13435
13532
  ),
13436
13533
  children: [
13437
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-[10px] uppercase tracking-[0.12em] text-white/35", children: label }),
13438
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums text-slate-100", children: value })
13534
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-[10px] uppercase text-muted-foreground/70", children: label }),
13535
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums text-foreground", children: value })
13439
13536
  ]
13440
13537
  }
13441
13538
  );
13442
13539
  }
13443
- function PendingTurnBadge({
13444
- count,
13445
- label = "Turn open"
13446
- }) {
13540
+ function AncestorActivityIndicator({ count }) {
13541
+ const label = `${count} open turn${count === 1 ? "" : "s"}`;
13447
13542
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
13448
13543
  "span",
13449
13544
  {
13450
- className: "inline-flex h-6 shrink-0 items-center gap-1.5 rounded-md bg-amber-300/[0.10] px-1.5 font-mono text-[10px] uppercase tracking-[0.14em] text-amber-100/90 ring-1 ring-amber-200/10",
13451
- title: `${count} turn${count !== 1 ? "s" : ""} not finished yet`,
13545
+ className: "relative inline-flex size-6 shrink-0 items-center justify-center rounded-md bg-[var(--inspector-surface-medium)] text-[var(--inspector-status-watch)] ring-1 ring-border/50",
13546
+ "aria-label": label,
13547
+ title: label,
13452
13548
  children: [
13453
13549
  /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-3 animate-spin" }),
13454
- label,
13455
- count > 1 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "tabular-nums", children: [
13456
- "x",
13457
- count
13458
- ] })
13550
+ count > 1 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "absolute translate-x-2 -translate-y-2 rounded bg-card px-0.5 font-mono text-[8px] tabular-nums text-[var(--inspector-status-watch)]", children: count })
13459
13551
  ]
13460
13552
  }
13461
13553
  );
13462
13554
  }
13463
- function LoadingSweep() {
13464
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
13465
- "span",
13466
- {
13467
- className: "pointer-events-none absolute inset-x-3 bottom-0 h-px overflow-hidden rounded-full bg-white/[0.06]",
13468
- "aria-hidden": "true",
13469
- children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "absolute inset-y-0 left-0 w-1/3 animate-pulse rounded-full bg-amber-200/65 shadow-[0_0_14px_rgba(252,211,77,0.32)]" })
13470
- }
13471
- );
13472
- }
13473
13555
  function ConversationGroupList({
13474
13556
  groups,
13475
13557
  ...groupProps
13476
13558
  }) {
13477
13559
  const hierarchy = reactExports.useMemo(() => buildConversationHierarchy(groups), [groups]);
13478
- const [collapsedIdeIds, setCollapsedIdeIds] = reactExports.useState(() => /* @__PURE__ */ new Set());
13479
- const [collapsedProcessIds, setCollapsedProcessIds] = reactExports.useState(
13560
+ const [collapsedClientIds, setCollapsedClientIds] = reactExports.useState(
13480
13561
  () => /* @__PURE__ */ new Set()
13481
13562
  );
13482
- const toggleIde = reactExports.useCallback((id) => {
13483
- setCollapsedIdeIds((previous) => {
13563
+ const [collapsedProcessIds, setCollapsedProcessIds] = reactExports.useState(
13564
+ () => buildDefaultCollapsedProcessIds(hierarchy)
13565
+ );
13566
+ const [storedCollapseStateLoaded, setStoredCollapseStateLoaded] = reactExports.useState(false);
13567
+ reactExports.useEffect(() => {
13568
+ const storedClientIds = readStoredIdSet(COLLAPSED_CLIENTS_STORAGE_KEY);
13569
+ const storedProcessIds = readStoredIdSet(COLLAPSED_PROCESSES_STORAGE_KEY);
13570
+ if (storedClientIds !== null) setCollapsedClientIds(storedClientIds);
13571
+ if (storedProcessIds !== null) setCollapsedProcessIds(storedProcessIds);
13572
+ setStoredCollapseStateLoaded(true);
13573
+ }, []);
13574
+ reactExports.useEffect(() => {
13575
+ if (!storedCollapseStateLoaded) return;
13576
+ persistIdSet(COLLAPSED_CLIENTS_STORAGE_KEY, collapsedClientIds);
13577
+ persistIdSet(COLLAPSED_PROCESSES_STORAGE_KEY, collapsedProcessIds);
13578
+ }, [collapsedClientIds, collapsedProcessIds, storedCollapseStateLoaded]);
13579
+ reactExports.useEffect(() => {
13580
+ const activeClientIds = new Set(
13581
+ hierarchy.filter((group) => hasPendingLogs(group.logs)).map((group) => group.id)
13582
+ );
13583
+ const activeProcessIds = new Set(
13584
+ hierarchy.flatMap(
13585
+ (group) => group.processes.filter((process) => hasPendingLogs(process.logs)).map((process) => process.id)
13586
+ )
13587
+ );
13588
+ setCollapsedClientIds((previous) => removeIds(previous, activeClientIds));
13589
+ setCollapsedProcessIds((previous) => removeIds(previous, activeProcessIds));
13590
+ }, [hierarchy]);
13591
+ const toggleClient = reactExports.useCallback((id) => {
13592
+ setCollapsedClientIds((previous) => {
13484
13593
  const next = new Set(previous);
13485
13594
  if (next.has(id)) {
13486
13595
  next.delete(id);
@@ -13501,24 +13610,24 @@ function ConversationGroupList({
13501
13610
  return next;
13502
13611
  });
13503
13612
  }, []);
13504
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-4", children: hierarchy.map((ideGroup) => /* @__PURE__ */ jsxRuntimeExports.jsx(
13505
- IdeGroupSection,
13613
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-2", children: hierarchy.map((clientGroup) => /* @__PURE__ */ jsxRuntimeExports.jsx(
13614
+ ClientGroupSection,
13506
13615
  {
13507
- group: ideGroup,
13508
- collapsed: collapsedIdeIds.has(ideGroup.id),
13616
+ group: clientGroup,
13617
+ collapsed: collapsedClientIds.has(clientGroup.id),
13509
13618
  collapsedProcessIds,
13510
- onToggleIde: () => toggleIde(ideGroup.id),
13619
+ onToggleClient: () => toggleClient(clientGroup.id),
13511
13620
  onToggleProcess: toggleProcess,
13512
13621
  conversationProps: groupProps
13513
13622
  },
13514
- ideGroup.id
13623
+ clientGroup.id
13515
13624
  )) });
13516
13625
  }
13517
- function IdeGroupSection({
13626
+ function ClientGroupSection({
13518
13627
  group,
13519
13628
  collapsed,
13520
13629
  collapsedProcessIds,
13521
- onToggleIde,
13630
+ onToggleClient,
13522
13631
  onToggleProcess,
13523
13632
  conversationProps
13524
13633
  }) {
@@ -13531,8 +13640,8 @@ function IdeGroupSection({
13531
13640
  "section",
13532
13641
  {
13533
13642
  className: cn(
13534
- "bg-card/75 shadow-sm relative isolate overflow-hidden rounded-[8px]",
13535
- isWorking && "bg-card/85"
13643
+ "relative isolate overflow-hidden rounded-[8px] bg-card/65",
13644
+ isWorking && "bg-card/80"
13536
13645
  ),
13537
13646
  "data-ide-group": group.id,
13538
13647
  children: [
@@ -13540,25 +13649,25 @@ function IdeGroupSection({
13540
13649
  "button",
13541
13650
  {
13542
13651
  type: "button",
13543
- className: "flex w-full min-w-0 items-center gap-3 px-4 py-3 text-left transition-colors hover:bg-white/[0.03] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-cyan-300/45",
13544
- onClick: onToggleIde,
13652
+ className: "grid w-full min-w-0 grid-cols-[2.25rem_minmax(0,1fr)_auto] items-center gap-2.5 px-3 py-2.5 text-left transition-colors hover:bg-[var(--inspector-surface-low)] focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
13653
+ onClick: onToggleClient,
13545
13654
  "aria-expanded": !collapsed,
13546
13655
  children: [
13547
- group.client === "unknown" ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "bg-white/[0.045] inline-flex size-10 shrink-0 items-center justify-center rounded-[8px] text-slate-200", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Monitor, { className: "size-5" }) }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ClientLogo, { client: group.client, className: "size-10 rounded-[8px] text-cyan-100" }),
13548
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "min-w-0 flex-1", children: [
13656
+ group.client === "unknown" ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "inline-flex size-9 shrink-0 items-center justify-center rounded-md bg-[var(--inspector-surface-low)] text-muted-foreground", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Monitor, { className: "size-4" }) }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ClientLogo, { client: group.client, className: "size-9 rounded-md", decorative: true }),
13657
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "min-w-0", children: [
13549
13658
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [
13550
13659
  /* @__PURE__ */ jsxRuntimeExports.jsx(
13551
13660
  "span",
13552
13661
  {
13553
- className: "truncate text-sm font-semibold text-slate-50",
13662
+ className: "truncate text-sm font-semibold text-foreground",
13554
13663
  title: group.userAgent ?? group.label,
13555
13664
  children: group.label
13556
13665
  }
13557
13666
  ),
13558
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "rounded bg-cyan-300/[0.06] px-1.5 py-0.5 font-mono text-[10px] uppercase tracking-[0.16em] text-cyan-100/75", children: "IDE" }),
13559
- isWorking && /* @__PURE__ */ jsxRuntimeExports.jsx(PendingTurnBadge, { count: pendingTurnCount, label: "Turn open" })
13667
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "rounded bg-[var(--inspector-surface-medium)] px-1.5 py-0.5 font-mono text-[9px] uppercase text-muted-foreground", children: clientAppTypeLabel(group.client) }),
13668
+ isWorking && /* @__PURE__ */ jsxRuntimeExports.jsx(AncestorActivityIndicator, { count: pendingTurnCount })
13560
13669
  ] }),
13561
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "mt-1 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground", children: [
13670
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "mt-1 flex flex-wrap items-center gap-x-3 gap-y-1 text-[11px] text-muted-foreground", children: [
13562
13671
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
13563
13672
  group.processes.length,
13564
13673
  " process",
@@ -13571,21 +13680,21 @@ function IdeGroupSection({
13571
13680
  ] }),
13572
13681
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
13573
13682
  logCount,
13574
- " log",
13575
- logCount !== 1 ? "s" : ""
13683
+ " req"
13576
13684
  ] })
13577
13685
  ] })
13578
13686
  ] }),
13579
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "hidden shrink-0 items-center gap-2 md:flex", children: [
13580
- /* @__PURE__ */ jsxRuntimeExports.jsx(SummaryChip, { label: "IN", value: formatTokenCount(totals.inputTokens) }),
13581
- /* @__PURE__ */ jsxRuntimeExports.jsx(SummaryChip, { label: "OUT", value: formatTokenCount(totals.outputTokens) })
13582
- ] }),
13583
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "bg-white/[0.045] hover:bg-white/[0.075] inline-flex size-8 shrink-0 items-center justify-center rounded-md text-slate-200", children: collapsed ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-4" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-4" }) })
13687
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex shrink-0 items-center gap-2", children: [
13688
+ collapsed && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "hidden shrink-0 items-center gap-2 md:flex", children: [
13689
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SummaryChip, { label: "IN", value: formatTokenCount(totals.inputTokens) }),
13690
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SummaryChip, { label: "OUT", value: formatTokenCount(totals.outputTokens) })
13691
+ ] }),
13692
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "inline-flex size-8 shrink-0 items-center justify-center rounded-md bg-[var(--inspector-surface-low)] text-muted-foreground transition-colors group-hover:bg-[var(--inspector-surface-medium)]", children: collapsed ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-4" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-4" }) })
13693
+ ] })
13584
13694
  ]
13585
13695
  }
13586
13696
  ),
13587
- isWorking && /* @__PURE__ */ jsxRuntimeExports.jsx(LoadingSweep, {}),
13588
- !collapsed && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-3 px-3 pb-3 pt-2 sm:px-4", children: group.processes.map((processGroup) => /* @__PURE__ */ jsxRuntimeExports.jsx(
13697
+ !collapsed && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-0.5 px-2 pb-2 pt-0.5", children: group.processes.map((processGroup) => /* @__PURE__ */ jsxRuntimeExports.jsx(
13589
13698
  ProcessGroupSection,
13590
13699
  {
13591
13700
  group: processGroup,
@@ -13611,69 +13720,66 @@ function ProcessGroupSection({
13611
13720
  const logCount = group.logs.length;
13612
13721
  const pendingTurnCount = countPendingTurns(group.logs);
13613
13722
  const isWorking = pendingTurnCount > 0;
13614
- const processLabel = group.clientPid !== null && group.clientPid !== void 0 ? `PID ${group.clientPid}` : "process";
13615
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "relative pl-5", children: [
13616
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "absolute bottom-1 left-2 top-1 w-px bg-white/[0.055]", "aria-hidden": "true" }),
13617
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-black/[0.10] relative overflow-hidden rounded-[8px]", children: [
13618
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
13619
- "button",
13620
- {
13621
- type: "button",
13622
- className: "flex w-full min-w-0 items-center gap-3 px-3 py-2.5 text-left transition-colors hover:bg-white/[0.035] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-cyan-300/40",
13623
- onClick: onToggle,
13624
- "aria-expanded": !collapsed,
13625
- children: [
13626
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "bg-white/[0.045] inline-flex size-8 shrink-0 items-center justify-center rounded-md text-amber-100", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Cpu, { className: "size-4" }) }),
13627
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "min-w-0 flex-1", children: [
13628
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: [
13629
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-xs font-semibold tabular-nums text-slate-100", children: processLabel }),
13630
- isWorking && /* @__PURE__ */ jsxRuntimeExports.jsx(PendingTurnBadge, { count: pendingTurnCount, label: "Turn open" }),
13631
- projectLabel !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs(
13632
- "span",
13633
- {
13634
- className: "inline-flex min-w-0 items-center gap-1 text-xs text-muted-foreground",
13635
- title: group.clientProjectFolder ?? projectLabel,
13636
- children: [
13637
- /* @__PURE__ */ jsxRuntimeExports.jsx(FolderOpen, { className: "size-3 shrink-0" }),
13638
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate font-mono", children: projectLabel })
13639
- ]
13640
- }
13641
- )
13723
+ const processLabel = group.clientPid !== null && group.clientPid !== void 0 ? `PID ${group.clientPid}` : "Process unavailable";
13724
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "relative pl-3", children: [
13725
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
13726
+ "button",
13727
+ {
13728
+ type: "button",
13729
+ className: "grid w-full min-w-0 grid-cols-[2rem_minmax(0,1fr)_auto] items-center gap-2.5 rounded-md bg-[var(--inspector-surface-low)] px-2.5 py-2 text-left transition-colors hover:bg-[var(--inspector-surface-medium)] focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
13730
+ onClick: onToggle,
13731
+ "aria-expanded": !collapsed,
13732
+ children: [
13733
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "inline-flex size-8 shrink-0 items-center justify-center text-[var(--inspector-status-watch)]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Cpu, { className: "size-4" }) }),
13734
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "min-w-0", children: [
13735
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: [
13736
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-xs font-semibold tabular-nums text-foreground", children: processLabel }),
13737
+ isWorking && /* @__PURE__ */ jsxRuntimeExports.jsx(AncestorActivityIndicator, { count: pendingTurnCount }),
13738
+ projectLabel !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs(
13739
+ "span",
13740
+ {
13741
+ className: "inline-flex min-w-0 items-center gap-1 text-[11px] text-muted-foreground",
13742
+ title: group.clientProjectFolder ?? projectLabel,
13743
+ children: [
13744
+ /* @__PURE__ */ jsxRuntimeExports.jsx(FolderOpen, { className: "size-3 shrink-0" }),
13745
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate font-mono", children: projectLabel })
13746
+ ]
13747
+ }
13748
+ )
13749
+ ] }),
13750
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "mt-1 flex flex-wrap items-center gap-x-3 gap-y-1 text-[11px] text-muted-foreground", children: [
13751
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
13752
+ sessionCount,
13753
+ " session",
13754
+ sessionCount !== 1 ? "s" : ""
13642
13755
  ] }),
13643
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "mt-1 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground", children: [
13644
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
13645
- sessionCount,
13646
- " session",
13647
- sessionCount !== 1 ? "s" : ""
13648
- ] }),
13649
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
13650
- logCount,
13651
- " log",
13652
- logCount !== 1 ? "s" : ""
13653
- ] })
13756
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
13757
+ logCount,
13758
+ " req"
13654
13759
  ] })
13655
- ] }),
13656
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "hidden shrink-0 items-center gap-2 md:flex", children: [
13760
+ ] })
13761
+ ] }),
13762
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex shrink-0 items-center gap-2", children: [
13763
+ collapsed && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "hidden shrink-0 items-center gap-2 md:flex", children: [
13657
13764
  /* @__PURE__ */ jsxRuntimeExports.jsx(SummaryChip, { label: "IN", value: formatTokenCount(totals.inputTokens) }),
13658
13765
  /* @__PURE__ */ jsxRuntimeExports.jsx(SummaryChip, { label: "OUT", value: formatTokenCount(totals.outputTokens) })
13659
13766
  ] }),
13660
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "bg-white/[0.045] hover:bg-white/[0.075] inline-flex size-7 shrink-0 items-center justify-center rounded-md text-slate-200", children: collapsed ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-4" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-4" }) })
13661
- ]
13662
- }
13663
- ),
13664
- isWorking && /* @__PURE__ */ jsxRuntimeExports.jsx(LoadingSweep, {}),
13665
- !collapsed && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-2 p-2 pt-1 sm:p-3 sm:pt-2", children: group.sessions.map((session) => /* @__PURE__ */ jsxRuntimeExports.jsx(
13666
- ConversationGroup,
13667
- {
13668
- group: session,
13669
- ...conversationProps,
13670
- showClientIdentity: false,
13671
- showLogClientMetadata: false,
13672
- showProcessMetadata: false
13673
- },
13674
- session.id
13675
- )) })
13676
- ] })
13767
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "inline-flex size-7 shrink-0 items-center justify-center rounded-md bg-[var(--inspector-surface-low)] text-muted-foreground transition-colors hover:bg-[var(--inspector-surface-medium)]", children: collapsed ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-4" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-4" }) })
13768
+ ] })
13769
+ ]
13770
+ }
13771
+ ),
13772
+ !collapsed && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1 pb-1 pl-3 pr-1 pt-1", children: group.sessions.map((session) => /* @__PURE__ */ jsxRuntimeExports.jsx(
13773
+ ConversationGroup,
13774
+ {
13775
+ group: session,
13776
+ ...conversationProps,
13777
+ showClientIdentity: false,
13778
+ showLogClientMetadata: false,
13779
+ showProcessMetadata: false
13780
+ },
13781
+ session.id
13782
+ )) })
13677
13783
  ] });
13678
13784
  }
13679
13785
  const NAV_ATTR = "data-nav-id";
@@ -15421,6 +15527,27 @@ function ThemeModeToggle() {
15421
15527
  }
15422
15528
  );
15423
15529
  }
15530
+ function PetVisibilityToggle({
15531
+ visible,
15532
+ onToggle
15533
+ }) {
15534
+ const label = visible ? "Hide Inspector pet" : "Summon Inspector pet";
15535
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
15536
+ "button",
15537
+ {
15538
+ type: "button",
15539
+ onClick: onToggle,
15540
+ className: cn(
15541
+ "border-border/70 bg-muted/70 inline-flex size-8 shrink-0 items-center justify-center rounded-md border text-muted-foreground shadow-sm transition-colors hover:bg-muted hover:text-foreground focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none",
15542
+ visible && "bg-background text-amber-500 shadow-sm"
15543
+ ),
15544
+ "aria-label": label,
15545
+ "aria-pressed": visible,
15546
+ title: label,
15547
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(CrabLogo, { className: cn("size-4 transition-opacity", !visible && "opacity-45") })
15548
+ }
15549
+ );
15550
+ }
15424
15551
  function UiScaleControl({
15425
15552
  preference,
15426
15553
  resolvedScale,
@@ -15532,11 +15659,20 @@ function BrandHeader({
15532
15659
  ] });
15533
15660
  }
15534
15661
  const DETAILS_PANEL_COLLAPSED_STORAGE_KEY = "agent-inspector.detailsPanelCollapsed";
15662
+ const INSPECTOR_PET_VISIBLE_STORAGE_KEY = "agent-inspector.pet.visible";
15535
15663
  function readStoredDetailsPanelCollapsed() {
15536
15664
  if (typeof window === "undefined") return true;
15537
15665
  const stored = window.localStorage.getItem(DETAILS_PANEL_COLLAPSED_STORAGE_KEY);
15538
15666
  return stored === null || stored === "1";
15539
15667
  }
15668
+ function readStoredInspectorPetVisible() {
15669
+ if (typeof window === "undefined") return true;
15670
+ try {
15671
+ return window.localStorage.getItem(INSPECTOR_PET_VISIBLE_STORAGE_KEY) !== "0";
15672
+ } catch {
15673
+ return true;
15674
+ }
15675
+ }
15540
15676
  function SessionContextLogButton({ label, logId }) {
15541
15677
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
15542
15678
  "button",
@@ -15863,6 +15999,8 @@ function ProxyViewer({
15863
15999
  const [deletingCurrentView, setDeletingCurrentView] = reactExports.useState(false);
15864
16000
  const [detailsPanelCollapsed, setDetailsPanelCollapsed] = reactExports.useState(true);
15865
16001
  const [detailsPanelStorageLoaded, setDetailsPanelStorageLoaded] = reactExports.useState(false);
16002
+ const [petVisible, setPetVisible] = reactExports.useState(true);
16003
+ const [petVisibilityStorageLoaded, setPetVisibilityStorageLoaded] = reactExports.useState(false);
15866
16004
  const [comparePair, setComparePair] = reactExports.useState(null);
15867
16005
  const [crabEntrancePhase, setCrabEntrancePhase] = reactExports.useState(
15868
16006
  "hidden"
@@ -15910,6 +16048,17 @@ function ProxyViewer({
15910
16048
  detailsPanelCollapsed ? "1" : "0"
15911
16049
  );
15912
16050
  }, [detailsPanelCollapsed, detailsPanelStorageLoaded]);
16051
+ reactExports.useEffect(() => {
16052
+ setPetVisible(readStoredInspectorPetVisible());
16053
+ setPetVisibilityStorageLoaded(true);
16054
+ }, []);
16055
+ reactExports.useEffect(() => {
16056
+ if (!petVisibilityStorageLoaded) return;
16057
+ try {
16058
+ window.localStorage.setItem(INSPECTOR_PET_VISIBLE_STORAGE_KEY, petVisible ? "1" : "0");
16059
+ } catch {
16060
+ }
16061
+ }, [petVisibilityStorageLoaded, petVisible]);
15913
16062
  reactExports.useEffect(() => {
15914
16063
  if (pinnedSessionId === void 0) {
15915
16064
  document.title = "Agent Inspector";
@@ -16027,6 +16176,9 @@ function ProxyViewer({
16027
16176
  const toggleDetailsPanelCollapsed = reactExports.useCallback(() => {
16028
16177
  setDetailsPanelCollapsed((value) => !value);
16029
16178
  }, []);
16179
+ const togglePetVisibility = reactExports.useCallback(() => {
16180
+ setPetVisible((value) => !value);
16181
+ }, []);
16030
16182
  const groups = reactExports.useMemo(() => groupLogsByConversation(logs), [logs]);
16031
16183
  const displayNumberByLogId = reactExports.useMemo(() => buildDisplayNumberByLogId(groups), [groups]);
16032
16184
  const sessionContextScope = reactExports.useMemo(
@@ -16105,7 +16257,7 @@ function ProxyViewer({
16105
16257
  ]
16106
16258
  }
16107
16259
  ),
16108
- detailsPanelCollapsed && /* @__PURE__ */ jsxRuntimeExports.jsx(InspectorPet, { logs }),
16260
+ petVisibilityStorageLoaded && petVisible && /* @__PURE__ */ jsxRuntimeExports.jsx(InspectorPet, { logs }),
16109
16261
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
16110
16262
  "div",
16111
16263
  {
@@ -16229,6 +16381,7 @@ function ProxyViewer({
16229
16381
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm font-semibold text-foreground", children: "Logs" }),
16230
16382
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-0.5 font-mono text-[11px] text-muted-foreground", children: activeScopeLabel })
16231
16383
  ] }),
16384
+ /* @__PURE__ */ jsxRuntimeExports.jsx(PetVisibilityToggle, { visible: petVisible, onToggle: togglePetVisibility }),
16232
16385
  onImportLogs !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
16233
16386
  /* @__PURE__ */ jsxRuntimeExports.jsx(
16234
16387
  "input",