@tonyclaw/agent-inspector 3.0.2 → 3.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/{CompareDrawer-Dqpwaku6.js → CompareDrawer-Bs2kzUSp.js} +1 -1
  3. package/.output/public/assets/ProxyViewerContainer-BUnlrfiS.js +106 -0
  4. package/.output/public/assets/{ReplayDialog-eaMk-WFG.js → ReplayDialog-B6xy7pl5.js} +1 -1
  5. package/.output/public/assets/{RequestAnatomy-DCnoqam_.js → RequestAnatomy-BSvSmpCO.js} +1 -1
  6. package/.output/public/assets/{ResponseView-Q7HW0fAd.js → ResponseView-BFnUva7Z.js} +2 -2
  7. package/.output/public/assets/{StreamingChunkSequence-K7qKD9VX.js → StreamingChunkSequence-u7ZaJOqn.js} +1 -1
  8. package/.output/public/assets/{_sessionId-CHwYmqKk.js → _sessionId-CH4nsMOA.js} +1 -1
  9. package/.output/public/assets/{index-EI9mxK7O.js → index-B5HS6AxR.js} +1 -1
  10. package/.output/public/assets/index-BqVL284D.js +1 -0
  11. package/.output/public/assets/index-DJW6qbnH.css +1 -0
  12. package/.output/public/assets/{json-viewer-Dbu2fh6-.js → json-viewer-5Tj5vkqe.js} +1 -1
  13. package/.output/public/assets/{main-CLNurSfs.js → main-ChxZWG8K.js} +2 -2
  14. package/.output/server/{_sessionId-1KajCUiB.mjs → _sessionId-B3r-VBdM.mjs} +2 -2
  15. package/.output/server/_ssr/{CompareDrawer-iM778CsC.mjs → CompareDrawer-DAYrKHKe.mjs} +2 -2
  16. package/.output/server/_ssr/{ProxyViewerContainer-DzVBZMbn.mjs → ProxyViewerContainer-CYmNmQK9.mjs} +357 -214
  17. package/.output/server/_ssr/{ReplayDialog-BxPm6uxq.mjs → ReplayDialog-CdKvdXxk.mjs} +3 -3
  18. package/.output/server/_ssr/{RequestAnatomy-D5aE8Qas.mjs → RequestAnatomy-BtmTUq7O.mjs} +2 -2
  19. package/.output/server/_ssr/{ResponseView-D0mzqj7J.mjs → ResponseView-DuD_z5hd.mjs} +2 -2
  20. package/.output/server/_ssr/{StreamingChunkSequence-BbeKs1PZ.mjs → StreamingChunkSequence-DpIV2wt_.mjs} +2 -2
  21. package/.output/server/_ssr/{index-BIrW_uL8.mjs → index-B4_8vH8k.mjs} +2 -2
  22. package/.output/server/_ssr/index.mjs +2 -2
  23. package/.output/server/_ssr/{json-viewer-DVAdcOds.mjs → json-viewer-gcNJEB7y.mjs} +2 -2
  24. package/.output/server/_ssr/{router-DtMA9SLr.mjs → router-CYjIsElo.mjs} +4 -4
  25. package/.output/server/{_tanstack-start-manifest_v-Rq5BNh_J.mjs → _tanstack-start-manifest_v-BRdOxY6q.mjs} +1 -1
  26. package/.output/server/index.mjs +72 -72
  27. package/package.json +1 -1
  28. package/src/assets/IDE/claudecode-color.svg +1 -0
  29. package/src/assets/IDE/codex-color.svg +1 -0
  30. package/src/assets/IDE/opencode.svg +1 -0
  31. package/src/assets/IDE/xiaomimimo.svg +1 -0
  32. package/src/assets/logos/opencode.svg +4 -4
  33. package/src/components/ProxyViewer.tsx +92 -25
  34. package/src/components/ProxyViewerContainer.tsx +154 -55
  35. package/src/components/clients/ClientLogo.tsx +14 -52
  36. package/src/components/providers/ProviderCard.tsx +83 -36
  37. package/src/components/proxy-viewer/ConversationGroup.tsx +1 -1
  38. package/src/components/proxy-viewer/ConversationHeader.tsx +4 -5
  39. package/src/components/proxy-viewer/LogEntryHeader.tsx +1 -7
  40. package/.output/public/assets/ProxyViewerContainer-tu_yG20v.js +0 -106
  41. package/.output/public/assets/index-CZnCJkDN.js +0 -1
  42. package/.output/public/assets/index-Tq5s9NV0.css +0 -1
@@ -1,5 +1,5 @@
1
1
  import { r as reactExports, j as jsxRuntimeExports, a as React } from "../_libs/react.mjs";
2
- import { I as InspectorGroupsListResponseSchema, 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, 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, l as AlertSummarySchema, m as AlertListResponseSchema, G as GroupEvidenceReadResponseSchema, u as maskApiKey, v as PATH_V1_MESSAGES, w as PATH_V1_CHAT_COMPLETIONS, x as PATH_V1_RESPONSES, r as providerHasContextMetadata, t as findProviderModelMetadata, 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, y as previewUpstreamUrl, K as KnowledgeCandidateSchema, J as isPlainRecord, k as stripClaudeCodeBillingHeader, L as LogBodyChunkSchema } from "./router-DtMA9SLr.mjs";
2
+ import { I as InspectorGroupsListResponseSchema, 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, 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, l as AlertSummarySchema, m as AlertListResponseSchema, G as GroupEvidenceReadResponseSchema, u as maskApiKey, v as PATH_V1_MESSAGES, w as PATH_V1_CHAT_COMPLETIONS, x as PATH_V1_RESPONSES, r as providerHasContextMetadata, t as findProviderModelMetadata, 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, y as previewUpstreamUrl, K as KnowledgeCandidateSchema, J as isPlainRecord, k as stripClaudeCodeBillingHeader, L as LogBodyChunkSchema } from "./router-CYjIsElo.mjs";
3
3
  import { u as useSWR, a as useSWRConfig } from "../_libs/swr.mjs";
4
4
  import { J as JSZip } from "../_libs/jszip.mjs";
5
5
  import { c as clsx } from "../_libs/clsx.mjs";
@@ -9,7 +9,7 @@ import { c as cva } from "../_libs/class-variance-authority.mjs";
9
9
  import { u as useWindowVirtualizer, a as useVirtualizer } from "../_libs/tanstack__react-virtual.mjs";
10
10
  import { d as diffJson, a as diffLines } from "../_libs/diff.mjs";
11
11
  import { R as Root2, T as Trigger, I as Icon, V as Value, P as Portal, C as Content2, a as Viewport, b as Item, c as ItemIndicator, d as ItemText, S as ScrollUpButton, e as ScrollDownButton } from "../_libs/radix-ui__react-select.mjs";
