@tonyclaw/agent-inspector 3.0.8 → 3.0.10

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 (45) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/{CompareDrawer-Bth_Ywyt.js → CompareDrawer-BxLP7jmX.js} +1 -1
  3. package/.output/public/assets/ProxyViewerContainer-D_2ez29e.js +106 -0
  4. package/.output/public/assets/{ReplayDialog-C2YYAuTe.js → ReplayDialog-Btm-wONI.js} +1 -1
  5. package/.output/public/assets/{RequestAnatomy-8k9dAX2j.js → RequestAnatomy-C9eZJN9E.js} +1 -1
  6. package/.output/public/assets/{ResponseView-DEL6JcXm.js → ResponseView-9R2MW1kp.js} +2 -2
  7. package/.output/public/assets/{StreamingChunkSequence-DngmoR9j.js → StreamingChunkSequence-zxqGpFfv.js} +1 -1
  8. package/.output/public/assets/{_sessionId-4vk9RMZ5.js → _sessionId-C0tPTQlC.js} +1 -1
  9. package/.output/public/assets/agent-inspector-58K1_MsC.ico +0 -0
  10. package/.output/public/assets/index-BIgsQvaF.css +1 -0
  11. package/.output/public/assets/index-DgVWrzsQ.js +1 -0
  12. package/.output/public/assets/{index-DINLvnm9.js → index-WiDkyjq8.js} +1 -1
  13. package/.output/public/assets/{json-viewer-CH5dvS2Y.js → json-viewer-BAmkfRDE.js} +1 -1
  14. package/.output/public/assets/{main-GWkZn4xy.js → main-2feHoEI6.js} +2 -2
  15. package/.output/server/_libs/lucide-react.mjs +2 -2
  16. package/.output/server/_libs/radix-ui__react-dialog.mjs +2 -2
  17. package/.output/server/{_sessionId-EgsjdkN7.mjs → _sessionId-BkoyescL.mjs} +2 -2
  18. package/.output/server/_ssr/{CompareDrawer-CaM8FYuD.mjs → CompareDrawer-irfFdkJ8.mjs} +3 -3
  19. package/.output/server/_ssr/{ProxyViewerContainer-EJIogcGd.mjs → ProxyViewerContainer-CcJr9STz.mjs} +574 -324
  20. package/.output/server/_ssr/{ReplayDialog-BPpJ2-q8.mjs → ReplayDialog-CJnmXQGT.mjs} +3 -3
  21. package/.output/server/_ssr/{RequestAnatomy-DeQAWnZx.mjs → RequestAnatomy-CupP0Wdb.mjs} +2 -2
  22. package/.output/server/_ssr/{ResponseView-Dshm8iQ7.mjs → ResponseView-Bp-0t5cd.mjs} +2 -2
  23. package/.output/server/_ssr/{StreamingChunkSequence-32yIU2hn.mjs → StreamingChunkSequence-BXSn4kMH.mjs} +2 -2
  24. package/.output/server/_ssr/{index-XRcx9blU.mjs → index-KVltJBV8.mjs} +2 -2
  25. package/.output/server/_ssr/index.mjs +2 -2
  26. package/.output/server/_ssr/{json-viewer-C0aX5rqC.mjs → json-viewer-EYQ5eG2Q.mjs} +2 -2
  27. package/.output/server/_ssr/{router-BI-Mvxz9.mjs → router-_cAQddXC.mjs} +39 -36
  28. package/.output/server/{_tanstack-start-manifest_v-jKScklL_.mjs → _tanstack-start-manifest_v-BfiF5iov.mjs} +1 -1
  29. package/.output/server/index.mjs +72 -65
  30. package/package.json +1 -1
  31. package/src/components/ProxyViewer.tsx +194 -29
  32. package/src/components/ProxyViewerContainer.tsx +145 -3
  33. package/src/components/clients/ClientLogo.tsx +16 -1
  34. package/src/components/providers/ProviderCard.tsx +83 -91
  35. package/src/components/providers/ProvidersPanel.tsx +7 -7
  36. package/src/components/providers/SettingsDialog.tsx +17 -22
  37. package/src/components/proxy-viewer/TurnGroup.tsx +0 -16
  38. package/src/components/proxy-viewer/log-formats/anthropic.ts +5 -5
  39. package/src/components/proxy-viewer/log-formats/openai.ts +7 -10
  40. package/src/components/proxy-viewer/requestTools.ts +5 -2
  41. package/src/routes/api/logs.ts +14 -5
  42. package/src/routes/api/providers.$providerId.test.log.ts +28 -24
  43. package/.output/public/assets/ProxyViewerContainer-C73EU9Jq.js +0 -106
  44. package/.output/public/assets/index-DBEB1rHe.css +0 -1
  45. package/.output/public/assets/index-LPIGiUMP.js +0 -1
@@ -1,19 +1,19 @@
1
1
  import { r as reactExports, j as jsxRuntimeExports, a as React } from "../_libs/react.mjs";
2
- import { C as CapturedLogSchema, D as DEFAULT_CAPTURE_MODE, a as DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS, b as DEFAULT_PROVIDER_TEST_TIMEOUT_SECONDS, c as DEFAULT_TIME_DISPLAY_FORMAT, d as RuntimeConfigSchema, p as packageJson, P as ProviderConfigSchema, i as apiFormatForPath, n as DeleteInspectorGroupsResponseSchema, o as GroupEvidenceExportResultSchema, q as DeleteInspectorGroupResponseSchema, l as AlertSummarySchema, m as AlertListResponseSchema, I as InspectorGroupsListResponseSchema, G as GroupEvidenceReadResponseSchema, z as createPendingProviderTestResults, B as ProviderTestResultsSchema, E as createFailedProviderTestResults, M as MAX_SLOW_RESPONSE_THRESHOLD_SECONDS, F as MAX_PROVIDER_TEST_TIMEOUT_SECONDS, T as TimeDisplayFormatSchema, t as maskApiKey, u as PATH_V1_MESSAGES, v as PATH_V1_CHAT_COMPLETIONS, w as PATH_V1_RESPONSES, r as providerHasContextMetadata, f as parseOpenAIResponse, g as parseOpenAIResponsesResponse, O as OpenAIRequestSchema, h as OpenAIResponsesRequestSchema, A as AnthropicResponseSchema$1, e as AnthropicRequestSchema, s as safeGetOwnProperty, H as resolveProviderContextWindow, j as getSessionPath, x as findProviderModelMetadata, y as previewUpstreamUrl, K as KnowledgeCandidateSchema, J as isPlainRecord, k as stripClaudeCodeBillingHeader, L as LogBodyChunkSchema } from "./router-BI-Mvxz9.mjs";
2
+ import { C as CapturedLogSchema, D as DEFAULT_CAPTURE_MODE, a as DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS, b as DEFAULT_PROVIDER_TEST_TIMEOUT_SECONDS, c as DEFAULT_TIME_DISPLAY_FORMAT, d as RuntimeConfigSchema, p as packageJson, P as ProviderConfigSchema, i as apiFormatForPath, n as DeleteInspectorGroupsResponseSchema, o as GroupEvidenceExportResultSchema, q as DeleteInspectorGroupResponseSchema, l as AlertSummarySchema, m as AlertListResponseSchema, I as InspectorGroupsListResponseSchema, G as GroupEvidenceReadResponseSchema, z as createPendingProviderTestResults, B as ProviderTestResultsSchema, E as createFailedProviderTestResults, M as MAX_SLOW_RESPONSE_THRESHOLD_SECONDS, F as MAX_PROVIDER_TEST_TIMEOUT_SECONDS, T as TimeDisplayFormatSchema, t as maskApiKey, v as PATH_V1_MESSAGES, w as PATH_V1_CHAT_COMPLETIONS, x as PATH_V1_RESPONSES, r as providerHasContextMetadata, f as parseOpenAIResponse, g as parseOpenAIResponsesResponse, O as OpenAIRequestSchema, h as OpenAIResponsesRequestSchema, A as AnthropicResponseSchema$1, e as AnthropicRequestSchema, s as safeGetOwnProperty, H as resolveProviderContextWindow, j as getSessionPath, u as findProviderModelMetadata, y as previewUpstreamUrl, K as KnowledgeCandidateSchema, J as isPlainRecord, k as stripClaudeCodeBillingHeader, L as LogBodyChunkSchema } from "./router-_cAQddXC.mjs";
3
3
  import { u as useSWR, a as useSWRConfig } from "../_libs/swr.mjs";
4
4
  import { J as JSZip } from "../_libs/jszip.mjs";
5
5
  import { c as clsx } from "../_libs/clsx.mjs";
6
6
  import { t as twMerge } from "../_libs/tailwind-merge.mjs";
7
- import { R as Root, T as Trigger$1, C as Content, a as Close, b as Title, D as Description, P as Portal$2, O as Overlay } from "../_libs/radix-ui__react-dialog.mjs";
7
+ import { R as Root, C as Content, a as Close, T as Title, D as Description, P as Portal$1, O as Overlay, b as Trigger$1 } from "../_libs/radix-ui__react-dialog.mjs";
8
8
  import { c as cva } from "../_libs/class-variance-authority.mjs";
9
9
  import { u as useWindowVirtualizer, a as useVirtualizer } from "../_libs/tanstack__react-virtual.mjs";
10
10
  import { d as diffJson, a as diffLines } from "../_libs/diff.mjs";
11
11
  import { R as Root2, T as Trigger, I as Icon, V as Value, P as Portal, C as Content2, a as Viewport, b as Item, c as ItemIndicator, d as ItemText, S as ScrollUpButton, e as ScrollDownButton } from "../_libs/radix-ui__react-select.mjs";
12
- import { T as TriangleAlert, C as CircleCheck, X, I as Info, a as ChevronDown, b as Check, R as RefreshCw, c as Trash2, S as Search, U as Upload, D as Download, F as FileBraces, P as Plus, A as ArrowLeft, d as ChevronUp, e as Copy, f as ChevronsLeft, g as ChevronLeft, h as ChevronRight, i as ChevronsRight, j as Clapperboard, k as Flag, l as Siren, m as Timer, G as Gauge, L as LoaderCircle, n as Layers, o as FlaskConical, p as Sparkles, q as Activity, B as Beaker, N as Network, r as Terminal, s as Settings, M as Monitor, t as Rocket, u as PackageCheck, v as Scan, w as CircleAlert, x as ArrowUpRight, y as ArrowDownRight, z as Cpu, E as FolderOpen, H as Bell, J as Clock3, K as ShieldAlert, O as EyeOff, Q as Eye, V as ExternalLink, W as Clock, Y as RotateCw, Z as Pencil, _ as MessageSquare, $ as Zap, a0 as Wrench, a1 as Brain, a2 as Minus, a3 as CircleCheckBig, a4 as CircleQuestionMark, a5 as Server, a6 as Lock, a7 as Wifi, a8 as WifiOff, a9 as CircleX, aa as ShieldCheck, ab as Save, ac as FileSearch, ad as CloudUpload, ae as OctagonAlert, af as Radio, ag as Globe, ah as FileTerminal, ai as ChevronsUp, aj as ChevronsDown, ak as FileDiff, al as History, am as RotateCcw, an as GitCompareArrows, ao as ArrowUp, ap as ArrowDown, aq as Ellipsis, ar as CodeXml, as as Blocks, at as MousePointerClick, au as FileText, av as Rows3, aw as Columns2 } from "../_libs/lucide-react.mjs";
13
- import { u as union, d as object, a as array, l as literal, b as string, n as number, c as boolean, _ as _enum } from "../_libs/zod.mjs";
12
+ import { T as TriangleAlert, C as CircleCheck, X, I as Info, a as ChevronDown, b as Check, R as RefreshCw, c as Trash2, S as Search, U as Upload, D as Download, F as FileBraces, P as Plus, A as ArrowLeft, d as ChevronUp, e as Copy, f as ChevronsLeft, g as ChevronLeft, h as ChevronRight, i as ChevronsRight, j as Clapperboard, k as Flag, l as Siren, m as Timer, G as Gauge, L as LoaderCircle, n as Layers, o as FlaskConical, p as Sparkles, q as Activity, B as Beaker, N as Network, r as Terminal, s as Settings, M as Monitor, t as Rocket, u as PackageCheck, v as Scan, w as CircleAlert, x as ArrowUpRight, y as ArrowDownRight, z as Cpu, E as FolderOpen, H as Bell, J as Clock3, K as ShieldAlert, O as EyeOff, Q as Eye, V as ExternalLink, W as Clock, Y as RotateCw, Z as Pencil, _ as MessageSquare, $ as Zap, a0 as Wrench, a1 as Brain, a2 as CircleCheckBig, a3 as Minus, a4 as CircleQuestionMark, a5 as Server, a6 as Lock, a7 as Wifi, a8 as WifiOff, a9 as CircleX, aa as ShieldCheck, ab as Save, ac as FileSearch, ad as CloudUpload, ae as OctagonAlert, af as Radio, ag as Globe, ah as FileTerminal, ai as ChevronsUp, aj as ChevronsDown, ak as FileDiff, al as History, am as RotateCcw, an as GitCompareArrows, ao as ArrowUp, ap as ArrowDown, aq as Ellipsis, ar as CodeXml, as as Blocks, at as MousePointerClick, au as FileText, av as Rows3, aw as Columns2 } from "../_libs/lucide-react.mjs";
13
+ import { u as union, d as object, a as array, l as literal, n as number, c as boolean, b as string, _ as _enum } from "../_libs/zod.mjs";
14
14
  import { S as Slot } from "../_libs/radix-ui__react-slot.mjs";
