@tonyclaw/agent-inspector 3.0.27 → 3.0.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/{CompareDrawer-BVCAAbbu.js → CompareDrawer-TghZr5t1.js} +1 -1
  3. package/.output/public/assets/{ProxyViewerContainer-CYOXB81n.js → ProxyViewerContainer-fShBAZjj.js} +198 -198
  4. package/.output/public/assets/{ReplayDialog-DMX23O5G.js → ReplayDialog-CZMApaF4.js} +1 -1
  5. package/.output/public/assets/{RequestAnatomy-S17pYDRc.js → RequestAnatomy-DNWccR7O.js} +1 -1
  6. package/.output/public/assets/{ResponseView-Cf1XrawD.js → ResponseView-d25MdFhY.js} +2 -2
  7. package/.output/public/assets/{StreamingChunkSequence-BdOrVlCi.js → StreamingChunkSequence-DIFZEnWe.js} +1 -1
  8. package/.output/public/assets/{_sessionId-BnKGmJrR.js → _sessionId-DRfvuE2k.js} +1 -1
  9. package/.output/public/assets/{index-9fMLCU4d.js → index-B3aAuqWq.js} +1 -1
  10. package/.output/public/assets/index-BsxAGqMA.css +1 -0
  11. package/.output/public/assets/{index-gY3I-7-D.js → index-D4HkS7Ct.js} +1 -1
  12. package/.output/public/assets/{index-B1atk19i.js → index-DzARL2Fi.js} +3 -3
  13. package/.output/public/assets/{json-viewer-CpyYpPjx.js → json-viewer-wuJSKaed.js} +1 -1
  14. package/.output/server/_libs/lucide-react.mjs +39 -39
  15. package/.output/server/{_sessionId-eA_h2_s6.mjs → _sessionId-BJTNiP_O.mjs} +2 -2
  16. package/.output/server/_ssr/{CompareDrawer-K2k9G7r1.mjs → CompareDrawer-BMRH3N97.mjs} +3 -3
  17. package/.output/server/_ssr/{ProxyViewerContainer-CbyBpCAj.mjs → ProxyViewerContainer-AFwcHAIR.mjs} +312 -172
  18. package/.output/server/_ssr/{ReplayDialog-DacI2Iv0.mjs → ReplayDialog-CbWvRHiN.mjs} +4 -4
  19. package/.output/server/_ssr/{RequestAnatomy-gh-pAdkO.mjs → RequestAnatomy-C4kcPyqN.mjs} +2 -2
  20. package/.output/server/_ssr/{ResponseView-BRJKN50-.mjs → ResponseView-D8VYt-gZ.mjs} +3 -3
  21. package/.output/server/_ssr/{StreamingChunkSequence-BQLVEuWY.mjs → StreamingChunkSequence-BUUo6vU0.mjs} +2 -2
  22. package/.output/server/_ssr/{index-DuSWrjbH.mjs → index-DTwMEEXO.mjs} +2 -2
  23. package/.output/server/_ssr/index.mjs +2 -2
  24. package/.output/server/_ssr/{json-viewer-DNs1ZjKI.mjs → json-viewer-BqF1pSQD.mjs} +3 -3
  25. package/.output/server/_ssr/{router-Dgx6-ot3.mjs → router-C8BOns7y.mjs} +138 -162
  26. package/.output/server/{_tanstack-start-manifest_v-CoGjnkQD.mjs → _tanstack-start-manifest_v-BBf2nRhb.mjs} +1 -1
  27. package/.output/server/index.mjs +74 -74
  28. package/package.json +1 -1
  29. package/src/components/ProxyViewer.tsx +57 -1
  30. package/src/components/clients/ClientLogo.tsx +43 -4
  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 +233 -152
  34. package/src/components/proxy-viewer/ConversationHeader.tsx +29 -13
  35. package/src/lib/jsonFile.ts +46 -0
  36. package/src/proxy/evidenceAnalysis.ts +116 -117
  37. package/src/proxy/groupEvidenceExporter.ts +4 -8
  38. package/src/proxy/groupStore.ts +3 -10
  39. package/src/proxy/providerSecretStore.ts +4 -8
  40. package/src/proxy/runFailures.ts +4 -10
  41. package/src/proxy/runStore.ts +4 -11
  42. 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-C8BOns7y.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";
@@ -874,7 +874,8 @@ const CLIENT_LABELS = {
874
874
  codex: "Codex",
875
875
  opencode: "OpenCode",
876
876
  "mimo-code": "MiMo Code",
877
- "claude-code": "Claude Code"
877
+ "claude-code": "Claude Code",
878
+ "ai-sdk": "AI SDK"
878
879
  };