12
- import { T as TriangleAlert, C as CircleCheck, X, I as Info, a as ChevronDown, b as Check, S as Search, U as Upload, D as Download, F as FileBraces, c as Trash2, 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, R as RefreshCw, n as Layers, o as Settings, M as Monitor, p as Scan, q as CircleAlert, r as Terminal, s as ArrowUpRight, t as ArrowDownRight, u as Cpu, v as FolderOpen, B as Bell, w as Clock3, x as ShieldAlert, E as EyeOff, y as Eye, z as ExternalLink, H as RotateCw, J as Clock, K as Pencil, N as MessageSquare, Z as Zap, W as Wrench, O as Brain, Q as Minus, V as CircleCheckBig, Y as CircleQuestionMark, _ as Server, $ as Lock, a0 as Wifi, a1 as WifiOff, a2 as CircleX, a3 as ShieldCheck, a4 as Save, a5 as FileSearch, a6 as CloudUpload, a7 as OctagonAlert, a8 as Radio, a9 as Globe, aa as FileTerminal, ab as ChevronsUp, ac as ChevronsDown, ad as FileDiff, ae as History, af as RotateCcw, ag as GitCompareArrows, ah as ArrowUp, ai as ArrowDown, aj as Ellipsis, ak as CodeXml, al as Blocks, am as MousePointerClick, an as FileText, ao as Rows3, ap as Columns2 } from "../_libs/lucide-react.mjs";
12
+ import { T as TriangleAlert, C as CircleCheck, X, I as Info, a as ChevronDown, b as Check, 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 Settings, M as Monitor, p as Scan, q as CircleAlert, r as Terminal, s as ArrowUpRight, t as ArrowDownRight, u as Cpu, v as FolderOpen, B as Bell, w as Clock3, x as ShieldAlert, E as EyeOff, y as Eye, z as ExternalLink, H as RotateCw, J as Clock, K as Pencil, N as MessageSquare, Z as Zap, W as Wrench, O as Brain, Q as Minus, V as CircleCheckBig, Y as CircleQuestionMark, _ as Server, $ as Lock, a0 as Wifi, a1 as WifiOff, a2 as CircleX, a3 as ShieldCheck, a4 as Save, a5 as FileSearch, a6 as CloudUpload, a7 as OctagonAlert, a8 as Radio, a9 as Globe, aa as FileTerminal, ab as ChevronsUp, ac as ChevronsDown, ad as FileDiff, ae as History, af as RotateCcw, ag as GitCompareArrows, ah as ArrowUp, ai as ArrowDown, aj as Ellipsis, ak as CodeXml, al as Blocks, am as MousePointerClick, an as FileText, ao as Rows3, ap as Columns2 } from "../_libs/lucide-react.mjs";
13
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";
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";
@@ -843,6 +843,10 @@ function ConfirmDialog({
843
843
  ] })
844
844
  ] }) });
845
845
  }
846
+ const ClaudeCodeLogoSvg = "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%3eClaude%20Code%3c/title%3e%3cpath%20clip-rule='evenodd'%20d='M20.998%2010.949H24v3.102h-3v3.028h-1.487V20H18v-2.921h-1.487V20H15v-2.921H9V20H7.488v-2.921H6V20H4.487v-2.921H3V14.05H0V10.95h3V5h17.998v5.949zM6%2010.949h1.488V8.102H6v2.847zm10.51%200H18V8.102h-1.49v2.847z'%20fill='%23D97757'%20fill-rule='evenodd'%3e%3c/path%3e%3c/svg%3e";
847
+ 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";
848
+ const OpenCodeLogoSvg = "data:image/svg+xml,%3csvg%20fill='currentColor'%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";
849
+ const MiMoCodeLogoSvg = "data:image/svg+xml,%3csvg%20fill='currentColor'%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%3eXiaomiMiMo%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";
846
850
  const CLIENT_LABELS = {
847
851
  codex: "Codex",
848
852
  opencode: "OpenCode",
@@ -883,68 +887,30 @@ function clientAppLabel(client) {
883
887
  return null;
884
888
  }
885
889
  }
886
- function CodexMark() {
887
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", className: "size-full", "aria-hidden": "true", children: [
888
- /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "12", cy: "12", r: "8", fill: "none", stroke: "currentColor", strokeWidth: "2.2" }),
889
- /* @__PURE__ */ jsxRuntimeExports.jsx(
890
- "path",
891
- {
892
- d: "M14.8 8.6a4.8 4.8 0 1 0 0 6.8",
893
- fill: "none",
894
- stroke: "currentColor",
895
- strokeLinecap: "round",
896
- strokeWidth: "2.2"
897
- }
898
- )
899
- ] });
900
- }
901
- function OpenCodeMark() {
902
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", className: "size-full", "aria-hidden": "true", children: [
903
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M7 4h10v16H7z", fill: "none", stroke: "currentColor", strokeWidth: "2.2" }),
904
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M10 8h4M10 12h4M10 16h2", stroke: "currentColor", strokeLinecap: "round" })
905
- ] });
906
- }
907
- function MiMoCodeMark() {
908
- return /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { viewBox: "0 0 24 24", className: "size-full", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
909
- "path",
910
- {
911
- d: "M5 18V6h3.2l3.8 6.1L15.8 6H19v12h-3V11.3l-3.1 5h-1.8L8 11.3V18z",
912
- fill: "currentColor"
913
- }
914
- ) });
915
- }
916
- function ClaudeCodeMark() {
917
- return /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { viewBox: "0 0 24 24", className: "size-full", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
918
- "path",
919
- {
920
- fill: "currentColor",
921
- fillRule: "evenodd",
922
- clipRule: "evenodd",
923
- d: "M21 10.95h3v3.1h-3v3.03h-1.49V20H18v-2.92h-1.49V20H15v-2.92H9V20H7.49v-2.92H6V20H4.49v-2.92H3v-3.03H0v-3.1h3V5h18v5.95zM6 10.95h1.49V8.1H6v2.85zm10.51 0H18V8.1h-1.49v2.85z"
924
- }
925
- ) });
926
- }
890
+ const CLIENT_LOGOS = {
891
+ codex: CodexLogoSvg,
892
+ opencode: OpenCodeLogoSvg,
893
+ "mimo-code": MiMoCodeLogoSvg,
894
+ "claude-code": ClaudeCodeLogoSvg
895
+ };
927
896
  function ClientLogo({
928
897
  client,
929
898
  className
930
899
  }) {
900
+ if (client === "unknown") return null;
931
901
  const label = clientAppLabel(client);
932
902
  if (label === null) return null;
933
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(
903
+ const logoSrc = CLIENT_LOGOS[client];
904
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
934
905
  "span",
935
906
  {
936
907
  className: cn(
937
- "border border-border bg-muted/40 inline-flex size-6 shrink-0 items-center justify-center rounded-md p-1 text-cyan-100",
908
+ "border border-border bg-muted/40 inline-flex size-6 shrink-0 items-center justify-center rounded-md p-0.5",
938
909
  className
939
910
  ),
940
911
  "aria-label": label,
941
912
  title: label,
942
- children: [
943
- client === "codex" && /* @__PURE__ */ jsxRuntimeExports.jsx(CodexMark, {}),
944
- client === "opencode" && /* @__PURE__ */ jsxRuntimeExports.jsx(OpenCodeMark, {}),
945
- client === "mimo-code" && /* @__PURE__ */ jsxRuntimeExports.jsx(MiMoCodeMark, {}),
946
- client === "claude-code" && /* @__PURE__ */ jsxRuntimeExports.jsx(ClaudeCodeMark, {})
947
- ]
913
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: logoSrc, alt: "", className: "size-full object-contain", "aria-hidden": "true" })
948
914
  }