15
15
  import { R as Root2$1, L as List, T as Trigger$2, C as Content$1 } from "../_libs/radix-ui__react-tabs.mjs";
16
- import { P as Provider, R as Root3, T as Trigger$3, a as Portal$1, C as Content2$1, A as Arrow2 } from "../_libs/radix-ui__react-tooltip.mjs";
16
+ import { P as Provider, R as Root3, T as Trigger$3, a as Portal$2, C as Content2$1, A as Arrow2 } from "../_libs/radix-ui__react-tooltip.mjs";
17
17
  import { R as Root$1, C as CollapsibleContent$1, a as CollapsibleTrigger$1 } from "../_libs/radix-ui__react-collapsible.mjs";
18
18
  import { R as Root$2, V as Viewport$1, C as Corner, S as ScrollAreaScrollbar, a as ScrollAreaThumb } from "../_libs/radix-ui__react-scroll-area.mjs";
19
19
  const ApiErrorSchema = object({
@@ -738,7 +738,7 @@ function DialogTrigger({
738
738
  function DialogPortal({
739
739
  ...props
740
740
  }) {
741
- return /* @__PURE__ */ jsxRuntimeExports.jsx(Portal$2, { "data-slot": "dialog-portal", ...props });
741
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Portal$1, { "data-slot": "dialog-portal", ...props });
742
742
  }
743
743
  function DialogOverlay({
744
744
  className,
@@ -892,7 +892,9 @@ const ClaudeCodeLogoSvg = "data:image/svg+xml,%3csvg%20height='1em'%20style='fle
892
892
  const CodexLogoSvg = "data:image/svg+xml,%3csvg%20height='1em'%20style='flex:none;line-height:1'%20viewBox='0%200%2024%2024'%20width='1em'%20xmlns='http://www.w3.org/2000/svg'%3e%3ctitle%3eCodex%3c/title%3e%3cpath%20d='M19.503%200H4.496A4.496%204.496%200%20000%204.496v15.007A4.496%204.496%200%20004.496%2024h15.007A4.496%204.496%200%200024%2019.503V4.496A4.496%204.496%200%200019.503%200z'%20fill='%23fff'%3e%3c/path%3e%3cpath%20d='M9.064%203.344a4.578%204.578%200%20012.285-.312c1%20.115%201.891.54%202.673%201.275.01.01.024.017.037.021a.09.09%200%2000.043%200%204.55%204.55%200%20013.046.275l.047.022.116.057a4.581%204.581%200%20012.188%202.399c.209.51.313%201.041.315%201.595a4.24%204.24%200%2001-.134%201.223.123.123%200%2000.03.115c.594.607.988%201.33%201.183%202.17.289%201.425-.007%202.71-.887%203.854l-.136.166a4.548%204.548%200%2001-2.201%201.388.123.123%200%2000-.081.076c-.191.551-.383%201.023-.74%201.494-.9%201.187-2.222%201.846-3.711%201.838-1.187-.006-2.239-.44-3.157-1.302a.107.107%200%2000-.105-.024c-.388.125-.78.143-1.204.138a4.441%204.441%200%2001-1.945-.466%204.544%204.544%200%2001-1.61-1.335c-.152-.202-.303-.392-.414-.617a5.81%205.81%200%2001-.37-.961%204.582%204.582%200%2001-.014-2.298.124.124%200%2000.006-.056.085.085%200%2000-.027-.048%204.467%204.467%200%2001-1.034-1.651%203.896%203.896%200%2001-.251-1.192%205.189%205.189%200%2001.141-1.6c.337-1.112.982-1.985%201.933-2.618.212-.141.413-.251.601-.33.215-.089.43-.164.646-.227a.098.098%200%2000.065-.066%204.51%204.51%200%2001.829-1.615%204.535%204.535%200%20011.837-1.388zm3.482%2010.565a.637.637%200%20000%201.272h3.636a.637.637%200%20100-1.272h-3.636zM8.462%209.23a.637.637%200%2000-1.106.631l1.272%202.224-1.266%202.136a.636.636%200%20101.095.649l1.454-2.455a.636.636%200%2000.005-.64L8.462%209.23z'%20fill='url(%23lobe-icons-codex-_R_0_)'%3e%3c/path%3e%3cdefs%3e%3clinearGradient%20gradientUnits='userSpaceOnUse'%20id='lobe-icons-codex-_R_0_'%20x1='12'%20x2='12'%20y1='3'%20y2='21'%3e%3cstop%20stop-color='%23B1A7FF'%3e%3c/stop%3e%3cstop%20offset='.5'%20stop-color='%237A9DFF'%3e%3c/stop%3e%3cstop%20offset='1'%20stop-color='%233941FF'%3e%3c/stop%3e%3c/linearGradient%3e%3c/defs%3e%3c/svg%3e";
893
893
  const OpenCodeLogoSvg = "data:image/svg+xml,%3csvg%20fill='%237dd3fc'%20fill-rule='evenodd'%20height='1em'%20style='flex:none;line-height:1'%20viewBox='0%200%2024%2024'%20width='1em'%20xmlns='http://www.w3.org/2000/svg'%3e%3ctitle%3eOpenCode%3c/title%3e%3cpath%20d='M16%206H8v12h8V6zm4%2016H4V2h16v20z'%3e%3c/path%3e%3c/svg%3e";
894
894
  const MiMoCodeLogoSvg = "data:image/svg+xml,%3csvg%20fill='%23ff6900'%20fill-rule='evenodd'%20height='1em'%20style='flex:none;line-height:1'%20viewBox='0%200%2024%2024'%20width='1em'%20xmlns='http://www.w3.org/2000/svg'%3e%3ctitle%3eMiMo%20Code%3c/title%3e%3cpath%20d='M.958%2015.936a.459.459%200%2001.459.44v2.729a.46.46%200%2001-.918%200v-2.729a.459.459%200%2001.459-.44zm4.814-2.035a.46.46%200%2001.553.45v4.754a.458.458%200%2011-.918%200V15.48L3.74%2017.202a.462.462%200%2001-.655.016.462.462%200%2001-.065-.082L.628%2014.67a.459.459%200%2001.658-.637l2.124%202.187%202.127-2.188a.46.46%200%2001.235-.13zm2.068.004a.46.46%200%2001.458.445v4.755a.46.46%200%2001-.458.458.459.459%200%2001-.458-.458V14.35a.459.459%200%2001.458-.445zm1.973%202.014a.46.46%200%2001.46.457v2.729a.46.46%200%2001-.784.324.46.46%200%2001-.134-.324v-2.729a.46.46%200%2001.458-.458zm.002-2.045a.458.458%200%2001.328.157l2.127%202.19%202.125-2.19a.459.459%200%2001.784.318v4.756a.46.46%200%2001-.455.458.46.46%200%2001-.458-.458V15.48l-1.667%201.723a.46.46%200%2001-.65.008l-.005-.005c0-.002-.002-.002-.004-.003l-2.455-2.534a.46.46%200%2001-.008-.667.461.461%200%2001.338-.128zm6.797%201.206a.46.46%200%2001.53.651A1.966%201.966%200%200019.81%2018.4a.462.462%200%2001.623.18.46.46%200%2001-.181.624%202.863%202.863%200%2001-1.38.353l-.142-.004a2.88%202.88%200%2001-2.393-4.263.461.461%200%2001.274-.21zm.864-.931a2.884%202.884%200%20013.915%203.914.46.46%200%2001-.402.24l-.057-.004a.458.458%200%2001-.164-.055.46.46%200%2001-.182-.622%201.967%201.967%200%2000-2.669-2.67.459.459%200%2011-.441-.803zM9.59%206.368c1.481%200%201.696%201.202%201.696%201.654v2.648h-.917v-.432c-.26.346-.792.535-1.36.535-.133%200-1.289-.03-1.384-1.136-.082-.932.675-1.61%202.053-1.61h.691c0-.563-.367-.886-.983-.886-.44.013-.864.174-1.2.458l-.36-.664c.484-.379%201.012-.567%201.764-.567zm4.427.1c1.263%200%202.082.97%202.083%202.15%200%201.181-.824%202.154-2.083%202.154-1.26%200-2.084-.972-2.084-2.152%200-1.18.82-2.153%202.084-2.153zm6.801.015c.68%200%201.202.465%201.197%201.548v2.642H21.1V8.29c0-.312-.002-.98-.63-.98s-.628.667-.628.838v2.524h-.89V8.148c0-.17-.001-.838-.63-.838-.628%200-.628.668-.628.98v2.383h-.917v-4.03h.917V7a1.22%201.22%200%2001.947-.516c.398%200%20.76.193.982.686a1.321%201.321%200%20011.195-.686zm-18.093.872l1.457-1.772H5.32L3.311%208.07l2.14%202.602H4.24L2.725%208.796%201.21%2010.672H0L2.138%208.07.13%205.583h1.138l1.458%201.772zm4.149%203.317h-.916V6.644h.916v4.028zm16.99%200h-.916V6.644h.916v4.028zM9.925%208.71c-1.055%200-1.359.412-1.326.742.032.329.324.537.757.537a1.013%201.013%200%20001.014-.968l.002-.31h-.447zM14.018%207.3c-.663%200-1.184.487-1.184%201.32%200%20.832.52%201.32%201.184%201.32.662%200%201.182-.49%201.182-1.32%200-.832-.52-1.32-1.182-1.32zM6.417%205.001a.568.568%200%2001.587.582.588.588%200%2001-1.175%200A.57.57%200%20016.417%205zm16.991%200a.57.57%200%2001.592.582.588.588%200%2001-1.174%200%20.57.57%200%2001.357-.542.572.572%200%2001.225-.04z'%3e%3c/path%3e%3c/svg%3e";
895
+ const AgentInspectorLogo = "/assets/agent-inspector-58K1_MsC.ico";
895
896
  const CLIENT_LABELS = {
897
+ "agent-inspector": "Inspector",
896
898
  codex: "Codex",
897
899
  opencode: "OpenCode",
898
900
  "mimo-code": "MiMo Code",
@@ -913,6 +915,9 @@ function detectClientApp(input) {
913
915
  normalize(input.conversationId),
914
916
  normalize(input.clientProjectFolder)
915
917
  ].join(" ");
918
+ if (matchesAny(haystack, ["agent-inspector", "agent inspector", "provider-test"])) {
919
+ return "agent-inspector";
920
+ }
916
921
  if (matchesAny(haystack, ["mimocode", "mimo-code", "mimo code"])) return "mimo-code";
917
922
  if (matchesAny(haystack, ["opencode", "open-code", "open code"])) return "opencode";
918
923
  if (matchesAny(haystack, ["claude-code", "claude code", "claudecode"])) return "claude-code";
@@ -923,6 +928,7 @@ function detectClientApp(input) {
923
928
  }
924
929
  function clientAppLabel(client) {
925
930
  switch (client) {
931
+ case "agent-inspector":
926
932
  case "codex":
927
933
  case "opencode":
928
934
  case "mimo-code":
@@ -933,18 +939,21 @@ function clientAppLabel(client) {
933
939
  }
934
940
  }
935
941
  const CLIENT_LOGOS = {
942
+ "agent-inspector": AgentInspectorLogo,
936
943
  codex: CodexLogoSvg,
937
944
  opencode: OpenCodeLogoSvg,
938
945
  "mimo-code": MiMoCodeLogoSvg,
939
946
  "claude-code": ClaudeCodeLogoSvg
940
947
  };
941
948
  const CLIENT_LOGO_FRAMES = {
949
+ "agent-inspector": "border-orange-200/25 bg-orange-300/[0.12]",
942
950
  codex: "border-cyan-200/20 bg-cyan-300/[0.08]",
943
951
  opencode: "border-sky-200/25 bg-sky-300/[0.12]",
944
952
  "mimo-code": "border-orange-200/25 bg-orange-400/[0.12]",
945
953
  "claude-code": "border-amber-100/20 bg-amber-300/[0.09]"
946
954
  };
947
955
  const CLIENT_LOGO_IMAGES = {
956
+ "agent-inspector": "p-0.5 drop-shadow-[0_0_8px_rgba(251,146,60,0.35)]",
948
957
  codex: "p-0.5",
949
958
  opencode: "p-1 drop-shadow-[0_0_8px_rgba(125,211,252,0.35)]",
950
959
  "mimo-code": "p-0.5 drop-shadow-[0_0_8px_rgba(255,105,0,0.35)]",
@@ -1089,7 +1098,7 @@ function TooltipContent({
1089
1098
  children,
1090
1099
  ...props
1091
1100
  }) {
1092
- return /* @__PURE__ */ jsxRuntimeExports.jsx(Portal$1, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
1101
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Portal$2, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
1093
1102
  Content2$1,
1094
1103
  {
1095
1104
  "data-slot": "tooltip-content",
@@ -1164,6 +1173,171 @@ function countCharacters(text) {
1164
1173
  });
1165
1174
  return n;
1166
1175
  }
1176
+ const CATEGORY_ORDER = [
1177
+ "file",
1178
+ "shell",
1179
+ "browser",
1180
+ "web",
1181
+ "mcp",
1182
+ "code",
1183
+ "other"
1184
+ ];
1185
+ function firstTextSlice(value) {
1186
+ const normalized = value.replace(/\s+/g, " ").trim();
1187
+ if (normalized.length <= 120) return normalized;
1188
+ return `${normalized.slice(0, 119)}...`;
1189
+ }
1190
+ function previewDescription(description) {
1191
+ if (description === null) return null;
1192
+ const normalized = description.replace(/\s+/g, " ").trim();
1193
+ if (normalized.length === 0) return null;
1194
+ const sentenceEnd = normalized.search(/[.!?。!?]/);
1195
+ if (sentenceEnd >= 24) return firstTextSlice(normalized.slice(0, sentenceEnd + 1));
1196
+ return firstTextSlice(normalized);
1197
+ }
1198
+ function lowerHaystack(name, description) {
1199
+ return `${name} ${description ?? ""}`.toLowerCase();
1200
+ }
1201
+ function includesAny(value, needles) {
1202
+ return needles.some((needle) => value.includes(needle));
1203
+ }
1204
+ function categorizeTool(name, description) {
1205
+ const haystack = lowerHaystack(name, description);
1206
+ if (name.startsWith("mcp__") || name.startsWith("inspector_") || includesAny(haystack, [" mcp", "model context protocol"])) {
1207
+ return "mcp";
1208
+ }
1209
+ if (includesAny(haystack, ["bash", "shell", "terminal", "command", "powershell", "exec", "process"])) {
1210
+ return "shell";
1211
+ }
1212
+ if (includesAny(haystack, [
1213
+ "browser",
1214
+ "playwright",
1215
+ "screenshot",
1216
+ "click",
1217
+ "navigate",
1218
+ "page",
1219
+ "tab"
1220
+ ])) {
1221
+ return "browser";
1222
+ }
1223
+ if (includesAny(haystack, [
1224
+ "read",
1225
+ "write",
1226
+ "edit",
1227
+ "file",
1228
+ "glob",
1229
+ "grep",
1230
+ "patch",
1231
+ "filesystem",
1232
+ "directory"
1233
+ ])) {
1234
+ return "file";
1235
+ }
1236
+ if (includesAny(haystack, ["web", "search", "http", "url", "fetch"])) {
1237
+ return "web";
1238
+ }
1239
+ if (includesAny(haystack, ["code", "typescript", "javascript", "python", "repl"])) {
1240
+ return "code";
1241
+ }
1242
+ return "other";
1243
+ }
1244
+ function parameterNames(schema) {
1245
+ const properties = safeGetOwnProperty(schema, "properties");
1246
+ if (properties === null || typeof properties !== "object" || Array.isArray(properties)) {
1247
+ return [];
1248
+ }
1249
+ return Object.keys(properties).sort((a, b) => a.localeCompare(b));
1250
+ }
1251
+ function requiredParameterNames(schema) {
1252
+ const required = safeGetOwnProperty(schema, "required");
1253
+ if (!Array.isArray(required)) return [];
1254
+ const names = [];
1255
+ for (const item of required) {
1256
+ if (typeof item === "string" && item.length > 0) names.push(item);
1257
+ }
1258
+ return names.sort((a, b) => a.localeCompare(b));
1259
+ }
1260
+ function parseAnthropicTool(tool) {
1261
+ const name = safeGetOwnProperty(tool, "name");
1262
+ if (typeof name !== "string" || name.length === 0) return null;
1263
+ const description = safeGetOwnProperty(tool, "description");
1264
+ const schema = safeGetOwnProperty(tool, "input_schema") ?? null;
1265
+ const normalizedDescription = typeof description === "string" ? description : null;
1266
+ return {
1267
+ name,
1268
+ description: normalizedDescription,
1269
+ descriptionPreview: previewDescription(normalizedDescription),
1270
+ category: categorizeTool(name, normalizedDescription),
1271
+ parameterCount: parameterNames(schema).length,
1272
+ requiredParameters: requiredParameterNames(schema),
1273
+ schema
1274
+ };
1275
+ }
1276
+ function parseOpenAITool(tool) {
1277
+ const fn = safeGetOwnProperty(tool, "function");
1278
+ const toolType = safeGetOwnProperty(tool, "type");
1279
+ if (fn === void 0 && typeof toolType !== "string") return null;
1280
+ const name = safeGetOwnProperty(fn, "name") ?? safeGetOwnProperty(tool, "name") ?? (typeof toolType === "string" ? toolType : void 0);
1281
+ if (typeof name !== "string" || name.length === 0) return null;
1282
+ const description = safeGetOwnProperty(fn, "description") ?? safeGetOwnProperty(tool, "description");
1283
+ const schema = safeGetOwnProperty(fn, "parameters") ?? safeGetOwnProperty(tool, "parameters") ?? null;
1284
+ const normalizedDescription = typeof description === "string" ? description : null;
1285
+ return {
1286
+ name,
1287
+ description: normalizedDescription,
1288
+ descriptionPreview: previewDescription(normalizedDescription),
1289
+ category: categorizeTool(name, normalizedDescription),
1290
+ parameterCount: parameterNames(schema).length,
1291
+ requiredParameters: requiredParameterNames(schema),
1292
+ schema
1293
+ };
1294
+ }
1295
+ function parseTool(tool) {
1296
+ const openAITool = parseOpenAITool(tool);
1297
+ if (openAITool !== null) return openAITool;
1298
+ return parseAnthropicTool(tool);
1299
+ }
1300
+ function formatToolChoice(choice) {
1301
+ if (choice === void 0 || choice === null) return null;
1302
+ if (typeof choice === "string") return choice;
1303
+ const type = safeGetOwnProperty(choice, "type");
1304
+ const name = safeGetOwnProperty(choice, "name");
1305
+ const fnName = safeGetOwnProperty(safeGetOwnProperty(choice, "function"), "name");
1306
+ if (typeof type === "string" && typeof fnName === "string" && fnName.length > 0) {
1307
+ return `${type}: ${fnName}`;
1308
+ }
1309
+ if (typeof type === "string" && typeof name === "string" && name.length > 0) {
1310
+ return `${type}: ${name}`;
1311
+ }
1312
+ if (typeof type === "string") return type;
1313
+ const encoded = JSON.stringify(choice);
1314
+ return encoded === void 0 ? null : firstTextSlice(encoded);
1315
+ }
1316
+ function summarizeCategories(tools) {
1317
+ const counts = /* @__PURE__ */ new Map();
1318
+ for (const tool of tools) {
1319
+ counts.set(tool.category, (counts.get(tool.category) ?? 0) + 1);
1320
+ }
1321
+ return CATEGORY_ORDER.flatMap((category) => {
1322
+ const count = counts.get(category) ?? 0;
1323
+ return count > 0 ? [{ category, count }] : [];
1324
+ });
1325
+ }
1326
+ function parseRequestTools(parsed) {
1327
+ const rawTools = safeGetOwnProperty(parsed, "tools");
1328
+ if (!Array.isArray(rawTools) || rawTools.length === 0) return null;
1329
+ const tools = [];
1330
+ for (const rawTool of rawTools) {
1331
+ const tool = parseTool(rawTool);
1332
+ if (tool !== null) tools.push(tool);
1333
+ }
1334
+ if (tools.length === 0) return null;
1335
+ return {
1336
+ tools,
1337
+ toolChoiceLabel: formatToolChoice(safeGetOwnProperty(parsed, "tool_choice")),
1338
+ categories: summarizeCategories(tools)
1339
+ };
1340
+ }
1167
1341
  function emptyRequestAnalysis(rawBody) {
1168
1342
  return {
1169
1343
  parsed: null,
@@ -1259,13 +1433,15 @@ const anthropicLogFormatAdapter = {
1259
1433
  analyzeRequest(rawBody) {
1260
1434
  if (rawBody === null) return emptyRequestAnalysis(rawBody);
1261
1435
  try {
1262
- const result = AnthropicRequestSchema.safeParse(JSON.parse(rawBody));
1436
+ const parsedBody = JSON.parse(rawBody);
1437
+ const toolCount = parseRequestTools(parsedBody)?.tools.length ?? null;
1438
+ const result = AnthropicRequestSchema.safeParse(parsedBody);
1263
1439
  if (!result.success) return emptyRequestAnalysis(rawBody);
1264
1440
  return {
1265
1441
  parsed: result.data,
1266
1442
  comparisonValue: result.data,
1267
1443
  messageCount: result.data.messages.length,
1268
- toolCount: result.data.tools !== void 0 && result.data.tools.length > 0 ? result.data.tools.length : null
1444
+ toolCount
1269
1445
  };
1270
1446
  } catch {
1271
1447
  return emptyRequestAnalysis(rawBody);
@@ -1416,22 +1592,24 @@ const openAILogFormatAdapter = {
1416
1592
  analyzeRequest(rawBody) {
1417
1593
  if (rawBody === null) return emptyRequestAnalysis(rawBody);
1418
1594
  try {
1419
- const result = OpenAIRequestSchema.safeParse(JSON.parse(rawBody));
1595
+ const parsedBody = JSON.parse(rawBody);
1596
+ const toolCount = parseRequestTools(parsedBody)?.tools.length ?? null;
1597
+ const result = OpenAIRequestSchema.safeParse(parsedBody);
1420
1598
  if (!result.success) {
1421
- const responsesResult = OpenAIResponsesRequestSchema.safeParse(JSON.parse(rawBody));
1599
+ const responsesResult = OpenAIResponsesRequestSchema.safeParse(parsedBody);
1422
1600
  if (!responsesResult.success) return emptyRequestAnalysis(rawBody);
1423
1601
  return {
1424
1602
  parsed: responsesResult.data,
1425
1603
  comparisonValue: responsesResult.data,
1426
1604
  messageCount: countResponsesInput(responsesResult.data.input),
1427
- toolCount: responsesResult.data.tools !== void 0 && responsesResult.data.tools.length > 0 ? responsesResult.data.tools.length : null
1605
+ toolCount
1428
1606
  };
1429
1607
  }
1430
1608
  return {
1431
1609
  parsed: result.data,
1432
1610
  comparisonValue: result.data,
1433
1611
  messageCount: result.data.messages.length,
1434
- toolCount: result.data.tools !== void 0 && result.data.tools.length > 0 ? result.data.tools.length : null
1612
+ toolCount
1435
1613
  };
1436
1614
  } catch {
1437
1615
  return emptyRequestAnalysis(rawBody);
@@ -2368,27 +2546,27 @@ function useCopyFeedback(text) {
2368
2546
  return { copied, copy };
2369
2547
  }
2370
2548
  const LazyCompareDrawer = reactExports.lazy(
2371
- () => import("./CompareDrawer-CaM8FYuD.mjs").then((m) => ({ default: m.CompareDrawer }))
2549
+ () => import("./CompareDrawer-irfFdkJ8.mjs").then((m) => ({ default: m.CompareDrawer }))
2372
2550
  );
2373
2551
  const LazyReplayDialog = reactExports.lazy(
2374
- () => import("./ReplayDialog-BPpJ2-q8.mjs").then((m) => ({ default: m.ReplayDialog }))
2552
+ () => import("./ReplayDialog-CJnmXQGT.mjs").then((m) => ({ default: m.ReplayDialog }))
2375
2553
  );
2376
2554
  const LazyRequestAnatomy = reactExports.lazy(
2377
- () => import("./RequestAnatomy-DeQAWnZx.mjs").then((m) => ({ default: m.RequestAnatomy }))
2555
+ () => import("./RequestAnatomy-CupP0Wdb.mjs").then((m) => ({ default: m.RequestAnatomy }))
2378
2556
  );
2379
2557
  const LazyResponseView = reactExports.lazy(
2380
- () => import("./ResponseView-Dshm8iQ7.mjs").then((m) => ({ default: m.ResponseView }))
2558
+ () => import("./ResponseView-Bp-0t5cd.mjs").then((m) => ({ default: m.ResponseView }))
2381
2559
  );
2382
2560
  const LazyStreamingChunkSequence = reactExports.lazy(
2383
- () => import("./StreamingChunkSequence-32yIU2hn.mjs").then((m) => ({
2561
+ () => import("./StreamingChunkSequence-BXSn4kMH.mjs").then((m) => ({
2384
2562
  default: m.StreamingChunkSequence
2385
2563
  }))
2386
2564
  );
2387
2565
  const LazyJsonViewer = reactExports.lazy(
2388
- () => import("./json-viewer-C0aX5rqC.mjs").then((m) => ({ default: m.JsonViewer }))
2566
+ () => import("./json-viewer-EYQ5eG2Q.mjs").then((m) => ({ default: m.JsonViewer }))
2389
2567
  );
2390
2568
  const LazyJsonViewerFromString = reactExports.lazy(
2391
- () => import("./json-viewer-C0aX5rqC.mjs").then((m) => ({ default: m.JsonViewerFromString }))
2569
+ () => import("./json-viewer-EYQ5eG2Q.mjs").then((m) => ({ default: m.JsonViewerFromString }))
2392
2570
  );
2393
2571
  const HIGHLIGHT_DURATION_MS = 1200;
2394
2572
  const MAX_HIGHLIGHT_ATTEMPTS = 12;
@@ -3535,171 +3713,6 @@ function shouldShowHeadersDiffButton(viewMode, hasRawHeaders) {
3535
3713
  function shouldShowRequestDiffButton(apiFormat, viewMode, strip, hasRawRequest) {
3536
3714
  return apiFormat === "anthropic" && viewMode === "full" && strip && hasRawRequest;
3537
3715
  }
3538
- const CATEGORY_ORDER = [
3539
- "file",
3540
- "shell",
3541
- "browser",
3542
- "web",
3543
- "mcp",
3544
- "code",
3545
- "other"
3546
- ];
3547
- function firstTextSlice(value) {
3548
- const normalized = value.replace(/\s+/g, " ").trim();
3549
- if (normalized.length <= 120) return normalized;
3550
- return `${normalized.slice(0, 119)}...`;
3551
- }
3552
- function previewDescription(description) {
3553
- if (description === null) return null;
3554
- const normalized = description.replace(/\s+/g, " ").trim();
3555
- if (normalized.length === 0) return null;
3556
- const sentenceEnd = normalized.search(/[.!?。!?]/);
3557
- if (sentenceEnd >= 24) return firstTextSlice(normalized.slice(0, sentenceEnd + 1));
3558
- return firstTextSlice(normalized);
3559
- }
3560
- function lowerHaystack(name, description) {
3561
- return `${name} ${description ?? ""}`.toLowerCase();
3562
- }
3563
- function includesAny(value, needles) {
3564
- return needles.some((needle) => value.includes(needle));
3565
- }
3566
- function categorizeTool(name, description) {
3567
- const haystack = lowerHaystack(name, description);
3568
- if (name.startsWith("mcp__") || name.startsWith("inspector_") || includesAny(haystack, [" mcp", "model context protocol"])) {
3569
- return "mcp";
3570
- }
3571
- if (includesAny(haystack, ["bash", "shell", "terminal", "command", "powershell", "exec", "process"])) {
3572
- return "shell";
3573
- }
3574
- if (includesAny(haystack, [
3575
- "browser",
3576
- "playwright",
3577
- "screenshot",
3578
- "click",
3579
- "navigate",
3580
- "page",
3581
- "tab"
3582
- ])) {
3583
- return "browser";
3584
- }
3585
- if (includesAny(haystack, [
3586
- "read",
3587
- "write",
3588
- "edit",
3589
- "file",
3590
- "glob",
3591
- "grep",
3592
- "patch",
3593
- "filesystem",
3594
- "directory"
3595
- ])) {
3596
- return "file";
3597
- }
3598
- if (includesAny(haystack, ["web", "search", "http", "url", "fetch"])) {
3599
- return "web";
3600
- }
3601
- if (includesAny(haystack, ["code", "typescript", "javascript", "python", "repl"])) {
3602
- return "code";
3603
- }
3604
- return "other";
3605
- }
3606
- function parameterNames(schema) {
3607
- const properties = safeGetOwnProperty(schema, "properties");
3608
- if (properties === null || typeof properties !== "object" || Array.isArray(properties)) {
3609
- return [];
3610
- }
3611
- return Object.keys(properties).sort((a, b) => a.localeCompare(b));
3612
- }
3613
- function requiredParameterNames(schema) {
3614
- const required = safeGetOwnProperty(schema, "required");
3615
- if (!Array.isArray(required)) return [];
3616
- const names = [];
3617
- for (const item of required) {
3618
- if (typeof item === "string" && item.length > 0) names.push(item);
3619
- }
3620
- return names.sort((a, b) => a.localeCompare(b));
3621
- }
3622
- function parseAnthropicTool(tool) {
3623
- const name = safeGetOwnProperty(tool, "name");
3624
- if (typeof name !== "string" || name.length === 0) return null;
3625
- const description = safeGetOwnProperty(tool, "description");
3626
- const schema = safeGetOwnProperty(tool, "input_schema") ?? null;
3627
- const normalizedDescription = typeof description === "string" ? description : null;
3628
- return {
3629
- name,
3630
- description: normalizedDescription,
3631
- descriptionPreview: previewDescription(normalizedDescription),
3632
- category: categorizeTool(name, normalizedDescription),
3633
- parameterCount: parameterNames(schema).length,
3634
- requiredParameters: requiredParameterNames(schema),
3635
- schema
3636
- };
3637
- }
3638
- function parseOpenAITool(tool) {
3639
- const fn = safeGetOwnProperty(tool, "function");
3640
- const toolType = safeGetOwnProperty(tool, "type");
3641
- if (fn === void 0 && toolType !== "function") return null;
3642
- const name = safeGetOwnProperty(fn, "name") ?? safeGetOwnProperty(tool, "name");
3643
- if (typeof name !== "string" || name.length === 0) return null;
3644
- const description = safeGetOwnProperty(fn, "description") ?? safeGetOwnProperty(tool, "description");
3645
- const schema = safeGetOwnProperty(fn, "parameters") ?? safeGetOwnProperty(tool, "parameters") ?? null;
3646
- const normalizedDescription = typeof description === "string" ? description : null;
3647
- return {
3648
- name,
3649
- description: normalizedDescription,
3650
- descriptionPreview: previewDescription(normalizedDescription),
3651
- category: categorizeTool(name, normalizedDescription),
3652
- parameterCount: parameterNames(schema).length,
3653
- requiredParameters: requiredParameterNames(schema),
3654
- schema
3655
- };
3656
- }
3657
- function parseTool(tool) {
3658
- const openAITool = parseOpenAITool(tool);
3659
- if (openAITool !== null) return openAITool;
3660
- return parseAnthropicTool(tool);
3661
- }
3662
- function formatToolChoice(choice) {
3663
- if (choice === void 0 || choice === null) return null;
3664
- if (typeof choice === "string") return choice;
3665
- const type = safeGetOwnProperty(choice, "type");
3666
- const name = safeGetOwnProperty(choice, "name");
3667
- const fnName = safeGetOwnProperty(safeGetOwnProperty(choice, "function"), "name");
3668
- if (typeof type === "string" && typeof fnName === "string" && fnName.length > 0) {
3669
- return `${type}: ${fnName}`;
3670
- }
3671
- if (typeof type === "string" && typeof name === "string" && name.length > 0) {
3672
- return `${type}: ${name}`;
3673
- }
3674
- if (typeof type === "string") return type;
3675
- const encoded = JSON.stringify(choice);
3676
- return encoded === void 0 ? null : firstTextSlice(encoded);
3677
- }
3678
- function summarizeCategories(tools) {
3679
- const counts = /* @__PURE__ */ new Map();
3680
- for (const tool of tools) {
3681
- counts.set(tool.category, (counts.get(tool.category) ?? 0) + 1);
3682
- }
3683
- return CATEGORY_ORDER.flatMap((category) => {
3684
- const count = counts.get(category) ?? 0;
3685
- return count > 0 ? [{ category, count }] : [];
3686
- });
3687
- }
3688
- function parseRequestTools(parsed) {
3689
- const rawTools = safeGetOwnProperty(parsed, "tools");
3690
- if (!Array.isArray(rawTools) || rawTools.length === 0) return null;
3691
- const tools = [];
3692
- for (const rawTool of rawTools) {
3693
- const tool = parseTool(rawTool);
3694
- if (tool !== null) tools.push(tool);
3695
- }
3696
- if (tools.length === 0) return null;
3697
- return {
3698
- tools,
3699
- toolChoiceLabel: formatToolChoice(safeGetOwnProperty(parsed, "tool_choice")),
3700
- categories: summarizeCategories(tools)
3701
- };
3702
- }
3703
3716
  function TabFallback() {
3704
3717
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-1", "aria-hidden": "true" });
3705
3718
  }
@@ -5067,7 +5080,6 @@ const TurnGroup = reactExports.memo(function TurnGroup2({
5067
5080
  }
5068
5081
  },
5069
5082
  children: [
5070
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-5 shrink-0 flex items-start pt-1.5", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] text-muted-foreground/50 font-mono tabular-nums leading-none select-none", children: turnIndex + 1 }) }),
5071
5083
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-6 shrink-0 flex flex-col items-center pt-1.5 pb-1.5", children: [
5072
5084
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex justify-center h-[calc(0.75rem-8px)]" }),
5073
5085
  /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -5174,7 +5186,6 @@ const TurnGroup = reactExports.memo(function TurnGroup2({
5174
5186
  const { log, stopReason: reason } = entry;
5175
5187
  const isTurnStart = visibleIdx === 0;
5176
5188
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-stretch", children: [
5177
- isTurnStart ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-5 shrink-0 flex items-start pt-1.5", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] text-muted-foreground/50 font-mono tabular-nums leading-none select-none", children: turnIndex + 1 }) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-5 shrink-0" }),
5178
5189
  /* @__PURE__ */ jsxRuntimeExports.jsx(
5179
5190
  ThreadConnector,
5180
5191
  {
@@ -8288,33 +8299,12 @@ function ProviderFormatTestStatus({
8288
8299
  ] })
8289
8300
  ] });
8290
8301
  }
8291
- function EndpointDiagnosticLine({
8292
- diagnostic
8293
- }) {
8294
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: diagnostic.severity === "warning" ? "text-amber-200" : "text-muted-foreground", children: diagnostic.message });
8295
- }
8296
- function ProviderEndpointSummary({
8302
+ function ProviderFormatStatusBlock({
8297
8303
  label,
8298
- baseUrl,
8299
- endpoint,
8300
- providerName,
8301
8304
  children
8302
8305
  }) {
8303
- const preview = previewUpstreamUrl(baseUrl, endpoint, { providerName });
8304
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-col gap-2 border-t border-border/60 pt-2 first:border-t-0 first:pt-0", children: [
8305
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid min-w-0 gap-1 text-xs sm:grid-cols-[104px_minmax(0,1fr)]", children: [
8306
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium text-muted-foreground", children: label }),
8307
- /* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "min-w-0 break-all font-mono text-foreground/80", children: baseUrl }),
8308
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] uppercase text-muted-foreground/80", children: "Final" }),
8309
- /* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "min-w-0 break-all font-mono text-foreground", children: preview.finalUrl })
8310
- ] }),
8311
- preview.diagnostics.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1 text-xs", children: preview.diagnostics.map((diagnostic) => /* @__PURE__ */ jsxRuntimeExports.jsx(
8312
- EndpointDiagnosticLine,
8313
- {
8314
- diagnostic
8315
- },
8316
- `${diagnostic.severity}:${diagnostic.message}`
8317
- )) }),
8306
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 space-y-2 rounded-md border border-border/60 bg-muted/15 p-2", children: [
8307
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs font-medium text-foreground/80", children: label }),
8318
8308
  children
8319
8309
  ] });
8320
8310
  }
@@ -8334,22 +8324,38 @@ function providerTestTargets(provider) {
8334
8324
  }
8335
8325
  return targets;
8336
8326
  }
8337
- function ProviderTestCoverage({ provider }) {
8338
- const targets = providerTestTargets(provider);
8339
- if (targets.length === 0) {
8327
+ function CapabilityChip({
8328
+ label,
8329
+ enabled,
8330
+ tone
8331
+ }) {
8332
+ const resolvedTone = tone ?? (enabled ? "active" : "quiet");
8333
+ const className = resolvedTone === "response" && enabled ? "border-sky-300/30 bg-sky-300/[0.09] text-sky-100" : enabled ? "border-border/70 bg-muted/25 text-foreground/80" : "border-border/50 bg-transparent text-muted-foreground/70";
8334
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: `inline-flex items-center gap-1 rounded border px-1.5 py-0.5 ${className}`, children: [
8335
+ enabled ? /* @__PURE__ */ jsxRuntimeExports.jsx(CircleCheckBig, { className: "size-3" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Minus, { className: "size-3" }),
8336
+ label
8337
+ ] });
8338
+ }
8339
+ function ProviderCapabilitySummary({ provider }) {
8340
+ const hasAnthropic = providerHasEndpoint(provider.anthropicBaseUrl);
8341
+ const hasChat = providerHasEndpoint(provider.openaiBaseUrl);
8342
+ const hasResponses = providerHasEndpoint(provider.openaiResponsesBaseUrl);
8343
+ if (!hasAnthropic && !hasChat && !hasResponses) {
8340
8344
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-muted-foreground", children: "Test requires at least one configured endpoint." });
8341
8345
  }
8342
8346
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-1.5 text-xs text-muted-foreground", children: [
8343
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Test covers" }),
8344
- targets.map((target) => /* @__PURE__ */ jsxRuntimeExports.jsx(
8345
- "span",
8347
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Capabilities" }),
8348
+ hasAnthropic && /* @__PURE__ */ jsxRuntimeExports.jsx(CapabilityChip, { label: "Anthropic", enabled: true }),
8349
+ hasChat && /* @__PURE__ */ jsxRuntimeExports.jsx(CapabilityChip, { label: "OpenAI Chat", enabled: true }),
8350
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
8351
+ CapabilityChip,
8346
8352
  {
8347
- className: "rounded border border-border/70 bg-muted/25 px-1.5 py-0.5 text-foreground/80",
8348
- children: target
8349
- },
8350
- target
8351
- )),
8352
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "non-stream + stream" })
8353
+ label: hasResponses ? "OpenAI Responses" : "No OpenAI Responses",
8354
+ enabled: hasResponses,
8355
+ tone: "response"
8356
+ }
8357
+ ),
8358
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "tested non-stream + stream" })
8353
8359
  ] });
8354
8360
  }
8355
8361
  function configuredFormatResults(provider, testResults) {
@@ -8714,7 +8720,7 @@ function ProviderCard({
8714
8720
  ] })
8715
8721
  ] }),