879
880
  function normalize(value) {
880
881
  return value?.toLowerCase() ?? "";
@@ -902,6 +903,7 @@ function detectClientApp(input) {
902
903
  if (matchesAny(haystack, ["codex desktop", "codex-cli", "openai-codex", "codex"])) {
903
904
  return "codex";
904
905
  }
906
+ if (matchesAny(normalize(input.userAgent), ["ai-sdk", "ai/"])) return "ai-sdk";
905
907
  return "unknown";
906
908
  }
907
909
  function clientAppLabel(client) {
@@ -911,11 +913,25 @@ function clientAppLabel(client) {
911
913
  case "opencode":
912
914
  case "mimo-code":
913
915
  case "claude-code":
916
+ case "ai-sdk":
914
917
  return CLIENT_LABELS[client];
915
918
  case "unknown":
916
919
  return null;
917
920
  }
918
921
  }
922
+ function clientAppTypeLabel(client) {
923
+ switch (client) {
924
+ case "codex":
925
+ case "opencode":
926
+ case "mimo-code":
927
+ case "claude-code":
928
+ return "IDE";
929
+ case "agent-inspector":
930
+ case "ai-sdk":
931
+ case "unknown":
932
+ return "CLIENT";
933
+ }
934
+ }
919
935
  const CLIENT_LOGOS = {
920
936
  "agent-inspector": AgentInspectorLogo,
921
937
  codex: CodexLogoSvg,
@@ -939,11 +955,27 @@ const CLIENT_LOGO_IMAGES = {
939
955
  };
940
956
  function ClientLogo({
941
957
  client,
942
- className
958
+ className,
959
+ decorative = false
943
960
  }) {
944
961
  if (client === "unknown") return null;
945
962
  const label = clientAppLabel(client);
946
963
  if (label === null) return null;
964
+ if (client === "ai-sdk") {
965
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
966
+ "span",
967
+ {
968
+ className: cn(
969
+ "inline-flex size-6 shrink-0 items-center justify-center rounded-md border border-cyan-200/20 bg-cyan-300/[0.08] text-cyan-100 shadow-sm",
970
+ className
971
+ ),
972
+ "aria-label": decorative ? void 0 : label,
973
+ "aria-hidden": decorative ? true : void 0,
974
+ title: label,
975
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(CodeXml, { className: "size-1/2", "aria-hidden": "true" })
976
+ }
977
+ );
978
+ }
947
979
  const logoSrc = CLIENT_LOGOS[client];
948
980
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
949
981
  "span",
@@ -953,7 +985,8 @@ function ClientLogo({
953
985
  CLIENT_LOGO_FRAMES[client],
954
986
  className
955
987
  ),
956
- "aria-label": label,
988
+ "aria-label": decorative ? void 0 : label,
989
+ "aria-hidden": decorative ? true : void 0,
957
990
  title: label,
958
991
  children: /* @__PURE__ */ jsxRuntimeExports.jsx(
959
992
  "img",
@@ -1670,6 +1703,13 @@ function resolveLogFormat(log) {
1670
1703
  return pathFormat === "unknown" ? log.apiFormat : pathFormat;
1671
1704
  }
1672
1705
  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";
1706
+ function isSyntheticSessionId(conversationId) {
1707
+ return conversationId.startsWith("PID:") || conversationId.startsWith("process:") || conversationId.startsWith("connection:") || conversationId.includes("|");
1708
+ }
1709
+ function compactSessionLabel(conversationId) {
1710
+ if (isSyntheticSessionId(conversationId)) return "Sessionless";
1711
+ return conversationId.length > 24 ? `${conversationId.slice(0, 12)}...${conversationId.slice(-12)}` : conversationId;
1712
+ }
1673
1713
  function HeaderMetric({
1674
1714
  icon,
1675
1715
  children,
@@ -1691,11 +1731,11 @@ function HeaderMetric({
1691
1731
  }
1692
1732
  );
1693
1733
  }
1694
- function PendingTurnBadge$1() {
1734
+ function PendingTurnBadge() {
1695
1735
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
1696
1736
  "span",
1697
1737
  {
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",
1738
+ 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 text-amber-100/90 ring-1 ring-amber-200/10",
1699
1739
  title: "This session has a turn that has not finished yet",
1700
1740
  children: [
1701
1741
  /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-3 animate-spin" }),
@@ -1745,8 +1785,8 @@ function ConversationHeader({
1745
1785
  const hasUserAgent = userAgent !== null && userAgent !== void 0 && userAgent !== "";
1746
1786
  const clientDisplayLabel = detectedClientLabel ?? userAgent ?? null;
1747
1787
  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;
1788
+ const isFallbackConversation = isSyntheticSessionId(conversationId);
1789
+ const sessionLabel = compactSessionLabel(conversationId);
1750
1790
  const timeLabel = formatTimestampRange(startTime, endTime, timeDisplayFormat);
1751
1791
  const callsLabel = `${totalCalls} call${totalCalls !== 1 ? "s" : ""}`;
1752
1792
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
@@ -1757,8 +1797,8 @@ function ConversationHeader({
1757
1797
  "data-nav-id": `conv-${conversationId}`,
1758
1798
  "data-nav-action": expanded ? "collapse" : "expand",
1759
1799
  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",
1800
+ "bg-black/[0.10] relative flex cursor-pointer items-start gap-2.5 overflow-hidden rounded-[8px] px-3 py-2.5 transition-colors",
1801
+ "hover:bg-black/[0.16]",
1762
1802
  "select-none",
1763
1803
  "sticky top-0 z-10 mb-2",
1764
1804
  "focus-visible:ring-1 focus-visible:ring-cyan-300/35 focus-visible:outline-none"
@@ -1782,10 +1822,11 @@ function ConversationHeader({
1782
1822
  ),
1783
1823
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "min-w-0 flex-1", children: [
1784
1824
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: [
1825
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0 rounded bg-white/[0.04] px-1.5 py-0.5 font-mono text-[9px] uppercase text-muted-foreground/70", children: "Session" }),
1785
1826
  isFallbackConversation && showProcessMetadata ? clientPid !== null && clientPid !== void 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs(
1786
1827
  "span",
1787
1828
  {
1788
- className: "min-w-0 max-w-full truncate font-mono text-xs font-semibold text-violet-200",
1829
+ className: "min-w-0 max-w-full truncate font-mono text-xs font-semibold text-slate-100",
1789
1830
  title: `PID ${clientPid}`,
1790
1831
  children: [
1791
1832
  "PID ",
@@ -1795,16 +1836,16 @@ function ConversationHeader({
1795
1836
  ) : /* @__PURE__ */ jsxRuntimeExports.jsx(
1796
1837
  "span",
1797
1838
  {
1798
- className: "min-w-0 max-w-full truncate font-mono text-xs font-semibold text-violet-200",
1839
+ className: "min-w-0 max-w-full truncate font-mono text-xs font-semibold text-slate-100",
1799
1840
  title: conversationId,
1800
1841
  children: conversationId
1801
1842
  }
1802
1843
  ) : /* @__PURE__ */ jsxRuntimeExports.jsx(
1803
1844
  "span",
1804
1845
  {
1805
- className: "min-w-0 max-w-full truncate font-mono text-xs font-semibold text-violet-200",
1846
+ className: "min-w-0 max-w-full truncate font-mono text-xs font-semibold text-slate-100",
1806
1847
  title: conversationId,
1807
- children: isFallbackConversation ? "sessionless" : compactSessionLabel
1848
+ children: sessionLabel
1808
1849
  }
1809
1850
  ),
1810
1851
  !isFallbackConversation && showProcessMetadata && clientPid !== null && clientPid !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
@@ -1832,12 +1873,12 @@ function ConversationHeader({
1832
1873
  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",
1833
1874
  title: clientTooltip ?? clientDisplayLabel,
1834
1875
  children: [
1835
- /* @__PURE__ */ jsxRuntimeExports.jsx(ClientLogo, { client: clientApp, className: "size-4 shrink-0" }),
1876
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ClientLogo, { client: clientApp, className: "size-4 shrink-0", decorative: true }),
1836
1877
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono leading-snug tabular-nums", children: clientDisplayLabel })
1837
1878
  ]
1838
1879
  }
1839
1880
  ),
1840
- isLoading && /* @__PURE__ */ jsxRuntimeExports.jsx(PendingTurnBadge$1, {})
1881
+ isLoading && /* @__PURE__ */ jsxRuntimeExports.jsx(PendingTurnBadge, {})
1841
1882
  ] }),
1842
1883
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "mt-1.5 flex min-w-0 flex-wrap items-center gap-1.5", children: [
1843
1884
  /* @__PURE__ */ jsxRuntimeExports.jsx(HeaderMetric, { icon: /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "size-3 shrink-0" }), title: timeLabel, children: timeLabel }),
@@ -2524,27 +2565,27 @@ function useCopyFeedback(text) {
2524
2565
  return { copied, copy };
2525
2566
  }
2526
2567
  const LazyCompareDrawer = reactExports.lazy(
2527
- () => import("./CompareDrawer-K2k9G7r1.mjs").then((m) => ({ default: m.CompareDrawer }))
2568
+ () => import("./CompareDrawer-BMRH3N97.mjs").then((m) => ({ default: m.CompareDrawer }))
2528
2569
  );
2529
2570
  const LazyReplayDialog = reactExports.lazy(
2530
- () => import("./ReplayDialog-DacI2Iv0.mjs").then((m) => ({ default: m.ReplayDialog }))
2571
+ () => import("./ReplayDialog-CbWvRHiN.mjs").then((m) => ({ default: m.ReplayDialog }))
2531
2572
  );
2532
2573
  const LazyRequestAnatomy = reactExports.lazy(
2533
- () => import("./RequestAnatomy-gh-pAdkO.mjs").then((m) => ({ default: m.RequestAnatomy }))
2574
+ () => import("./RequestAnatomy-C4kcPyqN.mjs").then((m) => ({ default: m.RequestAnatomy }))
2534
2575
  );
2535
2576
  const LazyResponseView = reactExports.lazy(
2536
- () => import("./ResponseView-BRJKN50-.mjs").then((m) => ({ default: m.ResponseView }))
2577
+ () => import("./ResponseView-D8VYt-gZ.mjs").then((m) => ({ default: m.ResponseView }))
2537
2578
  );
2538
2579
  const LazyStreamingChunkSequence = reactExports.lazy(
2539
- () => import("./StreamingChunkSequence-BQLVEuWY.mjs").then((m) => ({
2580
+ () => import("./StreamingChunkSequence-BUUo6vU0.mjs").then((m) => ({
2540
2581
  default: m.StreamingChunkSequence
2541
2582
  }))
2542
2583
  );
2543
2584
  const LazyJsonViewer = reactExports.lazy(
2544
- () => import("./json-viewer-DNs1ZjKI.mjs").then((m) => ({ default: m.JsonViewer }))
2585
+ () => import("./json-viewer-BqF1pSQD.mjs").then((m) => ({ default: m.JsonViewer }))
2545
2586
  );
2546
2587
  const LazyJsonViewerFromString = reactExports.lazy(
2547
- () => import("./json-viewer-DNs1ZjKI.mjs").then((m) => ({ default: m.JsonViewerFromString }))
2588
+ () => import("./json-viewer-BqF1pSQD.mjs").then((m) => ({ default: m.JsonViewerFromString }))
2548
2589
  );
2549
2590
  const HIGHLIGHT_DURATION_MS = 1200;
2550
2591
  const MAX_HIGHLIGHT_ATTEMPTS = 12;
@@ -6170,7 +6211,7 @@ const ConversationGroup = reactExports.memo(function({
6170
6211
  window.removeEventListener(LOG_FOCUS_REQUEST_EVENT, handleLogFocusRequest);
6171
6212
  };
6172
6213
  }, [group.logs, setExpanded]);
6173
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-2", children: [
6214
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-1.5", children: [
6174
6215
  /* @__PURE__ */ jsxRuntimeExports.jsx(
6175
6216
  ConversationHeader,
6176
6217
  {
@@ -12416,8 +12457,8 @@ function resolveInspectorPetStatus(logs, nowMs) {
12416
12457
  capturedCount
12417
12458
  };
12418
12459
  }
12419
- const latestTimestamp = Date.parse(latest.timestamp);
12420
- if (Number.isFinite(latestTimestamp) && nowMs - latestTimestamp >= INSPECTOR_PET_SLEEP_AFTER_MS) {
12460
+ const latestTimestamp2 = Date.parse(latest.timestamp);
12461
+ if (Number.isFinite(latestTimestamp2) && nowMs - latestTimestamp2 >= INSPECTOR_PET_SLEEP_AFTER_MS) {
12421
12462
  return {
12422
12463
  mood: "sleeping",
12423
12464
  label: "All quiet",
@@ -13043,16 +13084,6 @@ function InspectorPet({ logs }) {
13043
13084
  ) })
13044
13085
  }
13045
13086
  ),
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
13087
  reactionVisible && /* @__PURE__ */ jsxRuntimeExports.jsx(
13057
13088
  Heart,
13058
13089
  {
@@ -13268,6 +13299,11 @@ function compareField(previous, current) {
13268
13299
  if (current < previous) return { direction: "down", delta: previous - current };
13269
13300
  return null;
13270
13301
  }
13302
+ const COLLAPSED_CLIENTS_STORAGE_KEY = "agent-inspector.hierarchy.collapsedClients";
13303
+ const COLLAPSED_PROCESSES_STORAGE_KEY = "agent-inspector.hierarchy.collapsedProcesses";
13304
+ function hasPendingLogs(logs) {
13305
+ return logs.some((log) => log.responseStatus === null);
13306
+ }
13271
13307
  function countPendingTurns(logs) {
13272
13308
  return logs.filter((log) => log.responseStatus === null).length;
13273
13309
  }
@@ -13302,9 +13338,9 @@ function groupClient(group) {
13302
13338
  });
13303
13339
  }
13304
13340
  function fallbackClientLabel(userAgent) {
13305
- if (userAgent === null || userAgent === "") return "Unknown IDE";
13341
+ if (userAgent === null || userAgent === "") return "Unknown client";
13306
13342
  const firstToken = userAgent.split(/[ /;]/)[0] ?? "";
13307
- if (firstToken === "") return "Unknown IDE";
13343
+ if (firstToken === "") return "Unknown client";
13308
13344
  return firstToken;
13309
13345
  }
13310
13346
  function clientLabel(client, userAgent) {
@@ -13326,22 +13362,41 @@ function processKey(clientPid, projectFolder) {
13326
13362
  function sortLogsByTimestamp(logs) {
13327
13363
  return [...logs].sort((a, b) => a.timestamp.localeCompare(b.timestamp));
13328
13364
  }
13329
- function firstTimestamp(logs) {
13330
- return sortLogsByTimestamp(logs)[0]?.timestamp ?? "";
13365
+ function latestTimestamp(logs) {
13366
+ let latest = "";
13367
+ for (const log of logs) {
13368
+ if (log.timestamp > latest) latest = log.timestamp;
13369
+ }
13370
+ return latest;
13331
13371
  }
13332
- function sortByFirstLogTime(items) {
13333
- return [...items].sort((a, b) => firstTimestamp(a.logs).localeCompare(firstTimestamp(b.logs)));
13372
+ function operationalPriority(logs) {
13373
+ if (hasPendingLogs(logs)) return 0;
13374
+ if (logs.some(
13375
+ (log) => log.error !== null && log.error !== void 0 || log.responseStatus !== null && log.responseStatus !== void 0 && log.responseStatus >= 400
13376
+ )) {
13377
+ return 1;
13378
+ }
13379
+ return 2;
13380
+ }
13381
+ function sortByOperationalPriority(items) {
13382
+ return [...items].sort((left, right) => {
13383
+ const priorityDifference = operationalPriority(left.logs) - operationalPriority(right.logs);
13384
+ if (priorityDifference !== 0) return priorityDifference;
13385
+ const recencyDifference = latestTimestamp(right.logs).localeCompare(latestTimestamp(left.logs));
13386
+ if (recencyDifference !== 0) return recencyDifference;
13387
+ return left.id.localeCompare(right.id);
13388
+ });
13334
13389
  }
13335
13390
  function buildConversationHierarchy(groups) {
13336
- const ideGroups = /* @__PURE__ */ new Map();
13391
+ const clientGroups = /* @__PURE__ */ new Map();
13337
13392
  for (const group of groups) {
13338
13393
  const userAgent = firstUserAgent(group.logs);
13339
13394
  const projectFolder = firstClientProjectFolder(group.logs);
13340
13395
  const client = groupClient(group);
13341
13396
  const currentIdeKey = ideKey(client, userAgent, projectFolder);
13342
- let ideGroup = ideGroups.get(currentIdeKey);
13343
- if (ideGroup === void 0) {
13344
- ideGroup = {
13397
+ let clientGroup = clientGroups.get(currentIdeKey);
13398
+ if (clientGroup === void 0) {
13399
+ clientGroup = {
13345
13400
  id: currentIdeKey,
13346
13401
  client,
13347
13402
  label: clientLabel(client, userAgent),
@@ -13349,12 +13404,12 @@ function buildConversationHierarchy(groups) {
13349
13404
  processes: /* @__PURE__ */ new Map(),
13350
13405
  logs: []
13351
13406
  };
13352
- ideGroups.set(currentIdeKey, ideGroup);
13407
+ clientGroups.set(currentIdeKey, clientGroup);
13353
13408
  }
13354
- ideGroup.logs.push(...group.logs);
13409
+ clientGroup.logs.push(...group.logs);
13355
13410
  const clientPid = firstClientPid(group.logs);
13356
13411
  const currentProcessKey = `${currentIdeKey}:${processKey(clientPid, projectFolder)}`;
13357
- let processGroup = ideGroup.processes.get(currentProcessKey);
13412
+ let processGroup = clientGroup.processes.get(currentProcessKey);
13358
13413
  if (processGroup === void 0) {
13359
13414
  processGroup = {
13360
13415
  id: currentProcessKey,
@@ -13363,32 +13418,32 @@ function buildConversationHierarchy(groups) {
13363
13418
  sessions: [],
13364
13419
  logs: []
13365
13420
  };
13366
- ideGroup.processes.set(currentProcessKey, processGroup);
13421
+ clientGroup.processes.set(currentProcessKey, processGroup);
13367
13422
  }
13368
13423
  processGroup.sessions.push(group);
13369
13424
  processGroup.logs.push(...group.logs);
13370
13425
  }
13371
13426
  const hierarchy = [];
13372
- for (const ideGroup of ideGroups.values()) {
13373
- const processes = sortByFirstLogTime(
13374
- [...ideGroup.processes.values()].map((processGroup) => ({
13427
+ for (const clientGroup of clientGroups.values()) {
13428
+ const processes = sortByOperationalPriority(
13429
+ [...clientGroup.processes.values()].map((processGroup) => ({
13375
13430
  id: processGroup.id,
13376
13431
  clientPid: processGroup.clientPid,
13377
13432
  clientProjectFolder: processGroup.clientProjectFolder,
13378
- sessions: sortByFirstLogTime(processGroup.sessions),
13433
+ sessions: sortByOperationalPriority(processGroup.sessions),
13379
13434
  logs: sortLogsByTimestamp(processGroup.logs)
13380
13435
  }))
13381
13436
  );
13382
13437
  hierarchy.push({
13383
- id: ideGroup.id,
13384
- client: ideGroup.client,
13385
- label: ideGroup.label,
13386
- userAgent: ideGroup.userAgent,
13438
+ id: clientGroup.id,
13439
+ client: clientGroup.client,
13440
+ label: clientGroup.label,
13441
+ userAgent: clientGroup.userAgent,
13387
13442
  processes,
13388
- logs: sortLogsByTimestamp(ideGroup.logs)
13443
+ logs: sortLogsByTimestamp(clientGroup.logs)
13389
13444
  });
13390
13445
  }
13391
- return sortByFirstLogTime(hierarchy);
13446
+ return sortByOperationalPriority(hierarchy);
13392
13447
  }
13393
13448
  function formatTokenCount(count) {
13394
13449
  if (count <= 0) return "0";
@@ -13412,6 +13467,30 @@ function countSessions(processes) {
13412
13467
  }
13413
13468
  return sessions;
13414
13469
  }
13470
+ function readStoredIdSet(storageKey) {
13471
+ if (typeof window === "undefined") return /* @__PURE__ */ new Set();
13472
+ try {
13473
+ const parsed = JSON.parse(window.localStorage.getItem(storageKey) ?? "[]");
13474
+ if (!Array.isArray(parsed)) return /* @__PURE__ */ new Set();
13475
+ return new Set(parsed.filter((value) => typeof value === "string"));
13476
+ } catch {
13477
+ return /* @__PURE__ */ new Set();
13478
+ }
13479
+ }
13480
+ function persistIdSet(storageKey, values) {
13481
+ try {
13482
+ window.localStorage.setItem(storageKey, JSON.stringify([...values]));
13483
+ } catch {
13484
+ }
13485
+ }
13486
+ function removeIds(values, ids) {
13487
+ let changed = false;
13488
+ const next = new Set(values);
13489
+ for (const id of ids) {
13490
+ if (next.delete(id)) changed = true;
13491
+ }
13492
+ return changed ? next : values;
13493
+ }
13415
13494
  function shortProjectPath(projectFolder) {
13416
13495
  if (projectFolder === null || projectFolder === "") return null;
13417
13496
  const parts = projectFolder.replaceAll("\\", "/").split("/").filter((part) => part !== "");
@@ -13430,57 +13509,67 @@ function SummaryChip({
13430
13509
  "span",
13431
13510
  {
13432
13511
  className: cn(
13433
- "bg-white/[0.045] inline-flex h-7 items-center gap-1 rounded-md px-2 text-xs text-muted-foreground",
13512
+ "bg-white/[0.04] inline-flex h-7 items-center gap-1 rounded-md px-2 text-xs text-muted-foreground",
13434
13513
  className
13435
13514
  ),
13436
13515
  children: [
13437
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-[10px] uppercase tracking-[0.12em] text-white/35", children: label }),
13516
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-[10px] uppercase text-white/35", children: label }),
13438
13517
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums text-slate-100", children: value })
13439
13518
  ]
13440
13519
  }
13441
13520
  );
13442
13521
  }
13443
- function PendingTurnBadge({
13444
- count,
13445
- label = "Turn open"
13446
- }) {
13522
+ function AncestorActivityIndicator({ count }) {
13523
+ const label = `${count} open turn${count === 1 ? "" : "s"}`;
13447
13524
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
13448
13525
  "span",
13449
13526
  {
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`,
13527
+ className: "relative inline-flex size-6 shrink-0 items-center justify-center rounded-md bg-amber-300/[0.08] text-amber-100/90 ring-1 ring-amber-200/10",
13528
+ "aria-label": label,
13529
+ title: label,
13452
13530
  children: [
13453
13531
  /* @__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
- ] })
13532
+ count > 1 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "absolute translate-x-2 -translate-y-2 rounded bg-background px-0.5 font-mono text-[8px] tabular-nums text-amber-100", children: count })
13459
13533
  ]
13460
13534
  }
13461
13535
  );
13462
13536
  }
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
13537
  function ConversationGroupList({
13474
13538
  groups,
13475
13539
  ...groupProps
13476
13540
  }) {
13477
13541
  const hierarchy = reactExports.useMemo(() => buildConversationHierarchy(groups), [groups]);
13478
- const [collapsedIdeIds, setCollapsedIdeIds] = reactExports.useState(() => /* @__PURE__ */ new Set());
13542
+ const [collapsedClientIds, setCollapsedClientIds] = reactExports.useState(
13543
+ () => /* @__PURE__ */ new Set()
13544
+ );
13479
13545
  const [collapsedProcessIds, setCollapsedProcessIds] = reactExports.useState(
13480
13546
  () => /* @__PURE__ */ new Set()
13481
13547
  );
13482
- const toggleIde = reactExports.useCallback((id) => {
13483
- setCollapsedIdeIds((previous) => {
13548
+ const [storedCollapseStateLoaded, setStoredCollapseStateLoaded] = reactExports.useState(false);
13549
+ reactExports.useEffect(() => {
13550
+ setCollapsedClientIds(readStoredIdSet(COLLAPSED_CLIENTS_STORAGE_KEY));
13551
+ setCollapsedProcessIds(readStoredIdSet(COLLAPSED_PROCESSES_STORAGE_KEY));
13552
+ setStoredCollapseStateLoaded(true);
13553
+ }, []);
13554
+ reactExports.useEffect(() => {
13555
+ if (!storedCollapseStateLoaded) return;
13556
+ persistIdSet(COLLAPSED_CLIENTS_STORAGE_KEY, collapsedClientIds);
13557
+ persistIdSet(COLLAPSED_PROCESSES_STORAGE_KEY, collapsedProcessIds);
13558
+ }, [collapsedClientIds, collapsedProcessIds, storedCollapseStateLoaded]);
13559
+ reactExports.useEffect(() => {
13560
+ const activeClientIds = new Set(
13561
+ hierarchy.filter((group) => hasPendingLogs(group.logs)).map((group) => group.id)
13562
+ );
13563
+ const activeProcessIds = new Set(
13564
+ hierarchy.flatMap(
13565
+ (group) => group.processes.filter((process) => hasPendingLogs(process.logs)).map((process) => process.id)
13566
+ )
13567
+ );
13568
+ setCollapsedClientIds((previous) => removeIds(previous, activeClientIds));
13569
+ setCollapsedProcessIds((previous) => removeIds(previous, activeProcessIds));
13570
+ }, [hierarchy]);
13571
+ const toggleClient = reactExports.useCallback((id) => {
13572
+ setCollapsedClientIds((previous) => {
13484
13573
  const next = new Set(previous);
13485
13574
  if (next.has(id)) {
13486
13575
  next.delete(id);
@@ -13501,24 +13590,24 @@ function ConversationGroupList({
13501
13590
  return next;
13502
13591
  });
13503
13592
  }, []);
13504
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-4", children: hierarchy.map((ideGroup) => /* @__PURE__ */ jsxRuntimeExports.jsx(
13505
- IdeGroupSection,
13593
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-2", children: hierarchy.map((clientGroup) => /* @__PURE__ */ jsxRuntimeExports.jsx(
13594
+ ClientGroupSection,
13506
13595
  {
13507
- group: ideGroup,
13508
- collapsed: collapsedIdeIds.has(ideGroup.id),
13596
+ group: clientGroup,
13597
+ collapsed: collapsedClientIds.has(clientGroup.id),
13509
13598
  collapsedProcessIds,
13510
- onToggleIde: () => toggleIde(ideGroup.id),
13599
+ onToggleClient: () => toggleClient(clientGroup.id),
13511
13600
  onToggleProcess: toggleProcess,
13512
13601
  conversationProps: groupProps
13513
13602
  },
13514
- ideGroup.id
13603
+ clientGroup.id
13515
13604
  )) });
13516
13605
  }
13517
- function IdeGroupSection({
13606
+ function ClientGroupSection({
13518
13607
  group,
13519
13608
  collapsed,
13520
13609
  collapsedProcessIds,
13521
- onToggleIde,
13610
+ onToggleClient,
13522
13611
  onToggleProcess,
13523
13612
  conversationProps
13524
13613
  }) {
@@ -13531,8 +13620,8 @@ function IdeGroupSection({
13531
13620
  "section",
13532
13621
  {
13533
13622
  className: cn(
13534
- "bg-card/75 shadow-sm relative isolate overflow-hidden rounded-[8px]",
13535
- isWorking && "bg-card/85"
13623
+ "bg-card/60 relative isolate overflow-hidden rounded-[8px] shadow-sm",
13624
+ isWorking && "bg-card/70"
13536
13625
  ),
13537
13626
  "data-ide-group": group.id,
13538
13627
  children: [
@@ -13540,12 +13629,19 @@ function IdeGroupSection({
13540
13629
  "button",
13541
13630
  {
13542
13631
  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,
13632
+ 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-white/[0.025] focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-cyan-300/40",
13633
+ onClick: onToggleClient,
13545
13634
  "aria-expanded": !collapsed,
13546
13635
  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: [
13636
+ group.client === "unknown" ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "bg-white/[0.04] inline-flex size-9 shrink-0 items-center justify-center rounded-md text-slate-300", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Monitor, { className: "size-4" }) }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
13637
+ ClientLogo,
13638
+ {
13639
+ client: group.client,
13640
+ className: "size-9 rounded-md text-cyan-100",
13641
+ decorative: true
13642
+ }
13643
+ ),
13644
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "min-w-0", children: [
13549
13645
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [
13550
13646
  /* @__PURE__ */ jsxRuntimeExports.jsx(
13551
13647
  "span",
@@ -13555,10 +13651,10 @@ function IdeGroupSection({
13555
13651
  children: group.label
13556
13652
  }
13557
13653
  ),
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" })
13654
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "rounded bg-cyan-300/[0.05] px-1.5 py-0.5 font-mono text-[9px] uppercase text-cyan-100/70", children: clientAppTypeLabel(group.client) }),
13655
+ isWorking && /* @__PURE__ */ jsxRuntimeExports.jsx(AncestorActivityIndicator, { count: pendingTurnCount })
13560
13656
  ] }),
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: [
13657
+ /* @__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
13658
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
13563
13659
  group.processes.length,
13564
13660
  " process",
@@ -13571,21 +13667,21 @@ function IdeGroupSection({
13571
13667
  ] }),
13572
13668
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
13573
13669
  logCount,
13574
- " log",
13575
- logCount !== 1 ? "s" : ""
13670
+ " req"
13576
13671
  ] })
13577
13672
  ] })
13578
13673
  ] }),
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" }) })
13674
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex shrink-0 items-center gap-2", children: [
13675
+ collapsed && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "hidden shrink-0 items-center gap-2 md:flex", children: [
13676
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SummaryChip, { label: "IN", value: formatTokenCount(totals.inputTokens) }),
13677
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SummaryChip, { label: "OUT", value: formatTokenCount(totals.outputTokens) })
13678
+ ] }),
13679
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "bg-white/[0.04] hover:bg-white/[0.07] inline-flex size-8 shrink-0 items-center justify-center rounded-md text-slate-300", children: collapsed ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-4" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-4" }) })
13680
+ ] })
13584
13681
  ]
13585
13682
  }
13586
13683
  ),
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(
13684
+ !collapsed && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1 px-2 pb-2 pt-1", children: group.processes.map((processGroup) => /* @__PURE__ */ jsxRuntimeExports.jsx(
13589
13685
  ProcessGroupSection,
13590
13686
  {
13591
13687
  group: processGroup,
@@ -13611,69 +13707,66 @@ function ProcessGroupSection({
13611
13707
  const logCount = group.logs.length;
13612
13708
  const pendingTurnCount = countPendingTurns(group.logs);
13613
13709
  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
- )
13710
+ const processLabel = group.clientPid !== null && group.clientPid !== void 0 ? `PID ${group.clientPid}` : "PID unavailable";
13711
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "relative pl-4", children: [
13712
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
13713
+ "button",
13714
+ {
13715
+ type: "button",
13716
+ className: "bg-black/[0.07] grid w-full min-w-0 grid-cols-[2rem_minmax(0,1fr)_auto] items-center gap-2.5 rounded-md px-2.5 py-2 text-left transition-colors hover:bg-white/[0.03] focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-cyan-300/35",
13717
+ onClick: onToggle,
13718
+ "aria-expanded": !collapsed,
13719
+ children: [
13720
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "bg-white/[0.04] inline-flex size-8 shrink-0 items-center justify-center rounded-md text-amber-100/85", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Cpu, { className: "size-4" }) }),
13721
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "min-w-0", children: [
13722
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: [
13723
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-xs font-semibold tabular-nums text-slate-100", children: processLabel }),
13724
+ isWorking && /* @__PURE__ */ jsxRuntimeExports.jsx(AncestorActivityIndicator, { count: pendingTurnCount }),
13725
+ projectLabel !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs(
13726
+ "span",
13727
+ {
13728
+ className: "inline-flex min-w-0 items-center gap-1 text-[11px] text-muted-foreground",
13729
+ title: group.clientProjectFolder ?? projectLabel,
13730
+ children: [
13731
+ /* @__PURE__ */ jsxRuntimeExports.jsx(FolderOpen, { className: "size-3 shrink-0" }),
13732
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate font-mono", children: projectLabel })
13733
+ ]
13734
+ }
13735
+ )
13736
+ ] }),
13737
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "mt-1 flex flex-wrap items-center gap-x-3 gap-y-1 text-[11px] text-muted-foreground", children: [
13738
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
13739
+ sessionCount,
13740
+ " session",
13741
+ sessionCount !== 1 ? "s" : ""
13642
13742
  ] }),
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
- ] })
13743
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
13744
+ logCount,
13745
+ " req"
13654
13746
  ] })
13655
- ] }),
13656
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "hidden shrink-0 items-center gap-2 md:flex", children: [
13747
+ ] })
13748
+ ] }),
13749
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex shrink-0 items-center gap-2", children: [
13750
+ collapsed && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "hidden shrink-0 items-center gap-2 md:flex", children: [
13657
13751
  /* @__PURE__ */ jsxRuntimeExports.jsx(SummaryChip, { label: "IN", value: formatTokenCount(totals.inputTokens) }),
13658
13752
  /* @__PURE__ */ jsxRuntimeExports.jsx(SummaryChip, { label: "OUT", value: formatTokenCount(totals.outputTokens) })
13659
13753
  ] }),
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
- ] })
13754
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "bg-white/[0.04] hover:bg-white/[0.07] inline-flex size-7 shrink-0 items-center justify-center rounded-md text-slate-300", children: collapsed ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-4" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-4" }) })
13755
+ ] })
13756
+ ]
13757
+ }
13758
+ ),
13759
+ !collapsed && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1.5 pb-1 pl-4 pr-1 pt-1.5", children: group.sessions.map((session) => /* @__PURE__ */ jsxRuntimeExports.jsx(
13760
+ ConversationGroup,
13761
+ {
13762
+ group: session,
13763
+ ...conversationProps,
13764
+ showClientIdentity: false,
13765
+ showLogClientMetadata: false,
13766
+ showProcessMetadata: false
13767
+ },
13768
+ session.id
13769
+ )) })
13677
13770
  ] });
13678
13771
  }
13679
13772
  const NAV_ATTR = "data-nav-id";
@@ -15421,6 +15514,27 @@ function ThemeModeToggle() {
15421
15514
  }
15422
15515
  );
15423
15516
  }
15517
+ function PetVisibilityToggle({
15518
+ visible,
15519
+ onToggle
15520
+ }) {
15521
+ const label = visible ? "Hide Inspector pet" : "Summon Inspector pet";
15522
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
15523
+ "button",
15524
+ {
15525
+ type: "button",
15526
+ onClick: onToggle,
15527
+ className: cn(
15528
+ "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",
15529
+ visible && "bg-background text-amber-500 shadow-sm"
15530
+ ),
15531
+ "aria-label": label,
15532
+ "aria-pressed": visible,
15533
+ title: label,
15534
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(CrabLogo, { className: cn("size-4 transition-opacity", !visible && "opacity-45") })
15535
+ }
15536
+ );
15537
+ }
15424
15538
  function UiScaleControl({
15425
15539
  preference,
15426
15540
  resolvedScale,
@@ -15532,11 +15646,20 @@ function BrandHeader({
15532
15646
  ] });
15533
15647
  }
15534
15648
  const DETAILS_PANEL_COLLAPSED_STORAGE_KEY = "agent-inspector.detailsPanelCollapsed";
15649
+ const INSPECTOR_PET_VISIBLE_STORAGE_KEY = "agent-inspector.pet.visible";
15535
15650
  function readStoredDetailsPanelCollapsed() {
15536
15651
  if (typeof window === "undefined") return true;
15537
15652
  const stored = window.localStorage.getItem(DETAILS_PANEL_COLLAPSED_STORAGE_KEY);
15538
15653
  return stored === null || stored === "1";
15539
15654
  }
15655
+ function readStoredInspectorPetVisible() {
15656
+ if (typeof window === "undefined") return true;
15657
+ try {
15658
+ return window.localStorage.getItem(INSPECTOR_PET_VISIBLE_STORAGE_KEY) !== "0";
15659
+ } catch {
15660
+ return true;
15661
+ }
15662
+ }
15540
15663
  function SessionContextLogButton({ label, logId }) {
15541
15664
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
15542
15665
  "button",
@@ -15863,6 +15986,8 @@ function ProxyViewer({
15863
15986
  const [deletingCurrentView, setDeletingCurrentView] = reactExports.useState(false);
15864
15987
  const [detailsPanelCollapsed, setDetailsPanelCollapsed] = reactExports.useState(true);
15865
15988
  const [detailsPanelStorageLoaded, setDetailsPanelStorageLoaded] = reactExports.useState(false);
15989
+ const [petVisible, setPetVisible] = reactExports.useState(true);
15990
+ const [petVisibilityStorageLoaded, setPetVisibilityStorageLoaded] = reactExports.useState(false);
15866
15991
  const [comparePair, setComparePair] = reactExports.useState(null);
15867
15992
  const [crabEntrancePhase, setCrabEntrancePhase] = reactExports.useState(
15868
15993
  "hidden"
@@ -15910,6 +16035,17 @@ function ProxyViewer({
15910
16035
  detailsPanelCollapsed ? "1" : "0"
15911
16036
  );
15912
16037
  }, [detailsPanelCollapsed, detailsPanelStorageLoaded]);
16038
+ reactExports.useEffect(() => {
16039
+ setPetVisible(readStoredInspectorPetVisible());
16040
+ setPetVisibilityStorageLoaded(true);
16041
+ }, []);
16042
+ reactExports.useEffect(() => {
16043
+ if (!petVisibilityStorageLoaded) return;
16044
+ try {
16045
+ window.localStorage.setItem(INSPECTOR_PET_VISIBLE_STORAGE_KEY, petVisible ? "1" : "0");
16046
+ } catch {
16047
+ }
16048
+ }, [petVisibilityStorageLoaded, petVisible]);
15913
16049
  reactExports.useEffect(() => {
15914
16050
  if (pinnedSessionId === void 0) {
15915
16051
  document.title = "Agent Inspector";
@@ -16027,6 +16163,9 @@ function ProxyViewer({
16027
16163
  const toggleDetailsPanelCollapsed = reactExports.useCallback(() => {
16028
16164
  setDetailsPanelCollapsed((value) => !value);
16029
16165
  }, []);
16166
+ const togglePetVisibility = reactExports.useCallback(() => {
16167
+ setPetVisible((value) => !value);
16168
+ }, []);
16030
16169
  const groups = reactExports.useMemo(() => groupLogsByConversation(logs), [logs]);
16031
16170
  const displayNumberByLogId = reactExports.useMemo(() => buildDisplayNumberByLogId(groups), [groups]);
16032
16171
  const sessionContextScope = reactExports.useMemo(
@@ -16105,7 +16244,7 @@ function ProxyViewer({
16105
16244
  ]
16106
16245
  }
16107
16246
  ),
16108
- detailsPanelCollapsed && /* @__PURE__ */ jsxRuntimeExports.jsx(InspectorPet, { logs }),
16247
+ petVisibilityStorageLoaded && petVisible && /* @__PURE__ */ jsxRuntimeExports.jsx(InspectorPet, { logs }),
16109
16248
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
16110
16249
  "div",
16111
16250
  {
@@ -16229,6 +16368,7 @@ function ProxyViewer({
16229
16368
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm font-semibold text-foreground", children: "Logs" }),
16230
16369
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-0.5 font-mono text-[11px] text-muted-foreground", children: activeScopeLabel })
16231
16370
  ] }),
16371
+ /* @__PURE__ */ jsxRuntimeExports.jsx(PetVisibilityToggle, { visible: petVisible, onToggle: togglePetVisibility }),
16232
16372
  onImportLogs !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
16233
16373
  /* @__PURE__ */ jsxRuntimeExports.jsx(
16234
16374
  "input",