@tonyclaw/agent-inspector 2.0.6 → 2.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/CompareDrawer-Djb4XFZS.js +1 -0
  3. package/.output/public/assets/ProxyViewerContainer-CWdkPZsJ.js +114 -0
  4. package/.output/public/assets/ReplayDialog-DBPMIs2I.js +1 -0
  5. package/.output/public/assets/RequestAnatomy-FBfRNQN7.js +1 -0
  6. package/.output/public/assets/ResponseView-Db4pJL7U.js +1 -0
  7. package/.output/public/assets/StreamingChunkSequence-BH175O6R.js +1 -0
  8. package/.output/public/assets/_sessionId-3ipVoQtW.js +1 -0
  9. package/.output/public/assets/index-Bo1dGS4R.css +1 -0
  10. package/.output/public/assets/index-CJgaCJo8.js +1 -0
  11. package/.output/public/assets/{main-CKnTJ4-O.js → main-CwhqfJqM.js} +8 -8
  12. package/.output/server/_libs/lucide-react.mjs +170 -108
  13. package/.output/server/_libs/radix-ui__react-collapsible.mjs +2 -2
  14. package/.output/server/{_sessionId-B-x9fRY3.mjs → _sessionId-DzBy9gLa.mjs} +58 -5
  15. package/.output/server/_ssr/{CompareDrawer-BQVNsAY2.mjs → CompareDrawer-C5NBvE2e.mjs} +9 -8
  16. package/.output/server/_ssr/{ProxyViewerContainer-CYm2Dw19.mjs → ProxyViewerContainer-DiZjOTQT.mjs} +857 -32
  17. package/.output/server/_ssr/{ReplayDialog-CaMQBc79.mjs → ReplayDialog-EpvTwFvp.mjs} +7 -8
  18. package/.output/server/_ssr/{RequestAnatomy--P5arRH2.mjs → RequestAnatomy-DaQjhixp.mjs} +512 -7
  19. package/.output/server/_ssr/{ResponseView-RtFwNvgD.mjs → ResponseView-D8tGHCGY.mjs} +5 -74
  20. package/.output/server/_ssr/{StreamingChunkSequence-B5HPkzab.mjs → StreamingChunkSequence-DGQnb1QE.mjs} +8 -7
  21. package/.output/server/_ssr/{index-CZIKZU43.mjs → index-N25hqa7t.mjs} +58 -5
  22. package/.output/server/_ssr/index.mjs +2 -2
  23. package/.output/server/_ssr/{router-DGPt3MUc.mjs → router-Bf0m6F0G.mjs} +22 -6
  24. package/.output/server/{_tanstack-start-manifest_v-BzH4pNaI.mjs → _tanstack-start-manifest_v-DlAyJ5DB.mjs} +1 -1
  25. package/.output/server/index.mjs +61 -68
  26. package/package.json +1 -1
  27. package/src/components/proxy-viewer/LogEntry.tsx +17 -2
  28. package/src/components/proxy-viewer/RequestToolsPanel.tsx +292 -0
  29. package/src/components/proxy-viewer/anatomy/RequestAnatomy.tsx +197 -1
  30. package/src/components/proxy-viewer/anatomy/contextIntelligence.ts +414 -0
  31. package/src/components/proxy-viewer/requestTools.ts +213 -0
  32. package/src/routes/__root.tsx +27 -0
  33. package/.output/public/assets/CompareDrawer-DDmqSAfl.js +0 -1
  34. package/.output/public/assets/ProxyViewerContainer-Cxpdziwd.js +0 -101
  35. package/.output/public/assets/ReplayDialog-Bt5DGzlh.js +0 -1
  36. package/.output/public/assets/RequestAnatomy-BxX3_N9S.js +0 -1
  37. package/.output/public/assets/ResponseView-Bl_5S9gZ.js +0 -1
  38. package/.output/public/assets/StreamingChunkSequence-RJMwNf6F.js +0 -1
  39. package/.output/public/assets/_sessionId-b4isaoDp.js +0 -1
  40. package/.output/public/assets/index-BZ4x5UI6.js +0 -1
  41. package/.output/public/assets/index-C624DUk9.css +0 -1
  42. package/.output/public/assets/json-viewer-CRL_gWEZ.js +0 -14
  43. package/.output/server/_ssr/json-viewer-d4obyRaA.mjs +0 -515
@@ -1,5 +1,5 @@
1
1
  import { r as reactExports, j as jsxRuntimeExports, a as React } from "../_libs/react.mjs";
2
- import { C as CapturedLogSchema, D as DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS, a as DEFAULT_TIME_DISPLAY_FORMAT, b as RuntimeConfigSchema, r as requestFormatForPath, e as createPendingProviderTestResults, P as ProviderTestResultsSchema, f as createFailedProviderTestResults, M as MAX_SLOW_RESPONSE_THRESHOLD_SECONDS, T as TimeDisplayFormatSchema, g as getSessionPath, h as ProviderConfigSchema, K as KnowledgeCandidateSchema, s as stripClaudeCodeBillingHeader, d as safeGetOwnProperty, p as parseOpenAIResponse, O as OpenAIRequestSchema, A as AnthropicResponseSchema$1, c as AnthropicRequestSchema } from "./router-DGPt3MUc.mjs";
2
+ import { C as CapturedLogSchema, D as DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS, a as DEFAULT_TIME_DISPLAY_FORMAT, b as RuntimeConfigSchema, r as requestFormatForPath, e as createPendingProviderTestResults, P as ProviderTestResultsSchema, f as createFailedProviderTestResults, M as MAX_SLOW_RESPONSE_THRESHOLD_SECONDS, T as TimeDisplayFormatSchema, g as getSessionPath, h as ProviderConfigSchema, K as KnowledgeCandidateSchema, d as stripClaudeCodeBillingHeader, s as safeGetOwnProperty, p as parseOpenAIResponse, O as OpenAIRequestSchema, A as AnthropicResponseSchema$1, c as AnthropicRequestSchema } from "./router-Bf0m6F0G.mjs";
3
3
  import { u as useSWR, a as useSWRConfig } from "../_libs/swr.mjs";
4
4
  import { J as JSZip } from "../_libs/jszip.mjs";
5
5
  import { c as clsx } from "../_libs/clsx.mjs";