8716
8722
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-2 text-xs text-muted-foreground sm:flex-row sm:items-center sm:justify-between", children: [
8717
- /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderTestCoverage, { provider }),
8723
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderCapabilitySummary, { provider }),
8718
8724
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
8719
8725
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Key configured" }),
8720
8726
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: provider.authHeader === "x-api-key" ? "x-api-key" : "Bearer" }),
@@ -8781,36 +8787,21 @@ function ProviderCard({
8781
8787
  )
8782
8788
  ] }),
8783
8789
  provider.models !== void 0 && provider.models.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-wrap gap-1", children: provider.models.map((model) => /* @__PURE__ */ jsxRuntimeExports.jsx(ModelChip, { provider, model }, model)) }),
8784
- providerHasEndpoint(provider.anthropicBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsx(
8785
- ProviderEndpointSummary,
8786
- {
8787
- label: "Anthropic",
8788
- baseUrl: provider.anthropicBaseUrl,
8789
- endpoint: PATH_V1_MESSAGES,
8790
- providerName: provider.name,
8791
- children: testResults !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: testResults.anthropic })
8792
- }
8793
- ),
8794
- providerHasEndpoint(provider.openaiBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsx(
8795
- ProviderEndpointSummary,
8796
- {
8797
- label: "Chat",
8798
- baseUrl: provider.openaiBaseUrl,
8799
- endpoint: PATH_V1_CHAT_COMPLETIONS,
8800
- providerName: provider.name,
8801
- children: testResults !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: testResults.openaiChat })
8802
- }
8803
- ),
8804
- providerHasEndpoint(provider.openaiResponsesBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsx(
8805
- ProviderEndpointSummary,
8806
- {
8807
- label: "Responses",
8808
- baseUrl: provider.openaiResponsesBaseUrl,
8809
- endpoint: PATH_V1_RESPONSES,
8810
- providerName: provider.name,
8811
- children: testResults !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: testResults.openaiResponses })
8812
- }
8813
- ),
8790
+ (providerHasEndpoint(provider.anthropicBaseUrl) || providerHasEndpoint(provider.openaiBaseUrl) || providerHasEndpoint(provider.openaiResponsesBaseUrl)) && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid gap-2 lg:grid-cols-3", children: [
8791
+ providerHasEndpoint(provider.anthropicBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsxs(ProviderFormatStatusBlock, { label: "Anthropic", children: [
8792
+ testResults !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: testResults.anthropic }),
8793
+ testResults === void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-muted-foreground", children: "Not tested yet" })
8794
+ ] }),
8795
+ providerHasEndpoint(provider.openaiBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsxs(ProviderFormatStatusBlock, { label: "OpenAI Chat", children: [
8796
+ testResults !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: testResults.openaiChat }),
8797
+ testResults === void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-muted-foreground", children: "Not tested yet" })
8798
+ ] }),
8799
+ providerHasEndpoint(provider.openaiResponsesBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsxs(ProviderFormatStatusBlock, { label: "OpenAI Responses", children: [
8800
+ testResults !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: testResults.openaiResponses }),
8801
+ testResults === void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-muted-foreground", children: "Not tested yet" })
8802
+ ] }),
8803
+ !providerHasEndpoint(provider.openaiResponsesBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "min-w-0 rounded-md border border-border/50 bg-transparent p-2 text-xs text-muted-foreground/75", children: "OpenAI Responses not configured" })
8804
+ ] }),
8814
8805
  testResults?.models !== void 0 && Object.keys(testResults.models).length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
