@tonyclaw/agent-inspector 2.1.13 → 2.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/CompareDrawer-BcEd6V-V.js +1 -0
  3. package/.output/public/assets/ProxyViewerContainer-h851qWNp.js +106 -0
  4. package/.output/public/assets/ReplayDialog-BNpC0548.js +1 -0
  5. package/.output/public/assets/{RequestAnatomy-BjlBT-Cy.js → RequestAnatomy-Ds1uRLVB.js} +1 -1
  6. package/.output/public/assets/ResponseView-7KPVqKl5.js +3 -0
  7. package/.output/public/assets/{StreamingChunkSequence-D2_SMhlE.js → StreamingChunkSequence-BHQT261s.js} +1 -1
  8. package/.output/public/assets/_sessionId-DWePGjnS.js +1 -0
  9. package/.output/public/assets/index-CI1-G8ua.js +1 -0
  10. package/.output/public/assets/index-DdhFqPsI.css +1 -0
  11. package/.output/public/assets/index-DjKt8XKe.js +14 -0
  12. package/.output/public/assets/json-viewer-CkCu-rka.js +1 -0
  13. package/.output/public/assets/{main-Dtspb4Ui.js → main-DpD1N0S8.js} +2 -2
  14. package/.output/server/_libs/lucide-react.mjs +194 -200
  15. package/.output/server/_libs/react-markdown.mjs +90 -2
  16. package/.output/server/{_sessionId-CXDcLuvi.mjs → _sessionId-DF9Sy8cP.mjs} +6 -57
  17. package/.output/server/_ssr/{CompareDrawer-CMoCAoeq.mjs → CompareDrawer-BoxztaO7.mjs} +50 -74
  18. package/.output/server/_ssr/{ProxyViewerContainer-BW2vVCBN.mjs → ProxyViewerContainer-CRBkqFlJ.mjs} +1221 -799
  19. package/.output/server/_ssr/{ReplayDialog-ChXL1t8H.mjs → ReplayDialog-Cc1dyDuK.mjs} +18 -62
  20. package/.output/server/_ssr/{RequestAnatomy-DtKzIlfU.mjs → RequestAnatomy-CMGSsz5Z.mjs} +6 -57
  21. package/.output/server/_ssr/{ResponseView-B5I8drzc.mjs → ResponseView-Cp10DM1D.mjs} +139 -61
  22. package/.output/server/_ssr/{StreamingChunkSequence-DvwjQNcO.mjs → StreamingChunkSequence-B1VGxy3A.mjs} +13 -58
  23. package/.output/server/_ssr/{index-D_ZHtRfl.mjs → index-47XVPghS.mjs} +6 -57
  24. package/.output/server/_ssr/index.mjs +2 -2
  25. package/.output/server/_ssr/json-viewer-zDE2rrmJ.mjs +478 -0
  26. package/.output/server/_ssr/{router-DhL9Wp3N.mjs → router-DVeuZFqI.mjs} +680 -174
  27. package/.output/server/{_tanstack-start-manifest_v-BHgoAmxZ.mjs → _tanstack-start-manifest_v-Bp8JxtPW.mjs} +1 -1
  28. package/.output/server/index.mjs +72 -58
  29. package/package.json +1 -1
  30. package/src/components/ProxyViewer.tsx +28 -2
  31. package/src/components/ProxyViewerContainer.tsx +25 -17
  32. package/src/components/clients/ClientLogo.tsx +132 -0
  33. package/src/components/groups/GroupsDialog.tsx +18 -13
  34. package/src/components/providers/ImportWizardDialog.tsx +7 -1
  35. package/src/components/providers/ProviderCard.tsx +10 -1
  36. package/src/components/providers/ProviderForm.tsx +157 -41
  37. package/src/components/providers/ProvidersPanel.tsx +5 -1
  38. package/src/components/proxy-viewer/AgentTraceSummary.tsx +56 -23
  39. package/src/components/proxy-viewer/AnswerMarkdown.tsx +8 -3
  40. package/src/components/proxy-viewer/CompareDrawer.tsx +58 -14
  41. package/src/components/proxy-viewer/ConversationGroup.tsx +11 -15
  42. package/src/components/proxy-viewer/ConversationHeader.tsx +33 -41
  43. package/src/components/proxy-viewer/LogEntry.tsx +41 -12
  44. package/src/components/proxy-viewer/LogEntryHeader.tsx +122 -51
  45. package/src/components/proxy-viewer/ProviderLogoStack.tsx +60 -0
  46. package/src/components/proxy-viewer/ReplayDialog.tsx +8 -2
  47. package/src/components/proxy-viewer/RequestToolsPanel.tsx +19 -13
  48. package/src/components/proxy-viewer/StreamingChunkSequence.tsx +9 -3
  49. package/src/components/proxy-viewer/ThreadConnector.tsx +18 -7
  50. package/src/components/proxy-viewer/TurnGroup.tsx +67 -32
  51. package/src/components/proxy-viewer/TurnGroupList.tsx +153 -0
  52. package/src/components/proxy-viewer/anatomy/sessionContextSummary.ts +74 -2
  53. package/src/components/proxy-viewer/formats/anthropic/ContentBlocks.tsx +13 -7
  54. package/src/components/proxy-viewer/formats/index.tsx +10 -3
  55. package/src/components/proxy-viewer/formats/openai/ResponseView.tsx +185 -17
  56. package/src/components/proxy-viewer/log-formats/openai.ts +107 -15
  57. package/src/components/proxy-viewer/logFocus.ts +15 -2
  58. package/src/components/proxy-viewer/requestTools.ts +7 -3
  59. package/src/components/proxy-viewer/viewerState.ts +77 -5
  60. package/src/components/ui/json-viewer-bulk.ts +41 -6
  61. package/src/components/ui/json-viewer.tsx +9 -8
  62. package/src/contracts/index.ts +15 -1
  63. package/src/contracts/openai.ts +94 -0
  64. package/src/lib/providerContract.ts +1 -0
  65. package/src/lib/providerModelMetadata.ts +7 -1
  66. package/src/lib/sessionInfoContract.ts +1 -0
  67. package/src/lib/stopReason.ts +59 -15
  68. package/src/lib/upstreamUrl.ts +46 -0
  69. package/src/mcp/previewExtractor.ts +73 -3
  70. package/src/mcp/server.ts +2 -0
  71. package/src/mcp/toolHandlers.ts +2 -0
  72. package/src/proxy/constants.ts +2 -0
  73. package/src/proxy/formats/openai/handler.ts +40 -9
  74. package/src/proxy/formats/openai/index.ts +7 -0
  75. package/src/proxy/formats/openai/schemas.ts +15 -1
  76. package/src/proxy/formats/openai/stream.ts +529 -135
  77. package/src/proxy/formats/registry.ts +9 -1
  78. package/src/proxy/providerImporters.ts +45 -5
  79. package/src/proxy/providers.ts +31 -11
  80. package/src/proxy/schemas.ts +6 -0
  81. package/src/proxy/sessionInfo.ts +5 -1
  82. package/src/proxy/toolSchemaWarnings.ts +25 -3
  83. package/src/proxy/upstream.ts +18 -37
  84. package/src/routes/api/providers.$providerId.ts +1 -0
  85. package/src/routes/api/providers.ts +2 -0
  86. package/.output/public/assets/CompareDrawer-Cz_1vIpR.js +0 -1
  87. package/.output/public/assets/ProxyViewerContainer-7QSiluMf.js +0 -117
  88. package/.output/public/assets/ReplayDialog-sBA1KAYD.js +0 -1
  89. package/.output/public/assets/ResponseView-PtEKzml9.js +0 -1
  90. package/.output/public/assets/_sessionId-DZfB4ruK.js +0 -1
  91. package/.output/public/assets/index-B-QQLbpz.js +0 -1
  92. package/.output/public/assets/index-CmtfjQPv.css +0 -1
@@ -1,16 +1,15 @@
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, g as apiFormatForPath, l as GroupEvidenceExportResultSchema, m as DeleteInspectorGroupResponseSchema, r as createPendingProviderTestResults, t as ProviderTestResultsSchema, u as createFailedProviderTestResults, M as MAX_SLOW_RESPONSE_THRESHOLD_SECONDS, v as MAX_PROVIDER_TEST_TIMEOUT_SECONDS, T as TimeDisplayFormatSchema, h as getSessionPath, f as parseOpenAIResponse, O as OpenAIRequestSchema, A as AnthropicResponseSchema$1, e as AnthropicRequestSchema, s as safeGetOwnProperty, w as resolveProviderContextWindow, j as AlertSummarySchema, k as AlertListResponseSchema, G as GroupEvidenceReadResponseSchema, q as maskApiKey, n as providerHasContextMetadata, o as findProviderModelMetadata, K as KnowledgeCandidateSchema, i as stripClaudeCodeBillingHeader, L as LogBodyChunkSchema, x as isPlainRecord } from "./router-DhL9Wp3N.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 GroupEvidenceExportResultSchema, o as DeleteInspectorGroupResponseSchema, v as createPendingProviderTestResults, w as ProviderTestResultsSchema, x as createFailedProviderTestResults, M as MAX_SLOW_RESPONSE_THRESHOLD_SECONDS, y as MAX_PROVIDER_TEST_TIMEOUT_SECONDS, T as TimeDisplayFormatSchema, j as getSessionPath, l as AlertSummarySchema, m as AlertListResponseSchema, G as GroupEvidenceReadResponseSchema, t as maskApiKey, q as providerHasContextMetadata, r as findProviderModelMetadata, s as safeGetOwnProperty, K as KnowledgeCandidateSchema, f as parseOpenAIResponse, g as parseOpenAIResponsesResponse, O as OpenAIRequestSchema, h as OpenAIResponsesRequestSchema, A as AnthropicResponseSchema$1, e as AnthropicRequestSchema, z as resolveProviderContextWindow, u as buildUpstreamUrl, k as stripClaudeCodeBillingHeader, L as LogBodyChunkSchema, B as isPlainRecord } from "./router-DVeuZFqI.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
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";
8
8
  import { c as cva } from "../_libs/class-variance-authority.mjs";
9
- import { d as diffJson, a as diffLines } from "../_libs/diff.mjs";
10
9
  import { u as useWindowVirtualizer, a as useVirtualizer } from "../_libs/tanstack__react-virtual.mjs";
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 { I as Info, C as ChevronDown, a as Check, X, U as Upload, D as Download, F as FileBraces, T as Trash2, P as Plus, A as ArrowLeft, b as ChevronUp, c as Copy, d as ChevronsLeft, e as ChevronLeft, f as ChevronRight, g as ChevronsRight, h as Clapperboard, S as Siren, G as Gauge, L as LoaderCircle, R as RefreshCw, i as Layers, j as Settings, k as Scan, l as CircleAlert, m as Terminal, n as ArrowUpRight, o as ArrowDownRight, p as User, q as Clock, M as MessageSquare, Z as Zap, E as ExternalLink, W as Wrench, r as TriangleAlert, B as Brain, s as Bell, t as Clock3, u as ShieldAlert, v as EyeOff, w as Eye, x as RotateCw, y as Pencil, z as CircleX, H as ShieldCheck, J as Save, K as FileSearch, N as CircleCheck, O as CloudUpload, Q as OctagonAlert, V as Radio, Y as Globe, _ as FileTerminal, $ as ChevronsUp, a0 as ChevronsDown, a1 as FileDiff, a2 as History, a3 as RotateCcw, a4 as Search, a5 as GitCompareArrows, a6 as Minus, a7 as CircleCheckBig, a8 as ArrowUp, a9 as ArrowDown, aa as CircleQuestionMark, ab as Server, ac as Lock, ad as Wifi, ae as WifiOff, af as Ellipsis, ag as CodeXml, ah as Blocks, ai as MousePointerClick, aj as FileText, ak as Rows3, al as Columns2 } from "../_libs/lucide-react.mjs";
13
- import { M as Markdown } from "../_libs/react-markdown.mjs";
12
+ import { I as Info, C as ChevronDown, a as Check, X, U as Upload, D as Download, F as FileBraces, T as Trash2, P as Plus, A as ArrowLeft, b as ChevronUp, c as Copy, d as ChevronsLeft, e as ChevronLeft, f as ChevronRight, g as ChevronsRight, h as Clapperboard, S as Siren, G as Gauge, L as LoaderCircle, R as RefreshCw, i as Layers, j as Settings, k as Scan, l as CircleAlert, m as Terminal, n as ArrowUpRight, o as ArrowDownRight, p as Clock, M as MessageSquare, Z as Zap, E as ExternalLink, W as Wrench, q as TriangleAlert, B as Brain, r as Bell, s as Clock3, t as ShieldAlert, u as EyeOff, v as Eye, w as RotateCw, x as Pencil, y as CircleX, z as ShieldCheck, H as Save, J as FileSearch, K as CircleCheck, N as CloudUpload, O as Minus, Q as CircleCheckBig, V as CircleQuestionMark, Y as Server, _ as Lock, $ as Wifi, a0 as WifiOff, a1 as OctagonAlert, a2 as Radio, a3 as Globe, a4 as FileTerminal, a5 as ChevronsUp, a6 as ChevronsDown, a7 as FileDiff, a8 as History, a9 as RotateCcw, aa as Search, ab as GitCompareArrows, ac as ArrowUp, ad as ArrowDown, ae as Ellipsis, af as CodeXml, ag as Blocks, ah as MousePointerClick, ai as FileText, aj as Rows3, ak as Columns2 } from "../_libs/lucide-react.mjs";
14
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";
15
14
  import { S as Slot } from "../_libs/radix-ui__react-slot.mjs";
16
15
  import { R as Root2$1, L as List, T as Trigger$2, C as Content$1 } from "../_libs/radix-ui__react-tabs.mjs";
@@ -772,6 +771,111 @@ function ConfirmDialog({
772
771
  ] })
773
772
  ] }) });
774
773
  }
774
+ const CLIENT_LABELS = {
775
+ codex: "Codex",
776
+ opencode: "OpenCode",
777
+ "mimo-code": "MiMo Code",
778
+ "claude-code": "Claude Code"
779
+ };
780
+ function normalize(value) {
781
+ return value?.toLowerCase() ?? "";
782
+ }
783
+ function matchesAny(value, candidates) {
784
+ for (const candidate of candidates) {
785
+ if (value.includes(candidate)) return true;
786
+ }
787
+ return false;
788
+ }
789
+ function detectClientApp(input) {
790
+ const haystack = [
791
+ normalize(input.userAgent),
792
+ normalize(input.conversationId),
793
+ normalize(input.clientProjectFolder)
794
+ ].join(" ");
795
+ if (matchesAny(haystack, ["mimocode", "mimo-code", "mimo code"])) return "mimo-code";
796
+ if (matchesAny(haystack, ["opencode", "open-code", "open code"])) return "opencode";
797
+ if (matchesAny(haystack, ["claude-code", "claude code", "claudecode"])) return "claude-code";
798
+ if (matchesAny(haystack, ["codex desktop", "codex-cli", "openai-codex", "codex"])) {
799
+ return "codex";
800
+ }
801
+ return "unknown";
802
+ }
803
+ function clientAppLabel(client) {
804
+ switch (client) {
805
+ case "codex":
806
+ case "opencode":
807
+ case "mimo-code":
808
+ case "claude-code":
809
+ return CLIENT_LABELS[client];
810
+ case "unknown":
811
+ return null;
812
+ }
813
+ }
814
+ function CodexMark() {
815
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", className: "size-full", "aria-hidden": "true", children: [
816
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "12", cy: "12", r: "8", fill: "none", stroke: "currentColor", strokeWidth: "2.2" }),
817
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
818
+ "path",
819
+ {
820
+ d: "M14.8 8.6a4.8 4.8 0 1 0 0 6.8",
821
+ fill: "none",
822
+ stroke: "currentColor",
823
+ strokeLinecap: "round",
824
+ strokeWidth: "2.2"
825
+ }
826
+ )
827
+ ] });
828
+ }
829
+ function OpenCodeMark() {
830
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", className: "size-full", "aria-hidden": "true", children: [
831
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M7 4h10v16H7z", fill: "none", stroke: "currentColor", strokeWidth: "2.2" }),
832
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M10 8h4M10 12h4M10 16h2", stroke: "currentColor", strokeLinecap: "round" })
833
+ ] });
834
+ }
835
+ function MiMoCodeMark() {
836
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { viewBox: "0 0 24 24", className: "size-full", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
837
+ "path",
838
+ {
839
+ d: "M5 18V6h3.2l3.8 6.1L15.8 6H19v12h-3V11.3l-3.1 5h-1.8L8 11.3V18z",
840
+ fill: "currentColor"
841
+ }
842
+ ) });
843
+ }
844
+ function ClaudeCodeMark() {
845
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { viewBox: "0 0 24 24", className: "size-full", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
846
+ "path",
847
+ {
848
+ fill: "currentColor",
849
+ fillRule: "evenodd",
850
+ clipRule: "evenodd",
851
+ 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"
852
+ }
853
+ ) });
854
+ }
855
+ function ClientLogo({
856
+ client,
857
+ className
858
+ }) {
859
+ const label = clientAppLabel(client);
860
+ if (label === null) return null;
861
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
862
+ "span",
863
+ {
864
+ className: cn(
865
+ "inline-flex size-6 shrink-0 items-center justify-center rounded-md border border-white/10 bg-black/20 p-1 text-cyan-100 shadow-[inset_0_1px_0_rgba(255,255,255,0.05)]",
866
+ className
867
+ ),
868
+ "aria-label": label,
869
+ title: label,
870
+ children: [
871
+ client === "codex" && /* @__PURE__ */ jsxRuntimeExports.jsx(CodexMark, {}),
872
+ client === "opencode" && /* @__PURE__ */ jsxRuntimeExports.jsx(OpenCodeMark, {}),
873
+ client === "mimo-code" && /* @__PURE__ */ jsxRuntimeExports.jsx(MiMoCodeMark, {}),
874
+ client === "claude-code" && /* @__PURE__ */ jsxRuntimeExports.jsx(ClaudeCodeMark, {})
875
+ ]
876
+ }
877
+ );
878
+ }
775
879
  const AnthropicLogoSvg = "data:image/svg+xml,%3csvg%20height='2500'%20viewBox='0%206.603%201192.672%201193.397'%20width='2500'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='m233.96%20800.215%20234.684-131.678%203.947-11.436-3.947-6.363h-11.436l-39.221-2.416-134.094-3.624-116.296-4.832-112.67-6.04-28.35-6.04-26.577-35.035%202.738-17.477%2023.84-16.027%2034.147%202.98%2075.463%205.155%20113.235%207.812%2082.147%204.832%20121.692%2012.644h19.329l2.738-7.812-6.604-4.832-5.154-4.832-117.182-79.41-126.845-83.92-66.443-48.321-35.92-24.484-18.12-22.953-7.813-50.093%2032.618-35.92%2043.812%202.98%2011.195%202.98%2044.375%2034.147%2094.792%2073.37%20123.786%2091.167%2018.12%2015.06%207.249-5.154.886-3.624-8.135-13.61-67.329-121.692-71.838-123.785-31.974-51.302-8.456-30.765c-2.98-12.645-5.154-23.275-5.154-36.242l37.127-50.416%2020.537-6.604%2049.53%206.604%2020.86%2018.121%2030.765%2070.39%2049.852%20110.818%2077.315%20150.684%2022.631%2044.698%2012.08%2041.396%204.51%2012.645h7.813v-7.248l6.362-84.886%2011.759-104.215%2011.436-134.094%203.946-37.772%2018.685-45.262%2037.127-24.482%2028.994%2013.852%2023.839%2034.148-3.303%2022.067-14.174%2092.134-27.785%20144.323-18.121%2096.644h10.55l12.08-12.08%2048.887-64.913%2082.147-102.685%2036.242-40.752%2042.282-45.02%2027.14-21.423h51.303l37.772%2056.135-16.913%2057.986-52.832%2067.007-43.812%2056.779-62.82%2084.563-39.22%2067.651%203.623%205.396%209.343-.886%20141.906-30.201%2076.671-13.852%2091.49-15.705%2041.396%2019.329%204.51%2019.65-16.269%2040.189-97.852%2024.16-114.764%2022.954-170.9%2040.43-2.093%201.53%202.416%202.98%2076.993%207.248%2032.94%201.771h80.617l150.12%2011.195%2039.222%2025.933%2023.517%2031.732-3.946%2024.16-60.403%2030.766-81.503-19.33-190.228-45.26-65.235-16.27h-9.02v5.397l54.362%2053.154%2099.624%2089.96%20124.752%20115.973%206.362%2028.671-16.027%2022.63-16.912-2.415-109.611-82.47-42.282-37.127-95.758-80.618h-6.363v8.456l22.067%2032.296%20116.537%20175.167%206.04%2053.719-8.456%2017.476-30.201%2010.55-33.181-6.04-68.215-95.758-70.39-107.84-56.778-96.644-6.926%203.947-33.503%20360.886-15.705%2018.443-36.243%2013.852-30.201-22.953-16.027-37.127%2016.027-73.37%2019.329-95.758%2015.704-76.107%2014.175-94.55%208.456-31.41-.563-2.094-6.927.886-71.275%2097.852-108.402%20146.497-85.772%2091.812-20.537%208.134-35.597-18.443%203.301-32.94%2019.893-29.315%20118.712-151.007%2071.597-93.583%2046.228-54.04-.322-7.813h-2.738l-315.302%20204.725-56.135%207.248-24.16-22.63%202.98-37.128%2011.435-12.08%2094.792-65.236-.322.323z'%20fill='%23d97757'/%3e%3c/svg%3e";