949
915
  );
950
916
  }
@@ -1684,7 +1650,7 @@ function ConversationHeader({
1684
1650
  type: "button",
1685
1651
  onClick: handleClearClick,
1686
1652
  "aria-label": `Clear group (${totalCalls} request${totalCalls !== 1 ? "s" : ""})`,
1687
- title: "Clear this group",
1653
+ title: "Clear this group from the current view",
1688
1654
  className: HEADER_ACTION_BUTTON_CLASS$1,
1689
1655
  children: /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" })
1690
1656
  }
@@ -1711,8 +1677,8 @@ function ConversationHeader({
1711
1677
  {
1712
1678
  open: confirmOpen,
1713
1679
  onOpenChange: setConfirmOpen,
1714
- title: "Clear this group?",
1715
- description: `This will remove ${totalCalls} request${totalCalls !== 1 ? "s" : ""} from this conversation. This action cannot be undone.`,
1680
+ title: "Clear this group from the current view?",
1681
+ description: `This will hide ${totalCalls} request${totalCalls !== 1 ? "s" : ""} from the current view. Stored logs remain reloadable.`,
1716
1682
  confirmLabel: "Clear",
1717
1683
  variant: "destructive",
1718
1684
  onConfirm: () => {
@@ -2336,27 +2302,27 @@ function useCopyFeedback(text) {
2336
2302
  return { copied, copy };
2337
2303
  }
2338
2304
  const LazyCompareDrawer = reactExports.lazy(
2339
- () => import("./CompareDrawer-iM778CsC.mjs").then((m) => ({ default: m.CompareDrawer }))
2305
+ () => import("./CompareDrawer-DAYrKHKe.mjs").then((m) => ({ default: m.CompareDrawer }))
2340
2306
  );
2341
2307
  const LazyReplayDialog = reactExports.lazy(
2342
- () => import("./ReplayDialog-BxPm6uxq.mjs").then((m) => ({ default: m.ReplayDialog }))
2308
+ () => import("./ReplayDialog-CdKvdXxk.mjs").then((m) => ({ default: m.ReplayDialog }))
2343
2309
  );
2344
2310
  const LazyRequestAnatomy = reactExports.lazy(
2345
- () => import("./RequestAnatomy-D5aE8Qas.mjs").then((m) => ({ default: m.RequestAnatomy }))
2311
+ () => import("./RequestAnatomy-BtmTUq7O.mjs").then((m) => ({ default: m.RequestAnatomy }))
2346
2312
  );
2347
2313
  const LazyResponseView = reactExports.lazy(
2348
- () => import("./ResponseView-D0mzqj7J.mjs").then((m) => ({ default: m.ResponseView }))
2314
+ () => import("./ResponseView-DuD_z5hd.mjs").then((m) => ({ default: m.ResponseView }))
2349
2315
  );
2350
2316
  const LazyStreamingChunkSequence = reactExports.lazy(
2351
- () => import("./StreamingChunkSequence-BbeKs1PZ.mjs").then((m) => ({
2317
+ () => import("./StreamingChunkSequence-DpIV2wt_.mjs").then((m) => ({
2352
2318
  default: m.StreamingChunkSequence
2353
2319
  }))
2354
2320
  );
2355
2321
  const LazyJsonViewer = reactExports.lazy(
2356
- () => import("./json-viewer-DVAdcOds.mjs").then((m) => ({ default: m.JsonViewer }))
2322
+ () => import("./json-viewer-gcNJEB7y.mjs").then((m) => ({ default: m.JsonViewer }))
2357
2323
  );
2358
2324
  const LazyJsonViewerFromString = reactExports.lazy(
2359
- () => import("./json-viewer-DVAdcOds.mjs").then((m) => ({ default: m.JsonViewerFromString }))
2325
+ () => import("./json-viewer-gcNJEB7y.mjs").then((m) => ({ default: m.JsonViewerFromString }))
2360
2326
  );
2361
2327
  const HIGHLIGHT_DURATION_MS = 1200;
2362
2328
  const MAX_HIGHLIGHT_ATTEMPTS = 12;
@@ -2823,20 +2789,16 @@ const STATUS_BADGE_CLASSES = {
2823
2789
  };
2824
2790
  const STATUS_CUE_CLASSES = {
2825
2791
  success: {
2826
- frame: "border-cyan-200/15 bg-white/[0.04] text-slate-100",
2827
- dot: "bg-cyan-200/80 shadow-[0_0_14px_rgba(125,211,252,0.65)]"
2792
+ frame: "border-cyan-200/15 bg-white/[0.04] text-slate-100"
2828
2793
  },
2829
2794
  client_error: {
2830
- frame: "border-amber-300/25 bg-amber-300/[0.08] text-amber-100",
2831
- dot: "bg-amber-200 shadow-[0_0_14px_rgba(252,211,77,0.8)]"
2795
+ frame: "border-amber-300/25 bg-amber-300/[0.08] text-amber-100"
2832
2796
  },
2833
2797
  server_error: {
2834
- frame: "border-rose-300/25 bg-rose-300/[0.08] text-rose-100",
2835
- dot: "bg-rose-300 shadow-[0_0_14px_rgba(253,164,175,0.8)]"
2798
+ frame: "border-rose-300/25 bg-rose-300/[0.08] text-rose-100"
2836
2799
  },
2837
2800
  pending: {
2838
- frame: "border-cyan-300/25 bg-cyan-300/[0.08] text-cyan-100",
2839
- dot: "bg-cyan-200 shadow-[0_0_14px_rgba(103,232,249,0.8)]"
2801
+ frame: "border-cyan-300/25 bg-cyan-300/[0.08] text-cyan-100"
2840
2802
  }
2841
2803
  };
2842
2804
  const HEADER_ACTION_BUTTON_CLASS = "border border-transparent bg-white/[0.045] hover:bg-white/[0.075] size-8 text-muted-foreground shadow-none hover:text-cyan-100";
@@ -2927,20 +2889,17 @@ const LogEntryHeader = reactExports.memo(function({
2927
2889
  },
2928
2890
  children: [
2929
2891
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 flex-1 flex-wrap items-center gap-x-2 gap-y-1", children: [
2930
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
2892
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
2931
2893
  "span",
2932
2894
  {
2933
2895
  className: cn(
2934
- "inline-flex h-8 shrink-0 items-center gap-2 rounded-md px-2 font-mono",
2896
+ "inline-flex h-8 shrink-0 items-center rounded-md px-2 font-mono",
2935
2897
  statusCue.frame
2936
2898
  ),
2937
- children: [
2938
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn("size-1.5 rounded-full", statusCue.dot), "aria-hidden": "true" }),
2939
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xs font-semibold tabular-nums", title: `Log ID ${String(log.id)}`, children: [
2940
- "#",
2941
- displayNumber
2942
- ] })
2943
- ]
2899
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xs font-semibold tabular-nums", title: `Log ID ${String(log.id)}`, children: [
2900
+ "#",
2901
+ displayNumber
2902
+ ] })
2944
2903
  }
2945
2904
  ),
2946
2905
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "bg-white/[0.045] flex h-7 shrink-0 items-center gap-1 rounded-md px-2 text-xs text-muted-foreground", children: [
@@ -8368,6 +8327,40 @@ function ProviderEndpointSummary({
8368
8327
  children
8369
8328
  ] });
8370
8329
  }
8330
+ function providerHasEndpoint(value) {
8331
+ return value !== void 0 && value !== "";
8332
+ }
8333
+ function providerTestTargets(provider) {
8334
+ const targets = [];
8335
+ if (providerHasEndpoint(provider.anthropicBaseUrl)) {
8336
+ targets.push("Anthropic");
8337
+ }
8338
+ if (providerHasEndpoint(provider.openaiBaseUrl)) {
8339
+ targets.push("Chat");
8340
+ }
8341
+ if (providerHasEndpoint(provider.openaiResponsesBaseUrl)) {
8342
+ targets.push("Responses");
8343
+ }
8344
+ return targets;
8345
+ }
8346
+ function ProviderTestCoverage({ provider }) {
8347
+ const targets = providerTestTargets(provider);
8348
+ if (targets.length === 0) {
8349
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-muted-foreground", children: "Test requires at least one configured endpoint." });
8350
+ }
8351
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-1.5 text-xs text-muted-foreground", children: [
8352
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Test covers" }),
8353
+ targets.map((target) => /* @__PURE__ */ jsxRuntimeExports.jsx(
8354
+ "span",
8355
+ {
8356
+ className: "rounded border border-border/70 bg-muted/25 px-1.5 py-0.5 text-foreground/80",
8357
+ children: target
8358
+ },
8359
+ target
8360
+ )),
8361
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "non-stream + stream" })
8362
+ ] });
8363
+ }
8371
8364
  function getErrorIcon(type) {
8372
8365
  const iconProps = { className: "size-3", strokeWidth: 2 };
8373
8366
  switch (type) {
@@ -8691,30 +8684,30 @@ function ProviderCard({
8691
8684
  }
8692
8685
  )
8693
8686
  ] }),