8815
8806
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
8816
8807
  "button",
@@ -10233,7 +10224,7 @@ function ProvidersPanel({
10233
10224
  }
10234
10225
  if (showForm || editingProvider) {
10235
10226
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
10236
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "border border-border bg-background/95 shadow-sm sticky top-0 z-10 flex items-center justify-between rounded-[8px] px-3 py-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-lg font-medium", children: editingProvider ? "Edit Provider" : "Add New Provider" }) }),
10227
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sticky top-0 z-10 flex items-center justify-between gap-3 rounded-[8px] bg-background/95 px-1 py-1 backdrop-blur", children: /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-lg font-medium", children: editingProvider ? "Edit Provider" : "Add New Provider" }) }),
10237
10228
  /* @__PURE__ */ jsxRuntimeExports.jsx(
10238
10229
  ProviderForm,
10239
10230
  {
@@ -10248,7 +10239,7 @@ function ProvidersPanel({
10248
10239
  ] });
10249
10240
  }
10250
10241
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
10251
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border border-border bg-background/95 shadow-sm sticky top-0 z-10 flex items-center justify-between rounded-[8px] px-3 py-2", children: [
10242
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sticky top-0 z-10 flex items-center justify-between gap-3 rounded-[8px] bg-background/95 px-1 py-1 backdrop-blur", children: [
10252
10243
  /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-lg font-medium", children: "Providers" }),