776
880
  const OpenAILogoSvg = "data:image/svg+xml,%3csvg%20height='2500'%20viewBox='-1%20-.1%20949.1%20959.8'%20width='2474'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='m925.8%20456.3c10.4%2023.2%2017%2048%2019.7%2073.3%202.6%2025.3%201.3%2050.9-4.1%2075.8-5.3%2024.9-14.5%2048.8-27.3%2070.8-8.4%2014.7-18.3%2028.5-29.7%2041.2-11.3%2012.6-23.9%2024-37.6%2034-13.8%2010-28.5%2018.4-44.1%2025.3-15.5%206.8-31.7%2012-48.3%2015.4-7.8%2024.2-19.4%2047.1-34.4%2067.7-14.9%2020.6-33%2038.7-53.6%2053.6-20.6%2015-43.4%2026.6-67.6%2034.4-24.2%207.9-49.5%2011.8-75%2011.8-16.9.1-33.9-1.7-50.5-5.1-16.5-3.5-32.7-8.8-48.2-15.7s-30.2-15.5-43.9-25.5c-13.6-10-26.2-21.5-37.4-34.2-25%205.4-50.6%206.7-75.9%204.1-25.3-2.7-50.1-9.3-73.4-19.7-23.2-10.3-44.7-24.3-63.6-41.4s-35-37.1-47.7-59.1c-8.5-14.7-15.5-30.2-20.8-46.3s-8.8-32.7-10.6-49.6c-1.8-16.8-1.7-33.8.1-50.7%201.8-16.8%205.5-33.4%2010.8-49.5-17-18.9-31-40.4-41.4-63.6-10.3-23.3-17-48-19.6-73.3-2.7-25.3-1.3-50.9%204-75.8s14.5-48.8%2027.3-70.8c8.4-14.7%2018.3-28.6%2029.6-41.2s24-24%2037.7-34%2028.5-18.5%2044-25.3c15.6-6.9%2031.8-12%2048.4-15.4%207.8-24.3%2019.4-47.1%2034.3-67.7%2015-20.6%2033.1-38.7%2053.7-53.7%2020.6-14.9%2043.4-26.5%2067.6-34.4%2024.2-7.8%2049.5-11.8%2075-11.7%2016.9-.1%2033.9%201.6%2050.5%205.1s32.8%208.7%2048.3%2015.6c15.5%207%2030.2%2015.5%2043.9%2025.5%2013.7%2010.1%2026.3%2021.5%2037.5%2034.2%2024.9-5.3%2050.5-6.6%2075.8-4s50%209.3%2073.3%2019.6c23.2%2010.4%2044.7%2024.3%2063.6%2041.4%2018.9%2017%2035%2036.9%2047.7%2059%208.5%2014.6%2015.5%2030.1%2020.8%2046.3%205.3%2016.1%208.9%2032.7%2010.6%2049.6%201.8%2016.9%201.8%2033.9-.1%2050.8-1.8%2016.9-5.5%2033.5-10.8%2049.6%2017.1%2018.9%2031%2040.3%2041.4%2063.6zm-333.2%20426.9c21.8-9%2041.6-22.3%2058.3-39s30-36.5%2039-58.4c9-21.8%2013.7-45.2%2013.7-68.8v-223q-.1-.3-.2-.7-.1-.3-.3-.6-.2-.3-.5-.5-.3-.3-.6-.4l-80.7-46.6v269.4c0%202.7-.4%205.5-1.1%208.1-.7%202.7-1.7%205.2-3.1%207.6s-3%204.6-5%206.5a32.1%2032.1%200%200%201%20-6.5%205l-191.1%20110.3c-1.6%201-4.3%202.4-5.7%203.2%207.9%206.7%2016.5%2012.6%2025.5%2017.8%209.1%205.2%2018.5%209.6%2028.3%2013.2%209.8%203.5%2019.9%206.2%2030.1%208%2010.3%201.8%2020.7%202.7%2031.1%202.7%2023.6%200%2047-4.7%2068.8-13.8zm-455.1-151.4c11.9%2020.5%2027.6%2038.3%2046.3%2052.7%2018.8%2014.4%2040.1%2024.9%2062.9%2031s46.6%207.7%2070%204.6%2045.9-10.7%2066.4-22.5l193.2-111.5.5-.5q.2-.2.3-.6.2-.3.3-.6v-94l-233.2%20134.9c-2.4%201.4-4.9%202.4-7.5%203.2-2.7.7-5.4%201-8.2%201-2.7%200-5.4-.3-8.1-1-2.6-.8-5.2-1.8-7.6-3.2l-191.1-110.4c-1.7-1-4.2-2.5-5.6-3.4-1.8%2010.3-2.7%2020.7-2.7%2031.1s1%2020.8%202.8%2031.1c1.8%2010.2%204.6%2020.3%208.1%2030.1%203.6%209.8%208%2019.2%2013.2%2028.2zm-50.2-417c-11.8%2020.5-19.4%2043.1-22.5%2066.5s-1.5%2047.1%204.6%2070c6.1%2022.8%2016.6%2044.1%2031%2062.9%2014.4%2018.7%2032.3%2034.4%2052.7%2046.2l193.1%20111.6q.3.1.7.2h.7q.4%200%20.7-.2.3-.1.6-.3l81-46.8-233.2-134.6c-2.3-1.4-4.5-3.1-6.5-5a32.1%2032.1%200%200%201%20-5-6.5c-1.3-2.4-2.4-4.9-3.1-7.6-.7-2.6-1.1-5.3-1-8.1v-227.1c-9.8%203.6-19.3%208-28.3%2013.2-9%205.3-17.5%2011.3-25.5%2018-7.9%206.7-15.3%2014.1-22%2022.1-6.7%207.9-12.6%2016.5-17.8%2025.5zm663.3%20154.4c2.4%201.4%204.6%203%206.6%205%201.9%201.9%203.6%204.1%205%206.5%201.3%202.4%202.4%205%203.1%207.6.6%202.7%201%205.4.9%208.2v227.1c32.1-11.8%2060.1-32.5%2080.8-59.7%2020.8-27.2%2033.3-59.7%2036.2-93.7s-3.9-68.2-19.7-98.5-39.9-55.5-69.5-72.5l-193.1-111.6q-.3-.1-.7-.2h-.7q-.3.1-.7.2-.3.1-.6.3l-80.6%2046.6%20233.2%20134.7zm80.5-121h-.1v.1zm-.1-.1c5.8-33.6%201.9-68.2-11.3-99.7-13.1-31.5-35-58.6-63-78.2-28-19.5-61-30.7-95.1-32.2-34.2-1.4-68%206.9-97.6%2023.9l-193.1%20111.5q-.3.2-.5.5l-.4.6q-.1.3-.2.7-.1.3-.1.7v93.2l233.2-134.7c2.4-1.4%205-2.4%207.6-3.2%202.7-.7%205.4-1%208.1-1%202.8%200%205.5.3%208.2%201%202.6.8%205.1%201.8%207.5%203.2l191.1%20110.4c1.7%201%204.2%202.4%205.6%203.3zm-505.3-103.2c0-2.7.4-5.4%201.1-8.1.7-2.6%201.7-5.2%203.1-7.6%201.4-2.3%203-4.5%205-6.5%201.9-1.9%204.1-3.6%206.5-4.9l191.1-110.3c1.8-1.1%204.3-2.5%205.7-3.2-26.2-21.9-58.2-35.9-92.1-40.2-33.9-4.4-68.3%201-99.2%2015.5-31%2014.5-57.2%2037.6-75.5%2066.4-18.3%2028.9-28%2062.3-28%2096.5v223q.1.4.2.7.1.3.3.6.2.3.5.6.2.2.6.4l80.7%2046.6zm43.8%20294.7%20103.9%2060%20103.9-60v-119.9l-103.8-60-103.9%2060z'/%3e%3c/svg%3e";
777
881
  const DeepSeekLogoSvg = "data:image/svg+xml,%3csvg%20fill='none'%20height='1320'%20viewBox='3.771%206.973%2023.993%2017.652'%20width='2500'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='m27.501%208.469c-.252-.123-.36.111-.508.23-.05.04-.093.09-.135.135-.368.395-.797.652-1.358.621-.821-.045-1.521.213-2.14.842-.132-.776-.57-1.238-1.235-1.535-.349-.155-.701-.309-.944-.645-.171-.238-.217-.504-.303-.765-.054-.159-.108-.32-.29-.348-.197-.031-.274.135-.352.273-.31.567-.43%201.192-.419%201.825.028%201.421.628%202.554%201.82%203.36.136.093.17.186.128.321-.081.278-.178.547-.264.824-.054.178-.135.217-.324.14a5.448%205.448%200%200%201%20-1.719-1.169c-.848-.82-1.614-1.726-2.57-2.435-.225-.166-.449-.32-.681-.467-.976-.95.128-1.729.383-1.82.267-.096.093-.428-.77-.424s-1.653.293-2.659.677a2.782%202.782%200%200%201%20-.46.135%209.554%209.554%200%200%200%20-2.853-.1c-1.866.21-3.356%201.092-4.452%202.6-1.315%201.81-1.625%203.87-1.246%206.018.399%202.261%201.552%204.136%203.326%205.601%201.837%201.518%203.955%202.262%206.37%202.12%201.466-.085%203.1-.282%204.942-1.842.465.23.952.322%201.762.392.623.059%201.223-.031%201.687-.127.728-.154.677-.828.414-.953-2.132-.994-1.665-.59-2.09-.916%201.084-1.285%202.717-2.619%203.356-6.94.05-.343.007-.558%200-.837-.004-.168.034-.235.228-.254a4.084%204.084%200%200%200%201.529-.47c1.382-.757%201.938-1.997%202.07-3.485.02-.227-.004-.463-.243-.582zm-12.041%2013.391c-2.067-1.627-3.07-2.162-3.483-2.138-.387.021-.318.465-.233.754.089.285.205.482.368.732.113.166.19.414-.112.598-.666.414-1.823-.139-1.878-.166-1.347-.793-2.473-1.842-3.267-3.276-.765-1.38-1.21-2.861-1.284-4.441-.02-.383.093-.518.472-.586a4.692%204.692%200%200%201%201.514-.04c2.109.31%203.905%201.255%205.41%202.749.86.853%201.51%201.871%202.18%202.865.711%201.057%201.478%202.063%202.454%202.887.343.289.619.51.881.672-.792.088-2.117.107-3.022-.61zm.99-6.38a.304.304%200%201%201%20.609%200c0%20.17-.136.304-.306.304a.3.3%200%200%201%20-.303-.305zm3.077%201.581c-.197.08-.394.15-.584.159a1.246%201.246%200%200%201%20-.79-.252c-.27-.227-.463-.354-.546-.752a1.752%201.752%200%200%201%20.016-.582c.07-.324-.008-.531-.235-.72-.187-.155-.422-.196-.682-.196a.551.551%200%200%201%20-.252-.078c-.108-.055-.197-.19-.112-.356.027-.053.159-.183.19-.207.352-.201.758-.135%201.134.016.349.142.611.404.99.773.388.448.457.573.678.906.174.264.333.534.441.842.066.192-.02.35-.248.448z'%20fill='%234d6bfe'/%3e%3c/svg%3e";
@@ -894,6 +998,38 @@ function TooltipContent({
894
998
  }
895
999
  ) });
896
1000
  }
1001
+ const MAX_VISIBLE_LOGOS = 3;
1002
+ const ROW_CHEVRON_SLOT_CLASS = "flex h-8 w-5 shrink-0 items-center justify-center text-muted-foreground";
1003
+ function ProviderLogoStack({
1004
+ items,
1005
+ ariaLabel,
1006
+ className
1007
+ }) {
1008
+ if (items.length === 0) {
1009
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn("flex h-8 w-12 shrink-0 items-center", className), "aria-hidden": "true" });
1010
+ }
1011
+ const visibleItems = items.slice(0, MAX_VISIBLE_LOGOS);
1012
+ const overflowCount = items.length - visibleItems.length;
1013
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { delayDuration: 150, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: cn("flex h-8 w-12 shrink-0 items-center", className), "aria-label": ariaLabel, children: [
1014
+ visibleItems.map((item, index) => /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
1015
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
1016
+ "span",
1017
+ {
1018
+ className: cn(
1019
+ "inline-flex size-6 shrink-0 items-center justify-center rounded-md border border-white/10 bg-black/20 shadow-[inset_0_1px_0_rgba(255,255,255,0.05)]",
1020
+ index > 0 && "-ml-2"
1021
+ ),
1022
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderLogo, { provider: item.provider, className: "size-4" })
1023
+ }
1024
+ ) }),
1025
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: item.tooltip })
1026
+ ] }, `${item.provider}-${String(index)}`)),
1027
+ overflowCount > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "-ml-2 inline-flex h-6 min-w-6 shrink-0 items-center justify-center rounded-md border border-white/10 bg-black/40 px-1 font-mono text-[10px] text-muted-foreground", children: [
1028
+ "+",
1029
+ overflowCount
1030
+ ] })
1031
+ ] }) });
1032
+ }
897
1033
  function forEachCodePoint(text, visit) {
898
1034
  for (const ch of Array.from(text)) {
899
1035
  visit(ch);
@@ -1078,9 +1214,9 @@ function contentToText(content) {
1078
1214
  if (block === null || typeof block !== "object") continue;
1079
1215
  const b = block;
1080
1216
  const type = b.type;
1081
- if (type === "text" && typeof b.text === "string") {
1217
+ if ((type === "text" || type === "input_text" || type === "output_text") && typeof b.text === "string") {
1082
1218
  parts.push(b.text);
1083
- } else if (type === "image_url") {
1219
+ } else if (type === "image_url" || type === "input_image") {
1084
1220
  parts.push("[image]");
1085
1221
  }
1086
1222
  }
@@ -1110,15 +1246,54 @@ function toolsToText(tools) {
1110
1246
  const parts = [];
1111
1247
  for (const tool of tools) {
1112
1248
  if (tool === null || typeof tool !== "object") continue;
1113
- const t = tool;
1114
- const fn = t.function;
1115
- if (fn === void 0) continue;
1116
- if (typeof fn.name === "string") parts.push(fn.name);
1117
- if (typeof fn.description === "string") parts.push(fn.description);
1118
- if (fn.parameters !== void 0) parts.push(JSON.stringify(fn.parameters));
1249
+ const fn = safeGetOwnProperty(tool, "function");
1250
+ const name = safeGetOwnProperty(fn, "name") ?? safeGetOwnProperty(tool, "name");
1251
+ const description = safeGetOwnProperty(fn, "description") ?? safeGetOwnProperty(tool, "description");
1252
+ const parameters = safeGetOwnProperty(fn, "parameters") ?? safeGetOwnProperty(tool, "parameters");
1253
+ if (typeof name === "string") parts.push(name);
1254
+ if (typeof description === "string") parts.push(description);
1255
+ if (parameters !== void 0) parts.push(JSON.stringify(parameters));
1119
1256
  }
1120
1257
  return parts.join("\n");
1121
1258
  }
1259
+ function countResponsesInput(input) {
1260
+ if (typeof input === "string") return input.length > 0 ? 1 : 0;
1261
+ if (Array.isArray(input)) return input.length;
1262
+ if (input === void 0 || input === null) return null;
1263
+ return 1;
1264
+ }
1265
+ function responsesInputItemToText(input) {
1266
+ if (typeof input === "string") return input;
1267
+ const directText = safeGetOwnProperty(input, "text");
1268
+ if (typeof directText === "string") return directText;
1269
+ const contentText = contentToText(safeGetOwnProperty(input, "content"));
1270
+ if (contentText.length > 0) return contentText;
1271
+ const outputText = contentToText(safeGetOwnProperty(input, "output"));
1272
+ if (outputText.length > 0) return outputText;
1273
+ const argumentsText = safeGetOwnProperty(input, "arguments");
1274
+ return typeof argumentsText === "string" ? argumentsText : "";
1275
+ }
1276
+ function responsesInputRole(input) {
1277
+ const role = safeGetOwnProperty(input, "role");
1278
+ if (role === "system" || role === "user" || role === "assistant" || role === "tool") {
1279
+ return role;
1280
+ }
1281
+ const type = safeGetOwnProperty(input, "type");
1282
+ if (type === "function_call_output") return "tool";
1283
+ if (type === "message") return "user";
1284
+ return "user";
1285
+ }
1286
+ function responsesToolNames(response) {
1287
+ const output = safeGetOwnProperty(response, "output");
1288
+ if (!Array.isArray(output)) return [];
1289
+ const names = [];
1290
+ for (const item of output) {
1291
+ if (safeGetOwnProperty(item, "type") !== "function_call") continue;
1292
+ const name = safeGetOwnProperty(item, "name");
1293
+ if (typeof name === "string" && name.length > 0) names.push(name);
1294
+ }
1295
+ return names;
1296
+ }
1122
1297
  function segment(role, label, text, path) {
1123
1298
  return {
1124
1299
  role,
@@ -1135,7 +1310,16 @@ const openAILogFormatAdapter = {
1135
1310
  if (rawBody === null) return emptyRequestAnalysis(rawBody);
1136
1311
  try {
1137
1312
  const result = OpenAIRequestSchema.safeParse(JSON.parse(rawBody));
1138
- if (!result.success) return emptyRequestAnalysis(rawBody);
1313
+ if (!result.success) {
1314
+ const responsesResult = OpenAIResponsesRequestSchema.safeParse(JSON.parse(rawBody));
1315
+ if (!responsesResult.success) return emptyRequestAnalysis(rawBody);
1316
+ return {
1317
+ parsed: responsesResult.data,
1318
+ comparisonValue: responsesResult.data,
1319
+ messageCount: countResponsesInput(responsesResult.data.input),
1320
+ toolCount: responsesResult.data.tools !== void 0 && responsesResult.data.tools.length > 0 ? responsesResult.data.tools.length : null
1321
+ };
1322
+ }
1139
1323
  return {
1140
1324
  parsed: result.data,
1141
1325
  comparisonValue: result.data,
@@ -1149,7 +1333,15 @@ const openAILogFormatAdapter = {
1149
1333
  analyzeResponse(responseText) {
1150
1334
  if (responseText === null) return EMPTY_RESPONSE_ANALYSIS;
1151
1335
  const parsed = parseOpenAIResponse(responseText);
1152
- if (parsed === null) return EMPTY_RESPONSE_ANALYSIS;
1336
+ if (parsed === null) {
1337
+ const responsesParsed = parseOpenAIResponsesResponse(responseText);
1338
+ if (responsesParsed === null) return EMPTY_RESPONSE_ANALYSIS;
1339
+ const toolNames2 = responsesToolNames(responsesParsed);
1340
+ return {
1341
+ parsed: responsesParsed,
1342
+ toolNames: toolNames2.length > 0 ? toolNames2 : null
1343
+ };
1344
+ }
1153
1345
  const toolNames = parsed.choices[0]?.message?.tool_calls?.map((toolCall) => toolCall.function?.name ?? "").filter((name) => name !== "") ?? [];
1154
1346
  return {
1155
1347
  parsed,
@@ -1160,6 +1352,9 @@ const openAILogFormatAdapter = {
1160
1352
  if (parsed === null || typeof parsed !== "object") return null;
1161
1353
  const body = parsed;
1162
1354
  const segments = [];
1355
+ if (typeof body.instructions === "string" && body.instructions.length > 0) {
1356
+ segments.push(segment("system", "instructions", body.instructions, "/instructions"));
1357
+ }
1163
1358
  if (Array.isArray(body.messages)) {
1164
1359
  body.messages.forEach((message, index) => {
1165
1360
  if (message === null || typeof message !== "object") return;
@@ -1169,6 +1364,17 @@ const openAILogFormatAdapter = {
1169
1364
  segments.push(segment(role, `[${index}] ${role}`, text, `/messages/${index}`));
1170
1365
  });
1171
1366
  }
1367
+ if (!Array.isArray(body.messages)) {
1368
+ if (typeof body.input === "string" && body.input.length > 0) {
1369
+ segments.push(segment("user", "input", body.input, "/input"));
1370
+ } else if (Array.isArray(body.input)) {
1371
+ body.input.forEach((item, index) => {
1372
+ const role = responsesInputRole(item);
1373
+ const text = responsesInputItemToText(item);
1374
+ segments.push(segment(role, `[${index}] ${role}`, text, `/input/${index}`));
1375
+ });
1376
+ }
1377
+ }
1172
1378
  if (Array.isArray(body.tools) && body.tools.length > 0) {
1173
1379
  const text = toolsToText(body.tools);
1174
1380
  segments.push(segment("tools", "tools", text, "/tools"));
@@ -1230,6 +1436,15 @@ function ConversationHeader({
1230
1436
  },
1231
1437
  [conversationId]
1232
1438
  );
1439
+ const providerLogoItems = providers?.map(({ provider, models }) => ({
1440
+ provider,
1441
+ tooltip: models.length === 1 ? models[0] ?? provider : models.join(", ")
1442
+ })) ?? [];
1443
+ const clientApp = detectClientApp({ userAgent, conversationId, clientProjectFolder });
1444
+ const detectedClientLabel = clientAppLabel(clientApp);
1445
+ const hasUserAgent = userAgent !== null && userAgent !== void 0 && userAgent !== "";
1446
+ const clientDisplayLabel = detectedClientLabel ?? userAgent ?? null;
1447
+ const clientTooltip = detectedClientLabel !== null && hasUserAgent ? `${detectedClientLabel} - ${userAgent}` : null;
1233
1448
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
1234
1449
  "div",
1235
1450
  {
@@ -1253,7 +1468,8 @@ function ConversationHeader({
1253
1468
  }
1254
1469
  },
1255
1470
  children: [
1256
- expanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-4 text-muted-foreground shrink-0" }) : isLoading ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-4 animate-spin text-muted-foreground shrink-0" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-4 text-muted-foreground shrink-0" }),
1471
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderLogoStack, { items: providerLogoItems, ariaLabel: "Models used in this session" }),
1472
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: ROW_CHEVRON_SLOT_CLASS, children: expanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-4 shrink-0" }) : isLoading ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-4 shrink-0 animate-spin" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-4 shrink-0" }) }),
1257
1473
  conversationId.startsWith("PID:") || conversationId.includes("|") ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1258
1474
  clientPid !== null && clientPid !== void 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs(
1259
1475
  "span",
@@ -1295,28 +1511,17 @@ function ConversationHeader({
1295
1511
  }
1296
1512
  )
1297
1513
  ] }),
1298
- userAgent !== null && userAgent !== void 0 && userAgent !== "" && /* @__PURE__ */ jsxRuntimeExports.jsxs(
1514
+ clientDisplayLabel !== null && clientDisplayLabel !== "" && /* @__PURE__ */ jsxRuntimeExports.jsxs(
1299
1515
  "span",
1300
1516
  {
1301
1517
  className: "flex items-center gap-1 text-muted-foreground text-xs shrink-0",
1302
- title: userAgent,
1518
+ title: clientTooltip ?? clientDisplayLabel,
1303
1519
  children: [
1304
- /* @__PURE__ */ jsxRuntimeExports.jsx(User, { className: "size-3" }),
1305
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums truncate max-w-[120px]", children: userAgent })
1520
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ClientLogo, { client: clientApp, className: "size-5" }),
1521
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums truncate max-w-[120px]", children: clientDisplayLabel })
1306
1522
  ]
1307
1523
  }
1308
1524
  ),
1309
- providers !== void 0 && providers.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { delayDuration: 150, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
1310
- "span",
1311
- {
1312
- className: "flex items-center gap-0.5 shrink-0",
1313
- "aria-label": "Models used in this session",
1314
- children: providers.map(({ provider, models }) => /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
1315
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderLogo, { provider, className: "size-4" }) }) }),
1316
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: models.length === 1 ? models[0] : models.join(", ") })
1317
- ] }, provider))
1318
- }
1319
- ) }),
1320
1525
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1 text-muted-foreground text-xs shrink-0", children: [
1321
1526
  /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "size-3" }),
1322
1527
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", children: formatTimestampRange(startTime, endTime, timeDisplayFormat) })
@@ -1418,9 +1623,65 @@ function groupLogsByConversation(logs) {
1418
1623
  result.sort((a, b) => (a.logs[0]?.timestamp ?? "").localeCompare(b.logs[0]?.timestamp ?? ""));
1419
1624
  return result;
1420
1625
  }