8694
- provider.anthropicBaseUrl !== void 0 && provider.anthropicBaseUrl !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx(
8687
+ providerHasEndpoint(provider.anthropicBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsx(
8695
8688
  ProviderEndpointSummary,
8696
8689
  {
8697
- label: "Anthropic",
8690
+ label: "Test: Anthropic",
8698
8691
  baseUrl: provider.anthropicBaseUrl,
8699
8692
  endpoint: PATH_V1_MESSAGES,
8700
8693
  providerName: provider.name,
8701
8694
  children: testResults !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: testResults.anthropic })
8702
8695
  }
8703
8696
  ),
8704
- provider.openaiBaseUrl !== void 0 && provider.openaiBaseUrl !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx(
8697
+ providerHasEndpoint(provider.openaiBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsx(
8705
8698
  ProviderEndpointSummary,
8706
8699
  {
8707
- label: "OpenAI Chat",
8700
+ label: "Test: Chat",
8708
8701
  baseUrl: provider.openaiBaseUrl,
8709
8702
  endpoint: PATH_V1_CHAT_COMPLETIONS,
8710
8703
  providerName: provider.name,
8711
8704
  children: testResults !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: testResults.openaiChat })
8712
8705
  }
8713
8706
  ),
8714
- provider.openaiResponsesBaseUrl !== void 0 && provider.openaiResponsesBaseUrl !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx(
8707
+ providerHasEndpoint(provider.openaiResponsesBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsx(
8715
8708
  ProviderEndpointSummary,
8716
8709
  {
8717
- label: "OpenAI Responses",
8710
+ label: "Test: Responses",
8718
8711
  baseUrl: provider.openaiResponsesBaseUrl,
8719
8712
  endpoint: PATH_V1_RESPONSES,
8720
8713
  providerName: provider.name,
@@ -8758,49 +8751,52 @@ function ProviderCard({
8758
8751
  ] }, modelName)) })
8759
8752
  ] }) })
8760
8753
  ] }),