10253
10244
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
10254
10245
  /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
@@ -10315,7 +10306,7 @@ function ProvidersPanel({
10315
10306
  ] })
10316
10307
  ] })
10317
10308
  ] }),
10318
- configPath !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border border-border bg-card shadow-sm flex items-center gap-2 rounded-[8px] px-3 py-2 text-xs text-muted-foreground", children: [
10309
+ configPath !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 rounded-[8px] bg-muted/15 px-3 py-2 text-xs text-muted-foreground", children: [
10319
10310
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0", children: "Config:" }),
10320
10311
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono truncate", title: configPath, children: configPath }),
10321
10312
  /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
@@ -10349,13 +10340,13 @@ function ProvidersPanel({
10349
10340
  "Add Your First Provider"
10350
10341
  ] })
10351
10342
  ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-3", children: [
10352
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "border border-border bg-muted/40 flex gap-1 rounded-[8px] p-1", children: ["all", "personal", "company"].map((tab) => /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
10343
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "inline-flex w-fit gap-1 rounded-[8px] bg-muted/20 p-1", children: ["all", "personal", "company"].map((tab) => /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
10353
10344
  /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
10354
10345
  "button",
10355
10346
  {
10356
10347
  type: "button",
10357
10348
  onClick: () => setSourceFilter(tab),
10358
- className: `px-3 py-2 text-sm font-medium border-b-2 transition-colors ${sourceFilter === tab ? "border-primary text-primary" : "border-transparent text-muted-foreground hover:text-foreground"}`,
10349
+ className: `rounded-md px-3 py-1.5 text-sm font-medium transition-colors ${sourceFilter === tab ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`,
10359
10350
  children: tab === "all" ? "All" : tab === "personal" ? "Personal" : "Company"
10360
10351
  }
10361
10352
  ) }),
@@ -10460,17 +10451,17 @@ function SettingsDialog() {
10460
10451
  ]
10461
10452
  }
10462
10453
  ) }),
10463
- /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogContent, { className: "max-w-2xl max-h-[80vh] overflow-hidden flex flex-col", children: [
10454
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogContent, { className: "flex max-h-[80vh] max-w-2xl flex-col overflow-hidden", children: [
10464
10455
  /* @__PURE__ */ jsxRuntimeExports.jsx(DialogHeader, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(DialogTitle, { children: "Settings" }) }),
10465
10456
  /* @__PURE__ */ jsxRuntimeExports.jsxs(Tabs, { value: activeTab, onValueChange: setActiveTab, className: "flex-1 overflow-hidden", children: [
10466
- /* @__PURE__ */ jsxRuntimeExports.jsxs(TabsList, { children: [
10457
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(TabsList, { className: "w-full justify-start bg-muted/35", children: [
10467
10458
  /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "providers", children: "Providers" }),
10468
10459
  /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "proxy", children: "Proxy" }),
10469
10460
  /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "storage", children: "Storage" }),
10470
10461
  /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "mcp", children: "MCP" }),
10471
10462
  /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "onboarding", children: "Onboarding" })
10472
10463
  ] }),
10473
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-4 flex-1 overflow-x-hidden overflow-y-auto pr-3", children: [
10464
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-4 flex-1 overflow-x-hidden overflow-y-auto pr-2", children: [
10474
10465
  /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "providers", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
10475
10466
  ProvidersPanel,
10476
10467
  {
@@ -10550,7 +10541,7 @@ function StorageSettingsTab() {
10550
10541
  }, []);
10551
10542
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
10552
10543
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-3", children: [
10553
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
10544
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0", children: [
10554
10545
  /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-sm font-semibold", children: "Log storage" }),
10555
10546
  /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: "Inspect local log and streaming chunk footprint before exporting or clearing sessions." })
10556
10547
  ] }),
@@ -10587,14 +10578,14 @@ function StorageSettingsTab() {
10587
10578
  onCopy: handleCopy
10588
10579
  }
10589
10580
  ),
10590
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border border-border bg-muted/40 rounded-md px-3 py-2", children: [
10581
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-md bg-muted/20 px-3 py-2", children: [
10591
10582
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-medium", children: "In-memory logs" }),
10592
10583
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-1 font-mono text-muted-foreground", children: [
10593
10584
  stats.memoryCount.toLocaleString(),
10594
10585
  " loaded"
10595
10586
  ] })
10596
10587
  ] }),
10597
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border border-border bg-muted/40 rounded-md px-3 py-2", children: [
10588
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-md bg-muted/20 px-3 py-2", children: [
10598
10589
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-medium", children: "Log files" }),
10599
10590
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-1 font-mono text-muted-foreground", children: [
10600
10591
  stats.logFileCount.toLocaleString(),
@@ -10602,7 +10593,7 @@ function StorageSettingsTab() {
10602
10593
  formatBytes(stats.logBytes)
10603
10594
  ] })
10604
10595
  ] }),
10605
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border border-border bg-muted/40 rounded-md px-3 py-2", children: [
10596
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-md bg-muted/20 px-3 py-2", children: [
10606
10597
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-medium", children: "Streaming chunks" }),
10607
10598
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-1 font-mono text-muted-foreground", children: [
10608
10599
  stats.chunkFileCount.toLocaleString(),
@@ -10610,7 +10601,7 @@ function StorageSettingsTab() {
10610
10601
  formatBytes(stats.chunkBytes)
10611
10602
  ] })
10612
10603
  ] }),
10613
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border border-border bg-muted/40 rounded-md px-3 py-2", children: [
10604
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-md bg-muted/20 px-3 py-2", children: [
10614
10605
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-medium", children: "Session archives" }),
10615
10606
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-1 font-mono text-muted-foreground", children: [
10616
10607
  stats.sessionArchiveFileCount.toLocaleString(),