1626
+ const LOG_FOCUS_REQUEST_EVENT = "agent-inspector:focus-log";
1627
+ function dispatchLogFocusRequest(request) {
1628
+ window.dispatchEvent(new CustomEvent(LOG_FOCUS_REQUEST_EVENT, { detail: request }));
1629
+ }
1630
+ function readLogFocusRequest(event) {
1631
+ if (typeof CustomEvent === "undefined" || !(event instanceof CustomEvent)) return null;
1632
+ const detail = event.detail;
1633
+ const logId = safeGetOwnProperty(detail, "logId");
1634
+ if (typeof logId !== "number" || !Number.isInteger(logId) || logId < 0) return null;
1635
+ const tab = safeGetOwnProperty(detail, "tab");
1636
+ switch (tab) {
1637
+ case "anatomy":
1638
+ case "request":
1639
+ break;
1640
+ case void 0:
1641
+ break;
1642
+ default:
1643
+ return null;
1644
+ }
1645
+ const source = safeGetOwnProperty(detail, "source");
1646
+ switch (source) {
1647
+ case "virtualizer":
1648
+ return { logId, tab: tab ?? "request", source };
1649
+ case void 0:
1650
+ return { logId, tab: tab ?? "request" };
1651
+ default:
1652
+ return null;
1653
+ }
1654
+ }
1421
1655
  function isRecord(value) {
1422
1656
  return typeof value === "object" && value !== null && !Array.isArray(value);
1423
1657
  }
1658
+ function normalizeAnthropicStopReason(value) {
1659
+ switch (value) {
1660
+ case "end_turn":
1661
+ case "tool_use":
1662
+ return value;
1663
+ default:
1664
+ return null;
1665
+ }
1666
+ }
1667
+ function normalizeOpenAIFinishReason(value) {
1668
+ switch (value) {
1669
+ case "stop":
1670
+ case "length":
1671
+ return value;
1672
+ default:
1673
+ return null;
1674
+ }
1675
+ }
1676
+ function isResponsesLengthLimitReason(value) {
1677
+ switch (value) {
1678
+ case "max_output_tokens":
1679
+ case "max_tokens":
1680
+ return true;
1681
+ default:
1682
+ return false;
1683
+ }
1684
+ }
1424
1685
  function extractStopReason(log) {
1425
1686
  if (log.responseText === null) return null;
1426
1687
  try {
@@ -1430,13 +1691,30 @@ function extractStopReason(log) {
1430
1691
  }
1431
1692
  if (!isRecord(json)) return null;
1432
1693
  if (typeof json.stop_reason === "string") {
1433
- if (json.stop_reason === "end_turn" || json.stop_reason === "tool_use") {
1434
- return json.stop_reason;
1694
+ return normalizeAnthropicStopReason(json.stop_reason);
1695
+ }
1696
+ if (Array.isArray(json.choices)) {
1697
+ for (const choice of json.choices) {
1698
+ if (!isRecord(choice) || typeof choice.finish_reason !== "string") continue;
1699
+ const reason = normalizeOpenAIFinishReason(choice.finish_reason);
1700
+ if (reason !== null) return reason;
1701
+ }
1702
+ }
1703
+ if (Array.isArray(json.output)) {
1704
+ for (const item of json.output) {
1705
+ if (isRecord(item) && item.type === "function_call") {
1706
+ return "tool_use";
1707
+ }
1708
+ }
1709
+ if (json.status === "completed") {
1710
+ return "stop";
1435
1711
  }
1436
- return null;
1437
1712
  }
1438
- if (Array.isArray(json.choices) && json.choices.length > 0 && isRecord(json.choices[0]) && typeof json.choices[0].finish_reason === "string" && json.choices[0].finish_reason === "stop") {
1439
- return "stop";
1713
+ if (json.status === "incomplete" && isRecord(json.incomplete_details)) {
1714
+ const reason = json.incomplete_details.reason;
1715
+ if (typeof reason === "string" && isResponsesLengthLimitReason(reason)) {
1716
+ return "length";
1717
+ }
1440
1718
  }
1441
1719
  return null;
1442
1720
  } catch {
@@ -1444,7 +1722,7 @@ function extractStopReason(log) {
1444
1722
  }
1445
1723
  }
1446
1724
  function isTurnBoundary(stopReason) {
1447
- return stopReason === "end_turn" || stopReason === "stop";
1725
+ return stopReason === "end_turn" || stopReason === "stop" || stopReason === "length";
1448
1726
  }
1449
1727
  function SvgShell({
1450
1728
  className,
@@ -1798,8 +2076,38 @@ function getInteriorCrabVariantIndex(seed) {
1798
2076
  function getInteriorCrabVariant(seed) {
1799
2077
  return getCrabVariant(getInteriorCrabVariantIndex(seed));
1800
2078
  }
1801
- function getJsonExpansionPolicy(_value) {
1802
- return { depth: Number.POSITIVE_INFINITY };
2079
+ const FULL_EXPAND_NODE_LIMIT = 400;
2080
+ const STRUCTURE_EXPAND_NODE_LIMIT = 2e3;
2081
+ function isJsonArray(value) {
2082
+ return Array.isArray(value);
2083
+ }
2084
+ function countJsonNodesUpTo(value, limit) {
2085
+ const stack = [value];
2086
+ let count = 0;
2087
+ while (stack.length > 0) {
2088
+ const current = stack.pop();
2089
+ if (current === void 0) continue;
2090
+ count += 1;
2091
+ if (count > limit) return count;
2092
+ if (current === null || typeof current !== "object") continue;
2093
+ if (isJsonArray(current)) {
2094
+ for (const child of current) {
2095
+ stack.push(child);
2096
+ }
2097
+ continue;
2098
+ }
2099
+ for (const key of Object.keys(current)) {
2100
+ const child = current[key];
2101
+ if (child !== void 0) stack.push(child);
2102
+ }
2103
+ }
2104
+ return count;
2105
+ }
2106
+ function getJsonExpansionPolicy(value) {
2107
+ const nodeCount = countJsonNodesUpTo(value, STRUCTURE_EXPAND_NODE_LIMIT + 1);
2108
+ if (nodeCount <= FULL_EXPAND_NODE_LIMIT) return { depth: Number.POSITIVE_INFINITY };
2109
+ if (nodeCount <= STRUCTURE_EXPAND_NODE_LIMIT) return { depth: 3 };
2110
+ return { depth: 2 };
1803
2111
  }
1804
2112
  function parseJsonText(text) {
1805
2113
  try {
@@ -1813,7 +2121,7 @@ function useJsonBulkExpansion(text) {
1813
2121
  const parsed = reactExports.useMemo(() => text === null ? null : parseJsonText(text), [text]);
1814
2122
  const parsedData = parsed?.kind === "json" ? parsed.data : null;
1815
2123
  const policy = reactExports.useMemo(
1816
- () => parsedData === null ? null : getJsonExpansionPolicy(),
2124
+ () => parsedData === null ? null : getJsonExpansionPolicy(parsedData),
1817
2125
  [parsedData]
1818
2126
  );
1819
2127
  const [isExpanded, setIsExpanded] = reactExports.useState(false);
@@ -1961,27 +2269,27 @@ function useCopyFeedback(text) {
1961
2269
  return { copied, copy };
1962
2270
  }
1963
2271
  const LazyCompareDrawer = reactExports.lazy(
1964
- () => import("./CompareDrawer-CMoCAoeq.mjs").then((m) => ({ default: m.CompareDrawer }))
2272
+ () => import("./CompareDrawer-BoxztaO7.mjs").then((m) => ({ default: m.CompareDrawer }))
1965
2273
  );
1966
2274
  const LazyReplayDialog = reactExports.lazy(
1967
- () => import("./ReplayDialog-ChXL1t8H.mjs").then((m) => ({ default: m.ReplayDialog }))
2275
+ () => import("./ReplayDialog-Cc1dyDuK.mjs").then((m) => ({ default: m.ReplayDialog }))
1968
2276
  );
1969
2277
  const LazyRequestAnatomy = reactExports.lazy(
1970
- () => import("./RequestAnatomy-DtKzIlfU.mjs").then((m) => ({ default: m.RequestAnatomy }))
2278
+ () => import("./RequestAnatomy-CMGSsz5Z.mjs").then((m) => ({ default: m.RequestAnatomy }))
1971
2279
  );
1972
2280
  const LazyResponseView = reactExports.lazy(
1973
- () => import("./ResponseView-B5I8drzc.mjs").then((m) => ({ default: m.ResponseView }))
2281
+ () => import("./ResponseView-Cp10DM1D.mjs").then((m) => ({ default: m.ResponseView }))
1974
2282
  );
1975
2283
  const LazyStreamingChunkSequence = reactExports.lazy(
1976
- () => import("./StreamingChunkSequence-DvwjQNcO.mjs").then((m) => ({
2284
+ () => import("./StreamingChunkSequence-B1VGxy3A.mjs").then((m) => ({
1977
2285
  default: m.StreamingChunkSequence
1978
2286
  }))
1979
2287
  );
1980
2288
  const LazyJsonViewer = reactExports.lazy(
1981
- () => Promise.resolve().then(() => jsonViewer).then((m) => ({ default: m.JsonViewer }))
2289
+ () => import("./json-viewer-zDE2rrmJ.mjs").then((m) => ({ default: m.JsonViewer }))
1982
2290
  );
1983
2291
  const LazyJsonViewerFromString = reactExports.lazy(
1984
- () => Promise.resolve().then(() => jsonViewer).then((m) => ({ default: m.JsonViewerFromString }))
2292
+ () => import("./json-viewer-zDE2rrmJ.mjs").then((m) => ({ default: m.JsonViewerFromString }))
1985
2293
  );
1986
2294
  const HIGHLIGHT_DURATION_MS = 1200;
1987
2295
  const MAX_HIGHLIGHT_ATTEMPTS = 12;
@@ -2405,12 +2713,35 @@ function Badge({
2405
2713
  );
2406
2714
  }
2407
2715
  const STATUS_BADGE_CLASSES = {
2408
- success: "bg-emerald-500/15 text-emerald-400 border-emerald-500/25",
2409
- client_error: "bg-amber-500/15 text-amber-400 border-amber-500/25",
2410
- server_error: "bg-rose-500/15 text-rose-400 border-rose-500/25",
2411
- pending: "bg-muted text-muted-foreground border-border"
2716
+ success: "bg-emerald-400/[0.08] text-emerald-200 border-emerald-300/25",
2717
+ client_error: "bg-amber-300/[0.10] text-amber-100 border-amber-300/30",
2718
+ server_error: "bg-rose-400/[0.10] text-rose-100 border-rose-300/30",
2719
+ pending: "bg-cyan-300/[0.08] text-cyan-100 border-cyan-300/25"
2720
+ };
2721
+ const STATUS_CUE_CLASSES = {
2722
+ success: {
2723
+ frame: "border-emerald-300/20 bg-emerald-300/[0.06] text-emerald-100",
2724
+ dot: "bg-emerald-300 shadow-[0_0_14px_rgba(110,231,183,0.8)]",
2725
+ rail: "bg-emerald-300/45 shadow-[0_0_22px_rgba(110,231,183,0.28)]"
2726
+ },
2727
+ client_error: {
2728
+ frame: "border-amber-300/25 bg-amber-300/[0.08] text-amber-100",
2729
+ dot: "bg-amber-200 shadow-[0_0_14px_rgba(252,211,77,0.8)]",
2730
+ rail: "bg-amber-300/50 shadow-[0_0_22px_rgba(252,211,77,0.28)]"
2731
+ },
2732
+ server_error: {
2733
+ frame: "border-rose-300/25 bg-rose-300/[0.08] text-rose-100",
2734
+ dot: "bg-rose-300 shadow-[0_0_14px_rgba(253,164,175,0.8)]",
2735
+ rail: "bg-rose-300/50 shadow-[0_0_22px_rgba(253,164,175,0.28)]"
2736
+ },
2737
+ pending: {
2738
+ frame: "border-cyan-300/25 bg-cyan-300/[0.08] text-cyan-100",
2739
+ dot: "bg-cyan-200 shadow-[0_0_14px_rgba(103,232,249,0.8)]",
2740
+ rail: "bg-cyan-300/50 shadow-[0_0_22px_rgba(103,232,249,0.28)]"
2741
+ }
2412
2742
  };
2413
2743
  const HEADER_ACTION_BUTTON_CLASS = "size-8 border-white/10 bg-[#0a0d11] text-muted-foreground shadow-none hover:border-cyan-300/30 hover:bg-cyan-400/10 hover:text-cyan-100";
2744
+ const TELEMETRY_CHIP_CLASS = "flex h-7 items-center gap-1 rounded-md border border-white/10 bg-black/20 px-2 text-xs shadow-[inset_0_1px_0_rgba(255,255,255,0.04)]";
2414
2745
  function formatElapsed$3(ms) {
2415
2746
  if (ms < 1e3) return `${ms}ms`;
2416
2747
  return `${(ms / 1e3).toFixed(1)}s`;
@@ -2419,6 +2750,18 @@ function formatTokenRate$1(tokensPerSecond) {
2419
2750
  if (tokensPerSecond >= 10) return `${tokensPerSecond.toFixed(0)}/s`;
2420
2751
  return `${tokensPerSecond.toFixed(1)}/s`;
2421
2752
  }
2753
+ function statusCueLabel(category, status) {
2754
+ switch (category) {
2755
+ case "success":
2756
+ return status === null ? "OK" : String(status);
2757
+ case "client_error":
2758
+ return status === null ? "WARN" : String(status);
2759
+ case "server_error":
2760
+ return status === null ? "FAIL" : String(status);
2761
+ case "pending":
2762
+ return "ROLL";
2763
+ }
2764
+ }
2422
2765
  function CacheTrendIndicator({ trend }) {
2423
2766
  if (trend === null) return null;
2424
2767
  const isUp = trend.direction === "up";
@@ -2434,6 +2777,7 @@ function CacheTrendIndicator({ trend }) {
2434
2777
  }
2435
2778
  const LogEntryHeader = reactExports.memo(function({
2436
2779
  log,
2780
+ displayNumber,
2437
2781
  messageCount = null,
2438
2782
  toolCount = null,
2439
2783
  expanded,
@@ -2456,6 +2800,8 @@ const LogEntryHeader = reactExports.memo(function({
2456
2800
  const hasClientPid = log.clientPid !== null && log.clientPid !== void 0;
2457
2801
  const hasClientProjectFolder = log.clientProjectFolder !== null && log.clientProjectFolder !== void 0 && log.clientProjectFolder !== "";
2458
2802
  const hasClientCwd = log.clientCwd !== null && log.clientCwd !== void 0 && log.clientCwd !== "";
2803
+ const statusCue = STATUS_CUE_CLASSES[statusCategory];
2804
+ const statusLabel2 = statusCueLabel(statusCategory, log.responseStatus);
2459
2805
  return /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
2460
2806
  "div",
2461
2807
  {
@@ -2465,9 +2811,9 @@ const LogEntryHeader = reactExports.memo(function({
2465
2811
  "data-nav-id": `log-${log.id}`,
2466
2812
  "data-nav-action": expanded ? "collapse" : "expand",
2467
2813
  className: cn(
2468
- "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1 px-3 py-1.5 cursor-pointer transition-colors",
2469
- expanded ? "bg-[#0c1015]" : "hover:bg-muted/30",
2470
- "select-none",
2814
+ "group/header relative isolate flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1 overflow-hidden px-3 py-2 cursor-pointer transition-[background-color,border-color,box-shadow]",
2815
+ expanded ? "bg-[linear-gradient(90deg,#0f1720_0%,#090d12_50%,#07090d_100%)] shadow-[inset_0_1px_0_rgba(255,255,255,0.06)]" : "bg-[#080b10] hover:bg-[#0b1016]",
2816
+ "select-none before:pointer-events-none before:absolute before:inset-x-0 before:top-0 before:h-px before:bg-white/10",
2471
2817
  "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:outline-none"
2472
2818
  ),
2473
2819
  onClick: onToggle,
@@ -2478,25 +2824,48 @@ const LogEntryHeader = reactExports.memo(function({
2478
2824
  }
2479
2825
  },
2480
2826
  children: [
2481
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-blue-400/80 font-mono text-xs font-semibold tabular-nums shrink-0", children: [
2482
- "#",
2483
- log.id
2484
- ] }),
2485
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1 text-muted-foreground text-xs shrink-0", children: [
2827
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
2828
+ "span",
2829
+ {
2830
+ className: cn(
2831
+ "absolute left-0 top-2 bottom-2 w-0.5 rounded-r-full transition-colors",
2832
+ statusCue.rail
2833
+ ),
2834
+ "aria-hidden": "true"
2835
+ }
2836
+ ),
2837
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: ROW_CHEVRON_SLOT_CLASS, children: expanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-4 shrink-0" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-4 shrink-0" }) }),
2838
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
2839
+ "span",
2840
+ {
2841
+ className: cn(
2842
+ "inline-flex h-8 shrink-0 items-center gap-2 rounded-md border px-2 font-mono shadow-[inset_0_1px_0_rgba(255,255,255,0.05)]",
2843
+ statusCue.frame
2844
+ ),
2845
+ children: [
2846
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn("size-1.5 rounded-full", statusCue.dot), "aria-hidden": "true" }),
2847
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xs font-semibold tabular-nums", title: `Log ID ${String(log.id)}`, children: [
2848
+ "#",
2849
+ displayNumber
2850
+ ] })
2851
+ ]
2852
+ }
2853
+ ),
2854
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex h-7 items-center gap-1 rounded-md border border-white/10 bg-black/20 px-2 text-muted-foreground text-xs shrink-0", children: [
2486
2855
  /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "size-3" }),
2487
2856
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", title: log.timestamp, children: formatTimestamp$2(log.timestamp, timeDisplayFormat) })
2488
2857
  ] }),
2489
- statusCategory !== "success" && /* @__PURE__ */ jsxRuntimeExports.jsxs(
2858
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
2490
2859
  Badge,
2491
2860
  {
2492
2861
  variant: "outline",
2493
2862
  className: cn(
2494
- "text-[10px] px-1.5 py-0 h-5 font-mono tabular-nums gap-1",
2863
+ "h-6 gap-1 rounded-md px-2 py-0 font-mono text-[10px] font-semibold uppercase tabular-nums shadow-[inset_0_1px_0_rgba(255,255,255,0.05)]",
2495
2864
  STATUS_BADGE_CLASSES[statusCategory]
2496
2865
  ),
2497
2866
  children: [
2498
- statusCategory === "server_error" ? /* @__PURE__ */ jsxRuntimeExports.jsx(OctagonAlert, { className: "size-3", "aria-label": "Server error" }) : statusCategory === "client_error" ? /* @__PURE__ */ jsxRuntimeExports.jsx(TriangleAlert, { className: "size-3", "aria-label": "Client error" }) : statusCategory === "pending" ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-3 animate-spin", "aria-label": "Pending" }) : null,
2499
- log.responseStatus
2867
+ statusCategory === "success" ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-3", "aria-label": "Success" }) : statusCategory === "server_error" ? /* @__PURE__ */ jsxRuntimeExports.jsx(OctagonAlert, { className: "size-3", "aria-label": "Server error" }) : statusCategory === "client_error" ? /* @__PURE__ */ jsxRuntimeExports.jsx(TriangleAlert, { className: "size-3", "aria-label": "Client error" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-3 animate-spin", "aria-label": "Pending" }),
2868
+ statusLabel2
2500
2869
  ]
2501
2870
  }
2502
2871
  ),
@@ -2505,7 +2874,7 @@ const LogEntryHeader = reactExports.memo(function({
2505
2874
  Badge,
2506
2875
  {
2507
2876
  variant: "outline",
2508
- className: "text-[10px] px-1.5 py-0 h-5 font-mono tabular-nums gap-1 bg-amber-500/15 text-amber-400 border-amber-500/25",
2877
+ className: "h-6 gap-1 rounded-md border-amber-300/30 bg-amber-300/[0.10] px-2 py-0 font-mono text-[10px] tabular-nums text-amber-100",
2509
2878
  children: [
2510
2879
  /* @__PURE__ */ jsxRuntimeExports.jsx(TriangleAlert, { className: "size-3", "aria-label": "Tool schema warnings" }),
2511
2880
  warningCount
@@ -2515,11 +2884,20 @@ const LogEntryHeader = reactExports.memo(function({
2515
2884
  /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: warningCount === 1 ? "1 tool schema warning" : `${warningCount} tool schema warnings` })
2516
2885
  ] }),
2517
2886
  log.elapsedMs !== null && (isSlowResponse ? /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
2518
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1 text-xs text-amber-400 shrink-0", children: [
2519
- /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "size-3" }),
2520
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", children: formatElapsed$3(log.elapsedMs) }),
2521
- /* @__PURE__ */ jsxRuntimeExports.jsx(TriangleAlert, { className: "size-3", "aria-label": "Slow response" })
2522
- ] }) }),
2887
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
2888
+ "span",
2889
+ {
2890
+ className: cn(
2891
+ TELEMETRY_CHIP_CLASS,
2892
+ "shrink-0 border-amber-300/25 text-amber-200"
2893
+ ),
2894
+ children: [
2895
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "size-3" }),
2896
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", children: formatElapsed$3(log.elapsedMs) }),
2897
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TriangleAlert, { className: "size-3", "aria-label": "Slow response" })
2898
+ ]
2899
+ }
2900
+ ) }),
2523
2901
  /* @__PURE__ */ jsxRuntimeExports.jsxs(TooltipContent, { children: [
2524
2902
  "Slow response: ",
2525
2903
  formatElapsed$3(log.elapsedMs),
@@ -2527,12 +2905,12 @@ const LogEntryHeader = reactExports.memo(function({
2527
2905
  " ",
2528
2906
  formatElapsed$3(slowResponseThresholdSeconds * 1e3)
2529
2907
  ] })
2530
- ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1 text-xs text-muted-foreground shrink-0", children: [
2908
+ ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: cn(TELEMETRY_CHIP_CLASS, "shrink-0 text-muted-foreground"), children: [
2531
2909
  /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "size-3" }),
2532
2910
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", children: formatElapsed$3(log.elapsedMs) })
2533
2911
  ] })),
2534
2912
  log.streaming && firstChunkLabel !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
2535
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1 text-xs text-cyan-400 shrink-0", children: [
2913
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: cn(TELEMETRY_CHIP_CLASS, "shrink-0 text-cyan-300"), children: [
2536
2914
  /* @__PURE__ */ jsxRuntimeExports.jsx(Radio, { className: "size-3" }),
2537
2915
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono tabular-nums", children: [
2538
2916
  "first ",
@@ -2542,13 +2920,13 @@ const LogEntryHeader = reactExports.memo(function({
2542
2920
  /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Time to first streaming chunk" })
2543
2921
  ] }),
2544
2922
  log.streaming && tokenRateLabel !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
2545
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1 text-xs text-emerald-400 shrink-0", children: [
2923
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: cn(TELEMETRY_CHIP_CLASS, "shrink-0 text-emerald-300"), children: [
2546
2924
  /* @__PURE__ */ jsxRuntimeExports.jsx(Gauge, { className: "size-3" }),
2547
2925
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", children: tokenRateLabel })
2548
2926
  ] }) }),
2549
2927
  /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Output token throughput after first chunk" })
2550
2928
  ] }),
2551
- hasTokens && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 items-center gap-1 text-xs sm:shrink-0", children: [
2929
+ hasTokens && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: cn(TELEMETRY_CHIP_CLASS, "min-w-0 sm:shrink-0"), children: [
2552
2930
  /* @__PURE__ */ jsxRuntimeExports.jsx(Zap, { className: "size-3 text-muted-foreground" }),
2553
2931
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 flex-wrap items-center gap-x-1 font-mono tabular-nums", children: [
2554
2932
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
@@ -2580,32 +2958,32 @@ const LogEntryHeader = reactExports.memo(function({
2580
2958
  )
2581
2959
  ] })