8761
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2 pt-1 border-t", children: [
8762
- onTest !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
8763
- Button,
8764
- {
8765
- variant: "outline",
8766
- size: "sm",
8767
- onClick: () => onTest(provider.id),
8768
- className: "text-xs h-7 gap-1",
8769
- disabled: isTesting ?? false,
8770
- children: [
8771
- /* @__PURE__ */ jsxRuntimeExports.jsx(RotateCw, { className: `size-3 ${isTesting ?? false ? "animate-spin" : ""}` }),
8772
- isTesting ?? false ? testingTimeLeft !== void 0 ? `Testing (${testingTimeLeft}s)` : "Testing..." : "Test"
8773
- ]
8774
- }
8775
- ),
8776
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
8777
- Button,
8778
- {
8779
- variant: "outline",
8780
- size: "sm",
8781
- onClick: () => onEdit(provider),
8782
- className: "text-xs h-7 gap-1",
8783
- disabled: isTesting ?? false,
8784
- children: [
8785
- /* @__PURE__ */ jsxRuntimeExports.jsx(Pencil, { className: "size-3" }),
8786
- "Edit"
8787
- ]
8788
- }
8789
- ),
8790
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
8791
- Button,
8792
- {
8793
- variant: "outline",
8794
- size: "sm",
8795
- onClick: () => onDelete(provider.id),
8796
- className: "text-xs h-7 gap-1 text-destructive hover:text-destructive",
8797
- disabled: isTesting ?? false,
8798
- children: [
8799
- /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3" }),
8800
- "Delete"
8801
- ]
8802
- }
8803
- )
8754
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-2 pt-1 border-t sm:flex-row sm:items-center sm:justify-between", children: [
8755
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderTestCoverage, { provider }),
8756
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
8757
+ onTest !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
8758
+ Button,
8759
+ {
8760
+ variant: "outline",
8761
+ size: "sm",
8762
+ onClick: () => onTest(provider.id),
8763
+ className: "text-xs h-7 gap-1",
8764
+ disabled: isTesting ?? false,
8765
+ children: [
8766
+ /* @__PURE__ */ jsxRuntimeExports.jsx(RotateCw, { className: `size-3 ${isTesting ?? false ? "animate-spin" : ""}` }),
8767
+ isTesting ?? false ? testingTimeLeft !== void 0 ? `Testing (${testingTimeLeft}s)` : "Testing..." : "Test"
8768
+ ]
8769
+ }
8770
+ ),
8771
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
8772
+ Button,
8773
+ {
8774
+ variant: "outline",
8775
+ size: "sm",
8776
+ onClick: () => onEdit(provider),
8777
+ className: "text-xs h-7 gap-1",
8778
+ disabled: isTesting ?? false,
8779
+ children: [
8780
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Pencil, { className: "size-3" }),
8781
+ "Edit"
8782
+ ]
8783
+ }
8784
+ ),
8785
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
8786
+ Button,
8787
+ {
8788
+ variant: "outline",
8789
+ size: "sm",
8790
+ onClick: () => onDelete(provider.id),
8791
+ className: "text-xs h-7 gap-1 text-destructive hover:text-destructive",
8792
+ disabled: isTesting ?? false,
8793
+ children: [
8794
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3" }),
8795
+ "Delete"
8796
+ ]
8797
+ }
8798
+ )
8799
+ ] })
8804
8800
  ] })
8805
8801
  ]
8806
8802
  }
@@ -13745,6 +13741,7 @@ function ProxyViewer({
13745
13741
  onSessionChange,
13746
13742
  onModelChange,
13747
13743
  onClearAll,
13744
+ onReloadSession,
13748
13745
  onClearGroup,
13749
13746
  onNotify,
13750
13747
  onImportLogs,
@@ -13870,6 +13867,8 @@ function ProxyViewer({
13870
13867
  const comparisonPredecessors = reactExports.useMemo(() => buildValidPredecessors(groups), [groups]);
13871
13868
  const exportActionVisibility = getExportActionVisibility(captureMode, logs.length);
13872
13869
  const isPinnedSessionPage = pinnedSessionId !== void 0;
13870
+ const canClearCurrentView = logs.length > 0;
13871
+ const reloadSessionLabel = logs.length === 0 ? "Load" : "Reload";
13873
13872
  const sessionInputValue = selectedSession === "__all__" ? "" : selectedSession;
13874
13873
  const sessionSelectValue = selectedSession === "__all__" || sessions.includes(selectedSession) ? selectedSession : "__typed__";
13875
13874
  const activeScopeLabel = hasSessionContext && sessionContextScope !== null ? truncateSessionId(sessionContextScope.label) : selectedSession === "__all__" ? "All sessions" : truncateSessionId(selectedSession);
@@ -13905,26 +13904,62 @@ function ProxyViewer({
13905
13904
  [onSessionChange]
13906
13905
  );
13907
13906
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-background min-h-screen w-full text-foreground", children: [
13908
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid min-h-screen w-full grid-cols-1 lg:grid-cols-[340px_minmax(0,1fr)] xl:grid-cols-[360px_minmax(0,1fr)]", children: [
13909
- /* @__PURE__ */ jsxRuntimeExports.jsx("aside", { className: "bg-background/95 border-b border-white/[0.045] lg:sticky lg:top-0 lg:h-screen lg:overflow-y-auto lg:border-b-0 lg:border-r lg:border-white/[0.055]", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4 p-4", children: [
13907
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid min-h-screen w-full grid-cols-1 lg:grid-cols-[minmax(0,1fr)_340px] xl:grid-cols-[minmax(0,1fr)_360px]", children: [
13908
+ /* @__PURE__ */ jsxRuntimeExports.jsx("aside", { className: "bg-background/95 order-1 border-b border-white/[0.045] lg:sticky lg:top-0 lg:order-2 lg:h-screen lg:overflow-y-auto lg:border-b-0 lg:border-l lg:border-white/[0.055]", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4 p-4", children: [
13910
13909
  /* @__PURE__ */ jsxRuntimeExports.jsx(BrandHeader, { compact: true, crabEntrancePhase }),
13911
- /* @__PURE__ */ jsxRuntimeExports.jsx(SidebarPanel, { label: "Session", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-3 gap-2", children: [
13912
- /* @__PURE__ */ jsxRuntimeExports.jsx(SidebarMetric, { label: "Requests", value: logs.length }),
13913
- /* @__PURE__ */ jsxRuntimeExports.jsx(
13914
- SidebarMetric,
13915
- {
13916
- label: "Input",
13917
- value: formatTokens(hasSessionContext ? sessionContextTotalIn : totalIn)
13918
- }
13919
- ),
13920
- /* @__PURE__ */ jsxRuntimeExports.jsx(
13921
- SidebarMetric,
13922
- {
13923
- label: "Output",
13924
- value: formatTokens(hasSessionContext ? sessionContextTotalOut : totalOut)
13925
- }
13926
- )
13927
- ] }) }),
13910
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(SidebarPanel, { label: "Session", children: [
13911
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
13912
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SidebarMetric, { label: "Requests", value: logs.length }),
13913
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SidebarMetric, { label: "Sessions", value: sessions.length }),
13914
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
13915
+ SidebarMetric,
13916
+ {
13917
+ label: "Input",
13918
+ value: formatTokens(hasSessionContext ? sessionContextTotalIn : totalIn)
13919
+ }
13920
+ ),
13921
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
13922
+ SidebarMetric,
13923
+ {
13924
+ label: "Output",
13925
+ value: formatTokens(hasSessionContext ? sessionContextTotalOut : totalOut)
13926
+ }
13927
+ )
13928
+ ] }),
13929
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-2 grid grid-cols-2 gap-2", children: [
13930
+ onReloadSession !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
13931
+ "button",
13932
+ {
13933
+ type: "button",
13934
+ onClick: onReloadSession,
13935
+ disabled: isLoading,
13936
+ className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 min-w-0 items-center justify-center gap-1.5 rounded-md px-2 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
13937
+ title: "Load stored logs for this session",
13938
+ children: [
13939
+ /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: cn("size-3.5", isLoading && "animate-spin") }),
13940
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: reloadSessionLabel })
13941
+ ]
13942
+ }
13943
+ ),
13944
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
13945
+ "button",
13946
+ {
13947
+ type: "button",
13948
+ onClick: onClearAll,
13949
+ disabled: !canClearCurrentView,
13950
+ className: cn(
13951
+ "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",
13952
+ onReloadSession === void 0 && "col-span-2"
13953
+ ),
13954
+ title: "Clear the current view. Stored logs remain reloadable.",
13955
+ children: [
13956
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" }),
13957
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Clear view" })
13958
+ ]
13959
+ }
13960
+ )
13961
+ ] })
13962
+ ] }),
13928
13963
  /* @__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: [
13929
13964
  /* @__PURE__ */ jsxRuntimeExports.jsx(
13930
13965
  "div",
@@ -13998,7 +14033,7 @@ function ProxyViewer({
13998
14033
  ] })