@@ -10631,7 +10622,7 @@ function CopyableSetupValue({
10631
10622
  onCopy
10632
10623
  }) {
10633
10624
  const copied = copiedId === id;
10634
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border border-border bg-muted/40 min-w-0 rounded-md px-3 py-2", children: [
10625
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 rounded-md border border-border/45 bg-muted/15 px-3 py-2 transition-colors hover:bg-muted/25", children: [
10635
10626
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-1 text-xs font-medium text-muted-foreground", children: label }),
10636
10627
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
10637
10628
  /* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "min-w-0 flex-1 truncate font-mono text-xs text-foreground", children: value }),
@@ -10730,7 +10721,7 @@ function OnboardingSettingsTab() {
10730
10721
  },
10731
10722
  item.id
10732
10723
  )) }),
10733
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid gap-2 rounded-md border border-border bg-background px-3 py-2 text-xs text-muted-foreground", children: [
10724
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid gap-2 rounded-md bg-muted/15 px-3 py-2 text-xs text-muted-foreground", children: [
10734
10725
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
10735
10726
  /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-3.5 text-emerald-500" }),
10736
10727
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Provider test creates a traceable memory probe session." })
@@ -10909,7 +10900,7 @@ args = ["stdio", "--url", "${endpoint}"]`
10909
10900
  /* @__PURE__ */ jsxRuntimeExports.jsx(Terminal, { className: "size-4 text-muted-foreground" }),
10910
10901
  /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-sm font-semibold", children: "MCP access" })
10911
10902
  ] }),
10912
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid gap-2 rounded-md border border-border bg-background px-3 py-2 text-xs text-muted-foreground", children: [
10903
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid gap-2 rounded-md bg-muted/15 px-3 py-2 text-xs text-muted-foreground", children: [
10913
10904
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Use Streamable HTTP when the client supports URL-based MCP. Use the stdio bridge only for stdio-only clients. Configure one entry for the same Inspector instance." }),
10914
10905
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "If the MCP client runs in another container or host, replace localhost with a reachable host/IP and verify the network path." })
10915
10906
  ] }),
@@ -11000,14 +10991,9 @@ function ProxySettingsTab() {
11000
10991
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1", children: [
11001
10992
  /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-sm font-semibold", children: "Claude Code billing header" }),
11002
10993
  /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-xs text-muted-foreground", children: [
11003
- "When enabled, the proxy strips the synthetic ",
11004
- /* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: "x-anthropic-billing-header" }),
11005
- " text block that Claude Code prepends to the system prompt before forwarding to upstream. Improves prefix-cache hit rates against third-party upstreams. The default at startup is controlled by the ",
11006
- /* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: "AGENT_INSPECTOR_STRIP_CLAUDE_CODE_BILLING_HEADER" }),
11007
- " ",
11008
- "environment variable; your choice is persisted to ",
10994
+ "Strip Claude Code's synthetic billing block before upstream forwarding. This can improve prefix-cache hits with third-party providers and is persisted to ",
11009
10995
  /* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: "config.json" }),
11010
- " and overrides the env var for subsequent requests."
10996
+ "."
11011
10997
  ] })
11012
10998
  ] }),
11013
10999
  /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "flex items-center gap-3", children: [
@@ -11029,9 +11015,9 @@ function ProxySettingsTab() {
11029
11015
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1", children: [
11030
11016
  /* @__PURE__ */ jsxRuntimeExports.jsx("label", { htmlFor: "slow-response-threshold", className: "text-sm font-semibold", children: "Slow response threshold" }),
11031
11017
  /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-xs text-muted-foreground", children: [
11032
- "Logs whose elapsed time exceeds this many seconds show a warning icon next to the duration. Set to ",
11018
+ "Show a slow marker when elapsed time exceeds this many seconds. Use ",
11033
11019
  /* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: "0" }),
11034
- " to disable the indicator."
11020
+ " to disable it."
11035
11021
  ] }),
11036
11022
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
11037
11023
  /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -11058,7 +11044,7 @@ function ProxySettingsTab() {
11058
11044
  ] }),
11059
11045
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1", children: [
11060
11046
  /* @__PURE__ */ jsxRuntimeExports.jsx("label", { htmlFor: "provider-test-timeout", className: "text-sm font-semibold", children: "Provider test timeout" }),
11061
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: "Provider Test waits this many seconds per configured model before aborting slow probes. The full test window scales with model count." }),
11047
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: "Abort slow Provider Test probes after this many seconds per model." }),
11062
11048
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
11063
11049
  /* @__PURE__ */ jsxRuntimeExports.jsx(
11064
11050
  "input",
@@ -11084,7 +11070,7 @@ function ProxySettingsTab() {
11084
11070
  ] }),
11085
11071
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1", children: [
11086
11072
  /* @__PURE__ */ jsxRuntimeExports.jsx("label", { htmlFor: "time-display-format", className: "text-sm font-semibold", children: "Time display" }),
11087
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: "Controls timestamps in session summaries, conversation headers, and log rows." }),
11073
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: "Controls timestamps in session summaries, headers, and log rows." }),
11088
11074
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
11089
11075
  "select",
11090
11076
  {
@@ -13777,6 +13763,36 @@ function LogPaginationButton({
13777
13763
  }
13778
13764
  );
13779
13765
  }
13766
+ function formatDurationSeconds(ms) {
13767
+ return `${Math.max(0, Math.ceil(ms / 1e3)).toString()}s`;
13768
+ }
13769
+ function SessionLoadProgressBar({ progress }) {
13770
+ const elapsedRatio = Math.min(1, progress.elapsedMs / progress.timeoutMs);
13771
+ const percent = Math.max(4, Math.round(elapsedRatio * 100));
13772
+ const remainingMs = Math.max(0, progress.timeoutMs - progress.elapsedMs);
13773
+ const nearTimeout = elapsedRatio >= 0.75;
13774
+ const details = [
13775
+ progress.loadedLogs > 0 ? `${progress.loadedLogs.toString()} logs` : null,
13776
+ progress.loadedPages > 0 ? `${progress.loadedPages.toString()} page${progress.loadedPages === 1 ? "" : "s"}` : null,
13777
+ `${formatDurationSeconds(remainingMs)} before timeout`
13778
+ ].filter((item) => item !== null);
13779
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 space-y-1 px-1 pb-1", children: [
13780
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center justify-between gap-3 font-mono text-[10px] text-muted-foreground", children: [
13781
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0 truncate", children: progress.label }),
13782
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn("shrink-0 tabular-nums", nearTimeout && "text-amber-300"), children: details.join(" / ") })
13783
+ ] }),
13784
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-1.5 overflow-hidden rounded-full bg-white/[0.06]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
13785
+ "div",
13786
+ {
13787
+ className: cn(
13788
+ "h-full rounded-full transition-all duration-300",
13789
+ nearTimeout ? "bg-amber-300/80" : "bg-cyan-300/70"
13790
+ ),
13791
+ style: { width: `${percent.toString()}%` }
13792
+ }
13793
+ ) })
13794
+ ] });
13795
+ }
13780
13796
  function LogPaginationBar({
13781
13797
  logs,
13782
13798
  pagination,
@@ -13794,7 +13810,8 @@ function LogPaginationBar({
13794
13810
  children: [
13795
13811
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full min-w-0 px-1 font-mono text-[11px] text-muted-foreground sm:flex-1", children: [
13796
13812
  formatPaginationStatus({ logs, pagination }),
13797
- pagination.isLoading && logs.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ml-2", children: "Loading..." })
13813
+ pagination.isLoading && logs.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ml-2", children: "Loading..." }),
13814
+ pagination.loadProgress !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(SessionLoadProgressBar, { progress: pagination.loadProgress })
13798
13815
  ] }),
13799
13816
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex w-full items-center gap-1 overflow-x-auto sm:w-auto", children: [
13800
13817
  /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -13932,16 +13949,6 @@ function CopyableCommand({ command }) {
13932
13949
  )
13933
13950
  ] });
13934
13951
  }
13935
- function McpReadyBadge() {
13936
- return /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
13937
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "bg-cyan-300/[0.055] shadow-[inset_0_1px_0_rgba(255,255,255,0.05)] inline-flex h-7 items-center gap-2 rounded-md px-2.5 font-mono text-[11px] font-medium text-cyan-200", children: [
13938
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "size-1.5 rounded-full bg-cyan-200 shadow-[0_0_8px_rgba(125,211,252,0.75)]" }),
13939
- "MCP Ready",
13940
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "hidden text-cyan-200/70 sm:inline", children: "/api/mcp" })
13941
- ] }) }),
13942
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { sideOffset: 8, className: "max-w-[320px] text-left leading-relaxed", children: "Coding agents can inspect logs, replay requests, test providers, and debug sessions through MCP at /api/mcp." })
13943
- ] }) });
13944
- }
13945
13952
  function SidebarPanel({
13946
13953
  label,
13947
13954
  children,
@@ -13986,7 +13993,7 @@ function CrabFamily({
13986
13993
  entrancePhase
13987
13994
  }) {
13988
13995
  if (compact) {
13989
- return /* @__PURE__ */ jsxRuntimeExports.jsx(CrabLogo, { className: "size-7 text-amber-500" });
13996
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(CrabLogo, { className: "size-14 text-amber-500" });
13990
13997
  }
13991
13998
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex shrink-0 items-end gap-1 group cursor-default", "aria-hidden": "true", children: [
13992
13999
  /* @__PURE__ */ jsxRuntimeExports.jsx(CrabLogo, { className: "size-10 text-amber-500 transition-all duration-300 group-hover:scale-125 group-hover:-translate-y-1.5" }),
@@ -14014,30 +14021,27 @@ function BrandHeader({
14014
14021
  logCount
14015
14022
  }) {
14016
14023
  if (compact) {
14017
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-white/[0.035] shadow-[inset_0_1px_0_rgba(255,255,255,0.045),0_16px_44px_rgba(0,0,0,0.18)] rounded-[8px] p-3", children: [
14018
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [
14019
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-fit items-start gap-2", children: [
14020
- /* @__PURE__ */ jsxRuntimeExports.jsx(CrabFamily, { compact: true, entrancePhase: crabEntrancePhase }),
14021
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-fit", children: [
14022
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-fit flex-wrap items-baseline gap-x-2 gap-y-0.5", children: [
14023
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "whitespace-nowrap text-base font-bold", children: "Agent Inspector" }),
14024
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "hidden shrink-0 font-mono text-[11px] font-semibold text-muted-foreground sm:inline", children: [
14025
- "v",
14026
- packageJson.version
14027
- ] })
14028
- ] }),
14029
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "hidden text-[11px] font-semibold text-muted-foreground sm:block", children: "Local First. Evidence First." })
14030
- ] })
14031
- ] }),
14032
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [
14033
- /* @__PURE__ */ jsxRuntimeExports.jsx(AlertsDialog, {}),
14034
- /* @__PURE__ */ jsxRuntimeExports.jsx(GroupsDialog, {}),
14035
- /* @__PURE__ */ jsxRuntimeExports.jsx(AgentLabDialog, { currentSessionId, logCount }),
14036
- /* @__PURE__ */ jsxRuntimeExports.jsx(SettingsDialog, {})
14024
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "bg-white/[0.035] shadow-[inset_0_1px_0_rgba(255,255,255,0.045),0_16px_44px_rgba(0,0,0,0.18)] rounded-[8px] p-3", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [
14025
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-fit items-start gap-3", children: [
14026
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CrabFamily, { compact: true, entrancePhase: crabEntrancePhase }),
14027
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-fit", children: [
14028
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-fit flex-wrap items-baseline gap-x-2 gap-y-0.5", children: [
14029
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "whitespace-nowrap text-base font-bold", children: "Agent Inspector" }),
14030
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "hidden shrink-0 font-mono text-[11px] font-semibold text-muted-foreground sm:inline", children: [
14031
+ "v",
14032
+ packageJson.version
14033
+ ] })
14034
+ ] }),
14035
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "hidden text-[11px] font-semibold text-muted-foreground sm:block", children: "Local First. Evidence First." })
14037
14036
  ] })
14038
14037
  ] }),
14039
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 hidden sm:block", children: /* @__PURE__ */ jsxRuntimeExports.jsx(McpReadyBadge, {}) })
14040
- ] });
14038
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [
14039
+ /* @__PURE__ */ jsxRuntimeExports.jsx(AlertsDialog, {}),
14040
+ /* @__PURE__ */ jsxRuntimeExports.jsx(GroupsDialog, {}),
14041
+ /* @__PURE__ */ jsxRuntimeExports.jsx(AgentLabDialog, { currentSessionId, logCount }),
14042
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SettingsDialog, {})
14043
+ ] })
14044
+ ] }) });
14041
14045
  }
14042
14046
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-start justify-between gap-x-4 gap-y-3 pb-6", children: [
14043
14047
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "min-w-10 flex-1", "aria-hidden": "true" }),
@@ -14054,8 +14058,7 @@ function BrandHeader({
14054
14058
  /* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "size-4 shrink-0 text-muted-foreground/70", "aria-hidden": "true" }),
14055
14059
  /* @__PURE__ */ jsxRuntimeExports.jsx(McpLogo, { className: "size-10 shrink-0" })
14056
14060
  ] }),