2582
2960
  ] }),
2583
- log.cacheCreationInputTokens !== null && log.cacheCreationInputTokens > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1 text-xs shrink-0", children: [
2961
+ log.cacheCreationInputTokens !== null && log.cacheCreationInputTokens > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: cn(TELEMETRY_CHIP_CLASS, "shrink-0"), children: [
2584
2962
  /* @__PURE__ */ jsxRuntimeExports.jsx(CacheTrendIndicator, { trend: cacheTrend?.creation ?? null }),
2585
2963
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono tabular-nums text-emerald-400", children: [
2586
2964
  "KV Cache +",
2587
2965
  formatTokens(log.cacheCreationInputTokens)
2588
2966
  ] })
2589
2967
  ] }),
2590
- log.cacheReadInputTokens !== null && log.cacheReadInputTokens > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1 text-xs shrink-0", children: [
2968
+ log.cacheReadInputTokens !== null && log.cacheReadInputTokens > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: cn(TELEMETRY_CHIP_CLASS, "shrink-0"), children: [
2591
2969
  /* @__PURE__ */ jsxRuntimeExports.jsx(CacheTrendIndicator, { trend: cacheTrend?.read ?? null }),
2592
2970
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono tabular-nums text-purple-400", children: [
2593
2971
  "KV Cache ~",
2594
2972
  formatTokens(log.cacheReadInputTokens)
2595
2973
  ] })
2596
2974
  ] }),
2597
- messageCount !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1 text-muted-foreground text-xs shrink-0", children: [
2975
+ messageCount !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: cn(TELEMETRY_CHIP_CLASS, "shrink-0 text-muted-foreground"), children: [
2598
2976
  /* @__PURE__ */ jsxRuntimeExports.jsx(MessageSquare, { className: "size-3" }),
2599
2977
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", children: messageCount })
2600
2978
  ] }),
2601
- toolCount !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1 text-muted-foreground text-xs shrink-0", children: [
2979
+ toolCount !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: cn(TELEMETRY_CHIP_CLASS, "shrink-0 text-muted-foreground"), children: [
2602
2980
  /* @__PURE__ */ jsxRuntimeExports.jsx(Wrench, { className: "size-3" }),
2603
2981
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", children: toolCount })
2604
2982
  ] }),
2605
2983
  log.origin !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs(
2606
2984
  "span",
2607
2985
  {
2608
- className: "hidden xl:flex items-center gap-1 text-muted-foreground text-xs shrink-0",
2986
+ className: cn(TELEMETRY_CHIP_CLASS, "hidden shrink-0 text-muted-foreground xl:flex"),
2609
2987
  title: `Origin: ${log.origin}`,
2610
2988
  children: [
2611
2989
  /* @__PURE__ */ jsxRuntimeExports.jsx(Globe, { className: "size-3" }),
@@ -2614,7 +2992,7 @@ const LogEntryHeader = reactExports.memo(function({
2614
2992
  }
2615
2993
  ),
2616
2994
  (hasClientPid || hasClientProjectFolder) && /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
2617
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "hidden xl:flex items-center gap-1 text-purple-400/80 text-xs shrink-0", children: [
2995
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: cn(TELEMETRY_CHIP_CLASS, "hidden shrink-0 text-purple-300 xl:flex"), children: [
2618
2996
  /* @__PURE__ */ jsxRuntimeExports.jsx(FileTerminal, { className: "size-3" }),
2619
2997
  hasClientProjectFolder ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", children: log.clientProjectFolder }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono tabular-nums", children: [
2620
2998
  "PID ",
@@ -2719,8 +3097,7 @@ const LogEntryHeader = reactExports.memo(function({
2719
3097
  ] })
2720
3098
  ]
2721
3099
  }
2722
- ),
2723
- expanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-4 text-muted-foreground shrink-0" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-4 text-muted-foreground shrink-0" })
3100
+ )
2724
3101
  ]
2725
3102
  }
2726
3103
  ) });
@@ -2740,365 +3117,6 @@ function CollapsibleContent({
2740
3117
  }) {
2741
3118
  return /* @__PURE__ */ jsxRuntimeExports.jsx(CollapsibleContent$1, { "data-slot": "collapsible-content", ...props });
2742
3119
  }
2743
- function classifyValue(value) {
2744
- if (value === null) return "null";
2745
- if (Array.isArray(value)) return "array";
2746
- switch (typeof value) {
2747
- case "string":
2748
- return "string";
2749
- case "number":
2750
- return "number";
2751
- case "boolean":
2752
- return "boolean";
2753
- case "object":
2754
- return "object";
2755
- case "bigint":
2756
- case "symbol":
2757
- case "undefined":
2758
- case "function":
2759
- return "object";
2760
- }
2761
- }
2762
- function isExpandable(value) {
2763
- return value !== null && (Array.isArray(value) || typeof value === "object");
2764
- }
2765
- function getEntries(value) {
2766
- if (Array.isArray(value)) {
2767
- return value.map((item, index) => [String(index), item]);
2768
- }
2769
- if (typeof value === "object" && value !== null) {
2770
- return Object.entries(value);
2771
- }
2772
- return [];
2773
- }
2774
- const STRING_TRUNCATE_LIMIT = 120;
2775
- function StringValue({ text }) {
2776
- const [expanded, setExpanded] = reactExports.useState(false);
2777
- const isLong = text.length > STRING_TRUNCATE_LIMIT;
2778
- if (!isLong) {
2779
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-emerald-400 break-all", children: [
2780
- '"',
2781
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "prose prose-sm dark:prose-invert inline max-w-none [&_p]:inline [&_p]:my-0 [&_code]:text-emerald-300 [&_a]:text-emerald-300", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Markdown, { children: text }) }),
2782
- '"'
2783
- ] });
2784
- }
2785
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-emerald-400 break-all", children: [
2786
- '"',
2787
- expanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(
2788
- "span",
2789
- {
2790
- className: "cursor-pointer prose prose-sm dark:prose-invert inline max-w-none [&_p]:inline [&_p]:my-0 [&_code]:text-emerald-300 [&_a]:text-emerald-300",
2791
- onClick: (e) => {
2792
- e.stopPropagation();
2793
- setExpanded(false);
2794
- },
2795
- onKeyDown: (e) => {
2796
- if (e.key === "Enter" || e.key === " ") {
2797
- e.stopPropagation();
2798
- setExpanded(false);
2799
- }
2800
- },
2801
- role: "button",
2802
- tabIndex: 0,
2803
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(Markdown, { children: text })
2804
- }
2805
- ) : /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { delayDuration: 300, children: [
2806
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
2807
- TooltipTrigger,
2808
- {
2809
- onClick: (e) => {
2810
- e.stopPropagation();
2811
- setExpanded(true);
2812
- },
2813
- className: "text-left cursor-pointer",
2814
- children: [
2815
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: text.slice(0, STRING_TRUNCATE_LIMIT) }),
2816
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-emerald-400/50", children: "…" })
2817
- ]
2818
- }
2819
- ),
2820
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
2821
- TooltipContent,
2822
- {
2823
- side: "bottom",
2824
- className: "max-w-md text-xs p-2 break-words whitespace-pre-wrap",
2825
- children: [
2826
- text.slice(0, 500),
2827
- text.length > 500 ? "…" : ""
2828
- ]
2829
- }
2830
- )
2831
- ] }),
2832
- '"'
2833
- ] });
2834
- }
2835
- function PrimitiveValue({ value }) {
2836
- if (value === null) {
2837
- return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-rose-400 italic", children: "null" });
2838
- }
2839
- switch (typeof value) {
2840
- case "string":
2841
- return /* @__PURE__ */ jsxRuntimeExports.jsx(StringValue, { text: value });
2842
- case "number":
2843
- return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-amber-400", children: value });
2844
- case "boolean":
2845
- return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-blue-400", children: value ? "true" : "false" });
2846
- case "object":
2847
- case "bigint":
2848
- case "symbol":
2849
- case "undefined":
2850
- case "function":
2851
- return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground", children: JSON.stringify(value) });
2852
- }
2853
- }
2854
- function CopyValueButton({ value }) {
2855
- const [copied, setCopied] = reactExports.useState(false);
2856
- function handleCopy(e) {
2857
- e.stopPropagation();
2858
- void copyTextToClipboard(JSON.stringify(value, null, 2)).then((success) => {
2859
- if (!success) return;
2860
- setCopied(true);
2861
- setTimeout(() => {
2862
- setCopied(false);
2863
- }, 2e3);
2864
- });
2865
- }
2866
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
2867
- "button",
2868
- {
2869
- type: "button",
2870
- onClick: handleCopy,
2871
- className: "inline-flex items-center gap-1 text-[10px] text-muted-foreground hover:text-foreground transition-colors",
2872
- "aria-label": copied ? "Copied JSON" : "Copy JSON",
2873
- title: "Copy JSON",
2874
- children: copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-3 text-green-500" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-3" })
2875
- }
2876
- );
2877
- }
2878
- function CopyButton({ value }) {
2879
- const [copied, setCopied] = reactExports.useState(false);
2880
- function handleCopy(e) {
2881
- e.stopPropagation();
2882
- void copyTextToClipboard(JSON.stringify(value, null, 2)).then((success) => {
2883
- if (!success) return;
2884
- setCopied(true);
2885
- setTimeout(() => {
2886
- setCopied(false);
2887
- }, 2e3);
2888
- });
2889
- }
2890
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
2891
- "button",
2892
- {
2893
- type: "button",
2894
- onClick: handleCopy,
2895
- className: "opacity-0 group-hover/row:opacity-100 hover:bg-muted p-0.5 rounded transition-opacity shrink-0",
2896
- "aria-label": copied ? "Copied JSON value" : "Copy JSON value",
2897
- title: "Copy to clipboard",
2898
- children: copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-3 text-green-500" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-3 text-muted-foreground" })
2899
- }
2900
- );
2901
- }
2902
- function ExpandCollapseButton({
2903
- onClick
2904
- }) {
2905
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
2906
- "button",
2907
- {
2908
- type: "button",
2909
- onClick,
2910
- className: "opacity-0 group-hover/row:opacity-100 hover:bg-muted p-0.5 rounded transition-opacity shrink-0",
2911
- title: "Expand all descendants",
2912
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronsDown, { className: "size-3.5 text-muted-foreground" })
2913
- }
2914
- );
2915
- }
2916
- const JsonNode = reactExports.memo(function JsonNode2({
2917
- name,
2918
- value,
2919
- level,
2920
- defaultExpandDepth,
2921
- isArrayItem,
2922
- path,
2923
- expandTargetPath,
2924
- anatomyPaths
2925
- }) {
2926
- const isAncestorOfTarget = reactExports.useMemo(() => {
2927
- if (expandTargetPath === null) return false;
2928
- if (path === "") return expandTargetPath.length > 0;
2929
- return expandTargetPath === path || expandTargetPath.startsWith(`${path}/`);
2930
- }, [expandTargetPath, path]);
2931
- const initialExpanded = level < defaultExpandDepth || isAncestorOfTarget && isExpandable(value);
2932
- const [expanded, setExpanded] = reactExports.useState(initialExpanded);
2933
- reactExports.useEffect(() => {
2934
- if (isAncestorOfTarget && isExpandable(value) && !expanded) {
2935
- setExpanded(true);
2936
- }
2937
- }, [expandTargetPath]);
2938
- const [childResetKey, setChildResetKey] = reactExports.useState(0);
2939
- const [childDepthOverride, setChildDepthOverride] = reactExports.useState(null);
2940
- const expandable = isExpandable(value);
2941
- const fullyExpanded = childDepthOverride === Number.POSITIVE_INFINITY;
2942
- const entries = reactExports.useMemo(() => getEntries(value), [value]);
2943
- const hasExpandableChild = reactExports.useMemo(
2944
- () => entries.some(([, child]) => isExpandable(child)),
2945
- [entries]
2946
- );
2947
- const dataType = classifyValue(value);
2948
- const openBracket = dataType === "array" ? "[" : "{";
2949
- const closeBracket = dataType === "array" ? "]" : "}";
2950
- const hasAnatomyPath = anatomyPaths !== null && anatomyPaths.has(path);
2951
- function expandAllDeep() {
2952
- setExpanded(true);
2953
- setChildDepthOverride(Number.POSITIVE_INFINITY);
2954
- setChildResetKey((k) => k + 1);
2955
- }
2956
- function collapseToDefault() {
2957
- setExpanded(false);
2958
- setChildDepthOverride(0);
2959
- setChildResetKey((k) => k + 1);
2960
- }
2961
- function handleRowToggle() {
2962
- if (fullyExpanded) {
2963
- collapseToDefault();
2964
- } else {
2965
- setExpanded(!expanded);
2966
- }
2967
- }
2968
- function handleExpandAll(e) {
2969
- e.stopPropagation();
2970
- expandAllDeep();
2971
- }
2972
- const effectiveChildDepth = childDepthOverride ?? defaultExpandDepth;
2973
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cn(level > 0 && "border-l border-border/50 ml-2"), children: [
2974
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
2975
- "div",
2976
- {
2977
- className: cn(
2978
- "flex items-start gap-1 py-0.5 px-1 -ml-1 rounded-sm group/row",
2979
- expandable && "cursor-pointer hover:bg-muted/50"
2980
- ),
2981
- "data-anatomy-path": hasAnatomyPath ? path : void 0,
2982
- onClick: expandable ? handleRowToggle : void 0,
2983
- onKeyDown: expandable ? (e) => {
2984
- if (e.key === "Enter" || e.key === " ") {
2985
- e.preventDefault();
2986
- handleRowToggle();
2987
- }
2988
- } : void 0,
2989
- onDoubleClick: expandable && hasExpandableChild ? () => expandAllDeep() : void 0,
2990
- role: expandable ? "button" : void 0,
2991
- tabIndex: expandable ? 0 : void 0,
2992
- children: [
2993
- expandable ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-4 h-5 flex items-center justify-center shrink-0", children: expanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-3 text-muted-foreground" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-3 text-muted-foreground" }) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-4 shrink-0" }),
2994
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn("shrink-0", isArrayItem ? "text-muted-foreground" : "text-cyan-400"), children: isArrayItem ? name : `"${name}"` }),
2995
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground shrink-0", children: expandable ? "" : ":" }),
2996
- expandable ? /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground", children: [
2997
- openBracket,
2998
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground/60 text-xs", children: [
2999
- " ",
3000
- entries.length,
3001
- " ",
3002
- entries.length === 1 ? "item" : "items",
3003
- " ",
3004
- closeBracket
3005
- ] })
3006
- ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(PrimitiveValue, { value }) }),
3007
- expandable && hasExpandableChild && !fullyExpanded && /* @__PURE__ */ jsxRuntimeExports.jsx(ExpandCollapseButton, { onClick: handleExpandAll }),
3008
- /* @__PURE__ */ jsxRuntimeExports.jsx(CopyButton, { value })
3009
- ]
3010
- }
3011
- ),
3012
- expandable && expanded && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "pl-4", children: [
3013
- entries.map(([key, childValue]) => /* @__PURE__ */ jsxRuntimeExports.jsx(
3014
- JsonNode2,
3015
- {
3016
- name: key,
3017
- value: childValue,
3018
- level: level + 1,
3019
- defaultExpandDepth: effectiveChildDepth,
3020
- isArrayItem: dataType === "array",
3021
- path: path === "" ? `/${key}` : `${path}/${key}`,
3022
- expandTargetPath,
3023
- anatomyPaths
3024
- },
3025
- key
3026
- )),
3027
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-muted-foreground py-0.5 px-1", children: closeBracket })
3028
- ] }, childResetKey)
3029
- ] });
3030
- });
3031
- function JsonViewer({
3032
- data,
3033
- defaultExpandDepth = 0,
3034
- className,
3035
- showCopy = false,
3036
- bulkDepth: controlledBulkDepth,
3037
- bulkRevision: controlledBulkRevision,
3038
- anatomyPaths = null,
3039
- expandToPath = null
3040
- }) {
3041
- const expandable = isExpandable(data);
3042
- const entries = reactExports.useMemo(() => getEntries(data), [data]);
3043
- const bulkDepth = controlledBulkDepth ?? defaultExpandDepth;
3044
- const bulkRevision = controlledBulkRevision ?? 0;
3045
- if (!expandable) {
3046
- return /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: cn("font-mono text-xs leading-relaxed", className), children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1", children: [
3047
- /* @__PURE__ */ jsxRuntimeExports.jsx(PrimitiveValue, { value: data }),
3048
- showCopy && /* @__PURE__ */ jsxRuntimeExports.jsx(CopyValueButton, { value: data })
3049
- ] }) }) });
3050
- }
3051
- const dataType = classifyValue(data);
3052
- const isArray = dataType === "array";
3053
- return /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cn("font-mono text-xs leading-relaxed", className), children: [
3054
- showCopy && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-2 flex items-center justify-end gap-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(CopyValueButton, { value: data }) }),
3055
- entries.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-md border border-white/10 bg-black/20 px-3 py-2 text-muted-foreground", children: [
3056
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-cyan-300", children: isArray ? "[]" : "{}" }),
3057
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ml-2 text-[10px] uppercase", children: "0 items" })
3058
- ] }),
3059
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: entries.map(([key, childValue]) => /* @__PURE__ */ jsxRuntimeExports.jsx(
3060
- JsonNode,
3061
- {
3062
- name: key,
3063
- value: childValue,
3064
- level: 0,
3065
- defaultExpandDepth: bulkDepth,
3066
- isArrayItem: isArray,
3067
- path: `/${key}`,
3068
- expandTargetPath: expandToPath,
3069
- anatomyPaths
3070
- },
3071
- key
3072
- )) }, bulkRevision)
3073
- ] }) });
3074
- }
3075
- const JsonViewerFromString = reactExports.memo(function JsonViewerFromString2({
3076
- text,
3077
- defaultExpandDepth = 0,
3078
- className,
3079
- bulkDepth,
3080
- bulkRevision
3081
- }) {
3082
- const parsed = reactExports.useMemo(() => parseJsonText(text), [text]);
3083
- if (parsed.kind === "json") {
3084
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
3085
- JsonViewer,
3086
- {
3087
- data: parsed.data,
3088
- defaultExpandDepth,
3089
- className,
3090
- bulkDepth,
3091
- bulkRevision
3092
- }
3093
- );
3094
- }
3095
- return /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: cn("font-mono text-xs whitespace-pre-wrap break-words", className), children: text });
3096
- });
3097
- const jsonViewer = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
3098
- __proto__: null,
3099
- JsonViewer,
3100
- JsonViewerFromString
3101
- }, Symbol.toStringTag, { value: "Module" }));
3102
3120
  function ScrollArea({
3103
3121
  className,
3104
3122
  children,
@@ -3253,10 +3271,16 @@ function ToolRow({ tool, called }) {
3253
3271
  }
3254
3272
  )
3255
3273
  ] }),
3256
- /* @__PURE__ */ jsxRuntimeExports.jsx(CollapsibleContent, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2 border-t border-white/10 bg-white/[0.02] px-2.5 py-2", children: [
3274
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CollapsibleContent, { children: open && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2 border-t border-white/10 bg-white/[0.02] px-2.5 py-2", children: [
3257
3275
  tool.description !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs leading-relaxed text-muted-foreground", children: tool.description }),
3258
3276
  /* @__PURE__ */ jsxRuntimeExports.jsx(RequiredParameters, { names: tool.requiredParameters }),
3259
- tool.schema !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(ScrollArea, { className: "max-h-64 rounded-md border border-white/10 bg-[#06080b] p-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(JsonViewer, { data: safeJsonValue(tool.schema), defaultExpandDepth: 0 }) })
3277
+ tool.schema !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(ScrollArea, { className: "max-h-64 rounded-md border border-white/10 bg-[#06080b] p-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
3278
+ reactExports.Suspense,
3279
+ {
3280
+ fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-muted-foreground", children: "Loading JSON..." }),
3281
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(LazyJsonViewer, { data: safeJsonValue(tool.schema), defaultExpandDepth: 0 })
3282
+ }
3283
+ ) })
3260
3284
  ] }) })
3261
3285
  ] }) });
3262
3286
  }
@@ -3369,26 +3393,6 @@ const RequestTools = reactExports.memo(function RequestTools2({
3369
3393
  ] })
3370
3394
  ] });
3371
3395
  });
3372
- const LOG_FOCUS_REQUEST_EVENT = "agent-inspector:focus-log";
3373
- function dispatchLogFocusRequest(request) {
3374
- window.dispatchEvent(new CustomEvent(LOG_FOCUS_REQUEST_EVENT, { detail: request }));
3375
- }
3376
- function readLogFocusRequest(event) {
3377
- if (typeof CustomEvent === "undefined" || !(event instanceof CustomEvent)) return null;
3378
- const detail = event.detail;
3379
- const logId = safeGetOwnProperty(detail, "logId");
3380
- if (typeof logId !== "number" || !Number.isInteger(logId) || logId < 0) return null;
3381
- const tab = safeGetOwnProperty(detail, "tab");
3382
- switch (tab) {
3383
- case "anatomy":
3384
- case "request":
3385
- return { logId, tab };
3386
- case void 0:
3387
- return { logId, tab: "request" };
3388
- default:
3389
- return null;
3390
- }
3391
- }
3392
3396
  function shouldShowRawRequestTab(apiFormat, viewMode, strip) {
3393
3397
  return apiFormat === "anthropic" && viewMode === "full" && strip;
3394
3398
  }
@@ -3500,10 +3504,12 @@ function parseAnthropicTool(tool) {
3500
3504
  }