13999
14034
  ] }) })
14000
14035
  ] }) }),
14001
- /* @__PURE__ */ jsxRuntimeExports.jsxs("main", { className: "min-w-0", children: [
14036
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("main", { className: "order-2 min-w-0 lg:order-1", children: [
14002
14037
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-background/95 shadow-[0_12px_36px_rgba(0,0,0,0.18),inset_0_-1px_0_rgba(255,255,255,0.045)] sticky top-0 z-30 px-4 py-3 lg:px-5", children: [
14003
14038
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
14004
14039
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-[180px] flex-1", children: [
@@ -14063,16 +14098,31 @@ function ProxyViewer({
14063
14098
  ] })
14064
14099
  }
14065
14100
  ),
14101
+ onReloadSession !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
14102
+ "button",
14103
+ {
14104
+ type: "button",
14105
+ onClick: onReloadSession,
14106
+ disabled: isLoading,
14107
+ className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
14108
+ title: "Reload this session from stored logs",
14109
+ children: [
14110
+ /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: cn("size-3.5", isLoading && "animate-spin") }),
14111
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: reloadSessionLabel })
14112
+ ]
14113
+ }
14114
+ ),
14066
14115
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
14067
14116
  "button",
14068
14117
  {
14069
14118
  type: "button",
14070
14119
  onClick: onClearAll,
14071
- className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground",
14072
- title: "Clear all logs",
14120
+ disabled: !canClearCurrentView,
14121
+ className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
14122
+ title: "Clear the current view. Stored logs remain reloadable.",
14073
14123
  children: [
14074
14124
  /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" }),
14075
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Clear" })
14125
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Clear view" })
14076
14126
  ]
14077
14127
  }
14078
14128
  )
@@ -14085,24 +14135,45 @@ function ProxyViewer({
14085
14135
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-4 lg:px-5", children: [
14086
14136
  /* @__PURE__ */ jsxRuntimeExports.jsx(SessionOpeningSlate, { stats: slateStats }),
14087
14137
  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: [
14088
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-medium", children: isLoading ? "Loading session data..." : "Session not found" }),
14138
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-medium", children: isLoading ? "Loading session data..." : "No logs loaded for this session" }),
14089
14139
  /* @__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) }),
14090
14140
  sessionMemberships.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-left", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SessionMembershipPanel, { memberships: sessionMemberships }) }),
14091
- !isLoading && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-xs", children: [
14092
- "This session may have been cleared or never existed.",
14093
- " ",
14094
- hideSessionFilter ? /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "/", className: "underline transition-colors hover:text-foreground", children: "Back to all sessions" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
14095
- "button",
14096
- {
14097
- type: "button",
14098
- onClick: () => onSessionChange("__all__"),
14099
- className: "underline transition-colors hover:text-foreground",
14100
- children: "Show all sessions"
14101
- }
14102
- )
14141
+ !isLoading && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center gap-3 text-xs", children: [
14142
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Stored logs may still be available." }),
14143
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center justify-center gap-2", children: [
14144
+ onReloadSession !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
14145
+ "button",
14146
+ {
14147
+ type: "button",
14148
+ onClick: onReloadSession,
14149
+ className: "bg-white/[0.045] hover:bg-white/[0.075] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground",
14150
+ children: [
14151
+ /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: "size-3.5" }),
14152
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Load session" })
14153
+ ]
14154
+ }
14155
+ ),
14156
+ hideSessionFilter ? /* @__PURE__ */ jsxRuntimeExports.jsx(
14157
+ "a",
14158
+ {
14159
+ href: "/",
14160
+ className: "inline-flex h-8 items-center rounded-md px-3 text-xs text-muted-foreground underline transition-colors hover:text-foreground",
14161
+ children: "Back to all sessions"
14162
+ }
14163
+ ) : /* @__PURE__ */ jsxRuntimeExports.jsx(
14164
+ "button",
14165
+ {
14166
+ type: "button",
14167
+ onClick: () => onSessionChange("__all__"),
14168
+ className: "inline-flex h-8 items-center rounded-md px-3 text-xs text-muted-foreground underline transition-colors hover:text-foreground",
14169
+ children: "Show all sessions"
14170
+ }
14171
+ )
14172
+ ] })
14103
14173
  ] })
14104
14174
  ] }) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "py-16 text-center text-muted-foreground", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-white/[0.035] shadow-[inset_0_1px_0_rgba(255,255,255,0.045),0_18px_52px_rgba(0,0,0,0.18)] mx-auto max-w-2xl space-y-4 rounded-[8px] px-4 py-8", children: [
14105
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm", children: "No requests captured yet." }),
14175
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm", children: "No logs loaded in the current view." }),
14176
+ sessions.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mx-auto max-w-xl text-xs leading-relaxed text-muted-foreground", children: "Pick a session from the filter panel to load stored logs on demand." }),
14106
14177
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center gap-2", children: [
14107
14178
  /* @__PURE__ */ jsxRuntimeExports.jsx(CopyableCommand, { command: "ANTHROPIC_BASE_URL=http://localhost:9527/proxy <your-tool>" }),
14108
14179
  /* @__PURE__ */ jsxRuntimeExports.jsx(CopyableCommand, { command: "OPENAI_BASE_URL=http://localhost:9527/proxy <your-tool>" })
@@ -14168,6 +14239,7 @@ const LogCursorPageSchema = object({
14168
14239
  oldestLogId: number().int().positive().nullable(),
14169
14240
  newestLogId: number().int().positive().nullable()
14170
14241
  });