14057
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "max-w-full text-sm font-semibold text-muted-foreground", children: "Local First. Evidence First." }),
14058
- /* @__PURE__ */ jsxRuntimeExports.jsx(McpReadyBadge, {})
14061
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "max-w-full text-sm font-semibold text-muted-foreground", children: "Local First. Evidence First." })
14059
14062
  ] }),
14060
14063
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-1 justify-end gap-1", children: [
14061
14064
  /* @__PURE__ */ jsxRuntimeExports.jsx(AlertsDialog, {}),
@@ -14362,6 +14365,7 @@ function ProxyViewer({
14362
14365
  onSessionChange,
14363
14366
  onModelChange,
14364
14367
  onClearAll,
14368
+ onDeleteCurrentView,
14365
14369
  onReloadSession,
14366
14370
  onClearGroup,
14367
14371
  onNotify,
@@ -14373,6 +14377,7 @@ function ProxyViewer({
14373
14377
  timeDisplayFormat,
14374
14378
  isLoading = false,
14375
14379
  pagination,
14380
+ sessionLoadProgress,
14376
14381
  sessionMemberships = [],
14377
14382
  hideSessionFilter = false,
14378
14383
  pinnedSessionId
@@ -14384,6 +14389,9 @@ function ProxyViewer({
14384
14389
  const [importing, setImporting] = reactExports.useState(false);
14385
14390
  const [importStatus, setImportStatus] = reactExports.useState(null);
14386
14391
  const [importError, setImportError] = reactExports.useState(null);
14392
+ const [deleteDialogOpen, setDeleteDialogOpen] = reactExports.useState(false);
14393
+ const [deleteStoredData, setDeleteStoredData] = reactExports.useState(false);
14394
+ const [deletingCurrentView, setDeletingCurrentView] = reactExports.useState(false);
14387
14395
  const [comparePair, setComparePair] = reactExports.useState(null);
14388
14396
  const [crabEntrancePhase, setCrabEntrancePhase] = reactExports.useState(
14389
14397
  "hidden"
@@ -14500,6 +14508,34 @@ function ProxyViewer({
14500
14508
  setComparePair(null);
14501
14509
  onClearAll();
14502
14510
  }, [cancelTransientTasks, onClearAll]);
14511
+ const handleRequestDeleteCurrentView = reactExports.useCallback(() => {
14512
+ setDeleteStoredData(false);
14513
+ setDeleteDialogOpen(true);
14514
+ }, []);
14515
+ const handleConfirmDeleteCurrentView = reactExports.useCallback(() => {
14516
+ cancelTransientTasks();
14517
+ setImportStatus(null);
14518
+ setImportError(null);
14519
+ setComparePair(null);
14520
+ if (!deleteStoredData || onDeleteCurrentView === void 0) {
14521
+ setDeleteDialogOpen(false);
14522
+ onClearAll();
14523
+ return;
14524
+ }
14525
+ setDeletingCurrentView(true);
14526
+ void onDeleteCurrentView(logs.map((log) => log.id)).then(() => {
14527
+ setDeleteDialogOpen(false);
14528
+ }).catch((err) => {
14529
+ const message = err instanceof Error ? err.message : "Failed to delete stored logs";
14530
+ if (onNotify !== void 0) {
14531
+ onNotify({ message, tone: "error" });
14532
+ } else {
14533
+ setImportError(message);
14534
+ }
14535
+ }).finally(() => {
14536
+ setDeletingCurrentView(false);
14537
+ });
14538
+ }, [cancelTransientTasks, deleteStoredData, logs, onClearAll, onDeleteCurrentView, onNotify]);
14503
14539
  const handleReloadCurrentSession = reactExports.useCallback(() => {
14504
14540
  if (onReloadSession === void 0) return;
14505
14541
  cancelTransientTasks();
@@ -14622,16 +14658,31 @@ function ProxyViewer({
14622
14658
  disabled: !canClearCurrentView,
14623
14659
  className: cn(
14624
14660
  "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 min-w-0 items-center justify-center gap-1.5 rounded-md px-2 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
14625
- onReloadSession === void 0 && "col-span-2"
14661
+ onReloadSession === void 0 && onDeleteCurrentView === void 0 && "col-span-2"
14626
14662
  ),
14627
14663
  title: "Clear the current view. Stored logs remain reloadable.",
14628
14664
  children: [
14629
14665
  /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" }),
14630
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Clear view" })
14666
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Clear" })
14667
+ ]
14668
+ }
14669
+ ),
14670
+ onDeleteCurrentView !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
14671
+ "button",
14672
+ {
14673
+ type: "button",
14674
+ onClick: handleRequestDeleteCurrentView,
14675
+ disabled: !canClearCurrentView || deletingCurrentView,
14676
+ className: "bg-red-500/[0.07] hover:bg-red-500/[0.12] inline-flex h-8 min-w-0 items-center justify-center gap-1.5 rounded-md px-2 text-xs text-red-200 shadow-[inset_0_0_0_1px_rgba(248,113,113,0.14)] transition-colors hover:text-red-100 disabled:cursor-not-allowed disabled:opacity-50",
14677
+ title: "Choose whether to delete stored data for the current view.",
14678
+ children: [
14679
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" }),
14680
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Delete" })
14631
14681
  ]
14632
14682
  }
14633
14683
  )
14634
- ] })
14684
+ ] }),
14685
+ sessionLoadProgress !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 rounded-md bg-black/20 px-2 py-2 shadow-[inset_0_0_0_1px_rgba(255,255,255,0.045)]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SessionLoadProgressBar, { progress: sessionLoadProgress }) })
14635
14686
  ] }),
14636
14687
  /* @__PURE__ */ jsxRuntimeExports.jsx(SidebarPanel, { label: "Workspace", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-black/20 rounded-md px-3 py-2 shadow-[inset_0_1px_0_rgba(255,255,255,0.035)]", children: [
14637
14688
  /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -14795,11 +14846,26 @@ function ProxyViewer({
14795
14846
  title: "Clear the current view. Stored logs remain reloadable.",
14796
14847
  children: [
14797
14848
  /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" }),
14798
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Clear view" })
14849
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Clear" })
14850
+ ]
14851
+ }
14852
+ ),
14853
+ onDeleteCurrentView !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
14854
+ "button",
14855
+ {
14856
+ type: "button",
14857
+ onClick: handleRequestDeleteCurrentView,
14858
+ disabled: !canClearCurrentView || deletingCurrentView,
14859
+ className: "bg-red-500/[0.07] hover:bg-red-500/[0.12] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-red-200 shadow-[inset_0_0_0_1px_rgba(248,113,113,0.14)] transition-colors hover:text-red-100 disabled:cursor-not-allowed disabled:opacity-50",
14860
+ title: "Choose whether to delete stored data for the current view.",
14861
+ children: [
14862
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" }),
14863
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Delete" })
14799
14864
  ]
14800
14865
  }
14801
14866
  )
14802
14867
  ] }),
14868
+ pagination === void 0 && sessionLoadProgress !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 rounded-md bg-black/20 px-2 py-2 shadow-[inset_0_0_0_1px_rgba(255,255,255,0.045)]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SessionLoadProgressBar, { progress: sessionLoadProgress }) }),
14803
14869
  /* @__PURE__ */ jsxRuntimeExports.jsx(LogPaginationBar, { logs, pagination, embedded: true }),
14804
14870
  onNotify === void 0 && exportError !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-xs text-destructive", children: exportError }),
14805
14871
  onNotify === void 0 && importError !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-xs text-destructive", children: importError }),
@@ -14810,6 +14876,7 @@ function ProxyViewer({
14810
14876
  logs.length === 0 ? selectedSession !== "__all__" ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "py-16 text-center text-muted-foreground", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-white/[0.035] shadow-[inset_0_1px_0_rgba(255,255,255,0.045),0_18px_52px_rgba(0,0,0,0.18)] mx-auto max-w-xl space-y-4 rounded-[8px] px-4 py-8", children: [
14811
14877
  /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-medium", children: isLoading ? "Loading session data..." : "No logs loaded for this session" }),
14812
14878
  /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "inline-block max-w-full rounded bg-muted px-3 py-1 font-mono text-xs break-all", children: truncateSessionId(selectedSession) }),
14879
+ sessionLoadProgress !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mx-auto max-w-md rounded-md bg-black/20 px-2 py-2 text-left shadow-[inset_0_0_0_1px_rgba(255,255,255,0.045)]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SessionLoadProgressBar, { progress: sessionLoadProgress }) }),
14813
14880
  sessionMemberships.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-left", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SessionMembershipPanel, { memberships: sessionMemberships }) }),
14814
14881
  !isLoading && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center gap-3 text-xs", children: [
14815
14882
  /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Stored logs may still be available." }),
@@ -14881,6 +14948,59 @@ function ProxyViewer({
14881
14948
  ] })
14882
14949
  ] })
14883
14950
  ] }),
14951
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Dialog, { open: deleteDialogOpen, onOpenChange: setDeleteDialogOpen, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogContent, { className: "border-red-500/20 bg-zinc-950 text-zinc-100 sm:max-w-md", children: [
14952
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogHeader, { children: [
14953
+ /* @__PURE__ */ jsxRuntimeExports.jsx(DialogTitle, { children: "Delete current logs?" }),
14954
+ /* @__PURE__ */ jsxRuntimeExports.jsx(DialogDescription, { children: "Choose whether this only clears the UI or also deletes the stored log data for the current view." })
14955
+ ] }),
14956
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "flex items-start gap-3 rounded-md bg-red-500/[0.08] px-3 py-3 text-sm text-red-100 shadow-[inset_0_0_0_1px_rgba(248,113,113,0.16)]", children: [
14957
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
14958
+ "input",
14959
+ {
14960
+ type: "checkbox",
14961
+ className: "mt-0.5 size-4 shrink-0",
14962
+ checked: deleteStoredData,
14963
+ disabled: deletingCurrentView,
14964
+ onChange: (event) => setDeleteStoredData(event.currentTarget.checked)
14965
+ }
14966
+ ),
14967
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "min-w-0", children: [
14968
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "block font-medium", children: "Also delete stored data" }),
14969
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "mt-1 block text-xs text-red-200/80", children: [
14970
+ "Removes persisted log rows, streaming chunks, and session archive entries for these",
14971
+ " ",
14972
+ logs.length.toString(),
14973
+ " visible request",
14974
+ logs.length === 1 ? "" : "s",
14975
+ "."
14976
+ ] })
14977
+ ] })
14978
+ ] }),
14979
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-end gap-2", children: [
14980
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
14981
+ Button,
14982
+ {
14983
+ type: "button",
14984
+ variant: "outline",
14985
+ size: "sm",
14986
+ disabled: deletingCurrentView,
14987
+ onClick: () => setDeleteDialogOpen(false),
14988
+ children: "Cancel"
14989
+ }
14990
+ ),
14991
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
14992
+ Button,
14993
+ {
14994
+ type: "button",
14995
+ variant: deleteStoredData ? "destructive" : "secondary",
14996
+ size: "sm",
14997
+ disabled: deletingCurrentView,
14998
+ onClick: handleConfirmDeleteCurrentView,
14999
+ children: deletingCurrentView ? "Deleting..." : deleteStoredData ? "Delete data" : "Clear only"
15000
+ }
15001
+ )
15002
+ ] })
15003
+ ] }) }),
14884
15004
  comparePair !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
14885
15005
  LazyCompareDrawer,