3501
3505
  function parseOpenAITool(tool) {
3502
3506
  const fn = safeGetOwnProperty(tool, "function");
3503
- const name = safeGetOwnProperty(fn, "name");
3507
+ const toolType = safeGetOwnProperty(tool, "type");
3508
+ if (fn === void 0 && toolType !== "function") return null;
3509
+ const name = safeGetOwnProperty(fn, "name") ?? safeGetOwnProperty(tool, "name");
3504
3510
  if (typeof name !== "string" || name.length === 0) return null;
3505
- const description = safeGetOwnProperty(fn, "description");
3506
- const schema = safeGetOwnProperty(fn, "parameters") ?? null;
3511
+ const description = safeGetOwnProperty(fn, "description") ?? safeGetOwnProperty(tool, "description");
3512
+ const schema = safeGetOwnProperty(fn, "parameters") ?? safeGetOwnProperty(tool, "parameters") ?? null;
3507
3513
  const normalizedDescription = typeof description === "string" ? description : null;
3508
3514
  return {
3509
3515
  name,
@@ -3576,7 +3582,7 @@ const FULL_LOG_HYDRATION_TIMEOUT_MS = 15e3;
3576
3582
  const BODY_CHUNK_TIMEOUT_MS = 15e3;
3577
3583
  const BODY_CHUNK_BYTES = 256 * 1024;
3578
3584
  const CHUNKED_BODY_THRESHOLD_BYTES = 1024 * 1024;
3579
- const TAB_TRIGGER_CLASS = "h-9 flex-none rounded-none border-0 border-b-2 border-transparent bg-transparent px-3 text-xs font-semibold text-muted-foreground shadow-none hover:bg-cyan-400/[0.04] hover:text-foreground data-[state=active]:border-cyan-300 data-[state=active]:bg-transparent data-[state=active]:text-cyan-100 data-[state=active]:shadow-none";
3585
+ const TAB_TRIGGER_CLASS = "h-9 flex-none rounded-none border-0 border-b-2 border-transparent bg-transparent px-3 text-xs font-semibold text-muted-foreground shadow-none transition-colors hover:bg-cyan-400/[0.05] hover:text-foreground data-[state=active]:border-cyan-300 data-[state=active]:bg-cyan-300/[0.04] data-[state=active]:text-cyan-100 data-[state=active]:shadow-none";
3580
3586
  function createEmptyBodyPreviewState(totalBytes = null) {
3581
3587
  return {
3582
3588
  status: "idle",
@@ -3627,7 +3633,7 @@ function ExpandedPanel({
3627
3633
  "div",
3628
3634
  {
3629
3635
  className: cn(
3630
- "inspector-scrollbar mx-3 mb-3 max-h-[72vh] overflow-auto rounded-md border border-white/10 bg-[#06080b] p-3 shadow-[inset_0_1px_0_rgba(255,255,255,0.04)]",
3636
+ "inspector-scrollbar mx-3 mb-3 max-h-[72vh] overflow-auto rounded-md border border-cyan-300/10 bg-[#05070a] p-3 shadow-[0_16px_45px_rgba(0,0,0,0.24),inset_0_1px_0_rgba(255,255,255,0.05)]",
3631
3637
  className
3632
3638
  ),
3633
3639
  children
@@ -3763,6 +3769,7 @@ const HeadersDiffContent = reactExports.memo(function({
3763
3769
  });
3764
3770
  const LogEntry = reactExports.memo(function({
3765
3771
  log,
3772
+ displayNumber,
3766
3773
  viewMode = "simple",
3767
3774
  strip,
3768
3775
  slowResponseThresholdSeconds,
@@ -3786,6 +3793,7 @@ const LogEntry = reactExports.memo(function({
3786
3793
  );
3787
3794
  const requestJsonRef = reactExports.useRef(null);
3788
3795
  const logIdRef = reactExports.useRef(log.id);
3796
+ const bodyHydrationInFlightRef = reactExports.useRef(false);
3789
3797
  const displayLog = hydratedLog ?? log;
3790
3798
  const useChunkedBody = hydratedLog === null && shouldUseChunkedBodyLoading(log);
3791
3799
  const requestPreviewBody = bodyPreviewTextForView(useChunkedBody, requestPreview);
@@ -3817,10 +3825,10 @@ const LogEntry = reactExports.memo(function({
3817
3825
  requestPreviewShouldParse ? displayedRequestBody : null
3818
3826
  );
3819
3827
  const rawRequestExpansion = useJsonBulkExpansion(
3820
- requestPreviewShouldParse ? rawRequestBodyForView : null
3828
+ activeTab === "raw-request" && requestPreviewShouldParse ? rawRequestBodyForView : null
3821
3829
  );
3822
3830
  const responseExpansion = useJsonBulkExpansion(
3823
- responsePreviewShouldParse ? responseTextForView : null
3831
+ activeTab === "raw" && responsePreviewShouldParse ? responseTextForView : null
3824
3832
  );
3825
3833
  const headersText = reactExports.useMemo(
3826
3834
  () => displayLog.headers && Object.keys(displayLog.headers).length > 0 ? JSON.stringify(displayLog.headers, null, 2) : null,
@@ -3993,6 +4001,7 @@ const LogEntry = reactExports.memo(function({
3993
4001
  }, [anatomySegments, expanded]);
3994
4002
  reactExports.useEffect(() => {
3995
4003
  logIdRef.current = log.id;
4004
+ bodyHydrationInFlightRef.current = false;
3996
4005
  setHydratedLog(null);
3997
4006
  setBodyHydrationState("idle");
3998
4007
  setRequestPreview(createEmptyBodyPreviewState(log.rawRequestBodyBytes ?? null));
@@ -4001,8 +4010,9 @@ const LogEntry = reactExports.memo(function({
4001
4010
  reactExports.useEffect(() => {
4002
4011
  if (!expanded) return;
4003
4012
  if (!shouldHydrateLogBody(log)) return;
4004
- if (hydratedLog !== null || bodyHydrationState !== "idle") return;
4013
+ if (hydratedLog !== null || bodyHydrationInFlightRef.current) return;
4005
4014
  let cancelled = false;
4015
+ bodyHydrationInFlightRef.current = true;
4006
4016
  setBodyHydrationState("loading");
4007
4017
  void fetchJsonWithTimeout(
4008
4018
  `/api/logs/${String(log.id)}`,
@@ -4010,17 +4020,19 @@ const LogEntry = reactExports.memo(function({
4010
4020
  FULL_LOG_HYDRATION_TIMEOUT_MS
4011
4021
  ).then((fullLog) => {
4012
4022
  if (cancelled) return;
4023
+ bodyHydrationInFlightRef.current = false;
4013
4024
  setHydratedLog(fullLog);
4014
4025
  setBodyHydrationState("idle");
4015
4026
  }).catch(() => {
4016
4027
  if (cancelled) return;
4028
+ bodyHydrationInFlightRef.current = false;
4017
4029
  setBodyHydrationState("failed");
4018
4030
  });
4019
4031
  return () => {
4020
4032
  cancelled = true;
4033
+ bodyHydrationInFlightRef.current = false;
4021
4034
  };
4022
4035
  }, [
4023
- bodyHydrationState,
4024
4036
  expanded,
4025
4037
  hydratedLog,
4026
4038
  log.bodyContentMode,
@@ -4060,14 +4072,32 @@ const LogEntry = reactExports.memo(function({
4060
4072
  "div",
4061
4073
  {
4062
4074
  className: cn(
4063
- "mb-2 overflow-hidden rounded-md border bg-[#090a0d] transition-[background-color,border-color,box-shadow]",
4064
- expanded ? "border-cyan-300/20 shadow-[0_18px_60px_rgba(0,0,0,0.28),inset_0_1px_0_rgba(255,255,255,0.05)]" : "border-border/70 hover:border-border"
4075
+ "relative mb-2 overflow-hidden rounded-lg border bg-[#07090d] transition-[background-color,border-color,box-shadow]",
4076
+ expanded ? "border-cyan-300/25 shadow-[0_24px_80px_rgba(0,0,0,0.34),0_0_0_1px_rgba(103,232,249,0.04),inset_0_1px_0_rgba(255,255,255,0.06)]" : "border-white/10 shadow-[0_6px_24px_rgba(0,0,0,0.16)] hover:border-cyan-300/15"
4065
4077
  ),
4066
4078
  children: [
4079
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
4080
+ "div",
4081
+ {
4082
+ className: cn(
4083
+ "pointer-events-none absolute inset-y-3 left-1 w-px rounded-full",
4084
+ expanded ? "bg-cyan-300/45 shadow-[0_0_20px_rgba(103,232,249,0.28)]" : "bg-white/10"
4085
+ ),
4086
+ "aria-hidden": "true"
4087
+ }
4088
+ ),
4089
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
4090
+ "div",
4091
+ {
4092
+ className: "pointer-events-none absolute inset-x-3 top-0 h-px bg-gradient-to-r from-transparent via-white/15 to-transparent",
4093
+ "aria-hidden": "true"
4094
+ }
4095
+ ),
4067
4096
  /* @__PURE__ */ jsxRuntimeExports.jsx(
4068
4097
  LogEntryHeader,
4069
4098
  {
4070
4099
  log: displayLog,
4100
+ displayNumber,
4071
4101
  messageCount: requestAnalysis.messageCount,
4072
4102
  toolCount: requestAnalysis.toolCount,
4073
4103
  expanded,
@@ -4082,194 +4112,224 @@ const LogEntry = reactExports.memo(function({
4082
4112
  }
4083
4113
  }
4084
4114
  ),
4085
- expanded && /* @__PURE__ */ jsxRuntimeExports.jsx(
4115
+ expanded && /* @__PURE__ */ jsxRuntimeExports.jsxs(
4086
4116
  "div",
4087
4117
  {
4088
- className: "border-t border-white/10 bg-[#050607]/80 pt-2",
4118
+ className: "relative border-t border-cyan-300/10 bg-[linear-gradient(180deg,#06090d_0%,#040506_100%)] pt-2",
4089
4119
  onClick: (e) => e.stopPropagation(),
4090
4120
  onKeyDown: (e) => e.stopPropagation(),
4091
- children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tabs, { value: activeTab, onValueChange: setActiveTab, className: "gap-2", children: [
4092
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
4093
- TabsList,
4121
+ children: [
4122
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
4123
+ "div",
4094
4124
  {
4095
- variant: "line",
4096
- className: "inspector-scrollbar mx-3 h-auto w-[calc(100%-1.5rem)] justify-start overflow-x-auto rounded-none border-b border-white/10 bg-transparent p-0",
4097
- children: [
4098
- viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { className: TAB_TRIGGER_CLASS, value: "raw-headers", children: "Raw Headers" }),
4099
- viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { className: TAB_TRIGGER_CLASS, value: "headers", children: "Headers" }),
4100
- anatomySegments !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { className: TAB_TRIGGER_CLASS, value: "anatomy", children: "Context" }),
4101
- shouldShowRawRequestTab(resolvedFormat, viewMode, strip) && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { className: TAB_TRIGGER_CLASS, value: "raw-request", children: "Raw Request" }),
4102
- /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { className: TAB_TRIGGER_CLASS, value: "request", children: "Request" }),
4103
- viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { className: TAB_TRIGGER_CLASS, value: "raw", children: "Raw Response" }),
4104
- /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { className: TAB_TRIGGER_CLASS, value: "parsed", children: "Response" })
4105
- ]
4125
+ className: "pointer-events-none absolute inset-x-0 top-0 h-12 bg-gradient-to-b from-cyan-300/[0.035] to-transparent",
4126
+ "aria-hidden": "true"
4106
4127
  }
4107
4128
  ),
4108
- shouldShowRawRequestTab(resolvedFormat, viewMode, strip) && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "raw-request", children: activeTab === "raw-request" && /* @__PURE__ */ jsxRuntimeExports.jsxs(ExpandedPanel, { children: [
4109
- useChunkedBody && /* @__PURE__ */ jsxRuntimeExports.jsx(
4110
- BodyPreviewNotice,
4111
- {
4112
- label: "Request",
4113
- state: requestPreview,
4114
- expectedBytes: log.rawRequestBodyBytes ?? null,
4115
- onLoadMore: () => loadBodyChunk("request", requestPreview.offset)
4116
- }
4117
- ),
4118
- rawRequestBodyForView === null ? /* @__PURE__ */ jsxRuntimeExports.jsx(EmptyState, { children: useChunkedBody ? "Request preview is loading" : "No request body" }) : rawRequestExpansion.parsedData !== null ? /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
4119
- LazyJsonViewer,
4120
- {
4121
- data: rawRequestExpansion.parsedData,
4122
- bulkDepth: rawRequestExpansion.bulkDepth,
4123
- bulkRevision: rawRequestExpansion.bulkRevision
4124
- }
4125
- ) }) : /* @__PURE__ */ jsxRuntimeExports.jsx(RawTextBlock, { children: rawRequestBodyForView })
4126
- ] }) }),
4127
- /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "request", children: activeTab === "request" && /* @__PURE__ */ jsxRuntimeExports.jsxs(ExpandedPanel, { children: [
4128
- bodyHydrationState === "loading" && /* @__PURE__ */ jsxRuntimeExports.jsx(NoticeBlock, { tone: "loading", children: "Loading full request and response bodies..." }),
4129
- bodyHydrationState === "failed" && /* @__PURE__ */ jsxRuntimeExports.jsx(NoticeBlock, { tone: "warning", children: "Full request and response bodies could not be loaded. Compact metadata is still available." }),
4130
- useChunkedBody && /* @__PURE__ */ jsxRuntimeExports.jsx(
4131
- BodyPreviewNotice,
4129
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Tabs, { value: activeTab, onValueChange: setActiveTab, className: "gap-2", children: [
4130
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
4131
+ TabsList,
4132
4132
  {
4133
- label: "Request",
4134
- state: requestPreview,
4135
- expectedBytes: log.rawRequestBodyBytes ?? null,
4136
- onLoadMore: () => loadBodyChunk("request", requestPreview.offset)
4133
+ variant: "line",
4134
+ className: "inspector-scrollbar relative mx-3 h-auto w-[calc(100%-1.5rem)] justify-start overflow-x-auto rounded-none border-b border-cyan-300/10 bg-black/10 p-0",
4135
+ children: [
4136
+ viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { className: TAB_TRIGGER_CLASS, value: "raw-headers", children: "Raw Headers" }),
4137
+ viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { className: TAB_TRIGGER_CLASS, value: "headers", children: "Headers" }),
4138
+ anatomySegments !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { className: TAB_TRIGGER_CLASS, value: "anatomy", children: "Context" }),
4139
+ shouldShowRawRequestTab(resolvedFormat, viewMode, strip) && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { className: TAB_TRIGGER_CLASS, value: "raw-request", children: "Raw Request" }),
4140
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { className: TAB_TRIGGER_CLASS, value: "request", children: "Request" }),
4141
+ viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { className: TAB_TRIGGER_CLASS, value: "raw", children: "Raw Response" }),
4142
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { className: TAB_TRIGGER_CLASS, value: "parsed", children: "Response" })
4143
+ ]
4137
4144
  }
4138
4145
  ),
4139
- warnings.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(NoticeBlock, { tone: "warning", children: [
4140
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 font-semibold text-amber-300", children: [
4141
- /* @__PURE__ */ jsxRuntimeExports.jsx(TriangleAlert, { className: "size-3.5" }),
4142
- "Tool schema warnings"
4146
+ shouldShowRawRequestTab(resolvedFormat, viewMode, strip) && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "raw-request", children: activeTab === "raw-request" && /* @__PURE__ */ jsxRuntimeExports.jsxs(ExpandedPanel, { children: [
4147
+ useChunkedBody && /* @__PURE__ */ jsxRuntimeExports.jsx(
4148
+ BodyPreviewNotice,
4149
+ {
4150
+ label: "Request",
4151
+ state: requestPreview,
4152
+ expectedBytes: log.rawRequestBodyBytes ?? null,
4153
+ onLoadMore: () => loadBodyChunk("request", requestPreview.offset)
4154
+ }
4155
+ ),
4156
+ rawRequestBodyForView === null ? /* @__PURE__ */ jsxRuntimeExports.jsx(EmptyState, { children: useChunkedBody ? "Request preview is loading" : "No request body" }) : rawRequestExpansion.parsedData !== null ? /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
4157
+ LazyJsonViewer,
4158
+ {
4159
+ data: rawRequestExpansion.parsedData,
4160
+ bulkDepth: rawRequestExpansion.bulkDepth,
4161
+ bulkRevision: rawRequestExpansion.bulkRevision
4162
+ }
4163
+ ) }) : /* @__PURE__ */ jsxRuntimeExports.jsx(RawTextBlock, { children: rawRequestBodyForView })
4164
+ ] }) }),
4165
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "request", children: activeTab === "request" && /* @__PURE__ */ jsxRuntimeExports.jsxs(ExpandedPanel, { children: [
4166
+ bodyHydrationState === "loading" && /* @__PURE__ */ jsxRuntimeExports.jsx(NoticeBlock, { tone: "loading", children: "Loading full request and response bodies..." }),
4167
+ bodyHydrationState === "failed" && /* @__PURE__ */ jsxRuntimeExports.jsx(NoticeBlock, { tone: "warning", children: "Full request and response bodies could not be loaded. Compact metadata is still available." }),
4168
+ useChunkedBody && /* @__PURE__ */ jsxRuntimeExports.jsx(
4169
+ BodyPreviewNotice,
4170
+ {
4171
+ label: "Request",
4172
+ state: requestPreview,
4173
+ expectedBytes: log.rawRequestBodyBytes ?? null,
4174
+ onLoadMore: () => loadBodyChunk("request", requestPreview.offset)
4175
+ }
4176
+ ),
4177
+ warnings.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(NoticeBlock, { tone: "warning", children: [
4178
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 font-semibold text-amber-300", children: [
4179
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TriangleAlert, { className: "size-3.5" }),
4180
+ "Tool schema warnings"
4181
+ ] }),
4182
+ /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { className: "mt-2 space-y-1 text-muted-foreground", children: warnings.map((warning) => /* @__PURE__ */ jsxRuntimeExports.jsx("li", { children: warning }, warning)) })
4143
4183
  ] }),
4144
- /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { className: "mt-2 space-y-1 text-muted-foreground", children: warnings.map((warning) => /* @__PURE__ */ jsxRuntimeExports.jsx("li", { children: warning }, warning)) })
4145
- ] }),
4146
- /* @__PURE__ */ jsxRuntimeExports.jsx(
4147
- RequestTools,
4148
- {
4149
- summary: requestTools,
4150
- calledToolNames: responseAnalysis.toolNames ?? []
4151
- }
4152
- ),
4153
- requestDiff ? /* @__PURE__ */ jsxRuntimeExports.jsx(
4154
- RequestDiffContent,
4155
- {
4156
- rawBody: displayLog.rawRequestBody,
4157
- displayedBody: displayedRequestBody,
4158
- emptyLabel: "No transformation applied; raw and sent request bodies are identical."
4159
- }
4160
- ) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: requestJsonRef, children: displayedRequestBody === null ? /* @__PURE__ */ jsxRuntimeExports.jsx(EmptyState, { children: useChunkedBody ? "Request preview is loading" : "No request body" }) : requestExpansion.parsedData !== null ? /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
4161
- LazyJsonViewer,
4162
- {
4163
- data: requestExpansion.parsedData,
4164
- bulkDepth: requestExpansion.bulkDepth,
4165
- bulkRevision: requestExpansion.bulkRevision,
4166
- anatomyPaths,
4167
- expandToPath
4168
- }
4169
- ) }) : /* @__PURE__ */ jsxRuntimeExports.jsx(RawTextBlock, { children: displayedRequestBody }) })
4170
- ] }) }),
4171
- anatomySegments !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "anatomy", children: activeTab === "anatomy" && /* @__PURE__ */ jsxRuntimeExports.jsx(ExpandedPanel, { className: "p-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
4172
- LazyRequestAnatomy,
4173
- {
4174
- parsed: requestExpansion.parsedData,
4175
- inputTokens: displayLog.inputTokens ?? null,
4176
- model: displayLog.model,
4177
- segments: anatomySegments,
4178
- onSegmentActivate: jumpToAnatomySegment
4179
- }
4180
- ) }) }) }),
4181
- viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "headers", children: activeTab === "headers" && /* @__PURE__ */ jsxRuntimeExports.jsxs(ExpandedPanel, { children: [
4182
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex justify-end gap-2 mb-2", children: shouldShowHeadersDiffButton(
4183
- viewMode,
4184
- displayLog.rawHeaders !== void 0 && Object.keys(displayLog.rawHeaders).length > 0
4185
- ) && /* @__PURE__ */ jsxRuntimeExports.jsx(
4186
- DiffToggleButton,
4187
- {
4188
- active: headersDiff,
4189
- onClick: (e) => {
4190
- e.stopPropagation();
4191
- setHeadersDiff(!headersDiff);
4184
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
4185
+ RequestTools,
4186
+ {
4187
+ summary: requestTools,
4188
+ calledToolNames: responseAnalysis.toolNames ?? []
4192
4189
  }
4193
- }
4194
- ) }),
4195
- headersDiff ? /* @__PURE__ */ jsxRuntimeExports.jsx(
4196
- HeadersDiffContent,
4197
- {
4198
- rawHeaders: displayLog.rawHeaders,
4199
- headers: displayLog.headers,
4200
- emptyLabel: "No transformation applied; raw and processed headers are identical."
4201
- }
4202
- ) : /* @__PURE__ */ jsxRuntimeExports.jsx(HeaderRows, { headers: displayLog.headers, emptyLabel: "No headers captured" })
4203
- ] }) }),
4204
- viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "raw-headers", children: activeTab === "raw-headers" && /* @__PURE__ */ jsxRuntimeExports.jsx(ExpandedPanel, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(
4205
- HeaderRows,
4206
- {
4207
- headers: displayLog.rawHeaders,
4208
- emptyLabel: "No raw headers captured"
4209
- }
4210
- ) }) }),
4211
- /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "raw", children: activeTab === "raw" && /* @__PURE__ */ jsxRuntimeExports.jsxs(ExpandedPanel, { className: "space-y-3", children: [
4212
- useChunkedBody && /* @__PURE__ */ jsxRuntimeExports.jsx(
4213
- BodyPreviewNotice,
4214
- {
4215
- label: "Response",
4216
- state: responsePreview,
4217
- expectedBytes: log.responseTextBytes ?? null,
4218
- onLoadMore: () => loadBodyChunk("response", responsePreview.offset)
4219
- }
4220
- ),
4221
- displayLog.error !== void 0 && displayLog.error !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(NoticeBlock, { tone: "danger", title: "SSE Error", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono", children: displayLog.error }) }),
4222
- responseTextForView !== null && responsePreviewShouldParse ? /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
4223
- LazyJsonViewerFromString,
4224
- {
4225
- text: responseTextForView,
4226
- defaultExpandDepth: 0,
4227
- bulkDepth: responseExpansion.bulkDepth,
4228
- bulkRevision: responseExpansion.bulkRevision
4229
- }
4230
- ) }) : responseTextForView !== null ? /* @__PURE__ */ jsxRuntimeExports.jsx(RawTextBlock, { children: responseTextForView }) : /* @__PURE__ */ jsxRuntimeExports.jsx(EmptyState, { children: useChunkedBody ? "Response preview is loading" : "No response" }),
4231
- displayLog.streaming === true && /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
4232
- LazyStreamingChunkSequence,
4233
- {
4234
- logId: displayLog.id,
4235
- truncated: displayLog.streamingChunksPath !== null
4236
- }
4237
- ) })
4238
- ] }) }),
4239
- /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "parsed", children: activeTab === "parsed" && /* @__PURE__ */ jsxRuntimeExports.jsxs(ExpandedPanel, { children: [
4240
- useChunkedBody && /* @__PURE__ */ jsxRuntimeExports.jsx(
4241
- BodyPreviewNotice,
4190
+ ),
4191
+ requestDiff ? /* @__PURE__ */ jsxRuntimeExports.jsx(
4192
+ RequestDiffContent,
4193
+ {
4194
+ rawBody: displayLog.rawRequestBody,
4195
+ displayedBody: displayedRequestBody,
4196
+ emptyLabel: "No transformation applied; raw and sent request bodies are identical."
4197
+ }
4198
+ ) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: requestJsonRef, children: displayedRequestBody === null ? /* @__PURE__ */ jsxRuntimeExports.jsx(EmptyState, { children: useChunkedBody ? "Request preview is loading" : "No request body" }) : requestExpansion.parsedData !== null ? /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
4199
+ LazyJsonViewer,
4200
+ {
4201
+ data: requestExpansion.parsedData,
4202
+ bulkDepth: requestExpansion.bulkDepth,
4203
+ bulkRevision: requestExpansion.bulkRevision,
4204
+ anatomyPaths,
4205
+ expandToPath
4206
+ }
4207
+ ) }) : /* @__PURE__ */ jsxRuntimeExports.jsx(RawTextBlock, { children: displayedRequestBody }) })
4208
+ ] }) }),
4209
+ anatomySegments !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "anatomy", children: activeTab === "anatomy" && /* @__PURE__ */ jsxRuntimeExports.jsx(ExpandedPanel, { className: "p-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
4210
+ LazyRequestAnatomy,
4242
4211
  {
4243
- label: "Response",
4244
- state: responsePreview,
4245
- expectedBytes: log.responseTextBytes ?? null,
4246
- onLoadMore: () => loadBodyChunk("response", responsePreview.offset)
4212
+ parsed: requestExpansion.parsedData,
4213
+ inputTokens: displayLog.inputTokens ?? null,
4214
+ model: displayLog.model,
4215
+ segments: anatomySegments,
4216
+ onSegmentActivate: jumpToAnatomySegment
4247
4217
  }
4248
- ),
4249
- responsePreviewIsActive && !responsePreviewShouldParse ? /* @__PURE__ */ jsxRuntimeExports.jsx(RawTextBlock, { children: responseTextForView }) : /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
4250
- LazyResponseView,
4218
+ ) }) }) }),
4219
+ viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "headers", children: activeTab === "headers" && /* @__PURE__ */ jsxRuntimeExports.jsxs(ExpandedPanel, { children: [
4220
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex justify-end gap-2 mb-2", children: shouldShowHeadersDiffButton(
4221
+ viewMode,
4222
+ displayLog.rawHeaders !== void 0 && Object.keys(displayLog.rawHeaders).length > 0
4223
+ ) && /* @__PURE__ */ jsxRuntimeExports.jsx(
4224
+ DiffToggleButton,
4225
+ {
4226
+ active: headersDiff,
4227
+ onClick: (e) => {
4228
+ e.stopPropagation();
4229
+ setHeadersDiff(!headersDiff);
4230
+ }
4231
+ }
4232
+ ) }),
4233
+ headersDiff ? /* @__PURE__ */ jsxRuntimeExports.jsx(
4234
+ HeadersDiffContent,
4235
+ {
4236
+ rawHeaders: displayLog.rawHeaders,
4237
+ headers: displayLog.headers,
4238
+ emptyLabel: "No transformation applied; raw and processed headers are identical."
4239
+ }
4240
+ ) : /* @__PURE__ */ jsxRuntimeExports.jsx(HeaderRows, { headers: displayLog.headers, emptyLabel: "No headers captured" })
4241
+ ] }) }),
4242
+ viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "raw-headers", children: activeTab === "raw-headers" && /* @__PURE__ */ jsxRuntimeExports.jsx(ExpandedPanel, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(
4243
+ HeaderRows,
4251
4244
  {
4252
- responseText: responseTextForView,
4253
- responseStatus: displayLog.responseStatus,
4254
- streaming: displayLog.streaming,
4255
- inputTokens: displayLog.inputTokens,
4256
- outputTokens: displayLog.outputTokens,
4257
- cacheCreationInputTokens: displayLog.cacheCreationInputTokens,
4258
- cacheReadInputTokens: displayLog.cacheReadInputTokens,
4259
- apiFormat: resolvedFormat,
4260
- error: displayLog.error
4245
+ headers: displayLog.rawHeaders,
4246
+ emptyLabel: "No raw headers captured"
4261
4247
  }
4262
- ) })
4263
- ] }) })
4264
- ] })
4248
+ ) }) }),
4249
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "raw", children: activeTab === "raw" && /* @__PURE__ */ jsxRuntimeExports.jsxs(ExpandedPanel, { className: "space-y-3", children: [
4250
+ useChunkedBody && /* @__PURE__ */ jsxRuntimeExports.jsx(
4251
+ BodyPreviewNotice,
4252
+ {
4253
+ label: "Response",
4254
+ state: responsePreview,
4255
+ expectedBytes: log.responseTextBytes ?? null,
4256
+ onLoadMore: () => loadBodyChunk("response", responsePreview.offset)
4257
+ }
4258
+ ),
4259
+ displayLog.error !== void 0 && displayLog.error !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(NoticeBlock, { tone: "danger", title: "SSE Error", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono", children: displayLog.error }) }),
4260
+ responseTextForView !== null && responsePreviewShouldParse ? /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
4261
+ LazyJsonViewerFromString,
4262
+ {
4263
+ text: responseTextForView,
4264
+ defaultExpandDepth: 0,
4265
+ bulkDepth: responseExpansion.bulkDepth,
4266
+ bulkRevision: responseExpansion.bulkRevision
4267
+ }
4268
+ ) }) : responseTextForView !== null ? /* @__PURE__ */ jsxRuntimeExports.jsx(RawTextBlock, { children: responseTextForView }) : /* @__PURE__ */ jsxRuntimeExports.jsx(EmptyState, { children: useChunkedBody ? "Response preview is loading" : "No response" }),
4269
+ displayLog.streaming === true && /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
4270
+ LazyStreamingChunkSequence,
4271
+ {
4272
+ logId: displayLog.id,
4273
+ truncated: displayLog.streamingChunksPath !== null
4274
+ }
4275
+ ) })
4276
+ ] }) }),
4277
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "parsed", children: activeTab === "parsed" && /* @__PURE__ */ jsxRuntimeExports.jsxs(ExpandedPanel, { children: [
4278
+ useChunkedBody && /* @__PURE__ */ jsxRuntimeExports.jsx(
4279
+ BodyPreviewNotice,
4280
+ {
4281
+ label: "Response",
4282
+ state: responsePreview,
4283
+ expectedBytes: log.responseTextBytes ?? null,
4284
+ onLoadMore: () => loadBodyChunk("response", responsePreview.offset)
4285
+ }
4286
+ ),
4287
+ responsePreviewIsActive && !responsePreviewShouldParse ? /* @__PURE__ */ jsxRuntimeExports.jsx(RawTextBlock, { children: responseTextForView }) : /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
4288
+ LazyResponseView,
4289
+ {
4290
+ responseText: responseTextForView,
4291
+ responseStatus: displayLog.responseStatus,
4292
+ streaming: displayLog.streaming,
4293
+ inputTokens: displayLog.inputTokens,
4294
+ outputTokens: displayLog.outputTokens,
4295
+ cacheCreationInputTokens: displayLog.cacheCreationInputTokens,
4296
+ cacheReadInputTokens: displayLog.cacheReadInputTokens,
4297
+ apiFormat: resolvedFormat,
4298
+ error: displayLog.error
4299
+ }
4300
+ ) })
4301
+ ] }) })
4302
+ ] })
4303
+ ]
4265
4304
  }