@@ -9,11 +9,14 @@ import { R as Root, T as Trigger$2, C as Content, a as Close, b as Title, P as P
9
9
  import { d as diffJson, a as diffLines } from "../_libs/diff.mjs";
10
10
  import { u as useVirtualizer } from "../_libs/tanstack__react-virtual.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 { C as Check, X, P as Plus, D as Download, S as Settings, A as ArrowLeft, a as Copy, b as ChevronDown, U as Upload, c as Scan, d as CircleAlert, T as Terminal, e as ChevronUp, L as LoaderCircle, f as ChevronRight, g as User, h as Clock, M as MessageSquare, Z as Zap, E as ExternalLink, i as Trash2, W as Wrench, j as TriangleAlert, B as Brain, k as EyeOff, l as Eye, R as RotateCw, m as Pencil, n as Minus, o as CircleCheckBig, p as CircleX, q as ShieldCheck, r as RefreshCw, s as Save, F as FileSearch, t as CircleCheck, u as CloudUpload, O as OctagonAlert, G as Globe, v as FileTerminal, w as Radio, x as ChevronsUp, y as ChevronsDown, z as FileDiff, H as History, I as RotateCcw, J as GitCompareArrows, K as CircleQuestionMark, N as Server, Q as Gauge, V as Lock, Y as Wifi, _ as WifiOff, $ as ArrowUp, a0 as ArrowDown, a1 as Rows3, a2 as Columns2 } from "../_libs/lucide-react.mjs";
12
+ import { C as Check, X, P as Plus, D as Download, S as Settings, A as ArrowLeft, a as Copy, b as ChevronDown, U as Upload, c as Scan, d as CircleAlert, T as Terminal, e as ChevronUp, L as LoaderCircle, f as ChevronRight, g as User, h as Clock, M as MessageSquare, Z as Zap, E as ExternalLink, i as Trash2, W as Wrench, j as TriangleAlert, B as Brain, k as EyeOff, l as Eye, R as RotateCw, m as Pencil, n as Minus, o as CircleCheckBig, p as CircleX, q as ShieldCheck, r as RefreshCw, s as Save, F as FileSearch, t as CircleCheck, u as CloudUpload, O as OctagonAlert, G as Globe, v as FileTerminal, w as Radio, x as ChevronsUp, y as ChevronsDown, z as FileDiff, H as History, I as RotateCcw, J as Search, K as GitCompareArrows, N as CircleQuestionMark, Q as Server, V as Gauge, Y as Lock, _ as Wifi, $ as WifiOff, a0 as ArrowUp, a1 as ArrowDown, a2 as Ellipsis, a3 as CodeXml, a4 as Blocks, a5 as MousePointerClick, a6 as FileText, a7 as Rows3, a8 as Columns2 } from "../_libs/lucide-react.mjs";
13
+ import { M as Markdown } from "../_libs/react-markdown.mjs";
13
14
  import { u as union, d as object, a as array, l as literal, b as string, n as number, c as boolean, _ as _enum } from "../_libs/zod.mjs";
14
15
  import { P as Provider, R as Root3, T as Trigger$1, a as Portal$1, C as Content2$1, A as Arrow2 } from "../_libs/radix-ui__react-tooltip.mjs";
15
16
  import { R as Root2$1, L as List, T as Trigger$3, C as Content$1 } from "../_libs/radix-ui__react-tabs.mjs";
16
17
  import { S as Slot } from "../_libs/radix-ui__react-slot.mjs";
18
+ import { R as Root$1, C as CollapsibleContent$1, a as CollapsibleTrigger$1 } from "../_libs/radix-ui__react-collapsible.mjs";
19
+ import { R as Root$2, V as Viewport$1, C as Corner, S as ScrollAreaScrollbar, a as ScrollAreaThumb } from "../_libs/radix-ui__react-scroll-area.mjs";
17
20
  const ApiErrorSchema = object({
18
21
  error: string()
19
22
  });
@@ -295,7 +298,7 @@ function getStatusCategory(status) {
295
298
  if (status >= 500) return "server_error";
296
299
  return "pending";
297
300
  }
298
- const version = "2.0.6";
301
+ const version = "2.0.8";
299
302
  const packageJson = {
300
303
  version
301
304
  };
@@ -1356,27 +1359,27 @@ function useCopyFeedback(text) {
1356
1359
  return { copied, copy };
1357
1360
  }
1358
1361
  const LazyCompareDrawer = reactExports.lazy(
1359
- () => import("./CompareDrawer-BQVNsAY2.mjs").then((m) => ({ default: m.CompareDrawer }))
1362
+ () => import("./CompareDrawer-C5NBvE2e.mjs").then((m) => ({ default: m.CompareDrawer }))
1360
1363
  );
1361
1364
  const LazyReplayDialog = reactExports.lazy(
1362
- () => import("./ReplayDialog-CaMQBc79.mjs").then((m) => ({ default: m.ReplayDialog }))
1365
+ () => import("./ReplayDialog-EpvTwFvp.mjs").then((m) => ({ default: m.ReplayDialog }))
1363
1366
  );
1364
1367
  const LazyRequestAnatomy = reactExports.lazy(
1365
- () => import("./RequestAnatomy--P5arRH2.mjs").then((m) => ({ default: m.RequestAnatomy }))
1368
+ () => import("./RequestAnatomy-DaQjhixp.mjs").then((m) => ({ default: m.RequestAnatomy }))
1366
1369
  );
1367
1370
  const LazyResponseView = reactExports.lazy(
1368
- () => import("./ResponseView-RtFwNvgD.mjs").then((m) => ({ default: m.ResponseView }))
1371
+ () => import("./ResponseView-D8tGHCGY.mjs").then((m) => ({ default: m.ResponseView }))
1369
1372
  );
1370
1373
  const LazyStreamingChunkSequence = reactExports.lazy(
1371
- () => import("./StreamingChunkSequence-B5HPkzab.mjs").then((m) => ({
1374
+ () => import("./StreamingChunkSequence-DGQnb1QE.mjs").then((m) => ({
1372
1375
  default: m.StreamingChunkSequence
1373
1376
  }))
1374
1377
  );
1375
1378
  const LazyJsonViewer = reactExports.lazy(
1376
- () => import("./json-viewer-d4obyRaA.mjs").then((m) => ({ default: m.JsonViewer }))
1379
+ () => Promise.resolve().then(() => jsonViewer).then((m) => ({ default: m.JsonViewer }))
1377
1380
  );
1378
1381
  const LazyJsonViewerFromString = reactExports.lazy(
1379
- () => import("./json-viewer-d4obyRaA.mjs").then((m) => ({ default: m.JsonViewerFromString }))
1382
+ () => Promise.resolve().then(() => jsonViewer).then((m) => ({ default: m.JsonViewerFromString }))
1380
1383
  );
1381
1384
  const HIGHLIGHT_DURATION_MS = 1200;
1382
1385
  const MAX_HIGHLIGHT_ATTEMPTS = 12;
@@ -2041,6 +2044,642 @@ const LogEntryHeader = reactExports.memo(function({
2041
2044
  }
2042
2045
  ) });
2043
2046
  });
2047
+ function Collapsible({
2048
+ ...props
2049
+ }) {
2050
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Root$1, { "data-slot": "collapsible", ...props });
2051
+ }
2052
+ function CollapsibleTrigger({
2053
+ ...props
2054
+ }) {
2055
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(CollapsibleTrigger$1, { "data-slot": "collapsible-trigger", ...props });
2056
+ }
2057
+ function CollapsibleContent({
2058
+ ...props
2059
+ }) {
2060
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(CollapsibleContent$1, { "data-slot": "collapsible-content", ...props });
2061
+ }
2062
+ function classifyValue(value) {
2063
+ if (value === null) return "null";
2064
+ if (Array.isArray(value)) return "array";
2065
+ switch (typeof value) {
2066
+ case "string":
2067
+ return "string";
2068
+ case "number":
2069
+ return "number";
2070
+ case "boolean":
2071
+ return "boolean";
2072
+ case "object":
2073
+ return "object";
2074
+ case "bigint":
2075
+ case "symbol":
2076
+ case "undefined":
2077
+ case "function":
2078
+ return "object";
2079
+ }
2080
+ }
2081
+ function isExpandable(value) {
2082
+ return value !== null && (Array.isArray(value) || typeof value === "object");
2083
+ }
2084
+ function getEntries(value) {
2085
+ if (Array.isArray(value)) {
2086
+ return value.map((item, index) => [String(index), item]);
2087
+ }
2088
+ if (typeof value === "object" && value !== null) {
2089
+ return Object.entries(value);
2090
+ }
2091
+ return [];
2092
+ }
2093
+ const STRING_TRUNCATE_LIMIT = 120;
2094
+ function StringValue({ text }) {
2095
+ const [expanded, setExpanded] = reactExports.useState(false);
2096
+ const isLong = text.length > STRING_TRUNCATE_LIMIT;
2097
+ if (!isLong) {
2098
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-emerald-400 break-all", children: [
2099
+ '"',
2100
+ /* @__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 }) }),
2101
+ '"'
2102
+ ] });
2103
+ }
2104
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-emerald-400 break-all", children: [
2105
+ '"',
2106
+ expanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(
2107
+ "span",
2108
+ {
2109
+ 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",
2110
+ onClick: (e) => {
2111
+ e.stopPropagation();
2112
+ setExpanded(false);
2113
+ },
2114
+ onKeyDown: (e) => {
2115
+ if (e.key === "Enter" || e.key === " ") {
2116
+ e.stopPropagation();
2117
+ setExpanded(false);
2118
+ }
2119
+ },
2120
+ role: "button",
2121
+ tabIndex: 0,
2122
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(Markdown, { children: text })
2123
+ }
2124
+ ) : /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { delayDuration: 300, children: [
2125
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
2126
+ TooltipTrigger,
2127
+ {
2128
+ onClick: (e) => {
2129
+ e.stopPropagation();
2130
+ setExpanded(true);
2131
+ },
2132
+ className: "text-left cursor-pointer",
2133
+ children: [
2134
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: text.slice(0, STRING_TRUNCATE_LIMIT) }),
2135
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-emerald-400/50", children: "…" })
2136
+ ]
2137
+ }
2138
+ ),
2139
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
2140
+ TooltipContent,
2141
+ {
2142
+ side: "bottom",
2143
+ className: "max-w-md text-xs p-2 break-words whitespace-pre-wrap",
2144
+ children: [
2145
+ text.slice(0, 500),
2146
+ text.length > 500 ? "…" : ""
2147
+ ]
2148
+ }
2149
+ )
2150
+ ] }),
2151
+ '"'
2152
+ ] });
2153
+ }
2154
+ function PrimitiveValue({ value }) {
2155
+ if (value === null) {
2156
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-rose-400 italic", children: "null" });
2157
+ }
2158
+ switch (typeof value) {
2159
+ case "string":
2160
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(StringValue, { text: value });
2161
+ case "number":
2162
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-amber-400", children: value });
2163
+ case "boolean":
2164
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-blue-400", children: value ? "true" : "false" });
2165
+ case "object":
2166
+ case "bigint":
2167
+ case "symbol":
2168
+ case "undefined":
2169
+ case "function":
2170
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground", children: JSON.stringify(value) });
2171
+ }
2172
+ }
2173
+ function CopyValueButton({ value }) {
2174
+ const [copied, setCopied] = reactExports.useState(false);
2175
+ function handleCopy(e) {
2176
+ e.stopPropagation();
2177
+ void window.navigator.clipboard.writeText(JSON.stringify(value, null, 2)).then(() => {
2178
+ setCopied(true);
2179
+ setTimeout(() => {
2180
+ setCopied(false);
2181
+ }, 2e3);
2182
+ });
2183
+ }
2184
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
2185
+ "button",
2186
+ {
2187
+ type: "button",
2188
+ onClick: handleCopy,
2189
+ className: "inline-flex items-center gap-1 text-[10px] text-muted-foreground hover:text-foreground transition-colors",
2190
+ title: "Copy JSON",
2191
+ children: copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-3 text-green-500" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-3" })
2192
+ }
2193
+ );
2194
+ }
2195
+ function CopyButton({ value }) {
2196
+ const [copied, setCopied] = reactExports.useState(false);
2197
+ function handleCopy(e) {
2198
+ e.stopPropagation();
2199
+ void window.navigator.clipboard.writeText(JSON.stringify(value, null, 2)).then(() => {
2200
+ setCopied(true);
2201
+ setTimeout(() => {
2202
+ setCopied(false);
2203
+ }, 2e3);
2204
+ });
2205
+ }
2206
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
2207
+ "button",
2208
+ {
2209
+ type: "button",
2210
+ onClick: handleCopy,
2211
+ className: "opacity-0 group-hover/row:opacity-100 hover:bg-muted p-0.5 rounded transition-opacity shrink-0",
2212
+ title: "Copy to clipboard",
2213
+ children: copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-3 text-green-500" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-3 text-muted-foreground" })
2214
+ }
2215
+ );
2216
+ }
2217
+ function ExpandCollapseButton({
2218
+ onClick
2219
+ }) {
2220
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
2221
+ "button",
2222
+ {
2223
+ type: "button",
2224
+ onClick,
2225
+ className: "opacity-0 group-hover/row:opacity-100 hover:bg-muted p-0.5 rounded transition-opacity shrink-0",
2226
+ title: "Expand all descendants",
2227
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronsDown, { className: "size-3.5 text-muted-foreground" })
2228
+ }
2229
+ );
2230
+ }
2231
+ const JsonNode = reactExports.memo(function JsonNode2({
2232
+ name,
2233
+ value,
2234
+ level,
2235
+ defaultExpandDepth,
2236
+ isArrayItem,
2237
+ path,
2238
+ expandTargetPath,
2239
+ anatomyPaths
2240
+ }) {
2241
+ const isAncestorOfTarget = reactExports.useMemo(() => {
2242
+ if (expandTargetPath === null) return false;
2243
+ if (path === "") return expandTargetPath.length > 0;
2244
+ return expandTargetPath === path || expandTargetPath.startsWith(`${path}/`);
2245
+ }, [expandTargetPath, path]);
2246
+ const initialExpanded = level < defaultExpandDepth || isAncestorOfTarget && isExpandable(value);
2247
+ const [expanded, setExpanded] = reactExports.useState(initialExpanded);
2248
+ reactExports.useEffect(() => {
2249
+ if (isAncestorOfTarget && isExpandable(value) && !expanded) {
2250
+ setExpanded(true);
2251
+ }
2252
+ }, [expandTargetPath]);
2253
+ const [childResetKey, setChildResetKey] = reactExports.useState(0);
2254
+ const [childDepthOverride, setChildDepthOverride] = reactExports.useState(null);
2255
+ const expandable = isExpandable(value);
2256
+ const fullyExpanded = childDepthOverride === Number.POSITIVE_INFINITY;
2257
+ const entries = reactExports.useMemo(() => getEntries(value), [value]);
2258
+ const hasExpandableChild = reactExports.useMemo(
2259
+ () => entries.some(([, child]) => isExpandable(child)),
2260
+ [entries]
2261
+ );
2262
+ const dataType = classifyValue(value);
2263
+ const openBracket = dataType === "array" ? "[" : "{";
2264
+ const closeBracket = dataType === "array" ? "]" : "}";
2265
+ const hasAnatomyPath = anatomyPaths !== null && anatomyPaths.has(path);
2266
+ function expandAllDeep() {
2267
+ setExpanded(true);
2268
+ setChildDepthOverride(Number.POSITIVE_INFINITY);
2269
+ setChildResetKey((k) => k + 1);
2270
+ }
2271
+ function collapseToDefault() {
2272
+ setExpanded(false);
2273
+ setChildDepthOverride(0);
2274
+ setChildResetKey((k) => k + 1);
2275
+ }
2276
+ function handleRowToggle() {
2277
+ if (fullyExpanded) {
2278
+ collapseToDefault();
2279
+ } else {
2280
+ setExpanded(!expanded);
2281
+ }
2282
+ }
2283
+ function handleExpandAll(e) {
2284
+ e.stopPropagation();
2285
+ expandAllDeep();
2286
+ }
2287
+ const effectiveChildDepth = childDepthOverride ?? defaultExpandDepth;
2288
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cn(level > 0 && "border-l border-border/50 ml-2"), children: [
2289
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
2290
+ "div",
2291
+ {
2292
+ className: cn(
2293
+ "flex items-start gap-1 py-0.5 px-1 -ml-1 rounded-sm group/row",
2294
+ expandable && "cursor-pointer hover:bg-muted/50"
2295
+ ),
2296
+ "data-anatomy-path": hasAnatomyPath ? path : void 0,
2297
+ onClick: expandable ? handleRowToggle : void 0,
2298
+ onKeyDown: expandable ? (e) => {
2299
+ if (e.key === "Enter" || e.key === " ") {
2300
+ e.preventDefault();
2301
+ handleRowToggle();
2302
+ }
2303
+ } : void 0,
2304
+ onDoubleClick: expandable && hasExpandableChild ? () => expandAllDeep() : void 0,
2305
+ role: expandable ? "button" : void 0,
2306
+ tabIndex: expandable ? 0 : void 0,
2307
+ children: [
2308
+ 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" }),
2309
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn("shrink-0", isArrayItem ? "text-muted-foreground" : "text-cyan-400"), children: isArrayItem ? name : `"${name}"` }),
2310
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground shrink-0", children: expandable ? "" : ":" }),
2311
+ expandable ? /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground", children: [
2312
+ openBracket,
2313
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground/60 text-xs", children: [
2314
+ " ",
2315
+ entries.length,
2316
+ " ",
2317
+ entries.length === 1 ? "item" : "items",
2318
+ " ",
2319
+ closeBracket
2320
+ ] })
2321
+ ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(PrimitiveValue, { value }) }),
2322
+ expandable && hasExpandableChild && !fullyExpanded && /* @__PURE__ */ jsxRuntimeExports.jsx(ExpandCollapseButton, { onClick: handleExpandAll }),
2323
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CopyButton, { value })
2324
+ ]
2325
+ }
2326
+ ),
2327
+ expandable && expanded && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "pl-4", children: [
2328
+ entries.map(([key, childValue]) => /* @__PURE__ */ jsxRuntimeExports.jsx(
2329
+ JsonNode2,
2330
+ {
2331
+ name: key,
2332
+ value: childValue,
2333
+ level: level + 1,
2334
+ defaultExpandDepth: effectiveChildDepth,
2335
+ isArrayItem: dataType === "array",
2336
+ path: path === "" ? `/${key}` : `${path}/${key}`,
2337
+ expandTargetPath,
2338
+ anatomyPaths
2339
+ },
2340
+ key
2341
+ )),
2342
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-muted-foreground py-0.5 px-1", children: closeBracket })
2343
+ ] }, childResetKey)
2344
+ ] });
2345
+ });
2346
+ function JsonViewer({
2347
+ data,
2348
+ defaultExpandDepth = 0,
2349
+ className,
2350
+ showCopy = false,
2351
+ bulkDepth: controlledBulkDepth,
2352
+ bulkRevision: controlledBulkRevision,
2353
+ anatomyPaths = null,
2354
+ expandToPath = null
2355
+ }) {
2356
+ const expandable = isExpandable(data);
2357
+ const entries = reactExports.useMemo(() => getEntries(data), [data]);
2358
+ const bulkDepth = controlledBulkDepth ?? defaultExpandDepth;
2359
+ const bulkRevision = controlledBulkRevision ?? 0;
2360
+ if (!expandable) {
2361
+ 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: [
2362
+ /* @__PURE__ */ jsxRuntimeExports.jsx(PrimitiveValue, { value: data }),
2363
+ showCopy && /* @__PURE__ */ jsxRuntimeExports.jsx(CopyValueButton, { value: data })
2364
+ ] }) }) });
2365
+ }
2366
+ const dataType = classifyValue(data);
2367
+ const isArray = dataType === "array";
2368
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cn("font-mono text-xs leading-relaxed", className), children: [
2369
+ showCopy && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-2 flex items-center justify-end gap-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(CopyValueButton, { value: data }) }),
2370
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: entries.map(([key, childValue]) => /* @__PURE__ */ jsxRuntimeExports.jsx(
2371
+ JsonNode,
2372
+ {
2373
+ name: key,
2374
+ value: childValue,
2375
+ level: 0,
2376
+ defaultExpandDepth: bulkDepth,
2377
+ isArrayItem: isArray,
2378
+ path: `/${key}`,
2379
+ expandTargetPath: expandToPath,
2380
+ anatomyPaths
2381
+ },
2382
+ key
2383
+ )) }, bulkRevision)
2384
+ ] }) });
2385
+ }
2386
+ const JsonViewerFromString = reactExports.memo(function JsonViewerFromString2({
2387
+ text,
2388
+ defaultExpandDepth = 0,
2389
+ className,
2390
+ bulkDepth,
2391
+ bulkRevision
2392
+ }) {
2393
+ const parsed = reactExports.useMemo(() => parseJsonText(text), [text]);
2394
+ if (parsed.kind === "json") {
2395
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
2396
+ JsonViewer,
2397
+ {
2398
+ data: parsed.data,
2399
+ defaultExpandDepth,
2400
+ className,
2401
+ bulkDepth,
2402
+ bulkRevision
2403
+ }
2404
+ );
2405
+ }
2406
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: cn("font-mono text-xs whitespace-pre-wrap break-words", className), children: text });
2407
+ });
2408
+ const jsonViewer = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2409
+ __proto__: null,
2410
+ JsonViewer,
2411
+ JsonViewerFromString
2412
+ }, Symbol.toStringTag, { value: "Module" }));
2413
+ function ScrollArea({
2414
+ className,
2415
+ children,
2416
+ ...props
2417
+ }) {
2418
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
2419
+ Root$2,
2420
+ {
2421
+ "data-slot": "scroll-area",
2422
+ className: cn("relative", className),
2423
+ ...props,
2424
+ children: [
2425
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
2426
+ Viewport$1,
2427
+ {
2428
+ "data-slot": "scroll-area-viewport",
2429
+ className: "focus-visible:ring-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:outline-1",
2430
+ children
2431
+ }
2432
+ ),
2433
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ScrollBar, {}),
2434
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Corner, {})
2435
+ ]
2436
+ }
2437
+ );
2438
+ }
2439
+ function ScrollBar({
2440
+ className,
2441
+ orientation = "vertical",
2442
+ ...props
2443
+ }) {
2444
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
2445
+ ScrollAreaScrollbar,
2446
+ {
2447
+ "data-slot": "scroll-area-scrollbar",
2448
+ orientation,
2449
+ className: cn(
2450
+ "flex touch-none p-px transition-colors select-none",
2451
+ orientation === "vertical" && "h-full w-2.5 border-l border-l-transparent",
2452
+ orientation === "horizontal" && "h-2.5 flex-col border-t border-t-transparent",
2453
+ className
2454
+ ),
2455
+ ...props,
2456
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(
2457
+ ScrollAreaThumb,
2458
+ {
2459
+ "data-slot": "scroll-area-thumb",
2460
+ className: "bg-border relative flex-1 rounded-full"
2461
+ }
2462
+ )
2463
+ }
2464
+ );
2465
+ }
2466
+ const CATEGORY_LABELS = {
2467
+ file: "file",
2468
+ shell: "shell",
2469
+ browser: "browser",
2470
+ web: "web",
2471
+ mcp: "MCP",
2472
+ code: "code",
2473
+ other: "other"
2474
+ };
2475
+ const CATEGORY_CLASSES = {
2476
+ file: "border-blue-400/20 bg-blue-400/5 text-blue-300",
2477
+ shell: "border-teal-400/20 bg-teal-400/5 text-teal-300",
2478
+ browser: "border-cyan-400/20 bg-cyan-400/5 text-cyan-300",
2479
+ web: "border-sky-400/20 bg-sky-400/5 text-sky-300",
2480
+ mcp: "border-violet-400/20 bg-violet-400/5 text-violet-300",
2481
+ code: "border-emerald-400/20 bg-emerald-400/5 text-emerald-300",
2482
+ other: "border-muted-foreground/20 bg-muted/30 text-muted-foreground"
2483
+ };
2484
+ function CategoryIcon({ category }) {
2485
+ switch (category) {
2486
+ case "file":
2487
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(FileText, { className: "size-3.5" });
2488
+ case "shell":
2489
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Terminal, { className: "size-3.5" });
2490
+ case "browser":
2491
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(MousePointerClick, { className: "size-3.5" });
2492
+ case "web":
2493
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Globe, { className: "size-3.5" });
2494
+ case "mcp":
2495
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Blocks, { className: "size-3.5" });
2496
+ case "code":
2497
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(CodeXml, { className: "size-3.5" });
2498
+ case "other":
2499
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Ellipsis, { className: "size-3.5" });
2500
+ }
2501
+ }
2502
+ function RequiredParameters({ names }) {
2503
+ if (names.length === 0) return null;
2504
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-1", children: [
2505
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] uppercase tracking-wide text-muted-foreground", children: "required" }),
2506
+ names.slice(0, 4).map((name) => /* @__PURE__ */ jsxRuntimeExports.jsx(
2507
+ Badge,
2508
+ {
2509
+ variant: "outline",
2510
+ className: "h-5 max-w-36 truncate rounded-md px-1.5 py-0 font-mono text-[10px]",
2511
+ children: name
2512
+ },
2513
+ name
2514
+ )),
2515
+ names.length > 4 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono text-[10px] text-muted-foreground", children: [
2516
+ "+",
2517
+ names.length - 4
2518
+ ] })
2519
+ ] });
2520
+ }
2521
+ function ToolRow({ tool, called }) {
2522
+ const [open, setOpen] = reactExports.useState(false);
2523
+ const nameCopy = useCopyFeedback(tool.name);
2524
+ const hasDetails = tool.description !== null || tool.requiredParameters.length > 0 || tool.schema !== null;
2525
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Collapsible, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-md border border-border/60 bg-background/40", children: [
2526
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center gap-2 px-2.5 py-2", children: [
2527
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
2528
+ "button",
2529
+ {
2530
+ type: "button",
2531
+ className: "flex min-w-0 flex-1 items-center gap-2 text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
2532
+ onClick: () => setOpen((value) => !value),
2533
+ "aria-expanded": open,
2534
+ disabled: !hasDetails,
2535
+ children: [
2536
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CategoryIcon, { category: tool.category }),
2537
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0 truncate font-mono text-xs font-semibold text-foreground/90", children: tool.name }),
2538
+ called && /* @__PURE__ */ jsxRuntimeExports.jsx(
2539
+ Badge,
2540
+ {
2541
+ variant: "outline",
2542
+ className: "h-5 rounded-md border-emerald-400/20 bg-emerald-400/5 px-1.5 py-0 text-[10px] text-emerald-300",
2543
+ children: "called"
2544
+ }
2545
+ ),
2546
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono text-[10px] text-muted-foreground", children: [
2547
+ tool.parameterCount,
2548
+ " params"
2549
+ ] }),
2550
+ tool.descriptionPreview !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "hidden min-w-0 truncate text-xs text-muted-foreground md:inline", children: tool.descriptionPreview }),
2551
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1" }),
2552
+ hasDetails && (open ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-3.5 shrink-0 text-muted-foreground" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-3.5 shrink-0 text-muted-foreground" }))
2553
+ ]
2554
+ }
2555
+ ),
2556
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
2557
+ "button",
2558
+ {
2559
+ type: "button",
2560
+ className: "inline-flex size-7 shrink-0 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
2561
+ onClick: nameCopy.copy,
2562
+ "aria-label": nameCopy.copied ? "Copied tool name" : "Copy tool name",
2563
+ children: nameCopy.copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-3.5 text-emerald-400" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-3.5" })
2564
+ }
2565
+ )
2566
+ ] }),
2567
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CollapsibleContent, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2 border-t border-border/60 px-2.5 py-2", children: [
2568
+ tool.description !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs leading-relaxed text-muted-foreground", children: tool.description }),
2569
+ /* @__PURE__ */ jsxRuntimeExports.jsx(RequiredParameters, { names: tool.requiredParameters }),
2570
+ tool.schema !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(ScrollArea, { className: "max-h-64 rounded-md border border-border/60 bg-muted/20 p-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(JsonViewer, { data: safeJsonValue(tool.schema), defaultExpandDepth: 0 }) })
2571
+ ] }) })
2572
+ ] }) });
2573
+ }
2574
+ function matchesQuery(tool, query) {
2575
+ if (query.length === 0) return true;
2576
+ const haystack = `${tool.name} ${tool.description ?? ""} ${CATEGORY_LABELS[tool.category]}`.toLowerCase().trim();
2577
+ return haystack.includes(query);
2578
+ }
2579
+ const RequestTools = reactExports.memo(function RequestTools2({
2580
+ summary,
2581
+ calledToolNames
2582
+ }) {
2583
+ const [expanded, setExpanded] = reactExports.useState(false);
2584
+ const [query, setQuery] = reactExports.useState("");
2585
+ const calledNames = reactExports.useMemo(() => new Set(calledToolNames), [calledToolNames]);
2586
+ const normalizedQuery = query.trim().toLowerCase();
2587
+ const visibleTools = reactExports.useMemo(
2588
+ () => summary === null ? [] : summary.tools.filter((tool) => matchesQuery(tool, normalizedQuery)),
2589
+ [normalizedQuery, summary]
2590
+ );
2591
+ if (summary === null) return null;
2592
+ const previewTools = summary.tools.slice(0, 6);
2593
+ const hiddenPreviewCount = summary.tools.length - previewTools.length;
2594
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "mb-3 rounded-lg border border-border/70 bg-muted/20", children: [
2595
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-2 px-3 py-2", children: [
2596
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
2597
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Wrench, { className: "size-4 shrink-0 text-sky-300/80" }),
2598
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0", children: [
2599
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-1.5", children: [
2600
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm font-semibold text-foreground", children: "Request Tools" }),
2601
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { variant: "outline", className: "h-5 rounded-md px-1.5 py-0 font-mono text-[10px]", children: summary.tools.length }),
2602
+ summary.toolChoiceLabel !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs(
2603
+ Badge,
2604
+ {
2605
+ variant: "outline",
2606
+ className: "h-5 rounded-md px-1.5 py-0 font-mono text-[10px] text-muted-foreground",
2607
+ children: [
2608
+ "tool_choice: ",
2609
+ summary.toolChoiceLabel
2610
+ ]
2611
+ }
2612
+ )
2613
+ ] }),
2614
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1 flex min-w-0 flex-wrap gap-1", children: summary.categories.map((category) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
2615
+ Badge,
2616
+ {
2617
+ variant: "outline",
2618
+ className: cn(
2619
+ "h-5 rounded-md px-1.5 py-0 font-mono text-[10px]",
2620
+ CATEGORY_CLASSES[category.category]
2621
+ ),
2622
+ children: [
2623
+ category.count,
2624
+ " ",
2625
+ CATEGORY_LABELS[category.category]
2626
+ ]
2627
+ },
2628
+ category.category
2629
+ )) })
2630
+ ] })
2631
+ ] }),
2632
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
2633
+ Button,
2634
+ {
2635
+ type: "button",
2636
+ variant: "ghost",
2637
+ size: "sm",
2638
+ className: "h-7 px-2",
2639
+ onClick: () => setExpanded((value) => !value),
2640
+ "aria-expanded": expanded,
2641
+ children: [
2642
+ expanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-3.5" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-3.5" }),
2643
+ expanded ? "Hide" : "Show"
2644
+ ]
2645
+ }
2646
+ )
2647
+ ] }),
2648
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-wrap gap-1.5 border-t border-border/60 px-3 py-2", children: [
2649
+ previewTools.map((tool) => /* @__PURE__ */ jsxRuntimeExports.jsx(
2650
+ Badge,
2651
+ {
2652
+ variant: "outline",
2653
+ className: cn(
2654
+ "h-5 max-w-44 truncate rounded-md px-1.5 py-0 font-mono text-[10px]",
2655
+ calledNames.has(tool.name) && "border-emerald-400/20 text-emerald-300"
2656
+ ),
2657
+ children: tool.name
2658
+ },
2659
+ tool.name
2660
+ )),
2661
+ hiddenPreviewCount > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono text-[10px] leading-5 text-muted-foreground", children: [
2662
+ "+",
2663
+ hiddenPreviewCount
2664
+ ] })
2665
+ ] }),
2666
+ expanded && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2 border-t border-border/60 px-3 py-3", children: [
2667
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "flex h-8 items-center gap-2 rounded-md border border-border/70 bg-background/50 px-2 text-xs", children: [
2668
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Search, { className: "size-3.5 shrink-0 text-muted-foreground" }),
2669
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
2670
+ "input",
2671
+ {
2672
+ value: query,
2673
+ onChange: (event) => setQuery(event.target.value),
2674
+ placeholder: "Filter tools",
2675
+ className: "min-w-0 flex-1 bg-transparent font-mono text-xs outline-none placeholder:text-muted-foreground/70"
2676
+ }
2677
+ )
2678
+ ] }),
2679
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grid gap-1.5", children: visibleTools.length > 0 ? visibleTools.map((tool) => /* @__PURE__ */ jsxRuntimeExports.jsx(ToolRow, { tool, called: calledNames.has(tool.name) }, tool.name)) : /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "py-2 text-xs text-muted-foreground", children: "No matching tools" }) })
2680
+ ] })
2681
+ ] });
2682
+ });
2044
2683
  function forEachCodePoint(text, visit) {
2045
2684
  for (const ch of Array.from(text)) {
2046
2685
  visit(ch);
@@ -2356,6 +2995,169 @@ function shouldShowHeadersDiffButton(viewMode, hasRawHeaders) {
2356
2995
  function shouldShowRequestDiffButton(apiFormat, viewMode, strip, hasRawRequest) {
2357
2996
  return apiFormat === "anthropic" && viewMode === "full" && strip && hasRawRequest;
2358
2997
  }
2998
+ const CATEGORY_ORDER = [
2999
+ "file",
3000
+ "shell",
3001
+ "browser",
3002
+ "web",
3003
+ "mcp",
3004
+ "code",
3005
+ "other"
3006
+ ];
3007
+ function firstTextSlice(value) {
3008
+ const normalized = value.replace(/\s+/g, " ").trim();
3009
+ if (normalized.length <= 120) return normalized;
3010
+ return `${normalized.slice(0, 119)}...`;
3011
+ }
3012
+ function previewDescription(description) {
3013
+ if (description === null) return null;
3014
+ const normalized = description.replace(/\s+/g, " ").trim();
3015
+ if (normalized.length === 0) return null;
3016
+ const sentenceEnd = normalized.search(/[.!?。!?]/);
3017
+ if (sentenceEnd >= 24) return firstTextSlice(normalized.slice(0, sentenceEnd + 1));
3018
+ return firstTextSlice(normalized);
3019
+ }
3020
+ function lowerHaystack(name, description) {
3021
+ return `${name} ${description ?? ""}`.toLowerCase();
3022
+ }
3023
+ function includesAny(value, needles) {
3024
+ return needles.some((needle) => value.includes(needle));
3025
+ }
3026
+ function categorizeTool(name, description) {
3027
+ const haystack = lowerHaystack(name, description);
3028
+ if (name.startsWith("mcp__") || name.startsWith("inspector_") || includesAny(haystack, [" mcp", "model context protocol"])) {
3029
+ return "mcp";
3030
+ }
3031
+ if (includesAny(haystack, ["bash", "shell", "terminal", "command", "powershell", "exec", "process"])) {
3032
+ return "shell";
3033
+ }
3034
+ if (includesAny(haystack, [
3035
+ "browser",
3036
+ "playwright",
3037
+ "screenshot",
3038
+ "click",
3039
+ "navigate",
3040
+ "page",
3041
+ "tab"
3042
+ ])) {
3043
+ return "browser";
3044
+ }
3045
+ if (includesAny(haystack, [
3046
+ "read",
3047
+ "write",
3048
+ "edit",
3049
+ "file",
3050
+ "glob",
3051
+ "grep",
3052
+ "patch",
3053
+ "filesystem",
3054
+ "directory"
3055
+ ])) {
3056
+ return "file";
3057
+ }
3058
+ if (includesAny(haystack, ["web", "search", "http", "url", "fetch"])) {
3059
+ return "web";
3060
+ }
3061
+ if (includesAny(haystack, ["code", "typescript", "javascript", "python", "repl"])) {
3062
+ return "code";
3063
+ }
3064
+ return "other";
3065
+ }
3066
+ function parameterNames(schema) {
3067
+ const properties = safeGetOwnProperty(schema, "properties");
3068
+ if (properties === null || typeof properties !== "object" || Array.isArray(properties)) {
3069
+ return [];
3070
+ }
3071
+ return Object.keys(properties).sort((a, b) => a.localeCompare(b));
3072
+ }
3073
+ function requiredParameterNames(schema) {
3074
+ const required = safeGetOwnProperty(schema, "required");
3075
+ if (!Array.isArray(required)) return [];
3076
+ const names = [];
3077
+ for (const item of required) {
3078
+ if (typeof item === "string" && item.length > 0) names.push(item);
3079
+ }
3080
+ return names.sort((a, b) => a.localeCompare(b));
3081
+ }
3082
+ function parseAnthropicTool(tool) {
3083
+ const name = safeGetOwnProperty(tool, "name");
3084
+ if (typeof name !== "string" || name.length === 0) return null;
3085
+ const description = safeGetOwnProperty(tool, "description");
3086
+ const schema = safeGetOwnProperty(tool, "input_schema") ?? null;
3087
+ const normalizedDescription = typeof description === "string" ? description : null;
3088
+ return {
3089
+ name,
3090
+ description: normalizedDescription,
3091
+ descriptionPreview: previewDescription(normalizedDescription),
3092
+ category: categorizeTool(name, normalizedDescription),
3093
+ parameterCount: parameterNames(schema).length,
3094
+ requiredParameters: requiredParameterNames(schema),
3095
+ schema
3096
+ };
3097
+ }
3098
+ function parseOpenAITool(tool) {
3099
+ const fn = safeGetOwnProperty(tool, "function");
3100
+ const name = safeGetOwnProperty(fn, "name");
3101
+ if (typeof name !== "string" || name.length === 0) return null;
3102
+ const description = safeGetOwnProperty(fn, "description");
3103
+ const schema = safeGetOwnProperty(fn, "parameters") ?? null;
3104
+ const normalizedDescription = typeof description === "string" ? description : null;
3105
+ return {
3106
+ name,
3107
+ description: normalizedDescription,
3108
+ descriptionPreview: previewDescription(normalizedDescription),
3109
+ category: categorizeTool(name, normalizedDescription),
3110
+ parameterCount: parameterNames(schema).length,
3111
+ requiredParameters: requiredParameterNames(schema),
3112
+ schema
3113
+ };
3114
+ }
3115
+ function parseTool(tool) {
3116
+ const openAITool = parseOpenAITool(tool);
3117
+ if (openAITool !== null) return openAITool;
3118
+ return parseAnthropicTool(tool);
3119
+ }
3120
+ function formatToolChoice(choice) {
3121
+ if (choice === void 0 || choice === null) return null;
3122
+ if (typeof choice === "string") return choice;
3123
+ const type = safeGetOwnProperty(choice, "type");
3124
+ const name = safeGetOwnProperty(choice, "name");
3125
+ const fnName = safeGetOwnProperty(safeGetOwnProperty(choice, "function"), "name");
3126
+ if (typeof type === "string" && typeof fnName === "string" && fnName.length > 0) {
3127
+ return `${type}: ${fnName}`;
3128
+ }
3129
+ if (typeof type === "string" && typeof name === "string" && name.length > 0) {
3130
+ return `${type}: ${name}`;
3131
+ }
3132
+ if (typeof type === "string") return type;
3133
+ const encoded = JSON.stringify(choice);
3134
+ return encoded === void 0 ? null : firstTextSlice(encoded);
3135
+ }
3136
+ function summarizeCategories(tools) {
3137
+ const counts = /* @__PURE__ */ new Map();
3138
+ for (const tool of tools) {
3139
+ counts.set(tool.category, (counts.get(tool.category) ?? 0) + 1);
3140
+ }
3141
+ return CATEGORY_ORDER.flatMap((category) => {
3142
+ const count = counts.get(category) ?? 0;
3143
+ return count > 0 ? [{ category, count }] : [];
3144
+ });
3145
+ }
3146
+ function parseRequestTools(parsed) {
3147
+ const rawTools = safeGetOwnProperty(parsed, "tools");
3148
+ if (!Array.isArray(rawTools) || rawTools.length === 0) return null;
3149
+ const tools = [];
3150
+ for (const rawTool of rawTools) {
3151
+ const tool = parseTool(rawTool);
3152
+ if (tool !== null) tools.push(tool);
3153
+ }
3154
+ if (tools.length === 0) return null;
3155
+ return {
3156
+ tools,
3157
+ toolChoiceLabel: formatToolChoice(safeGetOwnProperty(parsed, "tool_choice")),
3158
+ categories: summarizeCategories(tools)
3159
+ };
3160
+ }
2359
3161
  function TabFallback() {
2360
3162
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-1", "aria-hidden": "true" });
2361
3163
  }
@@ -2422,6 +3224,10 @@ const LogEntry = reactExports.memo(function({
2422
3224
  () => adapter.analyzeRequest(log.rawRequestBody),
2423
3225
  [adapter, log.rawRequestBody]
2424
3226
  );
3227
+ const responseAnalysis = reactExports.useMemo(
3228
+ () => adapter.analyzeResponse(log.responseText),
3229
+ [adapter, log.responseText]
3230
+ );
2425
3231
  const strippedRequestBody = reactExports.useMemo(() => {
2426
3232
  if (!strip || resolvedFormat !== "anthropic" || log.rawRequestBody === null) {
2427
3233
  return null;
@@ -2533,6 +3339,10 @@ const LogEntry = reactExports.memo(function({
2533
3339
  () => requestExpansion.parsedData !== null ? adapter.anatomySegments(requestExpansion.parsedData) : null,
2534
3340
  [adapter, requestExpansion.parsedData]
2535
3341
  );
3342
+ const requestTools = reactExports.useMemo(
3343
+ () => parseRequestTools(requestExpansion.parsedData),
3344
+ [requestExpansion.parsedData]
3345
+ );
2536
3346
  const anatomyPaths = reactExports.useMemo(() => {
2537
3347
  if (anatomySegments === null) return void 0;
2538
3348
  return new Set(anatomySegments.map((s) => s.path));
@@ -2568,9 +3378,9 @@ const LogEntry = reactExports.memo(function({
2568
3378
  /* @__PURE__ */ jsxRuntimeExports.jsxs(TabsList, { className: "mx-4 mt-2", children: [
2569
3379
  viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "raw-headers", children: "Raw Headers" }),
2570
3380
  viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "headers", children: "Headers" }),
3381
+ anatomySegments !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "anatomy", children: "Context" }),
2571
3382
  shouldShowRawRequestTab(resolvedFormat, viewMode, strip) && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "raw-request", children: "Raw Request" }),
2572
3383
  /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "request", children: "Request" }),
2573
- anatomySegments !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "anatomy", children: "Context" }),
2574
3384
  viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "raw", children: "Raw Response" }),
2575
3385
  /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "parsed", children: "Response" })
2576
3386
  ] }),