14242
+ const SessionsResponseSchema = array(string());
14171
14243
  function buildSessionMembershipEvidence(groups, sessionId) {
14172
14244
  const memberships = [];
14173
14245
  for (const group of groups) {
@@ -14213,6 +14285,8 @@ const DEBOUNCE_MS = 100;
14213
14285
  const HASH_SCROLL_ATTEMPTS = 12;
14214
14286
  const HASH_HIGHLIGHT_MS = 1800;
14215
14287
  const SESSION_PAGE_LIMIT = 100;
14288
+ const SESSION_RELOAD_PAGE_LIMIT = 500;
14289
+ const MAX_SESSION_RELOAD_PAGES = 200;
14216
14290
  function buildLogsStreamUrl(sessionId) {
14217
14291
  const params = new URLSearchParams();
14218
14292
  if (sessionId !== void 0) {
@@ -14222,11 +14296,11 @@ function buildLogsStreamUrl(sessionId) {
14222
14296
  const query = params.toString();
14223
14297
  return query.length > 0 ? `/api/logs/stream?${query}` : "/api/logs/stream";
14224
14298
  }
14225
- function buildSessionLogsPageUrl(sessionId, request) {
14299
+ function buildSessionLogsPageUrl(sessionId, request, limit = SESSION_PAGE_LIMIT) {
14226
14300
  const params = new URLSearchParams({
14227
14301
  cursor: "1",
14228
14302
  compact: "1",
14229
- limit: String(SESSION_PAGE_LIMIT),
14303
+ limit: String(limit),
14230
14304
  sessionId
14231
14305
  });
14232
14306
  switch (request.kind) {
@@ -14261,12 +14335,23 @@ function mergeLogsById(previousLogs, incomingLogs) {
14261
14335
  }
14262
14336
  return [...byId.values()].sort((left, right) => left.id - right.id);
14263
14337
  }
14338
+ function mergeSessionIds(previousSessions, incomingSessions) {
14339
+ const sessions = /* @__PURE__ */ new Set();
14340
+ for (const session of previousSessions) {
14341
+ if (session !== "") sessions.add(session);
14342
+ }
14343
+ for (const session of incomingSessions) {
14344
+ if (session !== "") sessions.add(session);
14345
+ }
14346
+ return [...sessions].sort();
14347
+ }
14264
14348
  function ProxyViewerContainer({
14265
14349
  initialSessionId
14266
14350
  } = {}) {
14267
14351
  const [allLogs, setAllLogs] = reactExports.useState([]);
14268
14352
  const [selectedSession, setSelectedSession] = reactExports.useState(initialSessionId ?? "__all__");
14269
14353
  const [selectedModel, setSelectedModel] = reactExports.useState("__all__");
14354
+ const [knownSessions, setKnownSessions] = reactExports.useState([]);
14270
14355
  const { notice, showToast, dismissToast } = useTransientToast();
14271
14356
  const [streamInitialized, setStreamInitialized] = reactExports.useState(initialSessionId === void 0);
14272
14357
  const [logPage, setLogPage] = reactExports.useState(null);
@@ -14290,8 +14375,17 @@ function ProxyViewerContainer({
14290
14375
  () => filterLogs(allLogs, selectedSession, selectedModel),
14291
14376
  [allLogs, selectedSession, selectedModel]
14292
14377
  );
14293
- const sessions = reactExports.useMemo(() => extractSessions(allLogs), [allLogs]);
14378
+ const sessions = reactExports.useMemo(
14379
+ () => mergeSessionIds(knownSessions, extractSessions(allLogs)),
14380
+ [allLogs, knownSessions]
14381
+ );
14294
14382
  const models = reactExports.useMemo(() => extractModels(allLogs), [allLogs]);
14383
+ const refreshSessions = reactExports.useCallback(() => {
14384
+ void fetchJson("/api/sessions", SessionsResponseSchema).then((sessionIds) => {
14385
+ setKnownSessions((prev) => mergeSessionIds(prev, sessionIds));
14386
+ }).catch(() => {
14387
+ });
14388
+ }, []);
14295
14389
  const flushUpdates = reactExports.useCallback(() => {
14296
14390
  flushTimerRef.current = null;
14297
14391
  const updates = pendingUpdatesRef.current;
@@ -14342,9 +14436,14 @@ function ProxyViewerContainer({
14342
14436
  logIndexRef.current = buildLogIndex(nextLogs);
14343
14437
  return nextLogs;
14344
14438
  });
14439
+ setKnownSessions((prev) => mergeSessionIds(prev, extractSessions(update.logs)));
14345
14440
  setStreamInitialized(true);
14346
14441
  dismissToast();
14347
14442
  } else if (update.type === "update") {
14443
+ setKnownSessions((prev) => {
14444
+ if (update.log.sessionId === null || update.log.sessionId === "") return prev;
14445
+ return mergeSessionIds(prev, [update.log.sessionId]);
14446
+ });
14348
14447
  scheduleUpdate(update.log);
14349
14448
  }
14350
14449
  } catch {
@@ -14387,6 +14486,56 @@ function ProxyViewerContainer({
14387
14486
  },
14388
14487
  [dismissToast, initialSessionId, showErrorToast]
14389
14488
  );
14489
+ const reloadSessionLogs = reactExports.useCallback(
14490
+ (sessionId) => {
14491
+ const requestId = sessionPageRequestIdRef.current + 1;
14492
+ sessionPageRequestIdRef.current = requestId;
14493
+ setSessionPageLoading(true);
14494
+ dismissToast();
14495
+ void (async () => {
14496
+ const collected = [];
14497
+ let page = await fetchJson(
14498
+ buildSessionLogsPageUrl(sessionId, { kind: "oldest" }, SESSION_RELOAD_PAGE_LIMIT),
14499
+ LogCursorPageSchema
14500
+ );
14501
+ collected.push(...page.logs);
14502
+ let loadedPages = 1;
14503
+ while (page.hasNewer && page.newestLogId !== null && loadedPages < MAX_SESSION_RELOAD_PAGES) {
14504
+ page = await fetchJson(
14505
+ buildSessionLogsPageUrl(
14506
+ sessionId,
14507
+ { kind: "newer", afterLogId: page.newestLogId },
14508
+ SESSION_RELOAD_PAGE_LIMIT
14509
+ ),
14510
+ LogCursorPageSchema
14511
+ );
14512
+ collected.push(...page.logs);
14513
+ loadedPages += 1;
14514
+ }
14515
+ if (sessionPageRequestIdRef.current !== requestId) return;
14516
+ setAllLogs((prev) => {
14517
+ const next = mergeLogsById(prev, collected);
14518
+ logIndexRef.current = buildLogIndex(next);
14519
+ return next;
14520
+ });
14521
+ setKnownSessions((prev) => mergeSessionIds(prev, [sessionId]));
14522
+ setSessionPageLoading(false);
14523
+ if (page.hasNewer) {
14524
+ showToast({
14525
+ message: `Loaded ${String(collected.length)} logs for this session. More history is available.`,
14526
+ tone: "success"
14527
+ });
14528
+ } else {
14529
+ dismissToast();
14530
+ }
14531
+ })().catch((err) => {
14532
+ if (sessionPageRequestIdRef.current !== requestId) return;
14533
+ setSessionPageLoading(false);
14534
+ showErrorToast(err instanceof Error ? err.message : "Failed to reload session logs");
14535
+ });
14536
+ },
14537
+ [dismissToast, showErrorToast, showToast]
14538
+ );
14390
14539
  reactExports.useEffect(() => {
14391
14540
  if (initialSessionId === void 0) {
14392
14541
  setSessionMemberships([]);
@@ -14408,10 +14557,18 @@ function ProxyViewerContainer({
14408
14557
  cancelled = true;
14409
14558
  };
14410
14559
  }, [initialSessionId]);
14560
+ reactExports.useEffect(() => {
14561
+ refreshSessions();
14562
+ }, [refreshSessions]);
14411
14563
  reactExports.useEffect(() => {
14412
14564
  if (initialSessionId === void 0) return;
14413
14565
  loadSessionPage({ kind: "newest" });
14414
14566
  }, [initialSessionId, loadSessionPage]);
14567
+ reactExports.useEffect(() => {
14568
+ if (initialSessionId !== void 0) return;
14569
+ if (selectedSession === "__all__") return;
14570
+ reloadSessionLogs(selectedSession);
14571
+ }, [initialSessionId, reloadSessionLogs, selectedSession]);
14415
14572
  reactExports.useEffect(() => {
14416
14573
  if (initialSessionId !== void 0) return void 0;
14417
14574
  connectSSE();
@@ -14479,57 +14636,42 @@ function ProxyViewerContainer({
14479
14636
  };
14480
14637
  }, [logs.length]);
14481
14638
  const handleClearAll = reactExports.useCallback(() => {
14482
- if (initialSessionId !== void 0 && allLogs.length === 0) return;
14483
- void (async () => {
14484
- try {
14485
- const body = initialSessionId === void 0 ? void 0 : JSON.stringify({ ids: allLogs.map((log) => log.id) });
14486
- const res = await fetch("/api/logs", {
14487
- method: "DELETE",
14488
- ...body === void 0 ? {} : {
14489
- headers: { "Content-Type": "application/json" },
14490
- body
14491
- }
14492
- });
14493
- if (!res.ok) {
14494
- showErrorToast("Failed to clear logs");
14495
- return;
14496
- }
14497
- logIndexRef.current.clear();
14498
- setAllLogs([]);
14499
- dismissToast();
14500
- } catch (err) {
14501
- showErrorToast(err instanceof Error ? err.message : "Unknown error clearing logs");
14502
- }
14503
- })();
14504
- }, [allLogs, dismissToast, initialSessionId, showErrorToast]);
14639
+ const clearedSessions = extractSessions(allLogs);
14640
+ logIndexRef.current.clear();
14641
+ setAllLogs([]);
14642
+ setLogPage(null);
14643
+ setKnownSessions((prev) => mergeSessionIds(prev, clearedSessions));
14644
+ showToast({
14645
+ message: "Cleared the current view. Stored logs are still reloadable.",
14646
+ tone: "success"
14647
+ });
14648
+ }, [allLogs, showToast]);
14505
14649
  const handleClearGroup = reactExports.useCallback(
14506
14650
  (ids) => {
14507
14651
  if (ids.length === 0) return;
14508
- void (async () => {
14509
- try {
14510
- const res = await fetch("/api/logs", {
14511
- method: "DELETE",
14512
- headers: { "Content-Type": "application/json" },
14513
- body: JSON.stringify({ ids })
14514
- });
14515
- if (!res.ok) {
14516
- showErrorToast("Failed to clear group");
14517
- return;
14518
- }
14519
- const idSet = new Set(ids);
14520
- setAllLogs((prev) => {
14521
- const remaining = prev.filter((l) => !idSet.has(l.id));
14522
- logIndexRef.current = buildLogIndex(remaining);
14523
- return remaining;
14524
- });
14525
- dismissToast();
14526
- } catch (err) {
14527
- showErrorToast(err instanceof Error ? err.message : "Unknown error clearing group");
14528
- }
14529
- })();
14652
+ const idSet = new Set(ids);
14653
+ setAllLogs((prev) => {
14654
+ const removed = prev.filter((log) => idSet.has(log.id));
14655
+ const remaining = prev.filter((log) => !idSet.has(log.id));
14656
+ setKnownSessions((known) => mergeSessionIds(known, extractSessions(removed)));
14657
+ logIndexRef.current = buildLogIndex(remaining);
14658
+ return remaining;
14659
+ });
14660
+ showToast({ message: "Cleared this group from the current view.", tone: "success" });
14530
14661
  },
14531
- [dismissToast, showErrorToast]
14662
+ [showToast]
14532
14663
  );
14664
+ const handleReloadSession = reactExports.useCallback(() => {
14665
+ if (initialSessionId !== void 0) {
14666
+ loadSessionPage({ kind: "newest" });
14667
+ return;
14668
+ }
14669
+ if (selectedSession === "__all__") {
14670
+ refreshSessions();
14671
+ return;
14672
+ }
14673
+ reloadSessionLogs(selectedSession);
14674
+ }, [initialSessionId, loadSessionPage, refreshSessions, reloadSessionLogs, selectedSession]);
14533
14675
  const handleImportLogs = reactExports.useCallback(
14534
14676
  async (file) => {
14535
14677
  const formData = new FormData();
@@ -14613,10 +14755,11 @@ function ProxyViewerContainer({
14613
14755
  onSessionChange: setSelectedSession,
14614
14756
  onModelChange: setSelectedModel,
14615
14757
  onClearAll: handleClearAll,
14758
+ onReloadSession: initialSessionId !== void 0 || selectedSession !== "__all__" ? handleReloadSession : void 0,
14616
14759
  onClearGroup: handleClearGroup,
14617
14760
  onNotify: showToast,
14618
14761
  onImportLogs: initialSessionId === void 0 ? handleImportLogs : void 0,
14619
- isLoading: initialSessionId === void 0 ? !streamInitialized : sessionPageLoading,
14762
+ isLoading: initialSessionId === void 0 ? !streamInitialized || sessionPageLoading : sessionPageLoading,
14620
14763
  pagination,
14621
14764
  sessionMemberships,
14622
14765
  viewMode,