4266
4305
  )
4267
4306
  ]
4268
4307
  }
4269
4308
  ),
4270
- /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntimeExports.jsx(LazyReplayDialog, { log: displayLog, open: replayOpen, onOpenChange: setReplayOpen }) })
4309
+ /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
4310
+ LazyReplayDialog,
4311
+ {
4312
+ log: displayLog,
4313
+ displayNumber,
4314
+ open: replayOpen,
4315
+ onOpenChange: setReplayOpen
4316
+ }
4317
+ ) })
4271
4318
  ] });
4272
4319
  });
4320
+ function boundaryTitle(stopReason) {
4321
+ switch (stopReason) {
4322
+ case "end_turn":
4323
+ return "End of Turn (Anthropic)";
4324
+ case "stop":
4325
+ return "End of Turn (OpenAI)";
4326
+ case "length":
4327
+ return "End of Turn (length limit)";
4328
+ case "tool_use":
4329
+ case null:
4330
+ return "End of Turn";
4331
+ }
4332
+ }
4273
4333
  function ThreadConnector({
4274
4334
  stopReason,
4275
4335
  isPending,
@@ -4280,7 +4340,7 @@ function ThreadConnector({
4280
4340
  collapsible = false,
4281
4341
  onToggle
4282
4342
  }) {
4283
- const isBoundary = stopReason === "end_turn" || stopReason === "stop";
4343
+ const isBoundary = isTurnBoundary(stopReason);
4284
4344
  const isFusedBoundary = isOnlyEntry && isTurnStart && isBoundary;
4285
4345
  const isRunning = isPending && !isBoundary;
4286
4346
  const Crab = reactExports.useMemo(() => getCrabVariant(crabIndex), [crabIndex]);
@@ -4311,23 +4371,16 @@ function ThreadConnector({
4311
4371
  "drop-shadow-[0_0_4px_rgba(128,255,0,0.5)]"
4312
4372
  )
4313
4373
  }
4314
- ) }) : isBoundary ? /* @__PURE__ */ jsxRuntimeExports.jsx(
4315
- "span",
4374
+ ) }) : isBoundary ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { title: boundaryTitle(stopReason), ...interactiveProps, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
4375
+ Crab,
4316
4376
  {
4317
- title: stopReason === "end_turn" ? "End of Turn (Anthropic)" : "End of Turn (OpenAI)",
4318
- ...interactiveProps,
4319
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(
4320
- Crab,
4321
- {
4322
- className: cn(
4323
- "size-3.5 text-amber-400",
4324
- "animate-crab-settle",
4325
- "drop-shadow-[0_0_4px_rgba(251,191,36,0.5)]"
4326
- )
4327
- }
4377
+ className: cn(
4378
+ "size-3.5 text-amber-400",
4379
+ "animate-crab-settle",
4380
+ "drop-shadow-[0_0_4px_rgba(251,191,36,0.5)]"
4328
4381
  )
4329
4382
  }
4330
- ) : isTurnStart ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { title: "Start of turn", ...interactiveProps, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
4383
+ ) }) : isTurnStart ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { title: "Start of turn", ...interactiveProps, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
4331
4384
  Crab,
4332
4385
  {
4333
4386
  className: cn(
@@ -4383,6 +4436,19 @@ function ToolTraceEvents({ events }) {
4383
4436
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mx-3 mb-2 grid gap-1.5", children: events.map((event) => /* @__PURE__ */ jsxRuntimeExports.jsx(ToolTraceEventRow, { event }, event.id)) });
4384
4437
  }
4385
4438
  const PREVIEW_LIMIT = 180;
4439
+ const toolTraceCache = /* @__PURE__ */ new WeakMap();
4440
+ function responseMayContainToolTrace(log, format) {
4441
+ const responseText = log.responseText;
4442
+ if (responseText === null) return false;
4443
+ switch (format) {
4444
+ case "anthropic":
4445
+ return responseText.includes("tool_use");
4446
+ case "openai":
4447
+ return responseText.includes("tool_calls") || responseText.includes("function_call");
4448
+ case "unknown":
4449
+ return false;
4450
+ }
4451
+ }
4386
4452
  function shouldRenderConversationContent(standalone, expanded) {
4387
4453
  return standalone || expanded;
4388
4454
  }
@@ -4393,8 +4459,10 @@ function buildTurnGroups(logs) {
4393
4459
  const groups = [];
4394
4460
  let entries = [];
4395
4461
  let turnIndex = 0;
4396
- for (const log of logs) {
4397
- entries.push({ log, stopReason: extractStopReason(log) });
4462
+ for (let index = 0; index < logs.length; index += 1) {
4463
+ const log = logs[index];
4464
+ if (log === void 0) continue;
4465
+ entries.push({ log, stopReason: extractStopReason(log), sessionLogNumber: index + 1 });
4398
4466
  const current = entries[entries.length - 1];
4399
4467
  if (current !== void 0 && isTurnBoundary(current.stopReason)) {
4400
4468
  groups.push({ entries, turnIndex });
@@ -4494,18 +4562,59 @@ function extractOpenAIToolTraceEvents(log) {
4494
4562
  });
4495
4563
  }
4496
4564
  }
4565
+ const output = safeGetOwnProperty(parsed, "output");
4566
+ if (Array.isArray(output)) {
4567
+ for (const item of output) {
4568
+ if (safeGetOwnProperty(item, "type") !== "function_call") continue;
4569
+ const name = safeGetOwnProperty(item, "name");
4570
+ if (typeof name !== "string" || name.length === 0) continue;
4571
+ const args = safeGetOwnProperty(item, "arguments");
4572
+ events.push({
4573
+ id: `${String(log.id)}-openai-tool-${String(events.length)}`,
4574
+ logId: log.id,
4575
+ index: events.length,
4576
+ provider: "openai",
4577
+ name,
4578
+ argumentsText: copyValue(args),
4579
+ argumentsPreview: previewValue(args)
4580
+ });
4581
+ }
4582
+ }
4497
4583
  return events;
4498
4584
  }
4499
4585
  function extractToolTraceEvents(log) {
4586
+ const cached = toolTraceCache.get(log);
4587
+ if (cached !== void 0 && cached.apiFormat === log.apiFormat && cached.responseText === log.responseText) {
4588
+ return cached.events;
4589
+ }
4500
4590
  const format = resolveLogFormat(log);
4591
+ if (!responseMayContainToolTrace(log, format)) {
4592
+ const events2 = [];
4593
+ toolTraceCache.set(log, {
4594
+ apiFormat: log.apiFormat,
4595
+ responseText: log.responseText,
4596
+ events: events2
4597
+ });
4598
+ return events2;
4599
+ }
4600
+ let events;
4501
4601
  switch (format) {
4502
4602
  case "anthropic":
4503
- return extractAnthropicToolTraceEvents(log);
4603
+ events = extractAnthropicToolTraceEvents(log);
4604
+ break;
4504
4605
  case "openai":
4505
- return extractOpenAIToolTraceEvents(log);
4606
+ events = extractOpenAIToolTraceEvents(log);
4607
+ break;
4506
4608
  case "unknown":
4507
- return [];
4609
+ events = [];
4610
+ break;
4508
4611
  }
4612
+ toolTraceCache.set(log, {
4613
+ apiFormat: log.apiFormat,
4614
+ responseText: log.responseText,
4615
+ events
4616
+ });
4617
+ return events;
4509
4618
  }
4510
4619
  function buildTraceSummary(logs, slowResponseThresholdSeconds, knowledgeCandidateCount = 0) {
4511
4620
  let failedCallCount = 0;
@@ -4571,7 +4680,8 @@ const TurnGroup = reactExports.memo(function TurnGroup2({
4571
4680
  onCompareWithPrevious,
4572
4681
  comparisonPredecessors,
4573
4682
  turnIndex = 0,
4574
- timeDisplayFormat
4683
+ timeDisplayFormat,
4684
+ pendingFocusRequest
4575
4685
  }) {
4576
4686
  const lastIdx = entries.length - 1;
4577
4687
  const lastStop = entries[lastIdx]?.stopReason ?? null;
@@ -4601,6 +4711,19 @@ const TurnGroup = reactExports.memo(function TurnGroup2({
4601
4711
  window.removeEventListener(LOG_FOCUS_REQUEST_EVENT, handleLogFocusRequest);
4602
4712
  };
4603
4713
  }, [collapsible, entries]);
4714
+ reactExports.useEffect(() => {
4715
+ if (pendingFocusRequest === void 0) return void 0;
4716
+ if (!entries.some((entry) => entry.log.id === pendingFocusRequest.logId)) return void 0;
4717
+ if (collapsible) setCollapsed(false);
4718
+ const timer = window.setTimeout(() => {
4719
+ dispatchLogFocusRequest({
4720
+ logId: pendingFocusRequest.logId,
4721
+ tab: pendingFocusRequest.tab,
4722
+ source: "virtualizer"
4723
+ });
4724
+ }, 0);
4725
+ return () => window.clearTimeout(timer);
4726
+ }, [collapsible, entries, pendingFocusRequest]);
4604
4727
  const toggleCollapse = reactExports.useCallback(() => {
4605
4728
  if (collapsible) setCollapsed((prev) => !prev);
4606
4729
  }, [collapsible]);
@@ -4629,17 +4752,9 @@ const TurnGroup = reactExports.memo(function TurnGroup2({
4629
4752
  maxElapsed
4630
4753
  };
4631
4754
  }, [entries, lastIdx]);
4632
- const uniqueProviders = reactExports.useMemo(() => {
4633
- const seen = /* @__PURE__ */ new Set();
4634
- for (const e of entries) {
4635
- const p = detectProvider(e.log.model);
4636
- if (p !== "unknown") seen.add(p);
4637
- }
4638
- return [...seen];
4639
- }, [entries]);
4640
4755
  const StartCrab = reactExports.useMemo(() => getCrabVariant(entries[0]?.log.id ?? 0), [entries]);
4641
4756
  const EndCrab = reactExports.useMemo(() => getCrabVariant(entries[lastIdx]?.log.id ?? 0), [entries, lastIdx]);
4642
- const bgClass = turnIndex % 2 === 0 ? "bg-muted/10" : "bg-muted/25";
4757
+ const bgClass = turnIndex % 2 === 0 ? "bg-[#070a0f]" : "bg-[#090d12]";
4643
4758
  const aggregateIsSlow = aggregate.maxElapsed !== null && slowResponseThresholdSeconds > 0 && aggregate.maxElapsed > slowResponseThresholdSeconds * 1e3;
4644
4759
  const toolEventsByLogId = reactExports.useMemo(() => {
4645
4760
  const events = /* @__PURE__ */ new Map();
@@ -4667,17 +4782,25 @@ const TurnGroup = reactExports.memo(function TurnGroup2({
4667
4782
  }, []);
4668
4783
  const firstLogId = entries[0]?.log.id ?? turnIndex;
4669
4784
  const turnLabel = `Turn ${String(turnIndex + 1)}`;
4785
+ const containmentStyle = reactExports.useMemo(
4786
+ () => ({
4787
+ contentVisibility: "auto",
4788
+ containIntrinsicSize: collapsed ? "48px" : "160px"
4789
+ }),
4790
+ [collapsed]
4791
+ );
4670
4792
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
4671
4793
  "div",
4672
4794
  {
4673
4795
  ref: containerRef,
4796
+ style: containmentStyle,
4674
4797
  tabIndex: collapsed ? void 0 : 0,
4675
4798
  role: collapsed ? void 0 : "group",
4676
4799
  "aria-label": collapsed ? void 0 : turnLabel,
4677
4800
  "data-nav-id": collapsed ? void 0 : `turn-${String(firstLogId)}`,
4678
4801
  className: cn(
4679
- "border rounded-lg",
4680
- isPending ? "border-amber-500/10" : "border-transparent",
4802
+ "border rounded-lg transition-[border-color,box-shadow]",
4803
+ isPending ? "border-amber-300/15 shadow-[0_0_0_1px_rgba(252,211,77,0.04)]" : "border-transparent",
4681
4804
  !collapsed && "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:outline-none"
4682
4805
  ),
4683
4806
  children: collapsed ? (
@@ -4763,22 +4886,31 @@ const TurnGroup = reactExports.memo(function TurnGroup2({
4763
4886
  "div",
4764
4887
  {
4765
4888
  className: cn(
4766
- "flex-1 min-w-0 mb-0.5 rounded-lg border border-border py-1 px-3 flex items-center gap-3 text-xs",
4889
+ "flex-1 min-w-0 mb-0.5 rounded-lg border border-cyan-300/10 py-1.5 px-3 flex items-center gap-3 text-xs shadow-[inset_0_1px_0_rgba(255,255,255,0.04)]",
4767
4890
  bgClass
4768
4891
  ),
4769
4892
  children: [
4770
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-blue-400/80 font-mono font-semibold tabular-nums shrink-0", children: [
4771
- "#",
4772
- entries[0]?.log.id ?? "?",
4773
- " ~ #",
4774
- entries[lastIdx]?.log.id ?? "?"
4775
- ] }),
4893
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: ROW_CHEVRON_SLOT_CLASS, children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-4 shrink-0" }) }),
4894
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
4895
+ "span",
4896
+ {
4897
+ className: "text-blue-400/80 font-mono font-semibold tabular-nums shrink-0",
4898
+ title: `Log IDs ${String(entries[0]?.log.id ?? "?")} ~ ${String(
4899
+ entries[lastIdx]?.log.id ?? "?"
4900
+ )}`,
4901
+ children: [
4902
+ "#",
4903
+ entries[0]?.sessionLogNumber ?? "?",
4904
+ " ~ #",
4905
+ entries[lastIdx]?.sessionLogNumber ?? "?"
4906
+ ]
4907
+ }
4908
+ ),
4776
4909
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground shrink-0", children: [
4777
4910
  entries.length,
4778
4911
  " request",
4779
4912
  entries.length > 1 ? "s" : ""
4780
4913
  ] }),
4781
- uniqueProviders.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex items-center gap-0.5 shrink-0", children: uniqueProviders.map((p) => /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderLogo, { provider: p, className: "size-4" }, p)) }),
4782
4914
  aggregate.maxElapsed !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
4783
4915
  /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
4784
4916
  "span",
@@ -4812,8 +4944,7 @@ const TurnGroup = reactExports.memo(function TurnGroup2({
4812
4944
  ] })
4813
4945
  ] })
4814
4946
  ] }),
4815
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1 min-w-0" }),
4816
- /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-4 text-muted-foreground shrink-0" })
4947
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1 min-w-0" })
4817
4948
  ]
4818
4949
  }
4819
4950
  )