@@ -2582,28 +3392,38 @@ const LogEntry = reactExports.memo(function({
2582
3392
  bulkRevision: rawRequestExpansion.bulkRevision
2583
3393
  }
2584
3394
  ) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "font-mono text-xs whitespace-pre-wrap break-words", children: log.rawRequestBody }) }) }),
2585
- /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "request", children: activeTab === "request" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-4 pt-1 pb-3", children: requestDiff ? /* @__PURE__ */ jsxRuntimeExports.jsx(
2586
- RequestDiffContent,
2587
- {
2588
- rawBody: log.rawRequestBody,
2589
- displayedBody: displayedRequestBody,
2590
- emptyLabel: "No transformation applied; raw and sent request bodies are identical."
2591
- }
2592
- ) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: requestJsonRef, children: displayedRequestBody === null ? /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground italic", children: "No request body" }) : requestExpansion.parsedData !== null ? /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
2593
- LazyJsonViewer,
2594
- {
2595
- data: requestExpansion.parsedData,
2596
- bulkDepth: requestExpansion.bulkDepth,
2597
- bulkRevision: requestExpansion.bulkRevision,
2598
- anatomyPaths,
2599
- expandToPath
2600
- }
2601
- ) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "font-mono text-xs whitespace-pre-wrap break-words", children: displayedRequestBody }) }) }) }),
3395
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "request", children: activeTab === "request" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 pt-1 pb-3", children: [
3396
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
3397
+ RequestTools,
3398
+ {
3399
+ summary: requestTools,
3400
+ calledToolNames: responseAnalysis.toolNames ?? []
3401
+ }
3402
+ ),
3403
+ requestDiff ? /* @__PURE__ */ jsxRuntimeExports.jsx(
3404
+ RequestDiffContent,
3405
+ {
3406
+ rawBody: log.rawRequestBody,
3407
+ displayedBody: displayedRequestBody,
3408
+ emptyLabel: "No transformation applied; raw and sent request bodies are identical."
3409
+ }
3410
+ ) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: requestJsonRef, children: displayedRequestBody === null ? /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground italic", children: "No request body" }) : requestExpansion.parsedData !== null ? /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
3411
+ LazyJsonViewer,
3412
+ {
3413
+ data: requestExpansion.parsedData,
3414
+ bulkDepth: requestExpansion.bulkDepth,
3415
+ bulkRevision: requestExpansion.bulkRevision,
3416
+ anatomyPaths,
3417
+ expandToPath
3418
+ }
3419
+ ) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "font-mono text-xs whitespace-pre-wrap break-words", children: displayedRequestBody }) })
3420
+ ] }) }),
2602
3421
  anatomySegments !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "anatomy", children: activeTab === "anatomy" && /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