14886
15006
  {
@@ -14913,6 +15033,13 @@ const LogCursorPageSchema = object({
14913
15033
  newestLogId: number().int().positive().nullable()
14914
15034
  });
14915
15035
  const SessionsResponseSchema = array(string());
15036
+ const DeleteLogsResponseSchema = object({
15037
+ success: boolean(),
15038
+ cleared: number().int().nonnegative(),
15039
+ logFilesRewritten: number().int().nonnegative().optional(),
15040
+ chunkFilesDeleted: number().int().nonnegative(),
15041
+ sessionArchiveLogsDeleted: number().int().nonnegative().optional()
15042
+ });
14916
15043
  function buildSessionMembershipEvidence(groups, sessionId) {
14917
15044
  const memberships = [];
14918
15045
  for (const group of groups) {
@@ -15038,12 +15165,17 @@ function ProxyViewerContainer({
15038
15165
  const [streamInitialized, setStreamInitialized] = reactExports.useState(initialSessionId === void 0);
15039
15166
  const [logPage, setLogPage] = reactExports.useState(null);
15040
15167
  const [sessionPageLoading, setSessionPageLoading] = reactExports.useState(initialSessionId !== void 0);
15168
+ const [sessionLoadProgress, setSessionLoadProgress] = reactExports.useState(
15169
+ void 0
15170
+ );
15041
15171
  const [sessionMemberships, setSessionMemberships] = reactExports.useState([]);
15042
15172
  const [, startLogTransition] = reactExports.useTransition();
15043
15173
  const eventSourceRef = reactExports.useRef(null);
15044
15174
  const reconnectTimeoutRef = reactExports.useRef(null);
15045
15175
  const handledHashRef = reactExports.useRef(null);
15046
15176
  const sessionPageRequestIdRef = reactExports.useRef(0);
15177
+ const sessionLoadStartedAtRef = reactExports.useRef(null);
15178
+ const sessionLoadTimerRef = reactExports.useRef(null);
15047
15179
  const logIndexRef = reactExports.useRef(/* @__PURE__ */ new Map());
15048
15180
  const pendingUpdatesRef = reactExports.useRef([]);
15049
15181
  const flushTimerRef = reactExports.useRef(null);
@@ -15053,6 +15185,50 @@ function ProxyViewerContainer({
15053
15185
  },
15054
15186
  [showToast]
15055
15187
  );
15188
+ const stopSessionLoadProgress = reactExports.useCallback(() => {
15189
+ if (sessionLoadTimerRef.current !== null) {
15190
+ clearInterval(sessionLoadTimerRef.current);
15191
+ sessionLoadTimerRef.current = null;
15192
+ }
15193
+ sessionLoadStartedAtRef.current = null;
15194
+ setSessionLoadProgress(void 0);
15195
+ }, []);
15196
+ const startSessionLoadProgress = reactExports.useCallback(
15197
+ (label, requestId, loadedLogs = 0, loadedPages = 0) => {
15198
+ if (sessionLoadTimerRef.current !== null) {
15199
+ clearInterval(sessionLoadTimerRef.current);
15200
+ }
15201
+ const startedAt = Date.now();
15202
+ sessionLoadStartedAtRef.current = startedAt;
15203
+ const update = () => {
15204
+ if (sessionPageRequestIdRef.current !== requestId) return;
15205
+ setSessionLoadProgress({
15206
+ label,
15207
+ elapsedMs: Date.now() - startedAt,
15208
+ timeoutMs: SESSION_LOGS_FETCH_TIMEOUT_MS,
15209
+ loadedLogs,
15210
+ loadedPages
15211
+ });
15212
+ };
15213
+ update();
15214
+ sessionLoadTimerRef.current = setInterval(update, 250);
15215
+ },
15216
+ []
15217
+ );
15218
+ const updateSessionLoadProgress = reactExports.useCallback(
15219
+ (label, requestId, loadedLogs, loadedPages) => {
15220
+ const startedAt = sessionLoadStartedAtRef.current;
15221
+ if (startedAt === null || sessionPageRequestIdRef.current !== requestId) return;
15222
+ setSessionLoadProgress({
15223
+ label,
15224
+ elapsedMs: Date.now() - startedAt,
15225
+ timeoutMs: SESSION_LOGS_FETCH_TIMEOUT_MS,
15226
+ loadedLogs,
15227
+ loadedPages
15228
+ });
15229
+ },
15230
+ []
15231
+ );
15056
15232
  const logs = reactExports.useMemo(
15057
15233
  () => filterLogs(allLogs, selectedSession, selectedModel),
15058
15234
  [allLogs, selectedSession, selectedModel]
@@ -15148,6 +15324,7 @@ function ProxyViewerContainer({
15148
15324
  const requestId = sessionPageRequestIdRef.current + 1;
15149
15325
  sessionPageRequestIdRef.current = requestId;
15150
15326
  setSessionPageLoading(true);
15327
+ startSessionLoadProgress("Loading session logs", requestId);
15151
15328
  dismissToast();
15152
15329
  void fetchSessionLogsPage(initialSessionId, request).then((page) => {
15153
15330
  if (sessionPageRequestIdRef.current !== requestId) return;
@@ -15157,22 +15334,31 @@ function ProxyViewerContainer({
15157
15334
  setLogPage(page);
15158
15335
  setSelectedSession(initialSessionId);
15159
15336
  setSessionPageLoading(false);
15337
+ stopSessionLoadProgress();
15160
15338
  dismissToast();
15161
15339
  }).catch((err) => {
15162
15340
  if (sessionPageRequestIdRef.current !== requestId) return;
15163
15341
  setAllLogs([]);
15164
15342
  setLogPage(null);
15165
15343
  setSessionPageLoading(false);
15344
+ stopSessionLoadProgress();
15166
15345
  showErrorToast(err instanceof Error ? err.message : "Failed to load session logs");
15167
15346
  });
15168
15347
  },
15169
- [dismissToast, initialSessionId, showErrorToast]
15348
+ [
15349
+ dismissToast,
15350
+ initialSessionId,
15351
+ showErrorToast,
15352
+ startSessionLoadProgress,
15353
+ stopSessionLoadProgress
15354
+ ]
15170
15355
  );
15171
15356
  const reloadSessionLogs = reactExports.useCallback(
15172
15357
  (sessionId) => {
15173
15358
  const requestId = sessionPageRequestIdRef.current + 1;
15174
15359
  sessionPageRequestIdRef.current = requestId;
15175
15360
  setSessionPageLoading(true);
15361
+ startSessionLoadProgress("Reloading full session", requestId);
15176
15362
  dismissToast();
15177
15363
  void (async () => {
15178
15364
  const collected = [];
@@ -15182,6 +15368,7 @@ function ProxyViewerContainer({
15182
15368
  SESSION_RELOAD_PAGE_LIMIT
15183
15369
  );
15184
15370
  collected.push(...page.logs);
15371
+ updateSessionLoadProgress("Reloading full session", requestId, collected.length, 1);
15185
15372
  let loadedPages = 1;
15186
15373
  while (page.hasNewer && page.newestLogId !== null && loadedPages < MAX_SESSION_RELOAD_PAGES) {
15187
15374
  page = await fetchSessionLogsPage(
@@ -15191,6 +15378,12 @@ function ProxyViewerContainer({
15191
15378
  );
15192
15379
  collected.push(...page.logs);
15193
15380
  loadedPages += 1;
15381
+ updateSessionLoadProgress(
15382
+ "Reloading full session",
15383
+ requestId,
15384
+ collected.length,
15385
+ loadedPages
15386
+ );
15194
15387
  }
15195
15388
  if (sessionPageRequestIdRef.current !== requestId) return;
15196
15389
  setAllLogs((prev) => {
@@ -15200,6 +15393,7 @@ function ProxyViewerContainer({
15200
15393
  });
15201
15394
  setKnownSessions((prev) => mergeSessionIds(prev, [sessionId]));
15202
15395
  setSessionPageLoading(false);
15396
+ stopSessionLoadProgress();
15203
15397
  if (page.hasNewer) {
15204
15398
  showToast({
15205
15399
  message: `Loaded ${String(collected.length)} logs for this session. More history is available.`,
@@ -15211,10 +15405,18 @@ function ProxyViewerContainer({
15211
15405
  })().catch((err) => {
15212
15406
  if (sessionPageRequestIdRef.current !== requestId) return;
15213
15407
  setSessionPageLoading(false);
15408
+ stopSessionLoadProgress();
15214
15409
  showErrorToast(err instanceof Error ? err.message : "Failed to reload session logs");
15215
15410
  });
15216
15411
  },
15217
- [dismissToast, showErrorToast, showToast]
15412
+ [
15413
+ dismissToast,
15414
+ showErrorToast,
15415
+ showToast,
15416
+ startSessionLoadProgress,
15417
+ stopSessionLoadProgress,
15418
+ updateSessionLoadProgress
15419
+ ]
15218
15420
  );
15219
15421
  reactExports.useEffect(() => {
15220
15422
  if (initialSessionId === void 0) {
@@ -15239,6 +15441,11 @@ function ProxyViewerContainer({
15239
15441
  reactExports.useEffect(() => {
15240
15442
  refreshSessions();
15241
15443
  }, [refreshSessions]);
15444
+ reactExports.useEffect(() => {
15445
+ return () => {
15446
+ stopSessionLoadProgress();
15447
+ };
15448
+ }, [stopSessionLoadProgress]);
15242
15449
  reactExports.useEffect(() => {
15243
15450
  if (initialSessionId === void 0) return;
15244
15451
  loadSessionPage({ kind: "newest" });
@@ -15316,6 +15523,8 @@ function ProxyViewerContainer({
15316
15523
  }, [logs.length]);
15317
15524
  const handleClearAll = reactExports.useCallback(() => {
15318
15525
  const clearedSessions = extractSessions(allLogs);
15526
+ stopSessionLoadProgress();
15527
+ setSessionPageLoading(false);
15319
15528
  logIndexRef.current.clear();
15320
15529
  setAllLogs([]);
15321
15530
  setLogPage(null);
@@ -15324,7 +15533,7 @@ function ProxyViewerContainer({
15324
15533
  message: "Cleared the current view. Stored logs are still reloadable.",
15325
15534
  tone: "success"
15326
15535
  });
15327
- }, [allLogs, showToast]);
15536
+ }, [allLogs, showToast, stopSessionLoadProgress]);
15328
15537
  const handleClearGroup = reactExports.useCallback(
15329
15538
  (ids) => {
15330
15539
  if (ids.length === 0) return;
@@ -15340,6 +15549,43 @@ function ProxyViewerContainer({
15340
15549
  },
15341
15550
  [showToast]
15342
15551
  );
15552
+ const handleDeleteCurrentView = reactExports.useCallback(
15553
+ async (ids) => {
15554
+ if (ids.length === 0) return;
15555
+ const persistedIds = ids.filter((id) => Number.isInteger(id) && id >= 0);
15556
+ if (persistedIds.length === 0) {
15557
+ showToast({
15558
+ message: "No persisted log records were found for this view.",
15559
+ tone: "error"
15560
+ });
15561
+ return;
15562
+ }
15563
+ const idSet = new Set(persistedIds);
15564
+ const removed = allLogs.filter((log) => idSet.has(log.id));
15565
+ const result = await fetchJson("/api/logs", DeleteLogsResponseSchema, {
15566
+ method: "DELETE",
15567
+ headers: { "content-type": "application/json" },
15568
+ body: JSON.stringify({ ids: persistedIds })
15569
+ });
15570
+ setAllLogs((prev) => {
15571
+ const remaining = prev.filter((log) => !idSet.has(log.id));
15572
+ logIndexRef.current = buildLogIndex(remaining);
15573
+ return remaining;
15574
+ });
15575
+ setLogPage(
15576
+ (prev) => prev === null ? null : {
15577
+ ...prev,
15578
+ logs: prev.logs.filter((log) => !idSet.has(log.id))
15579
+ }
15580
+ );
15581
+ setKnownSessions((prev) => mergeSessionIds(prev, extractSessions(removed)));
15582
+ showToast({
15583
+ message: `Deleted ${result.cleared.toString()} stored log${result.cleared === 1 ? "" : "s"} from the current view.`,
15584
+ tone: "success"
15585
+ });
15586
+ },
15587
+ [allLogs, showToast]
15588
+ );
15343
15589
  const handleReloadSession = reactExports.useCallback(() => {
15344
15590
  if (initialSessionId !== void 0) {
15345
15591
  loadSessionPage({ kind: "newest" });
@@ -15400,6 +15646,7 @@ function ProxyViewerContainer({
15400
15646
  if (initialSessionId === void 0) return void 0;
15401
15647
  return {
15402
15648
  isLoading: sessionPageLoading,
15649
+ loadProgress: sessionLoadProgress,
15403
15650
  total: logPage?.total ?? null,
15404
15651
  pageSize: logPage?.limit ?? SESSION_PAGE_LIMIT,
15405
15652
  hasOlder: logPage?.hasOlder ?? false,
@@ -15418,6 +15665,7 @@ function ProxyViewerContainer({
15418
15665
  loadOlderPage,
15419
15666
  loadOldestPage,
15420
15667
  logPage,
15668
+ sessionLoadProgress,
15421
15669
  sessionPageLoading
15422
15670
  ]);
15423
15671
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
@@ -15434,12 +15682,14 @@ function ProxyViewerContainer({
15434
15682
  onSessionChange: setSelectedSession,
15435
15683
  onModelChange: setSelectedModel,
15436
15684
  onClearAll: handleClearAll,
15685
+ onDeleteCurrentView: handleDeleteCurrentView,
15437
15686
  onReloadSession: initialSessionId !== void 0 || selectedSession !== "__all__" ? handleReloadSession : void 0,
15438
15687
  onClearGroup: handleClearGroup,
15439
15688
  onNotify: showToast,
15440
15689
  onImportLogs: initialSessionId === void 0 ? handleImportLogs : void 0,
15441
15690
  isLoading: initialSessionId === void 0 ? !streamInitialized || sessionPageLoading : sessionPageLoading,
15442
15691
  pagination,
15692
+ sessionLoadProgress,
15443
15693
  sessionMemberships,
15444
15694
  viewMode,
15445
15695
  captureMode,