@@ -4845,6 +4976,7 @@ const TurnGroup = reactExports.memo(function TurnGroup2({
4845
4976
  LogEntry,
4846
4977
  {
4847
4978
  log,
4979
+ displayNumber: entry.sessionLogNumber,
4848
4980
  viewMode,
4849
4981
  strip,
4850
4982
  slowResponseThresholdSeconds,
@@ -4861,6 +4993,103 @@ const TurnGroup = reactExports.memo(function TurnGroup2({
4861
4993
  }
4862
4994
  );
4863
4995
  });
4996
+ const VIRTUALIZE_TURN_THRESHOLD = 24;
4997
+ const ESTIMATED_TURN_HEIGHT = 132;
4998
+ const VIRTUAL_OVERSCAN$1 = 8;
4999
+ function shouldVirtualizeTurnGroups(turnCount) {
5000
+ return turnCount > VIRTUALIZE_TURN_THRESHOLD;
5001
+ }
5002
+ function buildLogTurnIndex(turnGroups) {
5003
+ const result = /* @__PURE__ */ new Map();
5004
+ for (let index = 0; index < turnGroups.length; index++) {
5005
+ const group = turnGroups[index];
5006
+ if (group === void 0) continue;
5007
+ for (const entry of group.entries) {
5008
+ result.set(entry.log.id, index);
5009
+ }
5010
+ }
5011
+ return result;
5012
+ }
5013
+ function renderTurnGroup(turnGroup, props, pendingFocusRequest) {
5014
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
5015
+ TurnGroup,
5016
+ {
5017
+ entries: turnGroup.entries,
5018
+ viewMode: props.viewMode,
5019
+ strip: props.strip,
5020
+ slowResponseThresholdSeconds: props.slowResponseThresholdSeconds,
5021
+ timeDisplayFormat: props.timeDisplayFormat,
5022
+ cacheTrends: props.cacheTrends,
5023
+ onCompareWithPrevious: props.onCompareWithPrevious,
5024
+ comparisonPredecessors: props.comparisonPredecessors,
5025
+ turnIndex: turnGroup.turnIndex,
5026
+ pendingFocusRequest
5027
+ },
5028
+ turnGroup.turnIndex
5029
+ );
5030
+ }
5031
+ function TurnGroupList(props) {
5032
+ if (!shouldVirtualizeTurnGroups(props.turnGroups.length)) {
5033
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: props.turnGroups.map((turnGroup) => renderTurnGroup(turnGroup, props)) });
5034
+ }
5035
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(VirtualizedTurnGroupList, { ...props });
5036
+ }
5037
+ function VirtualizedTurnGroupList(props) {
5038
+ const { turnGroups } = props;
5039
+ const [pendingFocusRequest, setPendingFocusRequest] = reactExports.useState(
5040
+ null
5041
+ );
5042
+ const virtualizer = useWindowVirtualizer({
5043
+ count: turnGroups.length,
5044
+ estimateSize: () => ESTIMATED_TURN_HEIGHT,
5045
+ overscan: VIRTUAL_OVERSCAN$1,
5046
+ getItemKey: (index) => turnGroups[index]?.turnIndex ?? index
5047
+ });
5048
+ const turnIndexByLogId = reactExports.useMemo(() => buildLogTurnIndex(turnGroups), [turnGroups]);
5049
+ reactExports.useEffect(() => {
5050
+ const handleLogFocusRequest = (event) => {
5051
+ const request = readLogFocusRequest(event);
5052
+ if (request === null) return;
5053
+ if (request.source === "virtualizer") return;
5054
+ const turnIndex = turnIndexByLogId.get(request.logId);
5055
+ if (turnIndex === void 0) return;
5056
+ virtualizer.scrollToIndex(turnIndex, { align: "center" });
5057
+ setPendingFocusRequest((previous) => ({
5058
+ ...request,
5059
+ turnIndex,
5060
+ nonce: previous === null ? 1 : previous.nonce + 1
5061
+ }));
5062
+ };
5063
+ window.addEventListener(LOG_FOCUS_REQUEST_EVENT, handleLogFocusRequest);
5064
+ return () => {
5065
+ window.removeEventListener(LOG_FOCUS_REQUEST_EVENT, handleLogFocusRequest);
5066
+ };
5067
+ }, [turnIndexByLogId, virtualizer]);
5068
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
5069
+ "div",
5070
+ {
5071
+ className: "relative w-full",
5072
+ style: { height: `${virtualizer.getTotalSize()}px` },
5073
+ "data-virtualized-turn-list": "true",
5074
+ children: virtualizer.getVirtualItems().map((virtualItem) => {
5075
+ const turnGroup = turnGroups[virtualItem.index];
5076
+ if (turnGroup === void 0) return null;
5077
+ const itemFocusRequest = pendingFocusRequest !== null && pendingFocusRequest.turnIndex === virtualItem.index ? pendingFocusRequest : void 0;
5078
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
5079
+ "div",
5080
+ {
5081
+ "data-index": virtualItem.index,
5082
+ ref: virtualizer.measureElement,
5083
+ className: "absolute left-0 top-0 w-full",
5084
+ style: { transform: `translateY(${virtualItem.start}px)` },
5085
+ children: renderTurnGroup(turnGroup, props, itemFocusRequest)
5086
+ },
5087
+ virtualItem.key
5088
+ );
5089
+ })
5090
+ }
5091
+ );
5092
+ }
4864
5093
  const CandidateResponseSchema = object({
4865
5094
  candidates: array(KnowledgeCandidateSchema)
4866
5095
  });
@@ -4926,6 +5155,18 @@ function firstToolLog(logs) {
4926
5155
  }
4927
5156
  return null;
4928
5157
  }
5158
+ function buildDisplayNumberByLogId$1(logs) {
5159
+ const result = /* @__PURE__ */ new Map();
5160
+ for (let index = 0; index < logs.length; index += 1) {
5161
+ const log = logs[index];
5162
+ if (log === void 0) continue;
5163
+ result.set(log.id, index + 1);
5164
+ }
5165
+ return result;
5166
+ }
5167
+ function displayLogNumber(logId, displayNumberByLogId) {
5168
+ return String(displayNumberByLogId.get(logId) ?? logId);
5169
+ }
4929
5170
  function buildTraceInsights(input) {
4930
5171
  const insights = [
4931
5172
  {
@@ -4940,7 +5181,7 @@ function buildTraceInsights(input) {
4940
5181
  insights.push({
4941
5182
  kind: "tool",
4942
5183
  title: `${String(input.summary.toolCallCount)} tool call${input.summary.toolCallCount === 1 ? "" : "s"}`,
4943
- detail: `First tool evidence at #${String(toolLog.id)}`,
5184
+ detail: `First tool evidence at #${displayLogNumber(toolLog.id, input.displayNumberByLogId)}`,
4944
5185
  logId: toolLog.id
4945
5186
  });
4946
5187
  }
@@ -4949,7 +5190,7 @@ function buildTraceInsights(input) {
4949
5190
  insights.push({
4950
5191
  kind: "failure",
4951
5192
  title: `Failure #${String(failure.responseStatus)}`,
4952
- detail: `First failed request is #${String(failure.id)}`,
5193
+ detail: `First failed request is #${displayLogNumber(failure.id, input.displayNumberByLogId)}`,
4953
5194
  logId: failure.id
4954
5195
  });
4955
5196
  }
@@ -4958,7 +5199,7 @@ function buildTraceInsights(input) {
4958
5199
  insights.push({
4959
5200
  kind: "slow",
4960
5201
  title: `Slowest ${formatElapsed$1(input.summary.maxElapsedMs)}`,
4961
- detail: `Max latency observed at #${String(slowest.id)}`,
5202
+ detail: `Max latency observed at #${displayLogNumber(slowest.id, input.displayNumberByLogId)}`,
4962
5203
  logId: slowest.id
4963
5204
  });
4964
5205
  }
@@ -5046,12 +5287,13 @@ function previewText(value, maxLength) {
5046
5287
  if (normalized.length <= maxLength) return normalized;
5047
5288
  return `${normalized.slice(0, maxLength - 3)}...`;
5048
5289
  }
5049
- function logRangeLabel(logIds) {
5290
+ function logRangeLabel(logIds, displayNumberByLogId) {
5050
5291
  const first = logIds[0];
5051
5292
  const last = logIds[logIds.length - 1];
5052
5293
  if (first === void 0) return "No evidence logs";
5053
- if (last === void 0 || first === last) return `#${String(first)}`;
5054
- return `#${String(first)}-#${String(last)}`;
5294
+ const firstLabel = displayLogNumber(first, displayNumberByLogId);
5295
+ if (last === void 0 || first === last) return `#${firstLabel}`;
5296
+ return `#${firstLabel}-#${displayLogNumber(last, displayNumberByLogId)}`;
5055
5297
  }
5056
5298
  function tagsToText(tags) {
5057
5299
  return tags.join(", ");
@@ -5064,7 +5306,8 @@ function CandidateItem({
5064
5306
  isPromoting,
5065
5307
  isUpdating,
5066
5308
  onPromoteCandidate,
5067
- onUpdateCandidate
5309
+ onUpdateCandidate,
5310
+ displayNumberByLogId
5068
5311
  }) {
5069
5312
  const [editing, setEditing] = reactExports.useState(false);
5070
5313
  const [draftType, setDraftType] = reactExports.useState(candidate.type);
@@ -5233,7 +5476,7 @@ function CandidateItem({
5233
5476
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 text-[10px] text-muted-foreground", children: [
5234
5477
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1", children: [
5235
5478
  /* @__PURE__ */ jsxRuntimeExports.jsx(FileSearch, { className: "size-3" }),
5236
- logRangeLabel(candidate.logIds)
5479
+ logRangeLabel(candidate.logIds, displayNumberByLogId)
5237
5480
  ] }),
5238
5481
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1", children: [
5239
5482
  /* @__PURE__ */ jsxRuntimeExports.jsx(ShieldCheck, { className: "size-3" }),
@@ -5249,23 +5492,27 @@ function CandidateItem({
5249
5492
  ] })
5250
5493
  ] }),
5251
5494
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-1 flex flex-wrap items-center gap-1.5", children: [
5252
- candidate.logIds.map((logId) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
5253
- "a",
5254
- {
5255
- href: `#${getLogAnchor(logId)}`,
5256
- onClick: (event) => {
5257
- event.preventDefault();
5258
- jumpToLog(logId);
5495
+ candidate.logIds.map((logId) => {
5496
+ const displayNumber = displayLogNumber(logId, displayNumberByLogId);
5497
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
5498
+ "a",
5499
+ {
5500
+ href: `#${getLogAnchor(logId)}`,
5501
+ onClick: (event) => {
5502
+ event.preventDefault();
5503
+ jumpToLog(logId);
5504
+ },
5505
+ className: "rounded border border-blue-400/25 px-1.5 py-0.5 font-mono text-[10px] text-blue-400 underline-offset-2 transition-colors hover:bg-blue-400/10 hover:text-blue-300 hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
5506
+ "aria-label": `Jump to evidence log ${displayNumber}`,
5507
+ title: `Log ID ${String(logId)}`,
5508
+ children: [
5509
+ "#",
5510
+ displayNumber
5511
+ ]
5259
5512
  },
5260
- className: "rounded border border-blue-400/25 px-1.5 py-0.5 font-mono text-[10px] text-blue-400 underline-offset-2 transition-colors hover:bg-blue-400/10 hover:text-blue-300 hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
5261
- "aria-label": `Jump to evidence log ${String(logId)}`,
5262
- children: [
5263
- "#",
5264
- logId
5265
- ]
5266
- },
5267
- logId
5268
- )),
5513
+ logId
5514
+ );
5515
+ }),
5269
5516
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1" }),
5270
5517
  canEdit && /* @__PURE__ */ jsxRuntimeExports.jsxs(
5271
5518
  Button,
@@ -5305,7 +5552,8 @@ function CandidateList({
5305
5552
  promotingCandidateIds,
5306
5553
  updatingCandidateIds,
5307
5554
  onPromoteCandidate,
5308
- onUpdateCandidate
5555
+ onUpdateCandidate,
5556
+ displayNumberByLogId
5309
5557
  }) {
5310
5558
  if (candidates.length === 0) return null;
5311
5559
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 grid gap-1.5", children: candidates.map((candidate) => /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -5315,7 +5563,8 @@ function CandidateList({
5315
5563
  isPromoting: promotingCandidateIds.has(candidate.id),
5316
5564
  isUpdating: updatingCandidateIds.has(candidate.id),
5317
5565
  onPromoteCandidate,
5318
- onUpdateCandidate
5566
+ onUpdateCandidate,
5567
+ displayNumberByLogId
5319
5568
  },
5320
5569
  candidate.id
5321
5570
  )) });
@@ -5344,9 +5593,10 @@ function AgentTraceSummary({
5344
5593
  () => buildTraceSummary(logs, slowResponseThresholdSeconds, candidates.length),
5345
5594
  [candidates.length, logs, slowResponseThresholdSeconds]
5346
5595
  );
5596
+ const displayNumberByLogId = reactExports.useMemo(() => buildDisplayNumberByLogId$1(logs), [logs]);
5347
5597
  const traceInsights = reactExports.useMemo(
5348
- () => buildTraceInsights({ logs, scopeId, summary, candidates }),
5349
- [candidates, logs, scopeId, summary]
5598
+ () => buildTraceInsights({ logs, scopeId, summary, candidates, displayNumberByLogId }),
5599
+ [candidates, displayNumberByLogId, logs, scopeId, summary]
5350
5600
  );
5351
5601
  const showElapsedSummary = showRollupMetrics || summary.maxElapsedMs !== null;
5352
5602
  const timeRange = reactExports.useMemo(
@@ -5574,7 +5824,8 @@ function AgentTraceSummary({
5574
5824
  promotingCandidateIds,
5575
5825
  updatingCandidateIds,
5576
5826
  onPromoteCandidate: promoteCandidate,
5577
- onUpdateCandidate: updateCandidate
5827
+ onUpdateCandidate: updateCandidate,
5828
+ displayNumberByLogId
5578
5829
  }
5579
5830
  )
5580
5831
  ] });
@@ -5703,21 +5954,19 @@ const ConversationGroup = reactExports.memo(function({
5703
5954
  timeDisplayFormat
5704
5955
  }
5705
5956
  ),
5706
- turnGroups.map((tg) => /* @__PURE__ */ jsxRuntimeExports.jsx(
5707
- TurnGroup,
5957
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
5958
+ TurnGroupList,
5708
5959
  {
5709
- entries: tg.entries,
5960
+ turnGroups,
5710
5961
  viewMode,
5711
5962
  strip,
5712
5963
  slowResponseThresholdSeconds,
5713
5964
  timeDisplayFormat,
5714
5965
  cacheTrends,
5715
5966
  onCompareWithPrevious,
5716
- comparisonPredecessors,
5717
- turnIndex: tg.turnIndex
5718
- },
5719
- tg.turnIndex
5720
- ))
5967
+ comparisonPredecessors
5968
+ }
5969
+ )
5721
5970
  ] })
5722
5971
  ] });
5723
5972
  });
@@ -7342,28 +7591,31 @@ function LatestLogsPreview({ logs }) {
7342
7591
  }
7343
7592
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "overflow-hidden rounded-md border border-border", children: [
7344
7593
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "border-b border-border bg-muted/30 px-3 py-2 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: "Latest logs" }),
7345
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "divide-y divide-border", children: visibleLogs.map((log) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
7346
- "div",
7347
- {
7348
- className: "grid gap-2 px-3 py-2 text-xs sm:grid-cols-[72px_1fr_88px_88px]",
7349
- children: [
7350
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono text-muted-foreground", children: [
7351
- "#",
7352
- log.id
7353
- ] }),
7354
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "min-w-0 truncate", children: [
7355
- displayText(log.model),
7356
- " · ",
7357
- log.apiFormat,
7358
- " · ",
7359
- log.path
7360
- ] }),
7361
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-muted-foreground", children: formatMs(log.firstChunkMs) }),
7362
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-muted-foreground", children: formatMs(log.latencyMs) })
7363
- ]
7364
- },
7365
- log.id
7366
- )) })
7594
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "divide-y divide-border", children: visibleLogs.map((log) => {
7595
+ const displayNumber = log.sessionLogNumber ?? log.id;
7596
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
7597
+ "div",
7598
+ {
7599
+ className: "grid gap-2 px-3 py-2 text-xs sm:grid-cols-[72px_1fr_88px_88px]",
7600
+ children: [
7601
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono text-muted-foreground", title: `Log ID ${String(log.id)}`, children: [
7602
+ "#",
7603
+ displayNumber
7604
+ ] }),
7605
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "min-w-0 truncate", children: [
7606
+ displayText(log.model),
7607
+ " · ",
7608
+ log.apiFormat,
7609
+ " · ",
7610
+ log.path
7611
+ ] }),
7612
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-muted-foreground", children: formatMs(log.firstChunkMs) }),
7613
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-muted-foreground", children: formatMs(log.latencyMs) })
7614
+ ]
7615
+ },
7616
+ log.id
7617
+ );
7618
+ }) })
7367
7619
  ] });
7368
7620
  }
7369
7621
  function MemberMetadata({ entries }) {
@@ -7449,6 +7701,7 @@ const ExternalProviderSchema = object({
7449
7701
  format: _enum(["anthropic", "openai"]),
7450
7702
  anthropicBaseUrl: string(),
7451
7703
  openaiBaseUrl: string(),
7704
+ openaiResponsesBaseUrl: string().optional().default(""),
7452
7705
  models: array(string()),
7453
7706
  sourceTool: _enum(["claude-code", "opencode", "mimo-code"]),
7454
7707
  alreadyExists: boolean()
@@ -7545,6 +7798,7 @@ function ImportWizardDialog({
7545
7798
  format: p.format,
7546
7799
  anthropicBaseUrl: p.anthropicBaseUrl,
7547
7800
  openaiBaseUrl: p.openaiBaseUrl,
7801
+ openaiResponsesBaseUrl: p.openaiResponsesBaseUrl,
7548
7802
  models: p.models,
7549
7803
  createdAt: now,
7550
7804
  updatedAt: now
@@ -7624,7 +7878,7 @@ function ImportWizardDialog({
7624
7878
  p.models.slice(0, 4).join(", "),
7625
7879
  p.models.length > 4 ? ` +${p.models.length - 4} more` : ""
7626
7880
  ] }),
7627
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-muted-foreground mt-0.5 truncate", children: p.format === "anthropic" ? p.anthropicBaseUrl : p.openaiBaseUrl }),
7881
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-muted-foreground mt-0.5 truncate", children: p.format === "anthropic" ? p.anthropicBaseUrl : p.openaiResponsesBaseUrl !== "" ? p.openaiResponsesBaseUrl : p.openaiBaseUrl }),
7628
7882
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-muted-foreground mt-0.5 font-mono", children: p.apiKey.length > 8 ? `${p.apiKey.slice(0, 4)}••••${p.apiKey.slice(-4)}` : "••••" })
7629
7883
  ] })
7630
7884
  ]
@@ -8069,12 +8323,17 @@ function ProviderCard({
8069
8323
  ] }),
8070
8324
  provider.openaiBaseUrl !== void 0 && provider.openaiBaseUrl !== "" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-col gap-2", children: [
8071
8325
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 text-xs text-muted-foreground", children: [
8072
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium", children: "OpenAI:" }),
8326
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium", children: "OpenAI Chat:" }),
8073
8327
  " ",
8074
8328
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate", children: provider.openaiBaseUrl })
8075
8329
  ] }),
8076
8330
  testResults !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: testResults.openai })
8077
8331
  ] }),
8332
+ provider.openaiResponsesBaseUrl !== void 0 && provider.openaiResponsesBaseUrl !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex min-w-0 flex-col gap-2", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 text-xs text-muted-foreground", children: [
8333
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium", children: "OpenAI Responses:" }),
8334
+ " ",
8335
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate", children: provider.openaiResponsesBaseUrl })
8336
+ ] }) }),
8078
8337
  testResults?.testedAt !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-xs text-muted-foreground flex items-center gap-1", children: [
8079
8338
  /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "size-3" }),
8080
8339
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
@@ -8166,12 +8425,17 @@ const ZHIPU_CODING_PROVIDER_KEYWORDS = [
8166
8425
  "z.ai coding",
8167
8426
  "zai coding"
8168
8427
  ];
8428
+ const ANTHROPIC_MESSAGES_ENDPOINT = "/v1/messages";
8429
+ const OPENAI_CHAT_COMPLETIONS_ENDPOINT = "/v1/chat/completions";
8430
+ const OPENAI_RESPONSES_ENDPOINT = "/v1/responses";
8169
8431
  const KNOWN_PROVIDER_PRESETS = {
8170
8432
  deepseek: {
8171
8433
  openaiBaseUrl: "https://api.deepseek.com"
8172
8434
  },
8173
8435
  minimax: {
8174
8436
  anthropicBaseUrl: "https://api.minimaxi.com/anthropic",
8437
+ openaiBaseUrl: "https://api.minimaxi.com",
8438
+ openaiResponsesBaseUrl: "https://api.minimaxi.com",
8175
8439
  apiDocsUrl: "https://platform.minimaxi.com/docs/api-reference/api-overview"
8176
8440
  },
8177
8441
  "zhipu coding": {
@@ -8345,6 +8609,27 @@ function readPositiveIntegerInput(value) {
8345
8609
  if (!Number.isInteger(parsed) || parsed <= 0) return null;
8346
8610
  return parsed;
8347
8611
  }
8612
+ function stripEndpointSuffix(value, endpoint) {
8613
+ if (value === void 0) return "";
8614
+ const trimmed = value.trim();
8615
+ const normalized = trimmed.replace(/\/+$/, "");
8616
+ return normalized.endsWith(endpoint) ? normalized.slice(0, -endpoint.length).replace(/\/+$/, "") : trimmed;
8617
+ }
8618
+ function previewEndpointUrl(baseUrl, endpoint) {
8619
+ const trimmed = baseUrl.trim();
8620
+ return trimmed === "" ? null : buildUpstreamUrl(trimmed, endpoint);
8621
+ }
8622
+ function EndpointUrlPreview({
8623
+ baseUrl,
8624
+ endpoint
8625
+ }) {
8626
+ const finalUrl = previewEndpointUrl(baseUrl, endpoint);
8627
+ if (finalUrl === null) return null;
8628
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-md border border-border/70 bg-muted/35 px-3 py-2 text-xs", children: [
8629
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-muted-foreground", children: "Final URL" }),
8630
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "break-all font-mono text-foreground", children: finalUrl })
8631
+ ] });
8632
+ }
8348
8633
  function ProviderForm({ provider, onSubmit, onCancel }) {
8349
8634
  const [name, setName] = reactExports.useState(provider?.name ?? "");
8350
8635
  const [apiKey, setApiKey] = reactExports.useState(provider?.apiKey ?? "");
@@ -8361,8 +8646,15 @@ function ProviderForm({ provider, onSubmit, onCancel }) {
8361
8646
  )
8362
8647
  );
8363
8648
  const [activeTab, setActiveTab] = reactExports.useState("anthropic");
8364
- const [anthropicBaseUrl, setAnthropicBaseUrl] = reactExports.useState(provider?.anthropicBaseUrl ?? "");
8365
- const [openaiBaseUrl, setOpenaiBaseUrl] = reactExports.useState(provider?.openaiBaseUrl ?? "");
8649
+ const [anthropicBaseUrl, setAnthropicBaseUrl] = reactExports.useState(
8650
+ stripEndpointSuffix(provider?.anthropicBaseUrl, ANTHROPIC_MESSAGES_ENDPOINT)
8651
+ );
8652
+ const [openaiBaseUrl, setOpenaiBaseUrl] = reactExports.useState(
8653
+ stripEndpointSuffix(provider?.openaiBaseUrl, OPENAI_CHAT_COMPLETIONS_ENDPOINT)
8654
+ );
8655
+ const [openaiResponsesBaseUrl, setOpenaiResponsesBaseUrl] = reactExports.useState(
8656
+ stripEndpointSuffix(provider?.openaiResponsesBaseUrl, OPENAI_RESPONSES_ENDPOINT)
8657
+ );
8366
8658
  const [apiDocsUrl, setApiDocsUrl] = reactExports.useState(provider?.apiDocsUrl ?? "");
8367
8659
  const [modelMetadataUrl, setModelMetadataUrl] = reactExports.useState(provider?.modelMetadataUrl ?? "");
8368
8660
  const [source, setSource] = reactExports.useState(provider?.source);
@@ -8385,6 +8677,7 @@ function ProviderForm({ provider, onSubmit, onCancel }) {
8385
8677
  }, [openModelDropdown]);
8386
8678
  const [manualAnthropicUrlOverride, setManualAnthropicUrlOverride] = reactExports.useState(false);
8387
8679
  const [manualOpenaiUrlOverride, setManualOpenaiUrlOverride] = reactExports.useState(false);
8680
+ const [manualOpenaiResponsesUrlOverride, setManualOpenaiResponsesUrlOverride] = reactExports.useState(false);
8388
8681
  const isMiniMax = name.toLowerCase().includes("minimax");
8389
8682
  const isAlibaba = name.toLowerCase().includes("alibaba");