2603
3422
  LazyRequestAnatomy,
2604
3423
  {
2605
- parsed: null,
3424
+ parsed: requestExpansion.parsedData,
2606
3425
  inputTokens: log.inputTokens ?? null,
3426
+ model: log.model,
2607
3427
  segments: anatomySegments,
2608
3428
  onSegmentActivate: jumpToAnatomySegment
2609
3429
  }
@@ -7014,8 +7834,11 @@ function ProxyViewerContainer({
7014
7834
  }
7015
7835
  export {
7016
7836
  Badge as B,
7837
+ Collapsible as C,
7017
7838
  Dialog as D,
7839
+ JsonViewerFromString as J,
7018
7840
  ProxyViewerContainer as P,
7841
+ ScrollArea as S,
7019
7842
  Tabs as T,
7020
7843
  getConversationId as a,
7021
7844
  DialogContent as b,
@@ -7033,8 +7856,10 @@ export {
7033
7856
  TooltipContent as n,
7034
7857
  Button as o,
7035
7858
  getStatusCategory as p,
7036
- parseJsonText as q,
7859
+ CollapsibleTrigger as q,
7037
7860
  resolveLogFormat as r,
7038
- safeJsonValue as s,
7039
- useProviders as u
7861
+ CollapsibleContent as s,
7862
+ JsonViewer as t,
7863
+ useProviders as u,
7864
+ safeJsonValue as v
7040
7865
  };