8390
8683
  const isZhipu = [...ZHIPU_PROVIDER_KEYWORDS, ...ZHIPU_CODING_PROVIDER_KEYWORDS].some(
@@ -8406,13 +8699,21 @@ function ProviderForm({ provider, onSubmit, onCancel }) {
8406
8699
  const nextModels = (provider.models?.length ?? 0) > 0 ? provider.models : [""];
8407
8700
  setModels(nextModels);
8408
8701
  setModelMetadataDrafts(createMetadataDrafts(provider, nextModels));
8409
- setAnthropicBaseUrl(provider.anthropicBaseUrl ?? "");
8410
- setOpenaiBaseUrl(provider.openaiBaseUrl ?? "");
8702
+ setAnthropicBaseUrl(
8703
+ stripEndpointSuffix(provider.anthropicBaseUrl, ANTHROPIC_MESSAGES_ENDPOINT)
8704
+ );
8705
+ setOpenaiBaseUrl(
8706
+ stripEndpointSuffix(provider.openaiBaseUrl, OPENAI_CHAT_COMPLETIONS_ENDPOINT)
8707
+ );
8708
+ setOpenaiResponsesBaseUrl(
8709
+ stripEndpointSuffix(provider.openaiResponsesBaseUrl, OPENAI_RESPONSES_ENDPOINT)
8710
+ );
8411
8711
  setApiDocsUrl(provider.apiDocsUrl ?? "");
8412
8712
  setModelMetadataUrl(provider.modelMetadataUrl ?? "");
8413
8713
  setSource(provider.source);
8414
8714
  setManualAnthropicUrlOverride(false);
8415
8715
  setManualOpenaiUrlOverride(false);
8716
+ setManualOpenaiResponsesUrlOverride(false);
8416
8717
  }
8417
8718
  }, [provider]);
8418
8719
  reactExports.useEffect(() => {
@@ -8425,6 +8726,9 @@ function ProviderForm({ provider, onSubmit, onCancel }) {
8425
8726
  if (preset.openaiBaseUrl !== void 0 && !manualOpenaiUrlOverride) {
8426
8727
  setOpenaiBaseUrl(preset.openaiBaseUrl);
8427
8728
  }
8729
+ if (preset.openaiResponsesBaseUrl !== void 0 && !manualOpenaiResponsesUrlOverride) {
8730
+ setOpenaiResponsesBaseUrl(preset.openaiResponsesBaseUrl);
8731
+ }
8428
8732
  if (preset.apiDocsUrl !== void 0 && !apiDocsUrl) {
8429
8733
  setApiDocsUrl(preset.apiDocsUrl);
8430
8734
  }
@@ -8458,6 +8762,9 @@ function ProviderForm({ provider, onSubmit, onCancel }) {
8458
8762
  if (openaiBaseUrl.trim() && !isValidUrl(openaiBaseUrl.trim())) {
8459
8763
  newErrors.openaiBaseUrl = "Invalid URL format";
8460
8764
  }
8765
+ if (openaiResponsesBaseUrl.trim() && !isValidUrl(openaiResponsesBaseUrl.trim())) {
8766
+ newErrors.openaiResponsesBaseUrl = "Invalid URL format";
8767
+ }
8461
8768
  if (modelMetadataUrl.trim() && !isValidUrl(modelMetadataUrl.trim())) {
8462
8769
  newErrors.modelMetadataUrl = "Invalid URL format";
8463
8770
  }
@@ -8474,7 +8781,7 @@ function ProviderForm({ provider, onSubmit, onCancel }) {
8474
8781
  newErrors[`modelMetadata.${index}.outputLimit`] = "Output limit should not exceed context window";
8475
8782
  }
8476
8783
  });
8477
- if (!anthropicBaseUrl.trim() && !openaiBaseUrl.trim()) {
8784
+ if (!anthropicBaseUrl.trim() && !openaiBaseUrl.trim() && !openaiResponsesBaseUrl.trim()) {
8478
8785
  newErrors.format = "At least one format URL (Anthropic or OpenAI) is required";
8479
8786
  }
8480
8787
  setErrors(newErrors);
@@ -8590,6 +8897,7 @@ function ProviderForm({ provider, onSubmit, onCancel }) {
8590
8897
  models: models.map((m) => m.trim()).filter((m) => m !== ""),
8591
8898
  anthropicBaseUrl: anthropicBaseUrl.trim() || void 0,
8592
8899
  openaiBaseUrl: openaiBaseUrl.trim() || void 0,
8900
+ openaiResponsesBaseUrl: openaiResponsesBaseUrl.trim() || void 0,
8593
8901
  apiDocsUrl: apiDocsUrl.trim() || void 0,
8594
8902
  modelMetadataUrl: modelMetadataUrl.trim() || void 0,
8595
8903
  modelMetadata: buildModelMetadata(),
@@ -8902,41 +9210,86 @@ function ProviderForm({ provider, onSubmit, onCancel }) {
8902
9210
  ] }),
8903
9211
  activeTab === "anthropic" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
8904
9212
  /* @__PURE__ */ jsxRuntimeExports.jsx("label", { htmlFor: "provider-anthropic-base-url", className: "text-sm font-medium", children: "Anthropic Base URL" }),
8905
- /* @__PURE__ */ jsxRuntimeExports.jsx(
8906
- "input",
8907
- {
8908
- id: "provider-anthropic-base-url",
8909
- type: "text",
8910
- value: anthropicBaseUrl,
8911
- onChange: (e) => {
8912
- setManualAnthropicUrlOverride(true);
8913
- setAnthropicBaseUrl(e.target.value);
8914
- },
8915
- placeholder: "https://api.anthropic.com",
8916
- className: "w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:border-ring focus-visible:outline-ring focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50"
8917
- }
8918
- ),
9213
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 overflow-hidden rounded-md border border-input bg-background ring-offset-background focus-within:border-ring focus-within:outline-ring focus-within:ring-[3px]", children: [
9214
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
9215
+ "input",
9216
+ {
9217
+ id: "provider-anthropic-base-url",
9218
+ type: "text",
9219
+ value: anthropicBaseUrl,
9220
+ onChange: (e) => {
9221
+ setManualAnthropicUrlOverride(true);
9222
+ setAnthropicBaseUrl(e.target.value);
9223
+ },
9224
+ placeholder: "https://api.anthropic.com",
9225
+ className: "min-w-0 flex-1 bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50"
9226
+ }
9227
+ ),
9228
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0 select-none border-l bg-muted px-3 py-2 font-mono text-xs text-muted-foreground", children: ANTHROPIC_MESSAGES_ENDPOINT })
9229
+ ] }),
8919
9230
  errors.anthropicBaseUrl !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-destructive", children: errors.anthropicBaseUrl }),
8920
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: "Anthropic-compatible endpoint URL. Leave empty if this provider does not support Anthropic format." })
9231
+ /* @__PURE__ */ jsxRuntimeExports.jsx(EndpointUrlPreview, { baseUrl: anthropicBaseUrl, endpoint: ANTHROPIC_MESSAGES_ENDPOINT }),
9232
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: "Anthropic-compatible base URL. Leave empty if this provider does not support Anthropic format." })
8921
9233
  ] }),
8922
- activeTab === "openai" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
8923
- /* @__PURE__ */ jsxRuntimeExports.jsx("label", { htmlFor: "provider-openai-base-url", className: "text-sm font-medium", children: "OpenAI Base URL" }),
8924
- /* @__PURE__ */ jsxRuntimeExports.jsx(
8925
- "input",
8926
- {
8927
- id: "provider-openai-base-url",
8928
- type: "text",
8929
- value: openaiBaseUrl,
8930
- onChange: (e) => {
8931
- setManualOpenaiUrlOverride(true);
8932
- setOpenaiBaseUrl(e.target.value);
8933
- },
8934
- placeholder: "https://api.openai.com/v1",
8935
- className: "w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:border-ring focus-visible:outline-ring focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50"
8936
- }
8937
- ),
8938
- errors.openaiBaseUrl !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-destructive", children: errors.openaiBaseUrl }),
8939
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: "OpenAI-compatible endpoint URL. Leave empty if this provider does not support OpenAI format." })
9234
+ activeTab === "openai" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
9235
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
9236
+ /* @__PURE__ */ jsxRuntimeExports.jsx("label", { htmlFor: "provider-openai-base-url", className: "text-sm font-medium", children: "OpenAI Chat Base URL" }),
9237
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 overflow-hidden rounded-md border border-input bg-background ring-offset-background focus-within:border-ring focus-within:outline-ring focus-within:ring-[3px]", children: [
9238
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
9239
+ "input",
9240
+ {
9241
+ id: "provider-openai-base-url",
9242
+ type: "text",
9243
+ value: openaiBaseUrl,
9244
+ onChange: (e) => {
9245
+ setManualOpenaiUrlOverride(true);
9246
+ setOpenaiBaseUrl(e.target.value);
9247
+ },
9248
+ placeholder: "https://api.openai.com",
9249
+ className: "min-w-0 flex-1 bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50"
9250
+ }
9251
+ ),
9252
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0 select-none border-l bg-muted px-3 py-2 font-mono text-xs text-muted-foreground", children: OPENAI_CHAT_COMPLETIONS_ENDPOINT })
9253
+ ] }),
9254
+ errors.openaiBaseUrl !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-destructive", children: errors.openaiBaseUrl }),
9255
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
9256
+ EndpointUrlPreview,
9257
+ {
9258
+ baseUrl: openaiBaseUrl,
9259
+ endpoint: OPENAI_CHAT_COMPLETIONS_ENDPOINT
9260
+ }
9261
+ ),
9262
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: "OpenAI Chat Completions-compatible base URL. Leave empty if this provider only supports the Responses API." })
9263
+ ] }),
9264
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
9265
+ /* @__PURE__ */ jsxRuntimeExports.jsx("label", { htmlFor: "provider-openai-responses-base-url", className: "text-sm font-medium", children: "OpenAI Responses Base URL" }),
9266
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 overflow-hidden rounded-md border border-input bg-background ring-offset-background focus-within:border-ring focus-within:outline-ring focus-within:ring-[3px]", children: [
9267
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
9268
+ "input",
9269
+ {
9270
+ id: "provider-openai-responses-base-url",
9271
+ type: "text",
9272
+ value: openaiResponsesBaseUrl,
9273
+ onChange: (e) => {
9274
+ setManualOpenaiResponsesUrlOverride(true);
9275
+ setOpenaiResponsesBaseUrl(e.target.value);
9276
+ },
9277
+ placeholder: "https://api.openai.com",
9278
+ className: "min-w-0 flex-1 bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50"
9279
+ }
9280
+ ),
9281
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0 select-none border-l bg-muted px-3 py-2 font-mono text-xs text-muted-foreground", children: OPENAI_RESPONSES_ENDPOINT })
9282
+ ] }),
9283
+ errors.openaiResponsesBaseUrl !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-destructive", children: errors.openaiResponsesBaseUrl }),
9284
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
9285
+ EndpointUrlPreview,
9286
+ {
9287
+ baseUrl: openaiResponsesBaseUrl,
9288
+ endpoint: OPENAI_RESPONSES_ENDPOINT
9289
+ }
9290
+ ),
9291
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: "Optional Responses-compatible base URL. Set only when the provider supports the Responses API." })
9292
+ ] })
8940
9293
  ] }),
8941
9294
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
8942
9295
  /* @__PURE__ */ jsxRuntimeExports.jsx("label", { htmlFor: "provider-api-docs-url", className: "text-sm font-medium", children: "API Docs URL" }),
@@ -8983,6 +9336,7 @@ function createProviderPayload(data) {
8983
9336
  models: data.models,
8984
9337
  anthropicBaseUrl: (data.anthropicBaseUrl?.length ?? 0) > 0 ? data.anthropicBaseUrl : void 0,
8985
9338
  openaiBaseUrl: (data.openaiBaseUrl?.length ?? 0) > 0 ? data.openaiBaseUrl : void 0,
9339
+ openaiResponsesBaseUrl: (data.openaiResponsesBaseUrl?.length ?? 0) > 0 ? data.openaiResponsesBaseUrl : void 0,
8986
9340
  apiDocsUrl: (data.apiDocsUrl?.length ?? 0) > 0 ? data.apiDocsUrl : void 0,
8987
9341
  modelMetadataUrl: (data.modelMetadataUrl?.length ?? 0) > 0 ? data.modelMetadataUrl : void 0,
8988
9342
  modelMetadata: data.modelMetadata,
@@ -9272,7 +9626,7 @@ function ProvidersPanel({
9272
9626
  await refreshProviderMetadata(updated.id, data.modelMetadataUrl, false);
9273
9627
  }
9274
9628
  refreshProviders();
9275
- const criticalFieldsChanged = (data.apiKey ?? "") !== (editingProvider.apiKey ?? "") || JSON.stringify(data.models) !== JSON.stringify(editingProvider.models) || (data.anthropicBaseUrl ?? "") !== (editingProvider.anthropicBaseUrl ?? "") || (data.openaiBaseUrl ?? "") !== (editingProvider.openaiBaseUrl ?? "");
9629
+ const criticalFieldsChanged = (data.apiKey ?? "") !== (editingProvider.apiKey ?? "") || JSON.stringify(data.models) !== JSON.stringify(editingProvider.models) || (data.anthropicBaseUrl ?? "") !== (editingProvider.anthropicBaseUrl ?? "") || (data.openaiBaseUrl ?? "") !== (editingProvider.openaiBaseUrl ?? "") || (data.openaiResponsesBaseUrl ?? "") !== (editingProvider.openaiResponsesBaseUrl ?? "");
9276
9630
  if (criticalFieldsChanged) {
9277
9631
  await runTest(updated.id);
9278
9632
  }
@@ -11259,6 +11613,13 @@ const CONTEXT_USAGE_THRESHOLDS = {
11259
11613
  watch: WATCH_USAGE_PERCENT,
11260
11614
  danger: DANGER_USAGE_PERCENT
11261
11615
  };
11616
+ const snapshotCache = /* @__PURE__ */ new WeakMap();
11617
+ function providerSignature(providers) {
11618
+ return providers.map((provider) => {
11619
+ const metadata = provider.modelMetadata?.map((entry) => `${entry.model}:${String(entry.contextWindow ?? "")}`).join(",") ?? "";
11620
+ return `${provider.id}:${provider.updatedAt}:${provider.models.join(",")}:${metadata}`;
11621
+ }).join("|");
11622
+ }
11262
11623
  function parseRequestBody(rawBody) {
11263
11624
  if (rawBody === null) return null;
11264
11625
  try {
@@ -11308,6 +11669,25 @@ function snapshotFromLog(log, providers) {
11308
11669
  roleTotalTokens: roleSegments.reduce((sum, segment2) => sum + segment2.size, 0)
11309
11670
  };
11310
11671
  }
11672
+ function cachedSnapshotFromLog(log, providers, providersSignature) {
11673
+ const cached = snapshotCache.get(log);
11674
+ if (cached !== void 0 && cached.id === log.id && cached.rawRequestBody === log.rawRequestBody && cached.inputTokens === log.inputTokens && cached.model === log.model && cached.path === log.path && cached.apiFormat === log.apiFormat && cached.timestamp === log.timestamp && cached.providersSignature === providersSignature) {
11675
+ return cached.snapshot;
11676
+ }
11677
+ const snapshot = snapshotFromLog(log, providers);
11678
+ snapshotCache.set(log, {
11679
+ id: log.id,
11680
+ rawRequestBody: log.rawRequestBody,
11681
+ inputTokens: log.inputTokens,
11682
+ model: log.model,
11683
+ path: log.path,
11684
+ apiFormat: log.apiFormat,
11685
+ timestamp: log.timestamp,
11686
+ providersSignature,
11687
+ snapshot
11688
+ });
11689
+ return snapshot;
11690
+ }
11311
11691
  function isHigherPeak(candidate, current) {
11312
11692
  if (candidate.usagePercent !== null && current.usagePercent !== null) {
11313
11693
  return candidate.usagePercent > current.usagePercent;
@@ -11341,11 +11721,21 @@ function trendPercent(first, latest) {
11341
11721
  if (first.usagePercent === null || latest.usagePercent === null) return null;
11342
11722
  return (latest.usagePercent - first.usagePercent) * 100;
11343
11723
  }
11724
+ function logsInAscendingIdOrder(logs) {
11725
+ for (let index = 1; index < logs.length; index++) {
11726
+ const previous = logs[index - 1];
11727
+ const current = logs[index];
11728
+ if (previous === void 0 || current === void 0) continue;
11729
+ if (previous.id > current.id) return [...logs].sort((left, right) => left.id - right.id);
11730
+ }
11731
+ return logs;
11732
+ }
11344
11733
  function buildSessionContextSummary(logs, providers = []) {
11345
- const sortedLogs = [...logs].sort((left, right) => left.id - right.id);
11734
+ const sortedLogs = logsInAscendingIdOrder(logs);
11735
+ const providersSignature = providerSignature(providers);
11346
11736
  const byModel = /* @__PURE__ */ new Map();
11347
11737
  for (const log of sortedLogs) {
11348
- const snapshot = snapshotFromLog(log, providers);
11738
+ const snapshot = cachedSnapshotFromLog(log, providers, providersSignature);
11349
11739
  if (snapshot === null) continue;
11350
11740
  const existing = byModel.get(snapshot.model);
11351
11741
  if (existing === void 0) {
@@ -11380,6 +11770,20 @@ function truncateSessionId(id) {
11380
11770
  if (id.length <= 30) return id;
11381
11771
  return `${id.slice(0, 12)}...${id.slice(-12)}`;
11382
11772
  }
11773
+ function buildDisplayNumberByLogId(groups) {
11774
+ const result = /* @__PURE__ */ new Map();
11775
+ for (const group of groups) {
11776
+ for (let index = 0; index < group.logs.length; index += 1) {
11777
+ const log = group.logs[index];
11778
+ if (log === void 0) continue;
11779
+ result.set(log.id, index + 1);
11780
+ }
11781
+ }
11782
+ return result;
11783
+ }
11784
+ function displayNumberForLog(log, displayNumberByLogId) {
11785
+ return displayNumberByLogId.get(log.id) ?? log.id;
11786
+ }
11383
11787
  function shouldShowRawExport(captureMode) {
11384
11788
  return captureMode === "full";
11385
11789
  }
@@ -12429,6 +12833,7 @@ function ProxyViewer({
12429
12833
  setComparePair(null);
12430
12834
  }, []);
12431
12835
  const groups = reactExports.useMemo(() => groupLogsByConversation(logs), [logs]);
12836
+ const displayNumberByLogId = reactExports.useMemo(() => buildDisplayNumberByLogId(groups), [groups]);
12432
12837
  const sessionContextScope = reactExports.useMemo(
12433
12838
  () => resolveSessionContextScope({ pinnedSessionId, selectedSession, sessions, logs }),
12434
12839
  [logs, pinnedSessionId, selectedSession, sessions]
@@ -12667,7 +13072,16 @@ function ProxyViewer({
12667
13072
  ] })
12668
13073
  ] })
12669
13074
  ] }),
12670
- comparePair !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntimeExports.jsx(LazyCompareDrawer, { left: comparePair[0], right: comparePair[1], onClose: closeCompare }) })
13075
+ comparePair !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
13076
+ LazyCompareDrawer,
13077
+ {
13078
+ left: comparePair[0],
13079
+ right: comparePair[1],
13080
+ leftDisplayNumber: displayNumberForLog(comparePair[0], displayNumberByLogId),
13081
+ rightDisplayNumber: displayNumberForLog(comparePair[1], displayNumberByLogId),
13082
+ onClose: closeCompare
13083
+ }
13084
+ ) })
12671
13085
  ] });
12672
13086
  }
12673
13087
  const SSEUpdateSchema = union([
@@ -12730,7 +13144,7 @@ function filterLogs(logs, selectedSession, selectedModel) {
12730
13144
  return true;
12731
13145
  });
12732
13146
  }
12733
- const DEBOUNCE_MS = 50;
13147
+ const DEBOUNCE_MS = 100;
12734
13148
  const HASH_SCROLL_ATTEMPTS = 12;
12735
13149
  const HASH_HIGHLIGHT_MS = 1800;
12736
13150
  const MAX_CLIENT_LOGS = 500;
@@ -12787,6 +13201,7 @@ function ProxyViewerContainer({
12787
13201
  const [logPage, setLogPage] = reactExports.useState(null);
12788
13202
  const [sessionPageLoading, setSessionPageLoading] = reactExports.useState(initialSessionId !== void 0);
12789
13203
  const [sessionMemberships, setSessionMemberships] = reactExports.useState([]);
13204
+ const [, startLogTransition] = reactExports.useTransition();
12790
13205
  const eventSourceRef = reactExports.useRef(null);
12791
13206
  const reconnectTimeoutRef = reactExports.useRef(null);
12792
13207
  const handledHashRef = reactExports.useRef(null);
@@ -12805,22 +13220,28 @@ function ProxyViewerContainer({
12805
13220
  const updates = pendingUpdatesRef.current;
12806
13221
  pendingUpdatesRef.current = [];
12807
13222
  if (updates.length === 0) return;
12808
- setAllLogs((prev) => {
12809
- let next = prev;
12810
- for (const log of updates) {
12811
- const idx = logIndexRef.current.get(log.id);
12812
- if (idx !== void 0) {
12813
- next = [...next.slice(0, idx), log, ...next.slice(idx + 1)];
12814
- } else {
12815
- logIndexRef.current.set(log.id, next.length);
12816
- next = [...next, log];
13223
+ startLogTransition(() => {
13224
+ setAllLogs((prev) => {
13225
+ const next = [...prev];
13226
+ for (const log of updates) {
13227
+ const indexedPosition = logIndexRef.current.get(log.id);
13228
+ if (indexedPosition !== void 0 && next[indexedPosition]?.id === log.id) {
13229
+ next[indexedPosition] = log;
13230
+ continue;
13231
+ }
13232
+ const existingPosition = next.findIndex((entry) => entry.id === log.id);
13233
+ if (existingPosition >= 0) {
13234
+ next[existingPosition] = log;
13235
+ continue;
13236
+ }
13237
+ next.push(log);
12817
13238
  }
12818
- }
12819
- next = trimClientLogs(next);
12820
- logIndexRef.current = buildLogIndex(next);
12821
- return next;
13239
+ const trimmed = trimClientLogs(next);
13240
+ logIndexRef.current = buildLogIndex(trimmed);
13241
+ return trimmed;
13242
+ });
12822
13243
  });
12823
- }, []);
13244
+ }, [startLogTransition]);
12824
13245
  const scheduleUpdate = reactExports.useCallback(
12825
13246
  (log) => {
12826
13247
  pendingUpdatesRef.current.push(log);
@@ -13142,9 +13563,10 @@ export {
13142
13563
  Badge as B,
13143
13564
  CONTEXT_USAGE_THRESHOLDS as C,
13144
13565
  Dialog as D,
13145
- JsonViewer as E,
13566
+ LazyJsonViewer as E,
13146
13567
  safeJsonValue as F,
13147
- JsonViewerFromString as J,
13568
+ parseJsonText as G,
13569
+ LazyJsonViewerFromString as L,
13148
13570
  ProxyViewerContainer as P,
13149
13571
  ROLE_COLOR_CLASSES as R,
13150
13572
  SegmentBar as S,