@tonyclaw/agent-inspector 2.1.16 → 2.1.17

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 (51) hide show
  1. package/.output/cli.js +57 -13
  2. package/.output/nitro.json +1 -1
  3. package/.output/public/assets/{CompareDrawer-Ccrrcx1j.js → CompareDrawer-B9sLBHw5.js} +1 -1
  4. package/.output/public/assets/ProxyViewerContainer-DbWjc_BE.js +106 -0
  5. package/.output/public/assets/{ReplayDialog-C7axhr-l.js → ReplayDialog-D9I9W9n3.js} +1 -1
  6. package/.output/public/assets/{RequestAnatomy-WOptg8j_.js → RequestAnatomy-DGXK_Rii.js} +1 -1
  7. package/.output/public/assets/{ResponseView-CSAcxh_M.js → ResponseView-df_JzwsS.js} +2 -2
  8. package/.output/public/assets/{StreamingChunkSequence-DJS5KhPx.js → StreamingChunkSequence-i3DM5IKL.js} +1 -1
  9. package/.output/public/assets/_sessionId-CTpCHdFh.js +1 -0
  10. package/.output/public/assets/index-Blqvndcn.js +1 -0
  11. package/.output/public/assets/index-Cs79WRQj.css +1 -0
  12. package/.output/public/assets/{index-DMPNh46t.js → index-Dqc2r1ea.js} +1 -1
  13. package/.output/public/assets/{json-viewer-inX5QSa3.js → json-viewer-D3QWQlSB.js} +1 -1
  14. package/.output/public/assets/{main-aCAKYGSD.js → main-ZhxhOCmF.js} +2 -2
  15. package/.output/server/_libs/lucide-react.mjs +220 -202
  16. package/.output/server/{_sessionId-C0fhvQnn.mjs → _sessionId-YFrP0lZP.mjs} +2 -2
  17. package/.output/server/_ssr/{CompareDrawer-CO-Ti5sg.mjs → CompareDrawer-qC3adEeq.mjs} +3 -3
  18. package/.output/server/_ssr/{ProxyViewerContainer-N4J7uBCX.mjs → ProxyViewerContainer-DCZIJC2b.mjs} +1858 -1396
  19. package/.output/server/_ssr/{ReplayDialog-J1VxC0In.mjs → ReplayDialog-CvX4XYCi.mjs} +4 -4
  20. package/.output/server/_ssr/{RequestAnatomy-DBH-F3rq.mjs → RequestAnatomy-HQfrxjO1.mjs} +2 -2
  21. package/.output/server/_ssr/{ResponseView-DLFwV7Hd.mjs → ResponseView-QSlSD11e.mjs} +3 -3
  22. package/.output/server/_ssr/{StreamingChunkSequence-BywmuND0.mjs → StreamingChunkSequence-DTAiwlnI.mjs} +2 -2
  23. package/.output/server/_ssr/{index-CStymIc0.mjs → index-D_EzfXaN.mjs} +2 -2
  24. package/.output/server/_ssr/index.mjs +2 -2
  25. package/.output/server/_ssr/{json-viewer-DlQu0N1x.mjs → json-viewer-CrIX0e0Q.mjs} +3 -3
  26. package/.output/server/_ssr/{router-CQ4Zxhmr.mjs → router-__o2wrfO.mjs} +398 -95
  27. package/.output/server/{_tanstack-start-manifest_v-BHeJBGfo.mjs → _tanstack-start-manifest_v-DbqyLpsI.mjs} +1 -1
  28. package/.output/server/index.mjs +73 -73
  29. package/README.md +57 -2
  30. package/package.json +1 -1
  31. package/src/cli/startupOutput.ts +16 -0
  32. package/src/cli.ts +61 -15
  33. package/src/components/ProxyViewer.tsx +395 -64
  34. package/src/components/providers/ProviderCard.tsx +132 -31
  35. package/src/components/providers/ProviderForm.tsx +43 -11
  36. package/src/components/providers/ProvidersPanel.tsx +1 -1
  37. package/src/components/proxy-viewer/ConversationHeader.tsx +133 -112
  38. package/src/components/proxy-viewer/LogEntry.tsx +109 -26
  39. package/src/components/proxy-viewer/LogEntryHeader.tsx +339 -329
  40. package/src/components/proxy-viewer/ThreadConnector.tsx +102 -83
  41. package/src/components/proxy-viewer/TurnGroup.tsx +22 -63
  42. package/src/components/proxy-viewer/bodyHydration.ts +56 -0
  43. package/src/lib/providerTestContract.ts +56 -10
  44. package/src/lib/providerTestPrompt.ts +23 -1
  45. package/src/lib/upstreamUrl.ts +105 -1
  46. package/src/mcp/toolHandlers.ts +1 -1
  47. package/src/routes/api/providers.$providerId.test.log.ts +85 -10
  48. package/.output/public/assets/ProxyViewerContainer-DLqClc9A.js +0 -106
  49. package/.output/public/assets/_sessionId-DUSalzKH.js +0 -1
  50. package/.output/public/assets/index-BPpA21dY.css +0 -1
  51. package/.output/public/assets/index-Bt0Az2I2.js +0 -1
@@ -1,5 +1,5 @@
1
1
  import { r as reactExports, j as jsxRuntimeExports, a as React } from "../_libs/react.mjs";
2
- import { I as InspectorGroupsListResponseSchema, C as CapturedLogSchema, D as DEFAULT_CAPTURE_MODE, a as DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS, b as DEFAULT_PROVIDER_TEST_TIMEOUT_SECONDS, c as DEFAULT_TIME_DISPLAY_FORMAT, d as RuntimeConfigSchema, p as packageJson, P as ProviderConfigSchema, i as apiFormatForPath, n as 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, l as AlertSummarySchema, m as AlertListResponseSchema, G as GroupEvidenceReadResponseSchema, t as maskApiKey, q as providerHasContextMetadata, r as findProviderModelMetadata, f as parseOpenAIResponse, g as parseOpenAIResponsesResponse, O as OpenAIRequestSchema, h as OpenAIResponsesRequestSchema, A as AnthropicResponseSchema$1, e as AnthropicRequestSchema, s as safeGetOwnProperty, z as resolveProviderContextWindow, j as getSessionPath, u as buildUpstreamUrl, K as KnowledgeCandidateSchema, B as isPlainRecord, k as stripClaudeCodeBillingHeader, L as LogBodyChunkSchema } from "./router-CQ4Zxhmr.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, y as createPendingProviderTestResults, z as ProviderTestResultsSchema, B as createFailedProviderTestResults, M as MAX_SLOW_RESPONSE_THRESHOLD_SECONDS, E as MAX_PROVIDER_TEST_TIMEOUT_SECONDS, T as TimeDisplayFormatSchema, l as AlertSummarySchema, m as AlertListResponseSchema, G as GroupEvidenceReadResponseSchema, t as maskApiKey, u as PATH_V1_MESSAGES, v as PATH_V1_CHAT_COMPLETIONS, w as PATH_V1_RESPONSES, q as providerHasContextMetadata, r as findProviderModelMetadata, f as parseOpenAIResponse, g as parseOpenAIResponsesResponse, O as OpenAIRequestSchema, h as OpenAIResponsesRequestSchema, A as AnthropicResponseSchema$1, e as AnthropicRequestSchema, s as safeGetOwnProperty, F as resolveProviderContextWindow, j as getSessionPath, x as previewUpstreamUrl, K as KnowledgeCandidateSchema, H as isPlainRecord, k as stripClaudeCodeBillingHeader, L as LogBodyChunkSchema } from "./router-__o2wrfO.mjs";
3
3
  import { u as useSWR, a as useSWRConfig } from "../_libs/swr.mjs";
4
4
  import { J as JSZip } from "../_libs/jszip.mjs";
5
5
  import { c as clsx } from "../_libs/clsx.mjs";
@@ -9,7 +9,7 @@ import { c as cva } from "../_libs/class-variance-authority.mjs";
9
9
  import { u as useWindowVirtualizer, a as useVirtualizer } from "../_libs/tanstack__react-virtual.mjs";
10
10
  import { d as diffJson, a as diffLines } from "../_libs/diff.mjs";
11
11
  import { R as Root2, T as Trigger, I as Icon, V as Value, P as Portal, C as Content2, a as Viewport, b as Item, c as ItemIndicator, d as ItemText, S as ScrollUpButton, e as ScrollDownButton } from "../_libs/radix-ui__react-select.mjs";
12
- import { T as TriangleAlert, C as CircleCheck, X, I as Info, a as ChevronDown, b as Check, U as Upload, D as Download, F as FileBraces, c as Trash2, P as Plus, A as ArrowLeft, d as ChevronUp, e as Copy, f as ChevronsLeft, g as ChevronLeft, h as ChevronRight, i as ChevronsRight, j as Clapperboard, S as Siren, G as Gauge, L as LoaderCircle, R as RefreshCw, k as Layers, l as Settings, M as Monitor, m as Scan, n as CircleAlert, o as Terminal, p as ArrowUpRight, q as ArrowDownRight, r as Cpu, s as FolderOpen, B as Bell, t as Clock3, u as ShieldAlert, E as EyeOff, v as Eye, w as ExternalLink, x as RotateCw, y as Clock, z as Pencil, H as MessageSquare, Z as Zap, W as Wrench, J as Brain, K as Minus, N as CircleCheckBig, O as CircleQuestionMark, Q as Server, V as Lock, Y as Wifi, _ as WifiOff, $ as CircleX, a0 as ShieldCheck, a1 as Save, a2 as FileSearch, a3 as CloudUpload, a4 as OctagonAlert, a5 as Radio, a6 as Globe, a7 as FileTerminal, a8 as ChevronsUp, a9 as ChevronsDown, aa as FileDiff, ab as History, ac as RotateCcw, ad as Search, ae as GitCompareArrows, af as ArrowUp, ag as ArrowDown, ah as Ellipsis, ai as CodeXml, aj as Blocks, ak as MousePointerClick, al as FileText, am as Rows3, an as Columns2 } from "../_libs/lucide-react.mjs";
12
+ import { T as TriangleAlert, C as CircleCheck, X, I as Info, a as ChevronDown, b as Check, U as Upload, D as Download, F as FileBraces, c as Trash2, P as Plus, A as ArrowLeft, d as ChevronUp, e as Copy, f as ChevronsLeft, g as ChevronLeft, h as ChevronRight, i as ChevronsRight, j as Clapperboard, k as Flag, S as Siren, l as Timer, G as Gauge, L as LoaderCircle, R as RefreshCw, m as Layers, n as Settings, M as Monitor, o as Scan, p as CircleAlert, q as Terminal, r as ArrowUpRight, s as ArrowDownRight, t as Cpu, u as FolderOpen, B as Bell, v as Clock3, w as ShieldAlert, E as EyeOff, x as Eye, y as ExternalLink, z as RotateCw, H as Clock, J as Pencil, K as MessageSquare, Z as Zap, W as Wrench, N as Brain, O as Minus, Q as CircleCheckBig, V as CircleQuestionMark, Y as Server, _ as Lock, $ as Wifi, a0 as WifiOff, a1 as CircleX, a2 as ShieldCheck, a3 as Save, a4 as FileSearch, a5 as CloudUpload, a6 as OctagonAlert, a7 as Radio, a8 as Globe, a9 as FileTerminal, aa as ChevronsUp, ab as ChevronsDown, ac as FileDiff, ad as History, ae as RotateCcw, af as Search, ag as GitCompareArrows, ah as ArrowUp, ai as ArrowDown, aj as Ellipsis, ak as CodeXml, al as Blocks, am as MousePointerClick, an as FileText, ao as Rows3, ap as Columns2 } from "../_libs/lucide-react.mjs";
13
13
  import { u as union, d as object, a as array, l as literal, b as string, n as number, c as boolean, _ as _enum } from "../_libs/zod.mjs";
14
14
  import { S as Slot } from "../_libs/radix-ui__react-slot.mjs";
15
15
  import { R as Root2$1, L as List, T as Trigger$2, C as Content$1 } from "../_libs/radix-ui__react-tabs.mjs";
@@ -522,6 +522,78 @@ function formatTimestamp$2(iso, format) {
522
522
  function formatTimestampRange(startedAt, endedAt, format) {
523
523
  return `${formatTimestamp$2(startedAt, format)} - ${formatTimestamp$2(endedAt, format)}`;
524
524
  }
525
+ function isRecord(value) {
526
+ return typeof value === "object" && value !== null && !Array.isArray(value);
527
+ }
528
+ function normalizeAnthropicStopReason(value) {
529
+ switch (value) {
530
+ case "end_turn":
531
+ case "tool_use":
532
+ return value;
533
+ default:
534
+ return null;
535
+ }
536
+ }
537
+ function normalizeOpenAIFinishReason(value) {
538
+ switch (value) {
539
+ case "stop":
540
+ case "length":
541
+ return value;
542
+ default:
543
+ return null;
544
+ }
545
+ }
546
+ function isResponsesLengthLimitReason(value) {
547
+ switch (value) {
548
+ case "max_output_tokens":
549
+ case "max_tokens":
550
+ return true;
551
+ default:
552
+ return false;
553
+ }
554
+ }
555
+ function extractStopReason(log) {
556
+ if (log.responseText === null) return null;
557
+ try {
558
+ let json = JSON.parse(log.responseText);
559
+ if (typeof json === "string") {
560
+ json = JSON.parse(json);
561
+ }
562
+ if (!isRecord(json)) return null;
563
+ if (typeof json.stop_reason === "string") {
564
+ return normalizeAnthropicStopReason(json.stop_reason);
565
+ }
566
+ if (Array.isArray(json.choices)) {
567
+ for (const choice of json.choices) {
568
+ if (!isRecord(choice) || typeof choice.finish_reason !== "string") continue;
569
+ const reason = normalizeOpenAIFinishReason(choice.finish_reason);
570
+ if (reason !== null) return reason;
571
+ }
572
+ }
573
+ if (Array.isArray(json.output)) {
574
+ for (const item of json.output) {
575
+ if (isRecord(item) && item.type === "function_call") {
576
+ return "tool_use";
577
+ }
578
+ }
579
+ if (json.status === "completed") {
580
+ return "stop";
581
+ }
582
+ }
583
+ if (json.status === "incomplete" && isRecord(json.incomplete_details)) {
584
+ const reason = json.incomplete_details.reason;
585
+ if (typeof reason === "string" && isResponsesLengthLimitReason(reason)) {
586
+ return "length";
587
+ }
588
+ }
589
+ return null;
590
+ } catch {
591
+ return null;
592
+ }
593
+ }
594
+ function isTurnBoundary(stopReason) {
595
+ return stopReason === "end_turn" || stopReason === "stop" || stopReason === "length";
596
+ }
525
597
  function cn(...inputs) {
526
598
  return twMerge(clsx(inputs));
527
599
  }
@@ -1003,7 +1075,6 @@ function TooltipContent({
1003
1075
  ) });
1004
1076
  }
1005
1077
  const MAX_VISIBLE_LOGOS = 3;
1006
- const ROW_CHEVRON_SLOT_CLASS = "flex h-8 w-5 shrink-0 items-center justify-center text-muted-foreground";
1007
1078
  function ProviderLogoStack({
1008
1079
  items,
1009
1080
  ariaLabel,
@@ -1410,6 +1481,28 @@ function resolveLogFormat(log) {
1410
1481
  const pathFormat = apiFormatForPath(log.path);
1411
1482
  return pathFormat === "unknown" ? log.apiFormat : pathFormat;
1412
1483
  }
1484
+ const HEADER_ACTION_BUTTON_CLASS$1 = "border border-input bg-background hover:bg-accent hover:text-accent-foreground inline-flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-md text-muted-foreground transition-colors hover:text-foreground";
1485
+ function HeaderMetric({
1486
+ icon,
1487
+ children,
1488
+ title,
1489
+ className
1490
+ }) {
1491
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
1492
+ "span",
1493
+ {
1494
+ className: cn(
1495
+ "border border-border bg-muted/30 inline-flex h-7 min-w-0 items-center gap-1.5 rounded-md px-2 text-xs text-muted-foreground",
1496
+ className
1497
+ ),
1498
+ title,
1499
+ children: [
1500
+ icon,
1501
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0 font-mono tabular-nums", children })
1502
+ ]
1503
+ }
1504
+ );
1505
+ }
1413
1506
  function ConversationHeader({
1414
1507
  conversationId,
1415
1508
  startTime,
@@ -1453,6 +1546,8 @@ function ConversationHeader({
1453
1546
  const clientTooltip = detectedClientLabel !== null && hasUserAgent ? `${detectedClientLabel} - ${userAgent}` : null;
1454
1547
  const isFallbackConversation = conversationId.startsWith("PID:") || conversationId.includes("|");
1455
1548
  const compactSessionLabel = conversationId.length > 24 ? conversationId.slice(0, 12) + "..." + conversationId.slice(-12) : conversationId;
1549
+ const timeLabel = formatTimestampRange(startTime, endTime, timeDisplayFormat);
1550
+ const callsLabel = `${totalCalls} call${totalCalls !== 1 ? "s" : ""}`;
1456
1551
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
1457
1552
  "div",
1458
1553
  {
@@ -1461,11 +1556,11 @@ function ConversationHeader({
1461
1556
  "data-nav-id": `conv-${conversationId}`,
1462
1557
  "data-nav-action": expanded ? "collapse" : "expand",
1463
1558
  className: cn(
1464
- "border border-border bg-card shadow-sm flex cursor-pointer items-center gap-3 rounded-[8px] px-3 py-2 transition-colors",
1559
+ "border border-border bg-card shadow-sm flex cursor-pointer items-start gap-3 rounded-[8px] px-3 py-2.5 transition-colors",
1465
1560
  "hover:border-cyan-200/20",
1466
1561
  "select-none",
1467
1562
  "sticky top-0 z-10 mb-2",
1468
- "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:outline-none"
1563
+ "focus-visible:ring-1 focus-visible:ring-cyan-300/35 focus-visible:outline-none"
1469
1564
  ),
1470
1565
  onClick: onToggle,
1471
1566
  onKeyDown: (e) => {
@@ -1476,115 +1571,119 @@ function ConversationHeader({
1476
1571
  }
1477
1572
  },
1478
1573
  children: [
1479
- /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderLogoStack, { items: providerLogoItems, ariaLabel: "Models used in this session" }),
1480
- isFallbackConversation && showProcessMetadata ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1481
- clientPid !== null && clientPid !== void 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs(
1482
- "span",
1483
- {
1484
- className: "shrink-0 font-mono text-xs font-semibold text-violet-200",
1485
- title: `PID ${clientPid}`,
1486
- children: [
1487
- "PID ",
1488
- clientPid
1489
- ]
1490
- }
1491
- ) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0 font-mono text-xs font-semibold text-violet-200", children: conversationId }),
1492
- clientProjectFolder !== null && clientProjectFolder !== void 0 && clientProjectFolder !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx(
1493
- "span",
1574
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1575
+ ProviderLogoStack,
1576
+ {
1577
+ items: providerLogoItems,
1578
+ ariaLabel: "Models used in this session",
1579
+ className: "mt-0.5"
1580
+ }
1581
+ ),
1582
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "min-w-0 flex-1", children: [
1583
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: [
1584
+ isFallbackConversation && showProcessMetadata ? clientPid !== null && clientPid !== void 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs(
1585
+ "span",
1586
+ {
1587
+ className: "min-w-0 max-w-full truncate font-mono text-xs font-semibold text-violet-200",
1588
+ title: `PID ${clientPid}`,
1589
+ children: [
1590
+ "PID ",
1591
+ clientPid
1592
+ ]
1593
+ }
1594
+ ) : /* @__PURE__ */ jsxRuntimeExports.jsx(
1595
+ "span",
1596
+ {
1597
+ className: "min-w-0 max-w-full truncate font-mono text-xs font-semibold text-violet-200",
1598
+ title: conversationId,
1599
+ children: conversationId
1600
+ }
1601
+ ) : /* @__PURE__ */ jsxRuntimeExports.jsx(
1602
+ "span",
1603
+ {
1604
+ className: "min-w-0 max-w-full truncate font-mono text-xs font-semibold text-violet-200",
1605
+ title: conversationId,
1606
+ children: isFallbackConversation ? "sessionless" : compactSessionLabel
1607
+ }
1608
+ ),
1609
+ !isFallbackConversation && showProcessMetadata && clientPid !== null && clientPid !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
1610
+ "span",
1611
+ {
1612
+ className: "border border-border bg-muted/40 shrink-0 rounded px-1.5 py-0.5 font-mono text-xs tabular-nums text-muted-foreground",
1613
+ title: `Client process ID ${clientPid}`,
1614
+ children: [
1615
+ "PID ",
1616
+ clientPid
1617
+ ]
1618
+ }
1619
+ ),
1620
+ isFallbackConversation && showProcessMetadata && clientProjectFolder !== null && clientProjectFolder !== void 0 && clientProjectFolder !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx(
1621
+ "span",
1622
+ {
1623
+ className: "min-w-0 max-w-[240px] truncate font-mono text-xs text-muted-foreground",
1624
+ title: clientProjectFolder,
1625
+ children: clientProjectFolder
1626
+ }
1627
+ ),
1628
+ showClientIdentity && clientDisplayLabel !== null && clientDisplayLabel !== "" && /* @__PURE__ */ jsxRuntimeExports.jsxs(
1629
+ "span",
1630
+ {
1631
+ className: "border border-border bg-muted/30 inline-flex h-6 max-w-[180px] shrink-0 items-center gap-1 rounded-md px-1.5 text-xs text-muted-foreground",
1632
+ title: clientTooltip ?? clientDisplayLabel,
1633
+ children: [
1634
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ClientLogo, { client: clientApp, className: "size-4 shrink-0" }),
1635
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate font-mono tabular-nums", children: clientDisplayLabel })
1636
+ ]
1637
+ }
1638
+ )
1639
+ ] }),
1640
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "mt-1.5 flex min-w-0 flex-wrap items-center gap-1.5", children: [
1641
+ /* @__PURE__ */ jsxRuntimeExports.jsx(HeaderMetric, { icon: /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "size-3 shrink-0" }), title: timeLabel, children: timeLabel }),
1642
+ /* @__PURE__ */ jsxRuntimeExports.jsx(HeaderMetric, { icon: /* @__PURE__ */ jsxRuntimeExports.jsx(MessageSquare, { className: "size-3 shrink-0" }), children: callsLabel }),
1643
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(HeaderMetric, { icon: /* @__PURE__ */ jsxRuntimeExports.jsx(Zap, { className: "size-3 shrink-0" }), className: "max-w-full", children: [
1644
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-blue-400", children: formatTokens(totalInputTokens) }),
1645
+ " / ",
1646
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-amber-400", children: formatTokens(totalOutputTokens) })
1647
+ ] })
1648
+ ] })
1649
+ ] }),
1650
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex shrink-0 items-start gap-1.5", children: [
1651
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1652
+ "button",
1494
1653
  {
1495
- className: "text-muted-foreground text-xs font-mono truncate max-w-[200px] shrink-0",
1496
- title: clientProjectFolder,
1497
- children: clientProjectFolder
1654
+ type: "button",
1655
+ onClick: handleOpenInNewTab,
1656
+ onKeyDown: (e) => {
1657
+ if (e.key === "Enter" || e.key === " ") {
1658
+ handleOpenInNewTab(e);
1659
+ }
1660
+ },
1661
+ "aria-label": `Open session ${conversationId} in a new tab`,
1662
+ title: "Open this session in a new tab",
1663
+ className: HEADER_ACTION_BUTTON_CLASS$1,
1664
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(ExternalLink, { className: "size-3.5" })
1498
1665
  }
1499
- )
1500
- ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1501
- /* @__PURE__ */ jsxRuntimeExports.jsx(
1502
- "span",
1666
+ ),
1667
+ onClear !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(
1668
+ "button",
1503
1669
  {
1504
- className: "shrink-0 font-mono text-xs font-semibold text-violet-200",
1505
- title: conversationId,
1506
- children: isFallbackConversation ? "sessionless" : compactSessionLabel
1670
+ type: "button",
1671
+ onClick: handleClearClick,
1672
+ "aria-label": `Clear group (${totalCalls} request${totalCalls !== 1 ? "s" : ""})`,
1673
+ title: "Clear this group",
1674
+ className: HEADER_ACTION_BUTTON_CLASS$1,
1675
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" })
1507
1676
  }
1508
1677
  ),
1509
- showProcessMetadata && clientPid !== null && clientPid !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
1678
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1510
1679
  "span",
1511
1680
  {
1512
- className: "border border-border bg-muted/40 shrink-0 rounded px-1.5 py-0.5 font-mono text-xs tabular-nums text-muted-foreground",
1513
- title: `Client process ID ${clientPid}`,
1514
- children: [
1515
- "PID ",
1516
- clientPid
1517
- ]
1681
+ className: "border border-input bg-background hover:bg-accent hover:text-accent-foreground inline-flex size-8 shrink-0 items-center justify-center rounded-md text-slate-200",
1682
+ "aria-hidden": "true",
1683
+ 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" })
1518
1684
  }
1519
1685
  )
1520
1686
  ] }),
1521
- showClientIdentity && clientDisplayLabel !== null && clientDisplayLabel !== "" && /* @__PURE__ */ jsxRuntimeExports.jsxs(
1522
- "span",
1523
- {
1524
- className: "flex items-center gap-1 text-muted-foreground text-xs shrink-0",
1525
- title: clientTooltip ?? clientDisplayLabel,
1526
- children: [
1527
- /* @__PURE__ */ jsxRuntimeExports.jsx(ClientLogo, { client: clientApp, className: "size-5" }),
1528
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums truncate max-w-[120px]", children: clientDisplayLabel })
1529
- ]
1530
- }
1531
- ),
1532
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1 text-muted-foreground text-xs shrink-0", children: [
1533
- /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "size-3" }),
1534
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", children: formatTimestampRange(startTime, endTime, timeDisplayFormat) })
1535
- ] }),
1536
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1 text-muted-foreground text-xs shrink-0", children: [
1537
- /* @__PURE__ */ jsxRuntimeExports.jsx(MessageSquare, { className: "size-3" }),
1538
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono tabular-nums", children: [
1539
- totalCalls,
1540
- " call",
1541
- totalCalls !== 1 ? "s" : ""
1542
- ] })
1543
- ] }),
1544
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1 text-xs shrink-0", children: [
1545
- /* @__PURE__ */ jsxRuntimeExports.jsx(Zap, { className: "size-3 text-muted-foreground" }),
1546
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono tabular-nums", children: [
1547
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-blue-400", children: formatTokens(totalInputTokens) }),
1548
- " / ",
1549
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-amber-400", children: formatTokens(totalOutputTokens) })
1550
- ] })
1551
- ] }),
1552
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1 min-w-0" }),
1553
- /* @__PURE__ */ jsxRuntimeExports.jsx(
1554
- "button",
1555
- {
1556
- type: "button",
1557
- onClick: handleOpenInNewTab,
1558
- onKeyDown: (e) => {
1559
- if (e.key === "Enter" || e.key === " ") {
1560
- handleOpenInNewTab(e);
1561
- }
1562
- },
1563
- "aria-label": `Open session ${conversationId} in a new tab`,
1564
- title: "Open this session in a new tab",
1565
- className: "border border-input bg-background hover:bg-accent hover:text-accent-foreground inline-flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-md text-muted-foreground transition-colors hover:text-foreground",
1566
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(ExternalLink, { className: "size-3.5" })
1567
- }
1568
- ),
1569
- onClear !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(
1570
- "button",
1571
- {
1572
- type: "button",
1573
- onClick: handleClearClick,
1574
- "aria-label": `Clear group (${totalCalls} request${totalCalls !== 1 ? "s" : ""})`,
1575
- title: "Clear this group",
1576
- className: "border border-input bg-background hover:bg-accent hover:text-accent-foreground inline-flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-md text-muted-foreground transition-colors hover:text-foreground",
1577
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" })
1578
- }
1579
- ),
1580
- /* @__PURE__ */ jsxRuntimeExports.jsx(
1581
- "span",
1582
- {
1583
- className: "border border-input bg-background hover:bg-accent hover:text-accent-foreground inline-flex size-8 shrink-0 items-center justify-center rounded-md text-slate-200",
1584
- "aria-hidden": "true",
1585
- 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" })
1586
- }
1587
- ),
1588
1687
  /* @__PURE__ */ jsxRuntimeExports.jsx(
1589
1688
  ConfirmDialog,
1590
1689
  {
@@ -1667,794 +1766,406 @@ function readLogFocusRequest(event) {
1667
1766
  return null;
1668
1767
  }
1669
1768
  }
1670
- function isRecord(value) {
1671
- return typeof value === "object" && value !== null && !Array.isArray(value);
1769
+ const FULL_EXPAND_NODE_LIMIT = 400;
1770
+ const STRUCTURE_EXPAND_NODE_LIMIT = 2e3;
1771
+ function isJsonArray(value) {
1772
+ return Array.isArray(value);
1672
1773
  }
1673
- function normalizeAnthropicStopReason(value) {
1674
- switch (value) {
1675
- case "end_turn":
1676
- case "tool_use":
1677
- return value;
1678
- default:
1679
- return null;
1774
+ function countJsonNodesUpTo(value, limit) {
1775
+ const stack = [value];
1776
+ let count = 0;
1777
+ while (stack.length > 0) {
1778
+ const current = stack.pop();
1779
+ if (current === void 0) continue;
1780
+ count += 1;
1781
+ if (count > limit) return count;
1782
+ if (current === null || typeof current !== "object") continue;
1783
+ if (isJsonArray(current)) {
1784
+ for (const child of current) {
1785
+ stack.push(child);
1786
+ }
1787
+ continue;
1788
+ }
1789
+ for (const key of Object.keys(current)) {
1790
+ const child = current[key];
1791
+ if (child !== void 0) stack.push(child);
1792
+ }
1680
1793
  }
1794
+ return count;
1681
1795
  }
1682
- function normalizeOpenAIFinishReason(value) {
1683
- switch (value) {
1684
- case "stop":
1685
- case "length":
1686
- return value;
1687
- default:
1688
- return null;
1689
- }
1796
+ function getJsonExpansionPolicy(value) {
1797
+ const nodeCount = countJsonNodesUpTo(value, STRUCTURE_EXPAND_NODE_LIMIT + 1);
1798
+ if (nodeCount <= FULL_EXPAND_NODE_LIMIT) return { depth: Number.POSITIVE_INFINITY };
1799
+ if (nodeCount <= STRUCTURE_EXPAND_NODE_LIMIT) return { depth: 3 };
1800
+ return { depth: 2 };
1690
1801
  }
1691
- function isResponsesLengthLimitReason(value) {
1692
- switch (value) {
1693
- case "max_output_tokens":
1694
- case "max_tokens":
1695
- return true;
1696
- default:
1697
- return false;
1802
+ function parseJsonText(text) {
1803
+ try {
1804
+ const parsed = JSON.parse(text);
1805
+ return { kind: "json", data: safeJsonValue(parsed) };
1806
+ } catch {
1807
+ return { kind: "text" };
1698
1808
  }
1699
1809
  }
1700
- function extractStopReason(log) {
1701
- if (log.responseText === null) return null;
1702
- try {
1703
- let json = JSON.parse(log.responseText);
1704
- if (typeof json === "string") {
1705
- json = JSON.parse(json);
1706
- }
1707
- if (!isRecord(json)) return null;
1708
- if (typeof json.stop_reason === "string") {
1709
- return normalizeAnthropicStopReason(json.stop_reason);
1710
- }
1711
- if (Array.isArray(json.choices)) {
1712
- for (const choice of json.choices) {
1713
- if (!isRecord(choice) || typeof choice.finish_reason !== "string") continue;
1714
- const reason = normalizeOpenAIFinishReason(choice.finish_reason);
1715
- if (reason !== null) return reason;
1716
- }
1717
- }
1718
- if (Array.isArray(json.output)) {
1719
- for (const item of json.output) {
1720
- if (isRecord(item) && item.type === "function_call") {
1721
- return "tool_use";
1722
- }
1723
- }
1724
- if (json.status === "completed") {
1725
- return "stop";
1810
+ function useJsonBulkExpansion(text) {
1811
+ const parsed = reactExports.useMemo(() => text === null ? null : parseJsonText(text), [text]);
1812
+ const parsedData = parsed?.kind === "json" ? parsed.data : null;
1813
+ const policy = reactExports.useMemo(
1814
+ () => parsedData === null ? null : getJsonExpansionPolicy(parsedData),
1815
+ [parsedData]
1816
+ );
1817
+ const [isExpanded, setIsExpanded] = reactExports.useState(false);
1818
+ const [bulkDepth, setBulkDepth] = reactExports.useState(0);
1819
+ const [bulkRevision, setBulkRevision] = reactExports.useState(0);
1820
+ const [isPending, startTransition] = reactExports.useTransition();
1821
+ const toggle = reactExports.useCallback(() => {
1822
+ const nextExpanded = !isExpanded;
1823
+ const targetDepth = nextExpanded && policy !== null ? policy.depth : 0;
1824
+ startTransition(() => {
1825
+ setIsExpanded(nextExpanded);
1826
+ setBulkDepth(targetDepth);
1827
+ setBulkRevision((current) => current + 1);
1828
+ });
1829
+ }, [isExpanded, policy]);
1830
+ return { parsedData, policy, isExpanded, toggle, isPending, bulkDepth, bulkRevision };
1831
+ }
1832
+ function safeJsonValue(value) {
1833
+ if (value === null || value === void 0) return null;
1834
+ switch (typeof value) {
1835
+ case "string":
1836
+ return value;
1837
+ case "number":
1838
+ return value;
1839
+ case "boolean":
1840
+ return value;
1841
+ case "object": {
1842
+ if (Array.isArray(value)) {
1843
+ return value.map((item) => safeJsonValue(item));
1726
1844
  }
1727
- }
1728
- if (json.status === "incomplete" && isRecord(json.incomplete_details)) {
1729
- const reason = json.incomplete_details.reason;
1730
- if (typeof reason === "string" && isResponsesLengthLimitReason(reason)) {
1731
- return "length";
1845
+ const result = {};
1846
+ for (const key of Object.keys(value)) {
1847
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
1848
+ result[key] = safeJsonValue(descriptor?.value);
1732
1849
  }
1850
+ return result;
1733
1851
  }
1734
- return null;
1735
- } catch {
1736
- return null;
1852
+ case "bigint":
1853
+ case "symbol":
1854
+ case "function":
1855
+ case "undefined":
1856
+ return String(value);
1737
1857
  }
1858
+ return null;
1738
1859
  }
1739
- function isTurnBoundary(stopReason) {
1740
- return stopReason === "end_turn" || stopReason === "stop" || stopReason === "length";
1741
- }
1742
- function SvgShell({
1860
+ function Tabs({
1743
1861
  className,
1744
- style,
1745
- d,
1746
- eyeStalks,
1747
- eyes,
1748
- legs,
1749
- extras
1862
+ orientation = "horizontal",
1863
+ ...props
1750
1864
  }) {
1751
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(
1752
- "svg",
1753
- {
1754
- viewBox: "0 0 24 24",
1755
- fill: "none",
1756
- stroke: "currentColor",
1757
- strokeWidth: "1.5",
1758
- strokeLinecap: "round",
1759
- strokeLinejoin: "round",
1760
- "aria-hidden": "true",
1761
- style,
1762
- className: cn("inline-block size-5", className),
1763
- children: [
1764
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d }),
1765
- eyeStalks,
1766
- eyes,
1767
- legs,
1768
- extras
1769
- ]
1770
- }
1771
- );
1772
- }
1773
- const StdLegs = /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1774
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "6.5", y1: "16", x2: "4.5", y2: "19.5" }),
1775
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "9", y1: "17.5", x2: "8", y2: "20.5" }),
1776
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "15", y1: "17.5", x2: "16", y2: "20.5" }),
1777
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "17.5", y1: "16", x2: "19.5", y2: "19.5" })
1778
- ] });
1779
- const ShortLegs = /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1780
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "7", y1: "16", x2: "5.5", y2: "18.5" }),
1781
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "9.5", y1: "17", x2: "8.5", y2: "19.5" }),
1782
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14.5", y1: "17", x2: "15.5", y2: "19.5" }),
1783
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "17", y1: "16", x2: "18.5", y2: "18.5" })
1784
- ] });
1785
- function Crab1({ className }) {
1786
1865
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
1787
- SvgShell,
1866
+ Root2$1,
1788
1867
  {
1789
- className,
1790
- d: "M5 13 C5 9 8 7 12 7 C16 7 19 9 19 13 C19 16 16 18 12 18 C8 18 5 16 5 13 Z",
1791
- eyeStalks: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1792
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10", y1: "7", x2: "9.5", y2: "5" }),
1793
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14", y1: "7", x2: "14.5", y2: "5" })
1794
- ] }),
1795
- eyes: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1796
- /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "9.5", cy: "4.5", r: "0.9", fill: "currentColor", stroke: "none" }),
1797
- /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "14.5", cy: "4.5", r: "0.9", fill: "currentColor", stroke: "none" })
1798
- ] }),
1799
- legs: StdLegs,
1800
- extras: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1801
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M5 11 C3.5 9.5 1.5 10 2 12.5 C2.5 14 4 13.5 5 12.5" }),
1802
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M19 11 C20.5 9.5 22.5 10 22 12.5 C21.5 14 20 13.5 19 12.5" })
1803
- ] })
1868
+ "data-slot": "tabs",
1869
+ "data-orientation": orientation,
1870
+ orientation,
1871
+ className: cn("group/tabs flex gap-2 data-[orientation=horizontal]:flex-col", className),
1872
+ ...props
1804
1873
  }
1805
1874
  );
1806
1875
  }
1807
- function Crab2({ className }) {
1808
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
1809
- SvgShell,
1810
- {
1811
- className,
1812
- d: "M4 13 C4 7 7.5 5.5 12 5.5 C16.5 5.5 20 7 20 13 C20 17.5 16.5 19 12 19 C7.5 19 4 17.5 4 13 Z",
1813
- eyeStalks: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1814
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "9.5", y1: "6.5", x2: "9.5", y2: "4.5" }),
1815
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14.5", y1: "6.5", x2: "14.5", y2: "4.5" })
1816
- ] }),
1817
- eyes: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1818
- /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "9.5", cy: "4", r: "1.1", fill: "currentColor", stroke: "none" }),
1819
- /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "14.5", cy: "4", r: "1.1", fill: "currentColor", stroke: "none" })
1820
- ] }),
1821
- legs: ShortLegs,
1822
- extras: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1823
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M5 11 C4 9.5 2.5 10 3 12 C3.5 13.5 4.5 13 5 12" }),
1824
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M19 11 C20 9.5 21.5 10 21 12 C20.5 13.5 19.5 13 19 12" })
1825
- ] })
1876
+ const tabsListVariants = cva(
1877
+ "rounded-lg p-[3px] group-data-[orientation=horizontal]/tabs:h-9 data-[variant=line]:rounded-none group/tabs-list text-muted-foreground inline-flex w-fit items-center justify-center group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col",
1878
+ {
1879
+ variants: {
1880
+ variant: {
1881
+ default: "bg-muted",
1882
+ line: "gap-1 bg-transparent"
1883
+ }
1884
+ },
1885
+ defaultVariants: {
1886
+ variant: "default"
1826
1887
  }
1827
- );
1828
- }
1829
- function Crab3({ className }) {
1888
+ }
1889
+ );
1890
+ function TabsList({
1891
+ className,
1892
+ variant = "default",
1893
+ ...props
1894
+ }) {
1830
1895
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
1831
- SvgShell,
1896
+ List,
1832
1897
  {
1833
- className,
1834
- d: "M3 13.5 C3 8 7 6 12 6 C17 6 21 8 21 13.5 C21 17 17 19 12 19 C7 19 3 17 3 13.5 Z",
1835
- eyeStalks: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1836
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "7", y1: "7", x2: "6.5", y2: "4.5" }),
1837
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "17", y1: "7", x2: "17.5", y2: "4.5" })
1838
- ] }),
1839
- eyes: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1840
- /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "6.5", cy: "4", r: "0.8", fill: "currentColor", stroke: "none" }),
1841
- /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "17.5", cy: "4", r: "0.8", fill: "currentColor", stroke: "none" })
1842
- ] }),
1843
- legs: StdLegs,
1844
- extras: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1845
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M4 12 C2.5 10.5 1 11 1.5 13 C2 14.5 3.5 14 4.5 13" }),
1846
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M20 12 C21.5 10.5 23 11 22.5 13 C22 14.5 20.5 14 19.5 13" })
1847
- ] })
1898
+ "data-slot": "tabs-list",
1899
+ "data-variant": variant,
1900
+ className: cn(tabsListVariants({ variant }), className),
1901
+ ...props
1848
1902
  }
1849
1903
  );
1850
1904
  }
1851
- function Crab4({ className }) {
1905
+ function TabsTrigger({
1906
+ className,
1907
+ ...props
1908
+ }) {
1852
1909
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
1853
- SvgShell,
1910
+ Trigger$2,
1854
1911
  {
1855
- className,
1856
- d: "M6 14 C6 8 9 5.5 12 5.5 C15 5.5 18 8 18 14 C18 18 15 20 12 20 C9 20 6 18 6 14 Z",
1857
- eyeStalks: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1858
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10", y1: "6.5", x2: "10", y2: "3.5" }),
1859
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14", y1: "6.5", x2: "14", y2: "3.5" })
1860
- ] }),
1861
- eyes: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1862
- /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "10", cy: "3", r: "0.7", fill: "currentColor", stroke: "none" }),
1863
- /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "14", cy: "3", r: "0.7", fill: "currentColor", stroke: "none" })
1864
- ] }),
1865
- legs: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1866
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "7", y1: "17", x2: "5", y2: "20.5" }),
1867
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "9.5", y1: "18.5", x2: "8.5", y2: "21.5" }),
1868
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14.5", y1: "18.5", x2: "15.5", y2: "21.5" }),
1869
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "17", y1: "17", x2: "19", y2: "20.5" })
1870
- ] }),
1871
- extras: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1872
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M6.5 11 C5 8.5 3 9 3.5 11.5 C4 13.5 5 13 6 12" }),
1873
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M17.5 11 C19 8.5 21 9 20.5 11.5 C20 13.5 19 13 18 12" })
1874
- ] })
1912
+ "data-slot": "tabs-trigger",
1913
+ className: cn(
1914
+ "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring text-foreground/60 hover:text-foreground dark:text-muted-foreground dark:hover:text-foreground relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 group-data-[variant=default]/tabs-list:data-[state=active]:shadow-sm group-data-[variant=line]/tabs-list:data-[state=active]:shadow-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
1915
+ "group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:border-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent",
1916
+ "data-[state=active]:bg-background dark:data-[state=active]:text-foreground dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 data-[state=active]:text-foreground",
1917
+ "after:bg-foreground after:absolute after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-[state=active]:after:opacity-100",
1918
+ className
1919
+ ),
1920
+ ...props
1875
1921
  }
1876
1922
  );
1877
1923
  }
1878
- function Crab5({ className }) {
1924
+ function TabsContent({
1925
+ className,
1926
+ ...props
1927
+ }) {
1879
1928
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
1880
- SvgShell,
1929
+ Content$1,
1881
1930
  {
1882
- className,
1883
- d: "M5 13 C5 9 8 7 12 7 L13 4 L14 7 C16 7 19 9 19 13 C19 16 16 18 13 18 L12 21 L11 18 C8 18 5 16 5 13 Z",
1884
- eyeStalks: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1885
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10", y1: "7", x2: "9.5", y2: "5" }),
1886
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14", y1: "7", x2: "14.5", y2: "5" })
1887
- ] }),
1888
- eyes: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1889
- /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "9.5", cy: "4.5", r: "0.8", fill: "currentColor", stroke: "none" }),
1890
- /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "14.5", cy: "4.5", r: "0.8", fill: "currentColor", stroke: "none" })
1891
- ] }),
1892
- legs: StdLegs,
1893
- extras: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1894
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M5 11 C3.5 9.5 1.5 10 2 12.5 C2.5 14 4 13.5 5 12.5" }),
1895
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M19 11 C20.5 9.5 22.5 10 22 12.5 C21.5 14 20 13.5 19 12.5" })
1896
- ] })
1931
+ "data-slot": "tabs-content",
1932
+ className: cn("flex-1 outline-none", className),
1933
+ ...props
1897
1934
  }
1898
1935
  );
1899
1936
  }
1900
- function Crab6({ className }) {
1901
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
1902
- SvgShell,
1903
- {
1904
- className,
1905
- d: "M5 13 C5 9 8 7 12 7 C16 7 19 9 19 13 C19 16 16 18 12 18 C8 18 5 16 5 13 Z",
1906
- eyeStalks: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1907
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10", y1: "7", x2: "9.5", y2: "5" }),
1908
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14", y1: "7", x2: "14.5", y2: "5" })
1909
- ] }),
1910
- eyes: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1911
- /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "9.5", cy: "4.5", r: "0.9", fill: "currentColor", stroke: "none" }),
1912
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "13.5", y1: "4", x2: "15.5", y2: "5" })
1913
- ] }),
1914
- legs: StdLegs,
1915
- extras: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1916
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M5 11 C3.5 9.5 1.5 10 2 12.5 C2.5 14 4 13.5 5 12.5" }),
1917
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M19 11 C20.5 9.5 22.5 10 22 12.5 C21.5 14 20 13.5 19 12.5" })
1918
- ] })
1919
- }
1937
+ function useCopyFeedback(text) {
1938
+ const [copied, setCopied] = reactExports.useState(false);
1939
+ const timerRef = reactExports.useRef(null);
1940
+ reactExports.useEffect(
1941
+ () => () => {
1942
+ if (timerRef.current !== null) clearTimeout(timerRef.current);
1943
+ },
1944
+ []
1920
1945
  );
1921
- }
1922
- function Crab7({ className }) {
1923
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
1924
- SvgShell,
1925
- {
1926
- className,
1927
- d: "M5.5 13.5 C5.5 10 8.5 8 12 8 C15.5 8 18.5 10 18.5 13.5 C18.5 16 15.5 17.5 12 17.5 C8.5 17.5 5.5 16 5.5 13.5 Z",
1928
- eyeStalks: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1929
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10", y1: "8", x2: "10", y2: "6" }),
1930
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14", y1: "8", x2: "14", y2: "6" })
1931
- ] }),
1932
- eyes: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1933
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "9", y1: "6", x2: "11", y2: "6.5" }),
1934
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "13", y1: "6", x2: "15", y2: "6.5" })
1935
- ] }),
1936
- legs: ShortLegs,
1937
- extras: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1938
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M6 11.5 C4.5 10.5 3 11 3.5 12.5 C4 13.5 5 13 5.5 12.5" }),
1939
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M18 11.5 C19.5 10.5 21 11 20.5 12.5 C20 13.5 19 13 18.5 12.5" })
1940
- ] })
1941
- }
1946
+ const copy = reactExports.useCallback(
1947
+ (event) => {
1948
+ event.stopPropagation();
1949
+ if (text === null) return;
1950
+ void copyTextToClipboard(text).then((success) => {
1951
+ if (!success) return;
1952
+ setCopied(true);
1953
+ if (timerRef.current !== null) clearTimeout(timerRef.current);
1954
+ timerRef.current = setTimeout(() => setCopied(false), 2e3);
1955
+ });
1956
+ },
1957
+ [text]
1942
1958
  );
1959
+ return { copied, copy };
1943
1960
  }
1944
- function Crab8({ className }) {
1945
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
1946
- SvgShell,
1947
- {
1948
- className,
1949
- d: "M5 13 C5 9 8 7 12 7 C16 7 19 9 19 13 C19 16 16 18 12 18 C8 18 5 16 5 13 Z",
1950
- eyeStalks: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1951
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10", y1: "7", x2: "9.5", y2: "5" }),
1952
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14", y1: "7", x2: "14.5", y2: "5" })
1953
- ] }),
1954
- eyes: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1955
- /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "9.5", cy: "4.5", r: "0.7", fill: "currentColor", stroke: "none" }),
1956
- /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "14.5", cy: "4.5", r: "0.7", fill: "currentColor", stroke: "none" })
1957
- ] }),
1958
- legs: StdLegs,
1959
- extras: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1960
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M5 11 C3.5 9.5 1.5 10 2 12.5 C2.5 14 4 13.5 5 12.5" }),
1961
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M19 11 C20.5 9.5 22.5 10 22 12.5 C21.5 14 20 13.5 19 12.5" }),
1962
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "8.5", y1: "4", x2: "10.5", y2: "4.5" }),
1963
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "15.5", y1: "4", x2: "13.5", y2: "4.5" }),
1964
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M9 15.5 C10 14.5 14 14.5 15 15.5" })
1965
- ] })
1966
- }
1961
+ const LazyCompareDrawer = reactExports.lazy(
1962
+ () => import("./CompareDrawer-qC3adEeq.mjs").then((m) => ({ default: m.CompareDrawer }))
1963
+ );
1964
+ const LazyReplayDialog = reactExports.lazy(
1965
+ () => import("./ReplayDialog-CvX4XYCi.mjs").then((m) => ({ default: m.ReplayDialog }))
1966
+ );
1967
+ const LazyRequestAnatomy = reactExports.lazy(
1968
+ () => import("./RequestAnatomy-HQfrxjO1.mjs").then((m) => ({ default: m.RequestAnatomy }))
1969
+ );
1970
+ const LazyResponseView = reactExports.lazy(
1971
+ () => import("./ResponseView-QSlSD11e.mjs").then((m) => ({ default: m.ResponseView }))
1972
+ );
1973
+ const LazyStreamingChunkSequence = reactExports.lazy(
1974
+ () => import("./StreamingChunkSequence-DTAiwlnI.mjs").then((m) => ({
1975
+ default: m.StreamingChunkSequence
1976
+ }))
1977
+ );
1978
+ const LazyJsonViewer = reactExports.lazy(
1979
+ () => import("./json-viewer-CrIX0e0Q.mjs").then((m) => ({ default: m.JsonViewer }))
1980
+ );
1981
+ const LazyJsonViewerFromString = reactExports.lazy(
1982
+ () => import("./json-viewer-CrIX0e0Q.mjs").then((m) => ({ default: m.JsonViewerFromString }))
1983
+ );
1984
+ const HIGHLIGHT_DURATION_MS = 1200;
1985
+ const MAX_HIGHLIGHT_ATTEMPTS = 12;
1986
+ function useAnatomyJump(options) {
1987
+ const { containerRef, setExpandToPath, ensureTabActive, highlightMs } = options;
1988
+ const highlightTimer = reactExports.useRef(null);
1989
+ return reactExports.useCallback(
1990
+ (segment2) => {
1991
+ ensureTabActive?.();
1992
+ setExpandToPath(segment2.path);
1993
+ const applyHighlight = (target) => {
1994
+ target.scrollIntoView({ behavior: "smooth", block: "center" });
1995
+ target.classList.add(
1996
+ "ring-2",
1997
+ "ring-primary/60",
1998
+ "ring-offset-1",
1999
+ "ring-offset-background",
2000
+ "rounded-sm",
2001
+ "transition-shadow"
2002
+ );
2003
+ if (highlightTimer.current !== null) clearTimeout(highlightTimer.current);
2004
+ highlightTimer.current = setTimeout(() => {
2005
+ target.classList.remove(
2006
+ "ring-2",
2007
+ "ring-primary/60",
2008
+ "ring-offset-1",
2009
+ "ring-offset-background",
2010
+ "rounded-sm",
2011
+ "transition-shadow"
2012
+ );
2013
+ setExpandToPath(null);
2014
+ }, highlightMs ?? HIGHLIGHT_DURATION_MS);
2015
+ };
2016
+ const escape = (value) => {
2017
+ if (typeof CSS !== "undefined" && typeof CSS.escape === "function") {
2018
+ return CSS.escape(value);
2019
+ }
2020
+ return value.replace(/(["'\\[\](){}])/g, "\\$1");
2021
+ };
2022
+ const selector = `[data-anatomy-path="${escape(segment2.path)}"]`;
2023
+ const tryFindTarget = (attemptsLeft) => {
2024
+ const container = containerRef.current;
2025
+ if (container !== null) {
2026
+ const target = container.querySelector(selector);
2027
+ if (target !== null) {
2028
+ applyHighlight(target);
2029
+ return;
2030
+ }
2031
+ }
2032
+ if (attemptsLeft > 0) {
2033
+ window.requestAnimationFrame(() => tryFindTarget(attemptsLeft - 1));
2034
+ } else {
2035
+ setExpandToPath(null);
2036
+ }
2037
+ };
2038
+ window.requestAnimationFrame(() => tryFindTarget(MAX_HIGHLIGHT_ATTEMPTS));
2039
+ },
2040
+ [containerRef, ensureTabActive, highlightMs, setExpandToPath]
1967
2041
  );
1968
2042
  }
1969
- function Crab9({ className }) {
1970
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
1971
- SvgShell,
1972
- {
1973
- className,
1974
- d: "M5 13 C5 9 8 7 12 7 C16 7 19 9 19 13 C19 16 16 18 12 18 C8 18 5 16 5 13 Z",
1975
- eyeStalks: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1976
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10", y1: "7", x2: "9.5", y2: "5" }),
1977
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14", y1: "7", x2: "14.5", y2: "5" })
1978
- ] }),
1979
- eyes: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1980
- /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "9.5", cy: "4.5", r: "1.2", fill: "none", stroke: "currentColor" }),
1981
- /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "14.5", cy: "4.5", r: "1.2", fill: "none", stroke: "currentColor" })
1982
- ] }),
1983
- legs: StdLegs,
1984
- extras: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1985
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M5 11 C3.5 9.5 1.5 10 2 12.5 C2.5 14 4 13.5 5 12.5" }),
1986
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M19 11 C20.5 9.5 22.5 10 22 12.5 C21.5 14 20 13.5 19 12.5" }),
1987
- /* @__PURE__ */ jsxRuntimeExports.jsx("ellipse", { cx: "12", cy: "15", rx: "2", ry: "1.5", fill: "currentColor", stroke: "none" })
1988
- ] })
1989
- }
1990
- );
2043
+ const DEFAULT_FULL_BODY_HYDRATION_ERROR_DETAIL = "The compact log metadata is still available. Retry if the local server was restarting or the body store was briefly unavailable.";
2044
+ function formatBytes$1(bytes) {
2045
+ if (bytes < 1024) return `${bytes.toLocaleString()} B`;
2046
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KiB`;
2047
+ if (bytes < 1024 * 1024 * 1024) return `${(bytes / 1024 / 1024).toFixed(1)} MiB`;
2048
+ return `${(bytes / 1024 / 1024 / 1024).toFixed(1)} GiB`;
1991
2049
  }
1992
- function Crab10({ className }) {
1993
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
1994
- SvgShell,
1995
- {
1996
- className,
1997
- d: "M4.5 13 C4.5 8 7.5 6 12 6 C16.5 6 19.5 8 19.5 13 C19.5 17 16.5 18.5 12 18.5 C7.5 18.5 4.5 17 4.5 13 Z",
1998
- eyeStalks: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1999
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "9.5", y1: "7", x2: "9", y2: "5" }),
2000
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14.5", y1: "7", x2: "15", y2: "5" })
2001
- ] }),
2002
- eyes: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
2003
- /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "9", cy: "4.5", r: "1", fill: "currentColor", stroke: "none" }),
2004
- /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "15", cy: "4.5", r: "1", fill: "currentColor", stroke: "none" })
2005
- ] }),
2006
- legs: StdLegs,
2007
- extras: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
2008
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M5 11 C3.5 9 2 9.5 2.5 12 C3 14 4 13 5 12" }),
2009
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M19 11 C20.5 9 22 9.5 21.5 12 C21 14 20 13 19 12" }),
2010
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M9 14.5 C10 16 14 16 15 14.5" }),
2011
- /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "7", cy: "13", r: "1", fill: "currentColor", stroke: "none", opacity: "0.3" }),
2012
- /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "17", cy: "13", r: "1", fill: "currentColor", stroke: "none", opacity: "0.3" })
2013
- ] })
2014
- }
2015
- );
2050
+ function formatBodyHydrationFootprint(requestBytes, responseBytes) {
2051
+ const parts = [];
2052
+ if (requestBytes !== null && requestBytes !== void 0) {
2053
+ parts.push(`Request ${formatBytes$1(requestBytes)}`);
2054
+ }
2055
+ if (responseBytes !== null && responseBytes !== void 0) {
2056
+ parts.push(`Response ${formatBytes$1(responseBytes)}`);
2057
+ }
2058
+ return parts.length === 0 ? null : parts.join(" · ");
2016
2059
  }
2017
- function Crab11({ className }) {
2018
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
2019
- SvgShell,
2020
- {
2021
- className,
2022
- d: "M5 13 C5 9 8 7 12 7 C16 7 19 9 19 13 C19 16 16 18 12 18 C8 18 5 16 5 13 Z",
2023
- eyeStalks: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
2024
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10", y1: "7", x2: "9.5", y2: "5.5" }),
2025
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14", y1: "7", x2: "14.5", y2: "5.5" })
2026
- ] }),
2027
- eyes: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
2028
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "7.5", y1: "5.5", x2: "16.5", y2: "5.5" }),
2029
- /* @__PURE__ */ jsxRuntimeExports.jsx("rect", { x: "7", y: "5", width: "4", height: "2", rx: "0.5", fill: "currentColor", stroke: "none" }),
2030
- /* @__PURE__ */ jsxRuntimeExports.jsx("rect", { x: "13", y: "5", width: "4", height: "2", rx: "0.5", fill: "currentColor", stroke: "none" })
2031
- ] }),
2032
- legs: StdLegs,
2033
- extras: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
2034
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M5 11 C3.5 9.5 1.5 10 2 12.5 C2.5 14 4 13.5 5 12.5" }),
2035
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M19 11 C20.5 9.5 22.5 10 22 12.5 C21.5 14 20 13.5 19 12.5" }),
2036
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M9.5 15 C10.5 16 13.5 16 14.5 15" })
2037
- ] })
2038
- }
2039
- );
2060
+ function describeFullBodyHydrationError(error) {
2061
+ if (error instanceof ApiTimeoutError) {
2062
+ return {
2063
+ title: "Full bodies timed out",
2064
+ detail: "The log store did not answer before the UI timeout. Compact metadata is still available; retry loading the bodies."
2065
+ };
2066
+ }
2067
+ if (error instanceof Error) {
2068
+ const message = error.message.trim();
2069
+ return {
2070
+ title: "Full bodies could not be loaded",
2071
+ detail: message === "" ? DEFAULT_FULL_BODY_HYDRATION_ERROR_DETAIL : message
2072
+ };
2073
+ }
2074
+ return {
2075
+ title: "Full bodies could not be loaded",
2076
+ detail: DEFAULT_FULL_BODY_HYDRATION_ERROR_DETAIL
2077
+ };
2040
2078
  }
2041
- function Crab12({ className }) {
2042
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
2043
- SvgShell,
2044
- {
2045
- className,
2046
- d: "M7 13.5 C7 10.5 9.5 9 12 9 C14.5 9 17 10.5 17 13.5 C17 16 14.5 17.5 12 17.5 C9.5 17.5 7 16 7 13.5 Z",
2047
- eyeStalks: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
2048
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10.5", y1: "9.5", x2: "10.5", y2: "8" }),
2049
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "13.5", y1: "9.5", x2: "13.5", y2: "8" })
2050
- ] }),
2051
- eyes: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
2052
- /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "10.5", cy: "7.5", r: "0.8", fill: "currentColor", stroke: "none" }),
2053
- /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "13.5", cy: "7.5", r: "0.8", fill: "currentColor", stroke: "none" })
2054
- ] }),
2055
- legs: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
2056
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "8", y1: "16", x2: "6.5", y2: "18" }),
2057
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10", y1: "17", x2: "9.5", y2: "19" }),
2058
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14", y1: "17", x2: "14.5", y2: "19" }),
2059
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "16", y1: "16", x2: "17.5", y2: "18" })
2060
- ] }),
2061
- extras: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
2062
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M7.5 12 C6.5 11 5.5 11.5 6 13 C6.5 14 7 13.5 7.5 13" }),
2063
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M16.5 12 C17.5 11 18.5 11.5 18 13 C17.5 14 17 13.5 16.5 13" })
2064
- ] })
2065
- }
2066
- );
2067
- }
2068
- const crabVariants = [
2069
- Crab1,
2070
- Crab2,
2071
- Crab3,
2072
- Crab4,
2073
- Crab5,
2074
- Crab6,
2075
- Crab7,
2076
- Crab8,
2077
- Crab9,
2078
- Crab10,
2079
- Crab11,
2080
- Crab12
2081
- ];
2082
- function getCrabVariant(index) {
2083
- return crabVariants[Math.abs(index) % crabVariants.length] ?? Crab1;
2084
- }
2085
- function getInteriorCrabVariantIndex(seed) {
2086
- const interiorCount = crabVariants.length - 2;
2087
- if (interiorCount <= 0) return 0;
2088
- const normalizedSeed = Number.isFinite(seed) ? Math.trunc(seed) : 0;
2089
- return 1 + (normalizedSeed % interiorCount + interiorCount) % interiorCount;
2090
- }
2091
- function getInteriorCrabVariant(seed) {
2092
- return getCrabVariant(getInteriorCrabVariantIndex(seed));
2079
+ function normalizeHeaders(headers) {
2080
+ if (headers === void 0) return [];
2081
+ return Object.entries(headers).map((entry) => [entry[0].toLowerCase(), entry[1]]).sort(([a], [b]) => a.localeCompare(b));
2093
2082
  }
2094
- const FULL_EXPAND_NODE_LIMIT = 400;
2095
- const STRUCTURE_EXPAND_NODE_LIMIT = 2e3;
2096
- function isJsonArray(value) {
2097
- return Array.isArray(value);
2083
+ function headerLine([key, value]) {
2084
+ return `${key}: ${value}`;
2098
2085
  }
2099
- function countJsonNodesUpTo(value, limit) {
2100
- const stack = [value];
2101
- let count = 0;
2102
- while (stack.length > 0) {
2103
- const current = stack.pop();
2104
- if (current === void 0) continue;
2105
- count += 1;
2106
- if (count > limit) return count;
2107
- if (current === null || typeof current !== "object") continue;
2108
- if (isJsonArray(current)) {
2109
- for (const child of current) {
2110
- stack.push(child);
2086
+ function changesToLines(changes) {
2087
+ const lines = [];
2088
+ let oldNum = 0;
2089
+ let newNum = 0;
2090
+ for (const change of changes) {
2091
+ const parts = change.value.split("\n");
2092
+ if (parts.length > 0 && parts[parts.length - 1] === "") parts.pop();
2093
+ for (const text of parts) {
2094
+ if (change.added) {
2095
+ newNum += 1;
2096
+ lines.push({ kind: "added", text, oldLineNumber: null, newLineNumber: newNum });
2097
+ } else if (change.removed) {
2098
+ oldNum += 1;
2099
+ lines.push({ kind: "removed", text, oldLineNumber: oldNum, newLineNumber: null });
2100
+ } else {
2101
+ oldNum += 1;
2102
+ newNum += 1;
2103
+ lines.push({
2104
+ kind: "context",
2105
+ text,
2106
+ oldLineNumber: oldNum,
2107
+ newLineNumber: newNum
2108
+ });
2111
2109
  }
2112
- continue;
2113
- }
2114
- for (const key of Object.keys(current)) {
2115
- const child = current[key];
2116
- if (child !== void 0) stack.push(child);
2117
2110
  }
2118
2111
  }
2119
- return count;
2112
+ return lines;
2120
2113
  }
2121
- function getJsonExpansionPolicy(value) {
2122
- const nodeCount = countJsonNodesUpTo(value, STRUCTURE_EXPAND_NODE_LIMIT + 1);
2123
- if (nodeCount <= FULL_EXPAND_NODE_LIMIT) return { depth: Number.POSITIVE_INFINITY };
2124
- if (nodeCount <= STRUCTURE_EXPAND_NODE_LIMIT) return { depth: 3 };
2125
- return { depth: 2 };
2114
+ function computeHeadersDiff(rawHeaders, processedHeaders) {
2115
+ const left = normalizeHeaders(rawHeaders).map(headerLine).join("\n");
2116
+ const right = normalizeHeaders(processedHeaders).map(headerLine).join("\n");
2117
+ if (left === right) {
2118
+ return { lines: [], isEmpty: true };
2119
+ }
2120
+ const changes = diffLines(left, right);
2121
+ return { lines: changesToLines(changes), isEmpty: false };
2126
2122
  }
2127
- function parseJsonText(text) {
2123
+ function tryParseJson(text) {
2128
2124
  try {
2129
2125
  const parsed = JSON.parse(text);
2130
- return { kind: "json", data: safeJsonValue(parsed) };
2126
+ if (parsed === null) return parsed;
2127
+ if (typeof parsed === "string" || typeof parsed === "object") return parsed;
2128
+ return null;
2131
2129
  } catch {
2132
- return { kind: "text" };
2130
+ return null;
2133
2131
  }
2134
2132
  }
2135
- function useJsonBulkExpansion(text) {
2136
- const parsed = reactExports.useMemo(() => text === null ? null : parseJsonText(text), [text]);
2137
- const parsedData = parsed?.kind === "json" ? parsed.data : null;
2138
- const policy = reactExports.useMemo(
2139
- () => parsedData === null ? null : getJsonExpansionPolicy(parsedData),
2140
- [parsedData]
2141
- );
2142
- const [isExpanded, setIsExpanded] = reactExports.useState(false);
2143
- const [bulkDepth, setBulkDepth] = reactExports.useState(0);
2144
- const [bulkRevision, setBulkRevision] = reactExports.useState(0);
2145
- const [isPending, startTransition] = reactExports.useTransition();
2146
- const toggle = reactExports.useCallback(() => {
2147
- const nextExpanded = !isExpanded;
2148
- const targetDepth = nextExpanded && policy !== null ? policy.depth : 0;
2149
- startTransition(() => {
2150
- setIsExpanded(nextExpanded);
2151
- setBulkDepth(targetDepth);
2152
- setBulkRevision((current) => current + 1);
2153
- });
2154
- }, [isExpanded, policy]);
2155
- return { parsedData, policy, isExpanded, toggle, isPending, bulkDepth, bulkRevision };
2156
- }
2157
- function safeJsonValue(value) {
2158
- if (value === null || value === void 0) return null;
2159
- switch (typeof value) {
2160
- case "string":
2161
- return value;
2162
- case "number":
2163
- return value;
2164
- case "boolean":
2165
- return value;
2166
- case "object": {
2167
- if (Array.isArray(value)) {
2168
- return value.map((item) => safeJsonValue(item));
2169
- }
2170
- const result = {};
2171
- for (const key of Object.keys(value)) {
2172
- const descriptor = Object.getOwnPropertyDescriptor(value, key);
2173
- result[key] = safeJsonValue(descriptor?.value);
2174
- }
2175
- return result;
2176
- }
2177
- case "bigint":
2178
- case "symbol":
2179
- case "function":
2180
- case "undefined":
2181
- return String(value);
2133
+ function computeRequestDiff(rawBody, processedBody) {
2134
+ const left = rawBody ?? "";
2135
+ const right = processedBody ?? "";
2136
+ if (left === right) {
2137
+ return { lines: [], isEmpty: true };
2182
2138
  }
2183
- return null;
2184
- }
2185
- function Tabs({
2186
- className,
2187
- orientation = "horizontal",
2188
- ...props
2189
- }) {
2190
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
2191
- Root2$1,
2192
- {
2193
- "data-slot": "tabs",
2194
- "data-orientation": orientation,
2195
- orientation,
2196
- className: cn("group/tabs flex gap-2 data-[orientation=horizontal]:flex-col", className),
2197
- ...props
2198
- }
2199
- );
2200
- }
2201
- const tabsListVariants = cva(
2202
- "rounded-lg p-[3px] group-data-[orientation=horizontal]/tabs:h-9 data-[variant=line]:rounded-none group/tabs-list text-muted-foreground inline-flex w-fit items-center justify-center group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col",
2203
- {
2204
- variants: {
2205
- variant: {
2206
- default: "bg-muted",
2207
- line: "gap-1 bg-transparent"
2139
+ const leftJson = tryParseJson(left);
2140
+ const rightJson = tryParseJson(right);
2141
+ if (leftJson !== null && rightJson !== null) {
2142
+ const changes2 = diffJson(leftJson, rightJson) ?? [];
2143
+ if (changes2.length === 1) {
2144
+ const first = changes2[0];
2145
+ if (first !== void 0 && !first.added && !first.removed) {
2146
+ return { lines: [], isEmpty: true };
2208
2147
  }
2209
- },
2210
- defaultVariants: {
2211
- variant: "default"
2212
2148
  }
2149
+ return { lines: changesToLines(changes2), isEmpty: false };
2213
2150
  }
2214
- );
2215
- function TabsList({
2216
- className,
2217
- variant = "default",
2218
- ...props
2219
- }) {
2220
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
2221
- List,
2222
- {
2223
- "data-slot": "tabs-list",
2224
- "data-variant": variant,
2225
- className: cn(tabsListVariants({ variant }), className),
2226
- ...props
2227
- }
2228
- );
2151
+ const changes = diffLines(left, right);
2152
+ return { lines: changesToLines(changes), isEmpty: false };
2229
2153
  }
2230
- function TabsTrigger({
2231
- className,
2232
- ...props
2233
- }) {
2234
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
2235
- Trigger$2,
2236
- {
2237
- "data-slot": "tabs-trigger",
2238
- className: cn(
2239
- "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring text-foreground/60 hover:text-foreground dark:text-muted-foreground dark:hover:text-foreground relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 group-data-[variant=default]/tabs-list:data-[state=active]:shadow-sm group-data-[variant=line]/tabs-list:data-[state=active]:shadow-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
2240
- "group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:border-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent",
2241
- "data-[state=active]:bg-background dark:data-[state=active]:text-foreground dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 data-[state=active]:text-foreground",
2242
- "after:bg-foreground after:absolute after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-[state=active]:after:opacity-100",
2243
- className
2244
- ),
2245
- ...props
2246
- }
2247
- );
2154
+ const ESTIMATED_LINE_HEIGHT = 22;
2155
+ const MAX_RENDERED_LINES = 1e4;
2156
+ function kindPrefix(kind) {
2157
+ if (kind === "added") return "+";
2158
+ if (kind === "removed") return "-";
2159
+ return " ";
2248
2160
  }
2249
- function TabsContent({
2250
- className,
2251
- ...props
2252
- }) {
2253
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
2254
- Content$1,
2255
- {
2256
- "data-slot": "tabs-content",
2257
- className: cn("flex-1 outline-none", className),
2258
- ...props
2259
- }
2260
- );
2261
- }
2262
- function useCopyFeedback(text) {
2263
- const [copied, setCopied] = reactExports.useState(false);
2264
- const timerRef = reactExports.useRef(null);
2265
- reactExports.useEffect(
2266
- () => () => {
2267
- if (timerRef.current !== null) clearTimeout(timerRef.current);
2268
- },
2269
- []
2270
- );
2271
- const copy = reactExports.useCallback(
2272
- (event) => {
2273
- event.stopPropagation();
2274
- if (text === null) return;
2275
- void copyTextToClipboard(text).then((success) => {
2276
- if (!success) return;
2277
- setCopied(true);
2278
- if (timerRef.current !== null) clearTimeout(timerRef.current);
2279
- timerRef.current = setTimeout(() => setCopied(false), 2e3);
2280
- });
2281
- },
2282
- [text]
2283
- );
2284
- return { copied, copy };
2285
- }
2286
- const LazyCompareDrawer = reactExports.lazy(
2287
- () => import("./CompareDrawer-CO-Ti5sg.mjs").then((m) => ({ default: m.CompareDrawer }))
2288
- );
2289
- const LazyReplayDialog = reactExports.lazy(
2290
- () => import("./ReplayDialog-J1VxC0In.mjs").then((m) => ({ default: m.ReplayDialog }))
2291
- );
2292
- const LazyRequestAnatomy = reactExports.lazy(
2293
- () => import("./RequestAnatomy-DBH-F3rq.mjs").then((m) => ({ default: m.RequestAnatomy }))
2294
- );
2295
- const LazyResponseView = reactExports.lazy(
2296
- () => import("./ResponseView-DLFwV7Hd.mjs").then((m) => ({ default: m.ResponseView }))
2297
- );
2298
- const LazyStreamingChunkSequence = reactExports.lazy(
2299
- () => import("./StreamingChunkSequence-BywmuND0.mjs").then((m) => ({
2300
- default: m.StreamingChunkSequence
2301
- }))
2302
- );
2303
- const LazyJsonViewer = reactExports.lazy(
2304
- () => import("./json-viewer-DlQu0N1x.mjs").then((m) => ({ default: m.JsonViewer }))
2305
- );
2306
- const LazyJsonViewerFromString = reactExports.lazy(
2307
- () => import("./json-viewer-DlQu0N1x.mjs").then((m) => ({ default: m.JsonViewerFromString }))
2308
- );
2309
- const HIGHLIGHT_DURATION_MS = 1200;
2310
- const MAX_HIGHLIGHT_ATTEMPTS = 12;
2311
- function useAnatomyJump(options) {
2312
- const { containerRef, setExpandToPath, ensureTabActive, highlightMs } = options;
2313
- const highlightTimer = reactExports.useRef(null);
2314
- return reactExports.useCallback(
2315
- (segment2) => {
2316
- ensureTabActive?.();
2317
- setExpandToPath(segment2.path);
2318
- const applyHighlight = (target) => {
2319
- target.scrollIntoView({ behavior: "smooth", block: "center" });
2320
- target.classList.add(
2321
- "ring-2",
2322
- "ring-primary/60",
2323
- "ring-offset-1",
2324
- "ring-offset-background",
2325
- "rounded-sm",
2326
- "transition-shadow"
2327
- );
2328
- if (highlightTimer.current !== null) clearTimeout(highlightTimer.current);
2329
- highlightTimer.current = setTimeout(() => {
2330
- target.classList.remove(
2331
- "ring-2",
2332
- "ring-primary/60",
2333
- "ring-offset-1",
2334
- "ring-offset-background",
2335
- "rounded-sm",
2336
- "transition-shadow"
2337
- );
2338
- setExpandToPath(null);
2339
- }, highlightMs ?? HIGHLIGHT_DURATION_MS);
2340
- };
2341
- const escape = (value) => {
2342
- if (typeof CSS !== "undefined" && typeof CSS.escape === "function") {
2343
- return CSS.escape(value);
2344
- }
2345
- return value.replace(/(["'\\[\](){}])/g, "\\$1");
2346
- };
2347
- const selector = `[data-anatomy-path="${escape(segment2.path)}"]`;
2348
- const tryFindTarget = (attemptsLeft) => {
2349
- const container = containerRef.current;
2350
- if (container !== null) {
2351
- const target = container.querySelector(selector);
2352
- if (target !== null) {
2353
- applyHighlight(target);
2354
- return;
2355
- }
2356
- }
2357
- if (attemptsLeft > 0) {
2358
- window.requestAnimationFrame(() => tryFindTarget(attemptsLeft - 1));
2359
- } else {
2360
- setExpandToPath(null);
2361
- }
2362
- };
2363
- window.requestAnimationFrame(() => tryFindTarget(MAX_HIGHLIGHT_ATTEMPTS));
2364
- },
2365
- [containerRef, ensureTabActive, highlightMs, setExpandToPath]
2366
- );
2367
- }
2368
- function normalizeHeaders(headers) {
2369
- if (headers === void 0) return [];
2370
- return Object.entries(headers).map((entry) => [entry[0].toLowerCase(), entry[1]]).sort(([a], [b]) => a.localeCompare(b));
2371
- }
2372
- function headerLine([key, value]) {
2373
- return `${key}: ${value}`;
2374
- }
2375
- function changesToLines(changes) {
2376
- const lines = [];
2377
- let oldNum = 0;
2378
- let newNum = 0;
2379
- for (const change of changes) {
2380
- const parts = change.value.split("\n");
2381
- if (parts.length > 0 && parts[parts.length - 1] === "") parts.pop();
2382
- for (const text of parts) {
2383
- if (change.added) {
2384
- newNum += 1;
2385
- lines.push({ kind: "added", text, oldLineNumber: null, newLineNumber: newNum });
2386
- } else if (change.removed) {
2387
- oldNum += 1;
2388
- lines.push({ kind: "removed", text, oldLineNumber: oldNum, newLineNumber: null });
2389
- } else {
2390
- oldNum += 1;
2391
- newNum += 1;
2392
- lines.push({
2393
- kind: "context",
2394
- text,
2395
- oldLineNumber: oldNum,
2396
- newLineNumber: newNum
2397
- });
2398
- }
2399
- }
2400
- }
2401
- return lines;
2402
- }
2403
- function computeHeadersDiff(rawHeaders, processedHeaders) {
2404
- const left = normalizeHeaders(rawHeaders).map(headerLine).join("\n");
2405
- const right = normalizeHeaders(processedHeaders).map(headerLine).join("\n");
2406
- if (left === right) {
2407
- return { lines: [], isEmpty: true };
2408
- }
2409
- const changes = diffLines(left, right);
2410
- return { lines: changesToLines(changes), isEmpty: false };
2411
- }
2412
- function tryParseJson(text) {
2413
- try {
2414
- const parsed = JSON.parse(text);
2415
- if (parsed === null) return parsed;
2416
- if (typeof parsed === "string" || typeof parsed === "object") return parsed;
2417
- return null;
2418
- } catch {
2419
- return null;
2420
- }
2421
- }
2422
- function computeRequestDiff(rawBody, processedBody) {
2423
- const left = rawBody ?? "";
2424
- const right = processedBody ?? "";
2425
- if (left === right) {
2426
- return { lines: [], isEmpty: true };
2427
- }
2428
- const leftJson = tryParseJson(left);
2429
- const rightJson = tryParseJson(right);
2430
- if (leftJson !== null && rightJson !== null) {
2431
- const changes2 = diffJson(leftJson, rightJson) ?? [];
2432
- if (changes2.length === 1) {
2433
- const first = changes2[0];
2434
- if (first !== void 0 && !first.added && !first.removed) {
2435
- return { lines: [], isEmpty: true };
2436
- }
2437
- }
2438
- return { lines: changesToLines(changes2), isEmpty: false };
2439
- }
2440
- const changes = diffLines(left, right);
2441
- return { lines: changesToLines(changes), isEmpty: false };
2442
- }
2443
- const ESTIMATED_LINE_HEIGHT = 22;
2444
- const MAX_RENDERED_LINES = 1e4;
2445
- function kindPrefix(kind) {
2446
- if (kind === "added") return "+";
2447
- if (kind === "removed") return "-";
2448
- return " ";
2449
- }
2450
- function kindClass(kind) {
2451
- if (kind === "added") {
2452
- return "bg-green-500/10 text-green-700 dark:text-green-300";
2453
- }
2454
- if (kind === "removed") {
2455
- return "bg-red-500/10 text-red-700 dark:text-red-300";
2456
- }
2457
- return "text-foreground/80";
2161
+ function kindClass(kind) {
2162
+ if (kind === "added") {
2163
+ return "bg-green-500/10 text-green-700 dark:text-green-300";
2164
+ }
2165
+ if (kind === "removed") {
2166
+ return "bg-red-500/10 text-red-700 dark:text-red-300";
2167
+ }
2168
+ return "text-foreground/80";
2458
2169
  }
2459
2170
  const DiffViewInner = function DiffView2({ result, emptyLabel }) {
2460
2171
  const [mode, setMode] = reactExports.useState("unified");
@@ -2814,6 +2525,8 @@ const LogEntryHeader = reactExports.memo(function({
2814
2525
  const hasClientCwd = log.clientCwd !== null && log.clientCwd !== void 0 && log.clientCwd !== "";
2815
2526
  const statusCue = STATUS_CUE_CLASSES[statusCategory];
2816
2527
  const statusLabel2 = statusCueLabel(statusCategory, log.responseStatus);
2528
+ const showStatusBadge = statusCategory !== "success" || log.responseStatus !== 200;
2529
+ const showStandaloneStreamingIndicator = log.streaming && firstChunkLabel === null && tokenRateLabel === null;
2817
2530
  return /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
2818
2531
  "div",
2819
2532
  {
@@ -2823,7 +2536,7 @@ const LogEntryHeader = reactExports.memo(function({
2823
2536
  "data-nav-id": `log-${log.id}`,
2824
2537
  "data-nav-action": expanded ? "collapse" : "expand",
2825
2538
  className: cn(
2826
- "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]",
2539
+ "group/header relative isolate flex min-w-0 cursor-pointer items-start gap-2 overflow-hidden px-3 py-2 transition-[background-color,border-color,box-shadow]",
2827
2540
  expanded ? "bg-white/[0.035] shadow-[inset_0_1px_0_rgba(255,255,255,0.10)]" : "bg-transparent hover:bg-white/[0.035]",
2828
2541
  "select-none before:pointer-events-none before:absolute before:inset-x-3 before:top-0 before:h-px before:bg-white/12",
2829
2542
  "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:outline-none"
@@ -2836,277 +2549,286 @@ const LogEntryHeader = reactExports.memo(function({
2836
2549
  }
2837
2550
  },
2838
2551
  children: [
2839
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
2840
- "span",
2841
- {
2842
- className: cn(
2843
- "border border-border bg-muted/40 inline-flex h-8 shrink-0 items-center gap-2 rounded-md px-2 font-mono",
2844
- statusCue.frame
2845
- ),
2846
- children: [
2847
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn("size-1.5 rounded-full", statusCue.dot), "aria-hidden": "true" }),
2848
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xs font-semibold tabular-nums", title: `Log ID ${String(log.id)}`, children: [
2849
- "#",
2850
- displayNumber
2851
- ] })
2852
- ]
2853
- }
2854
- ),
2855
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "border border-border bg-muted/40 flex h-7 shrink-0 items-center gap-1 rounded-md px-2 text-xs text-muted-foreground", children: [
2856
- /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "size-3" }),
2857
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", title: log.timestamp, children: formatTimestamp$2(log.timestamp, timeDisplayFormat) })
2858
- ] }),
2859
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
2860
- Badge,
2861
- {
2862
- variant: "outline",
2863
- className: cn(
2864
- "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)]",
2865
- STATUS_BADGE_CLASSES[statusCategory]
2866
- ),
2867
- children: [
2868
- 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" }),
2869
- statusLabel2
2870
- ]
2871
- }
2872
- ),
2873
- warningCount > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
2874
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
2875
- Badge,
2552
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 flex-1 flex-wrap items-center gap-x-2 gap-y-1", children: [
2553
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
2554
+ "span",
2876
2555
  {
2877
- variant: "outline",
2878
- 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",
2556
+ className: cn(
2557
+ "border border-border bg-muted/40 inline-flex h-8 shrink-0 items-center gap-2 rounded-md px-2 font-mono",
2558
+ statusCue.frame
2559
+ ),
2879
2560
  children: [
2880
- /* @__PURE__ */ jsxRuntimeExports.jsx(TriangleAlert, { className: "size-3", "aria-label": "Tool schema warnings" }),
2881
- warningCount
2561
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn("size-1.5 rounded-full", statusCue.dot), "aria-hidden": "true" }),
2562
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xs font-semibold tabular-nums", title: `Log ID ${String(log.id)}`, children: [
2563
+ "#",
2564
+ displayNumber
2565
+ ] })
2882
2566
  ]
2883
2567
  }
2884
- ) }),
2885
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: warningCount === 1 ? "1 tool schema warning" : `${warningCount} tool schema warnings` })
2886
- ] }),
2887
- log.elapsedMs !== null && (isSlowResponse ? /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
2888
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
2889
- "span",
2568
+ ),
2569
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "border border-border bg-muted/40 flex h-7 shrink-0 items-center gap-1 rounded-md px-2 text-xs text-muted-foreground", children: [
2570
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "size-3" }),
2571
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", title: log.timestamp, children: formatTimestamp$2(log.timestamp, timeDisplayFormat) })
2572
+ ] }),
2573
+ showStatusBadge && /* @__PURE__ */ jsxRuntimeExports.jsxs(
2574
+ Badge,
2890
2575
  {
2576
+ variant: "outline",
2891
2577
  className: cn(
2892
- TELEMETRY_CHIP_CLASS,
2893
- "shrink-0 border-amber-300/25 text-amber-200"
2578
+ "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)]",
2579
+ STATUS_BADGE_CLASSES[statusCategory]
2894
2580
  ),
2895
2581
  children: [
2896
- /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "size-3" }),
2897
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", children: formatElapsed$3(log.elapsedMs) }),
2898
- /* @__PURE__ */ jsxRuntimeExports.jsx(TriangleAlert, { className: "size-3", "aria-label": "Slow response" })
2582
+ 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" }),
2583
+ statusLabel2
2899
2584
  ]
2900
2585
  }
2901
- ) }),
2902
- /* @__PURE__ */ jsxRuntimeExports.jsxs(TooltipContent, { children: [
2903
- "Slow response: ",
2904
- formatElapsed$3(log.elapsedMs),
2905
- " exceeds",
2906
- " ",
2907
- formatElapsed$3(slowResponseThresholdSeconds * 1e3)
2908
- ] })
2909
- ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: cn(TELEMETRY_CHIP_CLASS, "shrink-0 text-muted-foreground"), children: [
2910
- /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "size-3" }),
2911
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", children: formatElapsed$3(log.elapsedMs) })
2912
- ] })),
2913
- log.streaming && firstChunkLabel !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
2914
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: cn(TELEMETRY_CHIP_CLASS, "shrink-0 text-cyan-300"), children: [
2915
- /* @__PURE__ */ jsxRuntimeExports.jsx(Radio, { className: "size-3" }),
2916
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono tabular-nums", children: [
2917
- "first ",
2918
- firstChunkLabel
2919
- ] })
2920
- ] }) }),
2921
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Time to first streaming chunk" })
2922
- ] }),
2923
- log.streaming && tokenRateLabel !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
2924
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: cn(TELEMETRY_CHIP_CLASS, "shrink-0 text-cyan-300"), children: [
2925
- /* @__PURE__ */ jsxRuntimeExports.jsx(Gauge, { className: "size-3" }),
2926
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", children: tokenRateLabel })
2927
- ] }) }),
2928
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Output token throughput after first chunk" })
2929
- ] }),
2930
- hasTokens && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: cn(TELEMETRY_CHIP_CLASS, "min-w-0 sm:shrink-0"), children: [
2931
- /* @__PURE__ */ jsxRuntimeExports.jsx(Zap, { className: "size-3 text-muted-foreground" }),
2932
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 flex-wrap items-center gap-x-1 font-mono tabular-nums", children: [
2933
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
2934
- "span",
2586
+ ),
2587
+ warningCount > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
2588
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
2589
+ Badge,
2935
2590
  {
2936
- className: cn(
2937
- "whitespace-nowrap",
2938
- log.inputTokens !== null ? "text-blue-400" : "text-muted-foreground"
2939
- ),
2591
+ variant: "outline",
2592
+ 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",
2940
2593
  children: [
2941
- "IN ",
2942
- log.inputTokens !== null ? formatTokens(log.inputTokens) : "n/a"
2594
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TriangleAlert, { className: "size-3", "aria-label": "Tool schema warnings" }),
2595
+ warningCount
2943
2596
  ]
2944
2597
  }
2945
- ),
2946
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground", children: "/" }),
2947
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
2598
+ ) }),
2599
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: warningCount === 1 ? "1 tool schema warning" : `${warningCount} tool schema warnings` })
2600
+ ] }),
2601
+ log.elapsedMs !== null && (isSlowResponse ? /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
2602
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
2948
2603
  "span",
2949
2604
  {
2950
2605
  className: cn(
2951
- "whitespace-nowrap",
2952
- log.outputTokens !== null ? "text-amber-400" : "text-muted-foreground"
2606
+ TELEMETRY_CHIP_CLASS,
2607
+ "shrink-0 border-amber-300/25 text-amber-200"
2953
2608
  ),
2954
2609
  children: [
2955
- "OUT ",
2956
- log.outputTokens !== null ? formatTokens(log.outputTokens) : "n/a"
2610
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "size-3" }),
2611
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", children: formatElapsed$3(log.elapsedMs) }),
2612
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TriangleAlert, { className: "size-3", "aria-label": "Slow response" })
2957
2613
  ]
2958
2614
  }
2959
- )
2960
- ] })
2961
- ] }),
2962
- log.cacheCreationInputTokens !== null && log.cacheCreationInputTokens > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: cn(TELEMETRY_CHIP_CLASS, "shrink-0"), children: [
2963
- /* @__PURE__ */ jsxRuntimeExports.jsx(CacheTrendIndicator, { trend: cacheTrend?.creation ?? null }),
2964
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono tabular-nums text-cyan-300", children: [
2965
- "KV Cache +",
2966
- formatTokens(log.cacheCreationInputTokens)
2967
- ] })
2968
- ] }),
2969
- log.cacheReadInputTokens !== null && log.cacheReadInputTokens > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: cn(TELEMETRY_CHIP_CLASS, "shrink-0"), children: [
2970
- /* @__PURE__ */ jsxRuntimeExports.jsx(CacheTrendIndicator, { trend: cacheTrend?.read ?? null }),
2971
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono tabular-nums text-purple-400", children: [
2972
- "KV Cache ~",
2973
- formatTokens(log.cacheReadInputTokens)
2974
- ] })
2975
- ] }),
2976
- messageCount !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: cn(TELEMETRY_CHIP_CLASS, "shrink-0 text-muted-foreground"), children: [
2977
- /* @__PURE__ */ jsxRuntimeExports.jsx(MessageSquare, { className: "size-3" }),
2978
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", children: messageCount })
2979
- ] }),
2980
- toolCount !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: cn(TELEMETRY_CHIP_CLASS, "shrink-0 text-muted-foreground"), children: [
2981
- /* @__PURE__ */ jsxRuntimeExports.jsx(Wrench, { className: "size-3" }),
2982
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", children: toolCount })
2983
- ] }),
2984
- log.origin !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs(
2985
- "span",
2986
- {
2987
- className: cn(TELEMETRY_CHIP_CLASS, "hidden shrink-0 text-muted-foreground xl:flex"),
2988
- title: `Origin: ${log.origin}`,
2989
- children: [
2990
- /* @__PURE__ */ jsxRuntimeExports.jsx(Globe, { className: "size-3" }),
2991
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums truncate max-w-[120px]", title: log.origin, children: log.origin })
2992
- ]
2993
- }
2994
- ),
2995
- showClientMetadata && (hasClientPid || hasClientProjectFolder) && /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
2996
- /* @__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: [
2997
- /* @__PURE__ */ jsxRuntimeExports.jsx(FileTerminal, { className: "size-3" }),
2998
- hasClientProjectFolder ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", children: log.clientProjectFolder }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono tabular-nums", children: [
2999
- "PID ",
3000
- log.clientPid
2615
+ ) }),
2616
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(TooltipContent, { children: [
2617
+ "Slow response: ",
2618
+ formatElapsed$3(log.elapsedMs),
2619
+ " exceeds",
2620
+ " ",
2621
+ formatElapsed$3(slowResponseThresholdSeconds * 1e3)
3001
2622
  ] })
3002
- ] }) }),
3003
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: hasClientCwd ? `PID: ${log.clientPid ?? "?"} CWD: ${log.clientCwd}` : `Process ID: ${log.clientPid ?? "?"}` })
3004
- ] }),
3005
- log.streaming && /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
3006
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Radio, { className: "size-3 text-muted-foreground/60 shrink-0" }) }),
3007
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Request used SSE streaming" })
3008
- ] }),
3009
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1 min-w-0" }),
3010
- expanded && /* @__PURE__ */ jsxRuntimeExports.jsxs(
3011
- "span",
3012
- {
3013
- className: "flex items-center gap-1.5 shrink-0",
3014
- onClick: (e) => e.stopPropagation(),
3015
- onKeyDown: (e) => e.stopPropagation(),
3016
- children: [
3017
- tabActions !== void 0 && activeTab !== void 0 && (() => {
3018
- const action = tabActions[activeTab];
3019
- if (action === void 0) return null;
3020
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
3021
- action.expansion !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
3022
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
3023
- Button,
3024
- {
3025
- variant: "outline",
3026
- size: "icon",
3027
- className: HEADER_ACTION_BUTTON_CLASS,
3028
- onClick: action.expansion.onToggle,
3029
- disabled: action.expansion.isPending,
3030
- "aria-pressed": action.expansion.isExpanded,
3031
- "aria-label": action.expansion.isExpanded ? "Collapse all JSON" : "Expand all JSON",
3032
- children: action.expansion.isExpanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronsUp, { className: "size-3.5" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronsDown, { className: "size-3.5" })
3033
- }
3034
- ) }),
3035
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: action.expansion.isExpanded ? "Collapse all JSON nodes" : "Expand all JSON nodes" })
3036
- ] }),
3037
- action.diffWithRaw !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
3038
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
3039
- Button,
3040
- {
3041
- variant: "outline",
3042
- size: "icon",
3043
- className: cn(
3044
- HEADER_ACTION_BUTTON_CLASS,
3045
- action.diffWithRaw.active && "border-cyan-300/35 bg-cyan-400/15 text-cyan-100"
3046
- ),
3047
- onClick: action.diffWithRaw.onToggle,
3048
- "aria-pressed": action.diffWithRaw.active,
3049
- "aria-label": action.diffWithRaw.active ? "Hide raw diff" : "Diff with raw",
3050
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(FileDiff, { className: "size-3.5" })
3051
- }
3052
- ) }),
3053
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: action.diffWithRaw.active ? "Hide diff with raw request" : "Show diff between displayed and raw request body" })
3054
- ] }),
3055
- action.diffWithPrevious !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
3056
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
3057
- Button,
3058
- {
3059
- variant: "outline",
3060
- size: "icon",
3061
- className: HEADER_ACTION_BUTTON_CLASS,
3062
- onClick: action.diffWithPrevious,
3063
- "aria-label": "Diff with previous",
3064
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(History, { className: "size-3.5" })
3065
- }
3066
- ) }),
3067
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Compare this request with the immediately preceding one" })
3068
- ] }),
3069
- action.copyText !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
3070
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
3071
- Button,
3072
- {
3073
- variant: "outline",
3074
- size: "icon",
3075
- className: HEADER_ACTION_BUTTON_CLASS,
3076
- onClick: action.onCopy,
3077
- "aria-label": action.copyCopied ? "Copied" : action.copyLabel,
3078
- children: action.copyCopied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-3.5 text-cyan-300" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-3.5" })
3079
- }
3080
- ) }),
3081
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: action.copyCopied ? "Copied to clipboard" : action.copyLabel })
3082
- ] })
3083
- ] });
3084
- })(),
3085
- onReplay !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
3086
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
3087
- Button,
3088
- {
3089
- variant: "outline",
3090
- size: "icon",
3091
- className: HEADER_ACTION_BUTTON_CLASS,
3092
- onClick: onReplay,
3093
- "aria-label": "Replay request",
3094
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(RotateCcw, { className: "size-3.5" })
3095
- }
3096
- ) }),
3097
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Re-send this request to the provider" })
2623
+ ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: cn(TELEMETRY_CHIP_CLASS, "shrink-0 text-muted-foreground"), children: [
2624
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "size-3" }),
2625
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", children: formatElapsed$3(log.elapsedMs) })
2626
+ ] })),
2627
+ log.streaming && firstChunkLabel !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
2628
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: cn(TELEMETRY_CHIP_CLASS, "shrink-0 text-cyan-300"), children: [
2629
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Radio, { className: "size-3" }),
2630
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono tabular-nums", children: [
2631
+ "first ",
2632
+ firstChunkLabel
3098
2633
  ] })
3099
- ]
3100
- }
3101
- ),
3102
- /* @__PURE__ */ jsxRuntimeExports.jsx(
3103
- "span",
3104
- {
3105
- className: "border border-input bg-background hover:bg-accent hover:text-accent-foreground inline-flex size-8 shrink-0 items-center justify-center rounded-md text-slate-200",
3106
- "aria-hidden": "true",
3107
- children: expanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-4 shrink-0" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-4 shrink-0" })
3108
- }
3109
- )
2634
+ ] }) }),
2635
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Time to first streaming chunk" })
2636
+ ] }),
2637
+ log.streaming && tokenRateLabel !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
2638
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: cn(TELEMETRY_CHIP_CLASS, "shrink-0 text-cyan-300"), children: [
2639
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Gauge, { className: "size-3" }),
2640
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", children: tokenRateLabel })
2641
+ ] }) }),
2642
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Output token throughput after first chunk" })
2643
+ ] }),
2644
+ hasTokens && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: cn(TELEMETRY_CHIP_CLASS, "min-w-0 sm:shrink-0"), children: [
2645
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Zap, { className: "size-3 text-muted-foreground" }),
2646
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 flex-wrap items-center gap-x-1 font-mono tabular-nums", children: [
2647
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
2648
+ "span",
2649
+ {
2650
+ className: cn(
2651
+ "whitespace-nowrap",
2652
+ log.inputTokens !== null ? "text-blue-400" : "text-muted-foreground"
2653
+ ),
2654
+ children: [
2655
+ "IN ",
2656
+ log.inputTokens !== null ? formatTokens(log.inputTokens) : "n/a"
2657
+ ]
2658
+ }
2659
+ ),
2660
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground", children: "/" }),
2661
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
2662
+ "span",
2663
+ {
2664
+ className: cn(
2665
+ "whitespace-nowrap",
2666
+ log.outputTokens !== null ? "text-amber-400" : "text-muted-foreground"
2667
+ ),
2668
+ children: [
2669
+ "OUT ",
2670
+ log.outputTokens !== null ? formatTokens(log.outputTokens) : "n/a"
2671
+ ]
2672
+ }
2673
+ )
2674
+ ] })
2675
+ ] }),
2676
+ log.cacheCreationInputTokens !== null && log.cacheCreationInputTokens > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: cn(TELEMETRY_CHIP_CLASS, "shrink-0"), children: [
2677
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CacheTrendIndicator, { trend: cacheTrend?.creation ?? null }),
2678
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono tabular-nums text-cyan-300", children: [
2679
+ "KV Cache +",
2680
+ formatTokens(log.cacheCreationInputTokens)
2681
+ ] })
2682
+ ] }),
2683
+ log.cacheReadInputTokens !== null && log.cacheReadInputTokens > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: cn(TELEMETRY_CHIP_CLASS, "shrink-0"), children: [
2684
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CacheTrendIndicator, { trend: cacheTrend?.read ?? null }),
2685
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono tabular-nums text-purple-400", children: [
2686
+ "KV Cache ~",
2687
+ formatTokens(log.cacheReadInputTokens)
2688
+ ] })
2689
+ ] }),
2690
+ messageCount !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: cn(TELEMETRY_CHIP_CLASS, "shrink-0 text-muted-foreground"), children: [
2691
+ /* @__PURE__ */ jsxRuntimeExports.jsx(MessageSquare, { className: "size-3" }),
2692
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", children: messageCount })
2693
+ ] }),
2694
+ toolCount !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: cn(TELEMETRY_CHIP_CLASS, "shrink-0 text-muted-foreground"), children: [
2695
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Wrench, { className: "size-3" }),
2696
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", children: toolCount })
2697
+ ] }),
2698
+ log.origin !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs(
2699
+ "span",
2700
+ {
2701
+ className: cn(TELEMETRY_CHIP_CLASS, "hidden shrink-0 text-muted-foreground xl:flex"),
2702
+ title: `Origin: ${log.origin}`,
2703
+ children: [
2704
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Globe, { className: "size-3" }),
2705
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums truncate max-w-[120px]", title: log.origin, children: log.origin })
2706
+ ]
2707
+ }
2708
+ ),
2709
+ showClientMetadata && (hasClientPid || hasClientProjectFolder) && /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
2710
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
2711
+ "span",
2712
+ {
2713
+ className: cn(TELEMETRY_CHIP_CLASS, "hidden shrink-0 text-purple-300 xl:flex"),
2714
+ children: [
2715
+ /* @__PURE__ */ jsxRuntimeExports.jsx(FileTerminal, { className: "size-3" }),
2716
+ hasClientProjectFolder ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", children: log.clientProjectFolder }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono tabular-nums", children: [
2717
+ "PID ",
2718
+ log.clientPid
2719
+ ] })
2720
+ ]
2721
+ }
2722
+ ) }),
2723
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: hasClientCwd ? `PID: ${log.clientPid ?? "?"} CWD: ${log.clientCwd}` : `Process ID: ${log.clientPid ?? "?"}` })
2724
+ ] }),
2725
+ showStandaloneStreamingIndicator && /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
2726
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Radio, { className: "size-3 text-muted-foreground/60 shrink-0" }) }),
2727
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Request used SSE streaming" })
2728
+ ] })
2729
+ ] }),
2730
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex shrink-0 items-start gap-1.5", children: [
2731
+ expanded && /* @__PURE__ */ jsxRuntimeExports.jsxs(
2732
+ "span",
2733
+ {
2734
+ className: "flex items-center gap-1.5 shrink-0",
2735
+ onClick: (e) => e.stopPropagation(),
2736
+ onKeyDown: (e) => e.stopPropagation(),
2737
+ children: [
2738
+ tabActions !== void 0 && activeTab !== void 0 && (() => {
2739
+ const action = tabActions[activeTab];
2740
+ if (action === void 0) return null;
2741
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
2742
+ action.expansion !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
2743
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
2744
+ Button,
2745
+ {
2746
+ variant: "outline",
2747
+ size: "icon",
2748
+ className: HEADER_ACTION_BUTTON_CLASS,
2749
+ onClick: action.expansion.onToggle,
2750
+ disabled: action.expansion.isPending,
2751
+ "aria-pressed": action.expansion.isExpanded,
2752
+ "aria-label": action.expansion.isExpanded ? "Collapse all JSON" : "Expand all JSON",
2753
+ children: action.expansion.isExpanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronsUp, { className: "size-3.5" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronsDown, { className: "size-3.5" })
2754
+ }
2755
+ ) }),
2756
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: action.expansion.isExpanded ? "Collapse all JSON nodes" : "Expand all JSON nodes" })
2757
+ ] }),
2758
+ action.diffWithRaw !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
2759
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
2760
+ Button,
2761
+ {
2762
+ variant: "outline",
2763
+ size: "icon",
2764
+ className: cn(
2765
+ HEADER_ACTION_BUTTON_CLASS,
2766
+ action.diffWithRaw.active && "border-cyan-300/35 bg-cyan-400/15 text-cyan-100"
2767
+ ),
2768
+ onClick: action.diffWithRaw.onToggle,
2769
+ "aria-pressed": action.diffWithRaw.active,
2770
+ "aria-label": action.diffWithRaw.active ? "Hide raw diff" : "Diff with raw",
2771
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(FileDiff, { className: "size-3.5" })
2772
+ }
2773
+ ) }),
2774
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: action.diffWithRaw.active ? "Hide diff with raw request" : "Show diff between displayed and raw request body" })
2775
+ ] }),
2776
+ action.diffWithPrevious !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
2777
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
2778
+ Button,
2779
+ {
2780
+ variant: "outline",
2781
+ size: "icon",
2782
+ className: HEADER_ACTION_BUTTON_CLASS,
2783
+ onClick: action.diffWithPrevious,
2784
+ "aria-label": "Diff with previous",
2785
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(History, { className: "size-3.5" })
2786
+ }
2787
+ ) }),
2788
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Compare this request with the immediately preceding one" })
2789
+ ] }),
2790
+ action.copyText !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
2791
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
2792
+ Button,
2793
+ {
2794
+ variant: "outline",
2795
+ size: "icon",
2796
+ className: HEADER_ACTION_BUTTON_CLASS,
2797
+ onClick: action.onCopy,
2798
+ "aria-label": action.copyCopied ? "Copied" : action.copyLabel,
2799
+ children: action.copyCopied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-3.5 text-cyan-300" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-3.5" })
2800
+ }
2801
+ ) }),
2802
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: action.copyCopied ? "Copied to clipboard" : action.copyLabel })
2803
+ ] })
2804
+ ] });
2805
+ })(),
2806
+ onReplay !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
2807
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
2808
+ Button,
2809
+ {
2810
+ variant: "outline",
2811
+ size: "icon",
2812
+ className: HEADER_ACTION_BUTTON_CLASS,
2813
+ onClick: onReplay,
2814
+ "aria-label": "Replay request",
2815
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(RotateCcw, { className: "size-3.5" })
2816
+ }
2817
+ ) }),
2818
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Re-send this request to the provider" })
2819
+ ] })
2820
+ ]
2821
+ }
2822
+ ),
2823
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
2824
+ "span",
2825
+ {
2826
+ className: "border border-input bg-background hover:bg-accent hover:text-accent-foreground inline-flex size-8 shrink-0 items-center justify-center rounded-md text-slate-200",
2827
+ "aria-hidden": "true",
2828
+ children: expanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-4 shrink-0" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-4 shrink-0" })
2829
+ }
2830
+ )
2831
+ ] })
3110
2832
  ]
3111
2833
  }
3112
2834
  ) });
@@ -3615,12 +3337,6 @@ function shouldUseChunkedBodyLoading(log) {
3615
3337
  function shouldHydrateLogBody(log) {
3616
3338
  return isCompactBody(log) && !shouldUseChunkedBodyLoading(log);
3617
3339
  }
3618
- function formatBytes$1(bytes) {
3619
- if (bytes < 1024) return `${bytes.toLocaleString()} B`;
3620
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KiB`;
3621
- if (bytes < 1024 * 1024 * 1024) return `${(bytes / 1024 / 1024).toFixed(1)} MiB`;
3622
- return `${(bytes / 1024 / 1024 / 1024).toFixed(1)} GiB`;
3623
- }
3624
3340
  function bodyPreviewErrorMessage(error) {
3625
3341
  if (error instanceof ApiTimeoutError) {
3626
3342
  return "Body preview timed out. The log is still available on disk; try loading again.";
@@ -3628,6 +3344,43 @@ function bodyPreviewErrorMessage(error) {
3628
3344
  if (error instanceof Error) return error.message;
3629
3345
  return "Body preview could not be loaded.";
3630
3346
  }
3347
+ function FullBodyHydrationNotice({
3348
+ status,
3349
+ error,
3350
+ footprint,
3351
+ onRetry
3352
+ }) {
3353
+ switch (status) {
3354
+ case "idle":
3355
+ return null;
3356
+ case "loading":
3357
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(NoticeBlock, { tone: "loading", title: "Loading full bodies", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [
3358
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [
3359
+ /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-3.5 shrink-0 animate-spin text-cyan-200" }),
3360
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Loading full request and response bodies from the log store." })
3361
+ ] }),
3362
+ footprint !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "rounded border border-cyan-300/15 bg-cyan-300/[0.06] px-2 py-0.5 font-mono text-[11px] text-cyan-100", children: footprint })
3363
+ ] }) });
3364
+ case "failed":
3365
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(NoticeBlock, { tone: "warning", title: error?.title ?? "Full bodies could not be loaded", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [
3366
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: error?.detail ?? "Compact metadata is still available." }),
3367
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
3368
+ Button,
3369
+ {
3370
+ type: "button",
3371
+ variant: "outline",
3372
+ size: "sm",
3373
+ className: "border border-input bg-background hover:bg-accent hover:text-accent-foreground h-7 gap-1.5 text-xs text-amber-100",
3374
+ onClick: onRetry,
3375
+ children: [
3376
+ /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: "size-3" }),
3377
+ "Retry"
3378
+ ]
3379
+ }
3380
+ )
3381
+ ] }) });
3382
+ }
3383
+ }
3631
3384
  function bodyPreviewTextForView(enabled, state) {
3632
3385
  if (!enabled) return null;
3633
3386
  if (state.text !== "") return state.text;
@@ -3794,7 +3547,9 @@ const LogEntry = reactExports.memo(function({
3794
3547
  const [activeTab, setActiveTab] = reactExports.useState("request");
3795
3548
  const [expandToPath, setExpandToPath] = reactExports.useState(null);
3796
3549
  const [hydratedLog, setHydratedLog] = reactExports.useState(null);
3797
- const [bodyHydrationState, setBodyHydrationState] = reactExports.useState("idle");
3550
+ const [bodyHydrationStatus, setBodyHydrationStatus] = reactExports.useState("idle");
3551
+ const [bodyHydrationError, setBodyHydrationError] = reactExports.useState(null);
3552
+ const [bodyHydrationRetryNonce, setBodyHydrationRetryNonce] = reactExports.useState(0);
3798
3553
  const [requestPreview, setRequestPreview] = reactExports.useState(
3799
3554
  () => createEmptyBodyPreviewState(log.rawRequestBodyBytes ?? null)
3800
3555
  );
@@ -3806,6 +3561,10 @@ const LogEntry = reactExports.memo(function({
3806
3561
  const bodyHydrationInFlightRef = reactExports.useRef(false);
3807
3562
  const displayLog = hydratedLog ?? log;
3808
3563
  const useChunkedBody = hydratedLog === null && shouldUseChunkedBodyLoading(log);
3564
+ const fullBodyHydrationFootprint = reactExports.useMemo(
3565
+ () => formatBodyHydrationFootprint(log.rawRequestBodyBytes, log.responseTextBytes),
3566
+ [log.rawRequestBodyBytes, log.responseTextBytes]
3567
+ );
3809
3568
  const requestPreviewBody = bodyPreviewTextForView(useChunkedBody, requestPreview);
3810
3569
  const responsePreviewBody = bodyPreviewTextForView(useChunkedBody, responsePreview);
3811
3570
  const rawRequestBodyForView = displayLog.rawRequestBody ?? requestPreviewBody;
@@ -4002,6 +3761,13 @@ const LogEntry = reactExports.memo(function({
4002
3761
  },
4003
3762
  [log.id]
4004
3763
  );
3764
+ const retryFullBodyHydration = reactExports.useCallback(() => {
3765
+ if (bodyHydrationInFlightRef.current) return;
3766
+ setHydratedLog(null);
3767
+ setBodyHydrationStatus("idle");
3768
+ setBodyHydrationError(null);
3769
+ setBodyHydrationRetryNonce((current) => current + 1);
3770
+ }, []);
4005
3771
  const handleToggleExpanded = reactExports.useCallback(() => {
4006
3772
  const nextExpanded = !expanded;
4007
3773
  if (nextExpanded) {
@@ -4013,7 +3779,9 @@ const LogEntry = reactExports.memo(function({
4013
3779
  logIdRef.current = log.id;
4014
3780
  bodyHydrationInFlightRef.current = false;
4015
3781
  setHydratedLog(null);
4016
- setBodyHydrationState("idle");
3782
+ setBodyHydrationStatus("idle");
3783
+ setBodyHydrationError(null);
3784
+ setBodyHydrationRetryNonce(0);
4017
3785
  setRequestPreview(createEmptyBodyPreviewState(log.rawRequestBodyBytes ?? null));
4018
3786
  setResponsePreview(createEmptyBodyPreviewState(log.responseTextBytes ?? null));
4019
3787
  }, [log.id, log.rawRequestBodyBytes, log.responseTextBytes]);
@@ -4023,7 +3791,8 @@ const LogEntry = reactExports.memo(function({
4023
3791
  if (hydratedLog !== null || bodyHydrationInFlightRef.current) return;
4024
3792
  let cancelled = false;
4025
3793
  bodyHydrationInFlightRef.current = true;
4026
- setBodyHydrationState("loading");
3794
+ setBodyHydrationStatus("loading");
3795
+ setBodyHydrationError(null);
4027
3796
  void fetchJsonWithTimeout(
4028
3797
  `/api/logs/${String(log.id)}`,
4029
3798
  CapturedLogSchema,
@@ -4032,11 +3801,13 @@ const LogEntry = reactExports.memo(function({
4032
3801
  if (cancelled) return;
4033
3802
  bodyHydrationInFlightRef.current = false;
4034
3803
  setHydratedLog(fullLog);
4035
- setBodyHydrationState("idle");
4036
- }).catch(() => {
3804
+ setBodyHydrationStatus("idle");
3805
+ setBodyHydrationError(null);
3806
+ }).catch((error) => {
4037
3807
  if (cancelled) return;
4038
3808
  bodyHydrationInFlightRef.current = false;
4039
- setBodyHydrationState("failed");
3809
+ setBodyHydrationStatus("failed");
3810
+ setBodyHydrationError(describeFullBodyHydrationError(error));
4040
3811
  });
4041
3812
  return () => {
4042
3813
  cancelled = true;
@@ -4048,7 +3819,8 @@ const LogEntry = reactExports.memo(function({
4048
3819
  log.bodyContentMode,
4049
3820
  log.id,
4050
3821
  log.rawRequestBodyBytes,
4051
- log.responseTextBytes
3822
+ log.responseTextBytes,
3823
+ bodyHydrationRetryNonce
4052
3824
  ]);
4053
3825
  reactExports.useEffect(() => {
4054
3826
  if (!expanded) return;
@@ -4155,6 +3927,15 @@ const LogEntry = reactExports.memo(function({
4155
3927
  }
4156
3928
  ),
4157
3929
  shouldShowRawRequestTab(resolvedFormat, viewMode, strip) && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "raw-request", children: activeTab === "raw-request" && /* @__PURE__ */ jsxRuntimeExports.jsxs(ExpandedPanel, { children: [
3930
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
3931
+ FullBodyHydrationNotice,
3932
+ {
3933
+ status: bodyHydrationStatus,
3934
+ error: bodyHydrationError,
3935
+ footprint: fullBodyHydrationFootprint,
3936
+ onRetry: retryFullBodyHydration
3937
+ }
3938
+ ),
4158
3939
  useChunkedBody && /* @__PURE__ */ jsxRuntimeExports.jsx(
4159
3940
  BodyPreviewNotice,
4160
3941
  {
@@ -4174,8 +3955,15 @@ const LogEntry = reactExports.memo(function({
4174
3955
  ) }) : /* @__PURE__ */ jsxRuntimeExports.jsx(RawTextBlock, { children: rawRequestBodyForView })
4175
3956
  ] }) }),
4176
3957
  /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "request", children: activeTab === "request" && /* @__PURE__ */ jsxRuntimeExports.jsxs(ExpandedPanel, { children: [
4177
- bodyHydrationState === "loading" && /* @__PURE__ */ jsxRuntimeExports.jsx(NoticeBlock, { tone: "loading", children: "Loading full request and response bodies..." }),
4178
- bodyHydrationState === "failed" && /* @__PURE__ */ jsxRuntimeExports.jsx(NoticeBlock, { tone: "warning", children: "Full request and response bodies could not be loaded. Compact metadata is still available." }),
3958
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
3959
+ FullBodyHydrationNotice,
3960
+ {
3961
+ status: bodyHydrationStatus,
3962
+ error: bodyHydrationError,
3963
+ footprint: fullBodyHydrationFootprint,
3964
+ onRetry: retryFullBodyHydration
3965
+ }
3966
+ ),
4179
3967
  useChunkedBody && /* @__PURE__ */ jsxRuntimeExports.jsx(
4180
3968
  BodyPreviewNotice,
4181
3969
  {
@@ -4258,6 +4046,15 @@ const LogEntry = reactExports.memo(function({
4258
4046
  }
4259
4047
  ) }) }),
4260
4048
  /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "raw", children: activeTab === "raw" && /* @__PURE__ */ jsxRuntimeExports.jsxs(ExpandedPanel, { className: "space-y-3", children: [
4049
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
4050
+ FullBodyHydrationNotice,
4051
+ {
4052
+ status: bodyHydrationStatus,
4053
+ error: bodyHydrationError,
4054
+ footprint: fullBodyHydrationFootprint,
4055
+ onRetry: retryFullBodyHydration
4056
+ }
4057
+ ),
4261
4058
  useChunkedBody && /* @__PURE__ */ jsxRuntimeExports.jsx(
4262
4059
  BodyPreviewNotice,
4263
4060
  {
@@ -4286,6 +4083,15 @@ const LogEntry = reactExports.memo(function({
4286
4083
  ) })
4287
4084
  ] }) }),
4288
4085
  /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "parsed", children: activeTab === "parsed" && /* @__PURE__ */ jsxRuntimeExports.jsxs(ExpandedPanel, { children: [
4086
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
4087
+ FullBodyHydrationNotice,
4088
+ {
4089
+ status: bodyHydrationStatus,
4090
+ error: bodyHydrationError,
4091
+ footprint: fullBodyHydrationFootprint,
4092
+ onRetry: retryFullBodyHydration
4093
+ }
4094
+ ),
4289
4095
  useChunkedBody && /* @__PURE__ */ jsxRuntimeExports.jsx(
4290
4096
  BodyPreviewNotice,
4291
4097
  {
@@ -4341,66 +4147,107 @@ function boundaryTitle(stopReason) {
4341
4147
  return "End of Turn";
4342
4148
  }
4343
4149
  }
4150
+ function markerTone({
4151
+ isFusedBoundary,
4152
+ isBoundary,
4153
+ isTurnStart,
4154
+ isRunning
4155
+ }) {
4156
+ if (isFusedBoundary) return "fused";
4157
+ if (isBoundary) return "end";
4158
+ if (isTurnStart) return "start";
4159
+ if (isRunning) return "running";
4160
+ return "idle";
4161
+ }
4162
+ function markerClass(tone, interactive) {
4163
+ const base = "inline-flex size-3.5 items-center justify-center rounded-full border transition-colors";
4164
+ const cursor = interactive ? "cursor-pointer hover:border-cyan-200/70 hover:bg-cyan-300/20" : "";
4165
+ switch (tone) {
4166
+ case "start":
4167
+ return cn(base, cursor, "border-cyan-300/50 bg-cyan-300/12 text-cyan-200");
4168
+ case "end":
4169
+ return cn(base, cursor, "border-amber-300/55 bg-amber-300/12 text-amber-200");
4170
+ case "fused":
4171
+ return cn(
4172
+ base,
4173
+ cursor,
4174
+ "border-slate-200/50 bg-slate-200/10 text-slate-100 ring-2 ring-cyan-300/15"
4175
+ );
4176
+ case "running":
4177
+ return cn(
4178
+ base,
4179
+ cursor,
4180
+ "border-amber-300/45 bg-amber-300/10 text-amber-200 ring-2 ring-amber-300/10"
4181
+ );
4182
+ case "idle":
4183
+ return cn(base, cursor, "border-muted-foreground/25 bg-muted/30 text-muted-foreground/60");
4184
+ }
4185
+ }
4186
+ function markerInnerClass(tone) {
4187
+ switch (tone) {
4188
+ case "running":
4189
+ return "size-1.5 rounded-full bg-current animate-pulse";
4190
+ case "idle":
4191
+ return "size-1 rounded-full bg-current opacity-55";
4192
+ case "start":
4193
+ case "end":
4194
+ case "fused":
4195
+ return "size-1.5 rounded-full bg-current";
4196
+ }
4197
+ }
4198
+ function markerTitle(tone, stopReason) {
4199
+ switch (tone) {
4200
+ case "start":
4201
+ return "Start of turn";
4202
+ case "end":
4203
+ return boundaryTitle(stopReason);
4204
+ case "fused":
4205
+ return "Single-request turn";
4206
+ case "running":
4207
+ return "Processing";
4208
+ case "idle":
4209
+ return "Request in turn";
4210
+ }
4211
+ }
4344
4212
  function ThreadConnector({
4345
4213
  stopReason,
4346
4214
  isPending,
4347
4215
  isFirst,
4348
4216
  isTurnStart,
4349
4217
  isOnlyEntry = false,
4350
- crabIndex = 0,
4351
4218
  collapsible = false,
4352
4219
  onToggle
4353
4220
  }) {
4354
4221
  const isBoundary = isTurnBoundary(stopReason);
4355
4222
  const isFusedBoundary = isOnlyEntry && isTurnStart && isBoundary;
4356
4223
  const isRunning = isPending && !isBoundary;
4357
- const Crab = reactExports.useMemo(() => getCrabVariant(crabIndex), [crabIndex]);
4358
- const FusedCrab = reactExports.useMemo(() => getInteriorCrabVariant(crabIndex), [crabIndex]);
4359
- const interactiveProps = collapsible && onToggle ? {
4360
- role: "button",
4361
- tabIndex: 0,
4362
- className: "cursor-pointer",
4363
- onClick: (e) => {
4364
- e.stopPropagation();
4365
- onToggle();
4366
- },
4367
- onKeyDown: (e) => {
4368
- if (e.key === "Enter" || e.key === " ") {
4369
- e.preventDefault();
4370
- onToggle();
4371
- }
4372
- }
4373
- } : {};
4224
+ const tone = markerTone({ isFusedBoundary, isBoundary, isTurnStart, isRunning });
4225
+ const interactive = collapsible && onToggle !== void 0;
4226
+ const handleMarkerClick = (event) => {
4227
+ if (!interactive || onToggle === void 0) return;
4228
+ event.stopPropagation();
4229
+ onToggle();
4230
+ };
4231
+ const handleMarkerKeyDown = (event) => {
4232
+ if (!interactive || onToggle === void 0) return;
4233
+ if (event.key !== "Enter" && event.key !== " ") return;
4234
+ event.preventDefault();
4235
+ onToggle();
4236
+ };
4374
4237
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center w-6 shrink-0 pt-0.5 pb-0.5", children: [
4375
4238
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex justify-center h-[calc(0.75rem-8px)]", children: !isFirst && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-0.5 bg-muted-foreground/30 h-full" }) }),
4376
- isFusedBoundary ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { title: "Start and end of turn", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
4377
- FusedCrab,
4378
- {
4379
- className: cn(
4380
- "size-3.5 text-cyan-300/90",
4381
- "animate-crab-settle",
4382
- "drop-shadow-[0_0_4px_rgba(103,232,249,0.35)]"
4383
- )
4384
- }
4385
- ) }) : isBoundary ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { title: boundaryTitle(stopReason), ...interactiveProps, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
4386
- Crab,
4387
- {
4388
- className: cn(
4389
- "size-3.5 text-amber-400",
4390
- "animate-crab-settle",
4391
- "drop-shadow-[0_0_4px_rgba(251,191,36,0.5)]"
4392
- )
4393
- }
4394
- ) }) : isTurnStart ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { title: "Start of turn", ...interactiveProps, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
4395
- Crab,
4239
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
4240
+ "span",
4396
4241
  {
4397
- className: cn(
4398
- "size-3.5 text-cyan-300/85",
4399
- "animate-crab-appear",
4400
- "drop-shadow-[0_0_4px_rgba(103,232,249,0.32)]"
4401
- )
4242
+ role: interactive ? "button" : void 0,
4243
+ tabIndex: interactive ? 0 : void 0,
4244
+ title: markerTitle(tone, stopReason),
4245
+ className: markerClass(tone, interactive),
4246
+ onClick: handleMarkerClick,
4247
+ onKeyDown: handleMarkerKeyDown,
4248
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: markerInnerClass(tone) })
4402
4249
  }
4403
- ) }) : isRunning ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { title: "Processing…", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Crab, { className: cn("size-3.5 text-amber-300/80", "animate-crab-crawl") }) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: /* @__PURE__ */ jsxRuntimeExports.jsx(Crab, { className: "size-3.5 text-muted-foreground/40" }) }),
4250
+ ),
4404
4251
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 flex justify-center min-h-0", children: !isBoundary && /* @__PURE__ */ jsxRuntimeExports.jsx(
4405
4252
  "div",
4406
4253
  {
@@ -4761,8 +4608,6 @@ const TurnGroup = reactExports.memo(function TurnGroup2({
4761
4608
  maxElapsed
4762
4609
  };
4763
4610
  }, [entries, lastIdx]);
4764
- const StartCrab = reactExports.useMemo(() => getCrabVariant(entries[0]?.log.id ?? 0), [entries]);
4765
- const EndCrab = reactExports.useMemo(() => getCrabVariant(entries[lastIdx]?.log.id ?? 0), [entries, lastIdx]);
4766
4611
  const bgClass = turnIndex % 2 === 0 ? "bg-white/[0.012]" : "bg-cyan-300/[0.012]";
4767
4612
  const aggregateIsSlow = aggregate.maxElapsed !== null && slowResponseThresholdSeconds > 0 && aggregate.maxElapsed > slowResponseThresholdSeconds * 1e3;
4768
4613
  const toolEventsByLogId = reactExports.useMemo(() => {
@@ -4812,155 +4657,114 @@ const TurnGroup = reactExports.memo(function TurnGroup2({
4812
4657
  isPending ? "border-amber-300/15 shadow-[0_0_0_1px_rgba(252,211,77,0.04)]" : "border-transparent",
4813
4658
  !collapsed && "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:outline-none"
4814
4659
  ),
4815
- children: collapsed ? (
4816
- /* ---- Collapsed: dual-crab (+ summary card for multi-log turns) ---- */
4817
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
4818
- "div",
4819
- {
4820
- "data-nav-id": `turn-collapsed-${String(firstLogId)}`,
4821
- "data-nav-action": "expand",
4822
- role: "button",
4823
- tabIndex: 0,
4824
- className: "flex items-stretch cursor-pointer focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:outline-none rounded-lg",
4825
- onClick: toggleCollapse,
4826
- onKeyDown: (e) => {
4827
- if (e.key === "Enter" || e.key === " ") {
4828
- e.preventDefault();
4829
- toggleCollapse();
4830
- }
4831
- },
4832
- children: [
4833
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-5 shrink-0 flex items-start pt-1.5", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] text-muted-foreground/50 font-mono tabular-nums leading-none select-none", children: turnIndex + 1 }) }),
4834
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-6 shrink-0 flex flex-col items-center pt-0.5 pb-0.5", children: [
4835
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex justify-center h-[calc(0.75rem-8px)]" }),
4836
- /* @__PURE__ */ jsxRuntimeExports.jsx(
4837
- "span",
4838
- {
4839
- role: "button",
4840
- tabIndex: 0,
4841
- title: "Start of turn - click to expand",
4842
- className: "cursor-pointer",
4843
- onClick: (e) => {
4844
- e.stopPropagation();
4845
- toggleCollapse();
4846
- },
4847
- onKeyDown: (e) => {
4848
- if (e.key === "Enter" || e.key === " ") {
4849
- e.preventDefault();
4850
- toggleCollapse();
4851
- }
4852
- },
4853
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(
4854
- StartCrab,
4855
- {
4856
- className: cn(
4857
- "size-3.5 text-cyan-300/85",
4858
- "animate-crab-appear drop-shadow-[0_0_4px_rgba(103,232,249,0.32)]"
4859
- )
4860
- }
4861
- )
4862
- }
4863
- ),
4864
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 flex justify-center min-h-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-0.5 bg-muted-foreground/30 h-full" }) }),
4865
- /* @__PURE__ */ jsxRuntimeExports.jsx(
4866
- "span",
4867
- {
4868
- role: "button",
4869
- tabIndex: 0,
4870
- title: "End of Turn - click to expand",
4871
- className: "cursor-pointer",
4872
- onClick: (e) => {
4873
- e.stopPropagation();
4874
- toggleCollapse();
4875
- },
4876
- onKeyDown: (e) => {
4877
- if (e.key === "Enter" || e.key === " ") {
4878
- e.preventDefault();
4879
- toggleCollapse();
4880
- }
4881
- },
4882
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(
4883
- EndCrab,
4884
- {
4885
- className: cn(
4886
- "size-3.5 text-amber-400",
4887
- "animate-crab-settle drop-shadow-[0_0_4px_rgba(251,191,36,0.5)]"
4888
- )
4889
- }
4890
- )
4891
- }
4892
- )
4893
- ] }),
4894
- entries.length > 1 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
4895
- "div",
4660
+ children: collapsed ? /* @__PURE__ */ jsxRuntimeExports.jsxs(
4661
+ "div",
4662
+ {
4663
+ "data-nav-id": `turn-collapsed-${String(firstLogId)}`,
4664
+ "data-nav-action": "expand",
4665
+ role: "button",
4666
+ tabIndex: 0,
4667
+ className: "flex items-stretch cursor-pointer focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:outline-none rounded-lg",
4668
+ onClick: toggleCollapse,
4669
+ onKeyDown: (e) => {
4670
+ if (e.key === "Enter" || e.key === " ") {
4671
+ e.preventDefault();
4672
+ toggleCollapse();
4673
+ }
4674
+ },
4675
+ children: [
4676
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-5 shrink-0 flex items-start pt-1.5", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] text-muted-foreground/50 font-mono tabular-nums leading-none select-none", children: turnIndex + 1 }) }),
4677
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-6 shrink-0 flex flex-col items-center pt-1.5 pb-1.5", children: [
4678
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex justify-center h-[calc(0.75rem-8px)]" }),
4679
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "size-2 rounded-full border border-cyan-300/45 bg-cyan-300/20" }),
4680
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 flex justify-center min-h-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-px bg-muted-foreground/25 h-full" }) }),
4681
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
4682
+ "span",
4896
4683
  {
4897
4684
  className: cn(
4898
- "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)]",
4899
- "border border-border bg-card shadow-sm",
4900
- bgClass
4685
+ "size-2 rounded-full border",
4686
+ isComplete ? "border-amber-300/45 bg-amber-300/20" : "border-muted-foreground/30 bg-muted/30"
4687
+ )
4688
+ }
4689
+ )
4690
+ ] }),
4691
+ entries.length > 1 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
4692
+ "div",
4693
+ {
4694
+ className: cn(
4695
+ "flex-1 min-w-0 mb-0.5 rounded-[8px] py-1.5 px-3 flex items-center gap-3 text-xs shadow-[inset_0_1px_0_rgba(255,255,255,0.04)]",
4696
+ "border border-border bg-card shadow-sm transition-colors hover:border-cyan-200/20",
4697
+ bgClass
4698
+ ),
4699
+ children: [
4700
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-[10px] font-semibold uppercase tracking-[0.14em] text-muted-foreground/70", children: turnLabel }),
4701
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
4702
+ "span",
4703
+ {
4704
+ className: "text-blue-300/85 font-mono font-semibold tabular-nums shrink-0",
4705
+ title: `Log IDs ${String(entries[0]?.log.id ?? "?")} ~ ${String(
4706
+ entries[lastIdx]?.log.id ?? "?"
4707
+ )}`,
4708
+ children: [
4709
+ "#",
4710
+ entries[0]?.sessionLogNumber ?? "?",
4711
+ " ~ #",
4712
+ entries[lastIdx]?.sessionLogNumber ?? "?"
4713
+ ]
4714
+ }
4901
4715
  ),
4902
- children: [
4903
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: ROW_CHEVRON_SLOT_CLASS, children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-4 shrink-0" }) }),
4904
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
4716
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground shrink-0", children: [
4717
+ entries.length,
4718
+ " request",
4719
+ entries.length > 1 ? "s" : ""
4720
+ ] }),
4721
+ aggregate.maxElapsed !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
4722
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
4905
4723
  "span",
4906
4724
  {
4907
- className: "text-blue-400/80 font-mono font-semibold tabular-nums shrink-0",
4908
- title: `Log IDs ${String(entries[0]?.log.id ?? "?")} ~ ${String(
4909
- entries[lastIdx]?.log.id ?? "?"
4910
- )}`,
4725
+ className: cn(
4726
+ "flex items-center gap-1 shrink-0",
4727
+ aggregateIsSlow ? "text-amber-400" : "text-muted-foreground"
4728
+ ),
4911
4729
  children: [
4912
- "#",
4913
- entries[0]?.sessionLogNumber ?? "?",
4914
- " ~ #",
4915
- entries[lastIdx]?.sessionLogNumber ?? "?"
4730
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "size-3" }),
4731
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", children: formatElapsed$2(aggregate.maxElapsed) }),
4732
+ aggregateIsSlow && /* @__PURE__ */ jsxRuntimeExports.jsx(TriangleAlert, { className: "size-3", "aria-label": "Slow response" })
4916
4733
  ]
4917
4734
  }
4918
- ),
4919
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground shrink-0", children: [
4920
- entries.length,
4921
- " request",
4922
- entries.length > 1 ? "s" : ""
4923
- ] }),
4924
- aggregate.maxElapsed !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
4925
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
4926
- "span",
4927
- {
4928
- className: cn(
4929
- "flex items-center gap-1 shrink-0",
4930
- aggregateIsSlow ? "text-amber-400" : "text-muted-foreground"
4931
- ),
4932
- children: [
4933
- /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "size-3" }),
4934
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", children: formatElapsed$2(aggregate.maxElapsed) }),
4935
- aggregateIsSlow && /* @__PURE__ */ jsxRuntimeExports.jsx(TriangleAlert, { className: "size-3", "aria-label": "Slow response" })
4936
- ]
4937
- }
4938
- ) }),
4939
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: aggregateIsSlow ? `Slow response: ${formatElapsed$2(
4940
- aggregate.maxElapsed
4941
- )} exceeds ${formatElapsed$2(slowResponseThresholdSeconds * 1e3)}` : "Slowest request in this turn" })
4942
- ] }) }),
4943
- aggregate.hasTokens && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1 shrink-0", children: [
4944
- /* @__PURE__ */ jsxRuntimeExports.jsx(Zap, { className: "size-3 text-muted-foreground" }),
4945
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono tabular-nums", children: [
4946
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-blue-400", children: [
4947
- "IN ",
4948
- formatTokens(aggregate.totalInput)
4949
- ] }),
4950
- " / ",
4951
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-amber-400", children: [
4952
- "OUT ",
4953
- formatTokens(aggregate.totalOutput)
4954
- ] })
4735
+ ) }),
4736
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: aggregateIsSlow ? `Slow response: ${formatElapsed$2(
4737
+ aggregate.maxElapsed
4738
+ )} exceeds ${formatElapsed$2(slowResponseThresholdSeconds * 1e3)}` : "Slowest request in this turn" })
4739
+ ] }) }),
4740
+ aggregate.hasTokens && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1 shrink-0", children: [
4741
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Zap, { className: "size-3 text-muted-foreground" }),
4742
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono tabular-nums", children: [
4743
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-blue-400", children: [
4744
+ "IN ",
4745
+ formatTokens(aggregate.totalInput)
4746
+ ] }),
4747
+ " / ",
4748
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-amber-400", children: [
4749
+ "OUT ",
4750
+ formatTokens(aggregate.totalOutput)
4955
4751
  ] })
4956
- ] }),
4957
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1 min-w-0" })
4958
- ]
4959
- }
4960
- )
4961
- ]
4962
- }
4963
- )
4752
+ ] })
4753
+ ] }),
4754
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1 min-w-0" }),
4755
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
4756
+ "span",
4757
+ {
4758
+ className: "border border-input bg-background inline-flex size-7 shrink-0 items-center justify-center rounded-md text-slate-200",
4759
+ "aria-hidden": "true",
4760
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-4 shrink-0" })
4761
+ }
4762
+ )
4763
+ ]
4764
+ }
4765
+ )
4766
+ ]
4767
+ }
4964
4768
  ) : (
4965
4769
  /* ---- Expanded: full entries ---- */
4966
4770
  entries.map((entry, visibleIdx) => {
@@ -4976,7 +4780,6 @@ const TurnGroup = reactExports.memo(function TurnGroup2({
4976
4780
  isFirst: visibleIdx === 0,
4977
4781
  isTurnStart,
4978
4782
  isOnlyEntry: isSingleLog,
4979
- crabIndex: log.id % 12,
4980
4783
  collapsible: collapsible && isTurnStart,
4981
4784
  onToggle: toggleCollapse
4982
4785
  }
@@ -5993,30 +5796,370 @@ function CrabLogo({ className }) {
5993
5796
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
5994
5797
  "svg",
5995
5798
  {
5996
- viewBox: "0 0 24 24",
5997
- fill: "none",
5998
- stroke: "currentColor",
5999
- strokeWidth: "1.5",
6000
- strokeLinecap: "round",
6001
- strokeLinejoin: "round",
6002
- "aria-hidden": "true",
6003
- className: cn("inline-block size-5", className),
6004
- children: [
6005
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M5 13 C5 9 8 7 12 7 C16 7 19 9 19 13 C19 16 16 18 12 18 C8 18 5 16 5 13 Z" }),
5799
+ viewBox: "0 0 24 24",
5800
+ fill: "none",
5801
+ stroke: "currentColor",
5802
+ strokeWidth: "1.5",
5803
+ strokeLinecap: "round",
5804
+ strokeLinejoin: "round",
5805
+ "aria-hidden": "true",
5806
+ className: cn("inline-block size-5", className),
5807
+ children: [
5808
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M5 13 C5 9 8 7 12 7 C16 7 19 9 19 13 C19 16 16 18 12 18 C8 18 5 16 5 13 Z" }),
5809
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M5 11 C3.5 9.5 1.5 10 2 12.5 C2.5 14 4 13.5 5 12.5" }),
5810
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M19 11 C20.5 9.5 22.5 10 22 12.5 C21.5 14 20 13.5 19 12.5" }),
5811
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10", y1: "7", x2: "9.5", y2: "5" }),
5812
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14", y1: "7", x2: "14.5", y2: "5" }),
5813
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "9.5", cy: "4.5", r: "0.9", fill: "currentColor", stroke: "none" }),
5814
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "14.5", cy: "4.5", r: "0.9", fill: "currentColor", stroke: "none" }),
5815
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "6.5", y1: "16", x2: "4.5", y2: "19.5" }),
5816
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "9", y1: "17.5", x2: "8", y2: "20.5" }),
5817
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "15", y1: "17.5", x2: "16", y2: "20.5" }),
5818
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "17.5", y1: "16", x2: "19.5", y2: "19.5" })
5819
+ ]
5820
+ }
5821
+ );
5822
+ }
5823
+ function SvgShell({
5824
+ className,
5825
+ style,
5826
+ d,
5827
+ eyeStalks,
5828
+ eyes,
5829
+ legs,
5830
+ extras
5831
+ }) {
5832
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
5833
+ "svg",
5834
+ {
5835
+ viewBox: "0 0 24 24",
5836
+ fill: "none",
5837
+ stroke: "currentColor",
5838
+ strokeWidth: "1.5",
5839
+ strokeLinecap: "round",
5840
+ strokeLinejoin: "round",
5841
+ "aria-hidden": "true",
5842
+ style,
5843
+ className: cn("inline-block size-5", className),
5844
+ children: [
5845
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d }),
5846
+ eyeStalks,
5847
+ eyes,
5848
+ legs,
5849
+ extras
5850
+ ]
5851
+ }
5852
+ );
5853
+ }
5854
+ const StdLegs = /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
5855
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "6.5", y1: "16", x2: "4.5", y2: "19.5" }),
5856
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "9", y1: "17.5", x2: "8", y2: "20.5" }),
5857
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "15", y1: "17.5", x2: "16", y2: "20.5" }),
5858
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "17.5", y1: "16", x2: "19.5", y2: "19.5" })
5859
+ ] });
5860
+ const ShortLegs = /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
5861
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "7", y1: "16", x2: "5.5", y2: "18.5" }),
5862
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "9.5", y1: "17", x2: "8.5", y2: "19.5" }),
5863
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14.5", y1: "17", x2: "15.5", y2: "19.5" }),
5864
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "17", y1: "16", x2: "18.5", y2: "18.5" })
5865
+ ] });
5866
+ function Crab1({ className }) {
5867
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
5868
+ SvgShell,
5869
+ {
5870
+ className,
5871
+ d: "M5 13 C5 9 8 7 12 7 C16 7 19 9 19 13 C19 16 16 18 12 18 C8 18 5 16 5 13 Z",
5872
+ eyeStalks: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
5873
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10", y1: "7", x2: "9.5", y2: "5" }),
5874
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14", y1: "7", x2: "14.5", y2: "5" })
5875
+ ] }),
5876
+ eyes: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
5877
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "9.5", cy: "4.5", r: "0.9", fill: "currentColor", stroke: "none" }),
5878
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "14.5", cy: "4.5", r: "0.9", fill: "currentColor", stroke: "none" })
5879
+ ] }),
5880
+ legs: StdLegs,
5881
+ extras: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
5882
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M5 11 C3.5 9.5 1.5 10 2 12.5 C2.5 14 4 13.5 5 12.5" }),
5883
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M19 11 C20.5 9.5 22.5 10 22 12.5 C21.5 14 20 13.5 19 12.5" })
5884
+ ] })
5885
+ }
5886
+ );
5887
+ }
5888
+ function Crab2({ className }) {
5889
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
5890
+ SvgShell,
5891
+ {
5892
+ className,
5893
+ d: "M4 13 C4 7 7.5 5.5 12 5.5 C16.5 5.5 20 7 20 13 C20 17.5 16.5 19 12 19 C7.5 19 4 17.5 4 13 Z",
5894
+ eyeStalks: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
5895
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "9.5", y1: "6.5", x2: "9.5", y2: "4.5" }),
5896
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14.5", y1: "6.5", x2: "14.5", y2: "4.5" })
5897
+ ] }),
5898
+ eyes: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
5899
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "9.5", cy: "4", r: "1.1", fill: "currentColor", stroke: "none" }),
5900
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "14.5", cy: "4", r: "1.1", fill: "currentColor", stroke: "none" })
5901
+ ] }),
5902
+ legs: ShortLegs,
5903
+ extras: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
5904
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M5 11 C4 9.5 2.5 10 3 12 C3.5 13.5 4.5 13 5 12" }),
5905
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M19 11 C20 9.5 21.5 10 21 12 C20.5 13.5 19.5 13 19 12" })
5906
+ ] })
5907
+ }
5908
+ );
5909
+ }
5910
+ function Crab3({ className }) {
5911
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
5912
+ SvgShell,
5913
+ {
5914
+ className,
5915
+ d: "M3 13.5 C3 8 7 6 12 6 C17 6 21 8 21 13.5 C21 17 17 19 12 19 C7 19 3 17 3 13.5 Z",
5916
+ eyeStalks: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
5917
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "7", y1: "7", x2: "6.5", y2: "4.5" }),
5918
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "17", y1: "7", x2: "17.5", y2: "4.5" })
5919
+ ] }),
5920
+ eyes: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
5921
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "6.5", cy: "4", r: "0.8", fill: "currentColor", stroke: "none" }),
5922
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "17.5", cy: "4", r: "0.8", fill: "currentColor", stroke: "none" })
5923
+ ] }),
5924
+ legs: StdLegs,
5925
+ extras: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
5926
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M4 12 C2.5 10.5 1 11 1.5 13 C2 14.5 3.5 14 4.5 13" }),
5927
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M20 12 C21.5 10.5 23 11 22.5 13 C22 14.5 20.5 14 19.5 13" })
5928
+ ] })
5929
+ }
5930
+ );
5931
+ }
5932
+ function Crab4({ className }) {
5933
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
5934
+ SvgShell,
5935
+ {
5936
+ className,
5937
+ d: "M6 14 C6 8 9 5.5 12 5.5 C15 5.5 18 8 18 14 C18 18 15 20 12 20 C9 20 6 18 6 14 Z",
5938
+ eyeStalks: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
5939
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10", y1: "6.5", x2: "10", y2: "3.5" }),
5940
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14", y1: "6.5", x2: "14", y2: "3.5" })
5941
+ ] }),
5942
+ eyes: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
5943
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "10", cy: "3", r: "0.7", fill: "currentColor", stroke: "none" }),
5944
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "14", cy: "3", r: "0.7", fill: "currentColor", stroke: "none" })
5945
+ ] }),
5946
+ legs: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
5947
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "7", y1: "17", x2: "5", y2: "20.5" }),
5948
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "9.5", y1: "18.5", x2: "8.5", y2: "21.5" }),
5949
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14.5", y1: "18.5", x2: "15.5", y2: "21.5" }),
5950
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "17", y1: "17", x2: "19", y2: "20.5" })
5951
+ ] }),
5952
+ extras: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
5953
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M6.5 11 C5 8.5 3 9 3.5 11.5 C4 13.5 5 13 6 12" }),
5954
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M17.5 11 C19 8.5 21 9 20.5 11.5 C20 13.5 19 13 18 12" })
5955
+ ] })
5956
+ }
5957
+ );
5958
+ }
5959
+ function Crab5({ className }) {
5960
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
5961
+ SvgShell,
5962
+ {
5963
+ className,
5964
+ d: "M5 13 C5 9 8 7 12 7 L13 4 L14 7 C16 7 19 9 19 13 C19 16 16 18 13 18 L12 21 L11 18 C8 18 5 16 5 13 Z",
5965
+ eyeStalks: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
5966
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10", y1: "7", x2: "9.5", y2: "5" }),
5967
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14", y1: "7", x2: "14.5", y2: "5" })
5968
+ ] }),
5969
+ eyes: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
5970
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "9.5", cy: "4.5", r: "0.8", fill: "currentColor", stroke: "none" }),
5971
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "14.5", cy: "4.5", r: "0.8", fill: "currentColor", stroke: "none" })
5972
+ ] }),
5973
+ legs: StdLegs,
5974
+ extras: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
5975
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M5 11 C3.5 9.5 1.5 10 2 12.5 C2.5 14 4 13.5 5 12.5" }),
5976
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M19 11 C20.5 9.5 22.5 10 22 12.5 C21.5 14 20 13.5 19 12.5" })
5977
+ ] })
5978
+ }
5979
+ );
5980
+ }
5981
+ function Crab6({ className }) {
5982
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
5983
+ SvgShell,
5984
+ {
5985
+ className,
5986
+ d: "M5 13 C5 9 8 7 12 7 C16 7 19 9 19 13 C19 16 16 18 12 18 C8 18 5 16 5 13 Z",
5987
+ eyeStalks: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
5988
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10", y1: "7", x2: "9.5", y2: "5" }),
5989
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14", y1: "7", x2: "14.5", y2: "5" })
5990
+ ] }),
5991
+ eyes: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
5992
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "9.5", cy: "4.5", r: "0.9", fill: "currentColor", stroke: "none" }),
5993
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "13.5", y1: "4", x2: "15.5", y2: "5" })
5994
+ ] }),
5995
+ legs: StdLegs,
5996
+ extras: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
5997
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M5 11 C3.5 9.5 1.5 10 2 12.5 C2.5 14 4 13.5 5 12.5" }),
5998
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M19 11 C20.5 9.5 22.5 10 22 12.5 C21.5 14 20 13.5 19 12.5" })
5999
+ ] })
6000
+ }
6001
+ );
6002
+ }
6003
+ function Crab7({ className }) {
6004
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
6005
+ SvgShell,
6006
+ {
6007
+ className,
6008
+ d: "M5.5 13.5 C5.5 10 8.5 8 12 8 C15.5 8 18.5 10 18.5 13.5 C18.5 16 15.5 17.5 12 17.5 C8.5 17.5 5.5 16 5.5 13.5 Z",
6009
+ eyeStalks: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
6010
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10", y1: "8", x2: "10", y2: "6" }),
6011
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14", y1: "8", x2: "14", y2: "6" })
6012
+ ] }),
6013
+ eyes: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
6014
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "9", y1: "6", x2: "11", y2: "6.5" }),
6015
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "13", y1: "6", x2: "15", y2: "6.5" })
6016
+ ] }),
6017
+ legs: ShortLegs,
6018
+ extras: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
6019
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M6 11.5 C4.5 10.5 3 11 3.5 12.5 C4 13.5 5 13 5.5 12.5" }),
6020
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M18 11.5 C19.5 10.5 21 11 20.5 12.5 C20 13.5 19 13 18.5 12.5" })
6021
+ ] })
6022
+ }
6023
+ );
6024
+ }
6025
+ function Crab8({ className }) {
6026
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
6027
+ SvgShell,
6028
+ {
6029
+ className,
6030
+ d: "M5 13 C5 9 8 7 12 7 C16 7 19 9 19 13 C19 16 16 18 12 18 C8 18 5 16 5 13 Z",
6031
+ eyeStalks: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
6032
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10", y1: "7", x2: "9.5", y2: "5" }),
6033
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14", y1: "7", x2: "14.5", y2: "5" })
6034
+ ] }),
6035
+ eyes: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
6036
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "9.5", cy: "4.5", r: "0.7", fill: "currentColor", stroke: "none" }),
6037
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "14.5", cy: "4.5", r: "0.7", fill: "currentColor", stroke: "none" })
6038
+ ] }),
6039
+ legs: StdLegs,
6040
+ extras: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
6041
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M5 11 C3.5 9.5 1.5 10 2 12.5 C2.5 14 4 13.5 5 12.5" }),
6042
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M19 11 C20.5 9.5 22.5 10 22 12.5 C21.5 14 20 13.5 19 12.5" }),
6043
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "8.5", y1: "4", x2: "10.5", y2: "4.5" }),
6044
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "15.5", y1: "4", x2: "13.5", y2: "4.5" }),
6045
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M9 15.5 C10 14.5 14 14.5 15 15.5" })
6046
+ ] })
6047
+ }
6048
+ );
6049
+ }
6050
+ function Crab9({ className }) {
6051
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
6052
+ SvgShell,
6053
+ {
6054
+ className,
6055
+ d: "M5 13 C5 9 8 7 12 7 C16 7 19 9 19 13 C19 16 16 18 12 18 C8 18 5 16 5 13 Z",
6056
+ eyeStalks: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
6057
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10", y1: "7", x2: "9.5", y2: "5" }),
6058
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14", y1: "7", x2: "14.5", y2: "5" })
6059
+ ] }),
6060
+ eyes: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
6061
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "9.5", cy: "4.5", r: "1.2", fill: "none", stroke: "currentColor" }),
6062
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "14.5", cy: "4.5", r: "1.2", fill: "none", stroke: "currentColor" })
6063
+ ] }),
6064
+ legs: StdLegs,
6065
+ extras: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
6066
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M5 11 C3.5 9.5 1.5 10 2 12.5 C2.5 14 4 13.5 5 12.5" }),
6067
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M19 11 C20.5 9.5 22.5 10 22 12.5 C21.5 14 20 13.5 19 12.5" }),
6068
+ /* @__PURE__ */ jsxRuntimeExports.jsx("ellipse", { cx: "12", cy: "15", rx: "2", ry: "1.5", fill: "currentColor", stroke: "none" })
6069
+ ] })
6070
+ }
6071
+ );
6072
+ }
6073
+ function Crab10({ className }) {
6074
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
6075
+ SvgShell,
6076
+ {
6077
+ className,
6078
+ d: "M4.5 13 C4.5 8 7.5 6 12 6 C16.5 6 19.5 8 19.5 13 C19.5 17 16.5 18.5 12 18.5 C7.5 18.5 4.5 17 4.5 13 Z",
6079
+ eyeStalks: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
6080
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "9.5", y1: "7", x2: "9", y2: "5" }),
6081
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14.5", y1: "7", x2: "15", y2: "5" })
6082
+ ] }),
6083
+ eyes: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
6084
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "9", cy: "4.5", r: "1", fill: "currentColor", stroke: "none" }),
6085
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "15", cy: "4.5", r: "1", fill: "currentColor", stroke: "none" })
6086
+ ] }),
6087
+ legs: StdLegs,
6088
+ extras: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
6089
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M5 11 C3.5 9 2 9.5 2.5 12 C3 14 4 13 5 12" }),
6090
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M19 11 C20.5 9 22 9.5 21.5 12 C21 14 20 13 19 12" }),
6091
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M9 14.5 C10 16 14 16 15 14.5" }),
6092
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "7", cy: "13", r: "1", fill: "currentColor", stroke: "none", opacity: "0.3" }),
6093
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "17", cy: "13", r: "1", fill: "currentColor", stroke: "none", opacity: "0.3" })
6094
+ ] })
6095
+ }
6096
+ );
6097
+ }
6098
+ function Crab11({ className }) {
6099
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
6100
+ SvgShell,
6101
+ {
6102
+ className,
6103
+ d: "M5 13 C5 9 8 7 12 7 C16 7 19 9 19 13 C19 16 16 18 12 18 C8 18 5 16 5 13 Z",
6104
+ eyeStalks: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
6105
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10", y1: "7", x2: "9.5", y2: "5.5" }),
6106
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14", y1: "7", x2: "14.5", y2: "5.5" })
6107
+ ] }),
6108
+ eyes: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
6109
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "7.5", y1: "5.5", x2: "16.5", y2: "5.5" }),
6110
+ /* @__PURE__ */ jsxRuntimeExports.jsx("rect", { x: "7", y: "5", width: "4", height: "2", rx: "0.5", fill: "currentColor", stroke: "none" }),
6111
+ /* @__PURE__ */ jsxRuntimeExports.jsx("rect", { x: "13", y: "5", width: "4", height: "2", rx: "0.5", fill: "currentColor", stroke: "none" })
6112
+ ] }),
6113
+ legs: StdLegs,
6114
+ extras: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
6006
6115
  /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M5 11 C3.5 9.5 1.5 10 2 12.5 C2.5 14 4 13.5 5 12.5" }),
6007
6116
  /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M19 11 C20.5 9.5 22.5 10 22 12.5 C21.5 14 20 13.5 19 12.5" }),
6008
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10", y1: "7", x2: "9.5", y2: "5" }),
6009
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14", y1: "7", x2: "14.5", y2: "5" }),
6010
- /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "9.5", cy: "4.5", r: "0.9", fill: "currentColor", stroke: "none" }),
6011
- /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "14.5", cy: "4.5", r: "0.9", fill: "currentColor", stroke: "none" }),
6012
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "6.5", y1: "16", x2: "4.5", y2: "19.5" }),
6013
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "9", y1: "17.5", x2: "8", y2: "20.5" }),
6014
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "15", y1: "17.5", x2: "16", y2: "20.5" }),
6015
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "17.5", y1: "16", x2: "19.5", y2: "19.5" })
6016
- ]
6117
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M9.5 15 C10.5 16 13.5 16 14.5 15" })
6118
+ ] })
6119
+ }
6120
+ );
6121
+ }
6122
+ function Crab12({ className }) {
6123
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
6124
+ SvgShell,
6125
+ {
6126
+ className,
6127
+ d: "M7 13.5 C7 10.5 9.5 9 12 9 C14.5 9 17 10.5 17 13.5 C17 16 14.5 17.5 12 17.5 C9.5 17.5 7 16 7 13.5 Z",
6128
+ eyeStalks: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
6129
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10.5", y1: "9.5", x2: "10.5", y2: "8" }),
6130
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "13.5", y1: "9.5", x2: "13.5", y2: "8" })
6131
+ ] }),
6132
+ eyes: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
6133
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "10.5", cy: "7.5", r: "0.8", fill: "currentColor", stroke: "none" }),
6134
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "13.5", cy: "7.5", r: "0.8", fill: "currentColor", stroke: "none" })
6135
+ ] }),
6136
+ legs: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
6137
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "8", y1: "16", x2: "6.5", y2: "18" }),
6138
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10", y1: "17", x2: "9.5", y2: "19" }),
6139
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14", y1: "17", x2: "14.5", y2: "19" }),
6140
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "16", y1: "16", x2: "17.5", y2: "18" })
6141
+ ] }),
6142
+ extras: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
6143
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M7.5 12 C6.5 11 5.5 11.5 6 13 C6.5 14 7 13.5 7.5 13" }),
6144
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M16.5 12 C17.5 11 18.5 11.5 18 13 C17.5 14 17 13.5 16.5 13" })
6145
+ ] })
6017
6146
  }
6018
6147
  );
6019
6148
  }
6149
+ const crabVariants = [
6150
+ Crab1,
6151
+ Crab2,
6152
+ Crab3,
6153
+ Crab4,
6154
+ Crab5,
6155
+ Crab6,
6156
+ Crab7,
6157
+ Crab8,
6158
+ Crab9,
6159
+ Crab10,
6160
+ Crab11,
6161
+ Crab12
6162
+ ];
6020
6163
  const McpLogoPng = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6CAQAAAAi5ZK2AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfpCxsJDCnsge2KAAAM2ElEQVR42u2de3AW1RnGnyQQDARDwiUFpHIVMHIpYgFRB2nLxQrC0FIDiCKDWNqBUqBlai8wvciIpaRTWh3QDqCDIIjKDL0IaBC5SKlysWJArgqh3BMICYFs/wgpGUi+8579dr89e/Z5zp/59j2755fn3d2z5wJQFEVRFEVRoVQSm+AG1UFrtEdT1EcjNEA5SlCMIhxDAQoJ3S4lIwf9cD+6ozXq1vKbYuzHNmxEPo6xwcKtungIS3EajkYpwLPoyqYLp3KwACe1cFcvezATmWzEMOk+rMBV18CrSjHy0IqNGQb1wMa4cV8vZfgzGrNRTVYm8nDFQ+SV5QymIIWNa6ZGaz6y6ZR/I4cNbJrSkOcb8MpyCVPYzCapKz71GXllWY5b2dhm6EGcTwhyBw52oyUbPHgNx6WEIXfg4CDuYKMHq0kevI/rlhP4Ghs+OE1ERcKRO3BwEh3Z+NFC7sDBATQngMRrcoDIHTj4iE/yUXJ5VVlhYsMkWezy+a6urgRbsAP7cRincQGpqI+maI+O6IMuSHYRbwIW0X/mJvZTeAH9ah1CATTCaKxBmWbUi7iTOMxEXoCncIsodgvM1ezo2cFPMebdy89qfyHL0vxSN5FQzHL5ajRxVU8v7NO4cWQRjCnIy/DDOOq6FcvENS0gGjMS+wUMjvvdZ5awrsv4KvEE7/Iz+Lontc4Q1vc8AQXt8rO4x7Oa54hqLOLI2aBdfrenHVyviWqdQUx2uLxS6fhMUO8ugrLD5VXqLfpmfxdh2eHyKi0S1P5b4rLF5ZVqiiJl/Z8SmD0ur9TzgnNoQWi2uLxSt+Gy8ixGEpvZLs9AN3RGqsYRa5Xn8SeCM9XlDfFT7Ll2bDnWYYRwOMZjyjP5kOjMdPkDOHpTjPX4iuDILOWL2znCMxH5IyitMc4+ZAuO3q08nyYEaFpiHxbjYWyDIMm/qDyje4kwPMgdOBihjDBNeU7fJcQwIXewTnBzUJ3Vk8Rozr18mOAtuxT1FFH6KmNMJkhTkH+7lse3G0s7RZyuygjPEGVYEntV6aSIlKOM8CvCDEtirywVyFDE6q2M8WPiDJPLJcMgBiljPEWg4XG5AwfTlfEmKWPkEml4XO7gCBooI85TRvlm8I1ax3CX68w8PYeB2KGFfEWM6Yo3qgy5uKj8VU/lLz5HG2QjHRlIA1CCIhTjBI6ggg43LbGXYYggZj3lgkYVtbwaluITvIlf4gHhNEomdheJXfpeXoX8EVHUAR4sY1CKfEyN5gibMCIHXvJsBYur2IDxSCNy05HXx1mPFy/5L2ZFZb6rGR2uusiByb6sWlOMZ5FOl5vocqAuDvm2XNExjLV5t52wuhyY7vM6Ve+jA11uksuB5glYcLgIY+hyc1yeJBj87E35q6BXkC5PAHJgdgKXI9xlzzt8eF0OjE/wypQH7Li7h9nl4wJYjPQ4utPlwSF/LKD1Z8+gC10eLeQOHHyJ1nR54pGPCniVadmcGyK3xOVVZYvWnNpqb5hBIv+L1hCJAdiuhXyVcpT6dV3GSLylhXyxy7YrxHYU4CBO4yKABmiCNuiIe9DMVbT5mMp7eWJc/rgLl1dgC6bE2NelM6Zim4uoDzOxm5nYS/GicNOuznhJc0X5k2HprIkS8gos1cTSSrgYodFbhkQ5sR/F/a7aqD8Oa9TSny43x+UblDNialcmVovr2WP2qOYoIV8V57tREuaK6/o+E7sJid2bO+00Ya0HTPV6lFy+3LNWmymsMZfIg+1w9fZ5ep6ozp3mjaKjy90rGetF9d5H5Ha4vFLZOB62zYGIPH6NEk2NqEvk4U/s1V/f8gX1DyJye5ADQC/BGfyRyO1I7Nf1rvIcPiZye1xeqaGCua6ZNiMf7sOSAolD3h+v4otrH2RewYPCo1JxWnkmQ4jcROTZNcyGWSMcN7PQ5KUJw4zc33t5G+xHzfu3S7655wqmPRG5ccgPxxjkqN7DvbnyfDYRuVmJvY1iYMQEQYxCxRkVEnlYXF5ZdguibFLEKI/6S9pQg1x+Ow4IYrZSxlmqjJFGl4fF5dLVJBcoYzQl8jDcy3XestV7tbcl8vC43IGD3spo6gEVtxF5mJCXCu7H6u6ZRlFE/nAoE7sDB8sEEd9URqkTfuT2P7FXlSuiZQb2KKKU0OXhcbmDGYKYdZWrTO8l8nDcyx04mCeKqh5IsYaJPRyJ3cEfhHFnePTPQ+ShQQ68r4z1NJEHkdj9Q95KcN7didwmlwOzBC2dTOT2uByoj5PBPcbR5UEgly0tPo3I7XE5kI1zgoVOWhO5PS4HXhHE/IDI7XE5MFIU9QdEbo/LO6NIEPWS98Mn/F04pD+R16oWOCiK+4LXyMf4irwnin1ErrtWzGtGIW+MXcJvdB4v/H87LvqIvL1yWG90XZ6J7UHNpVvoI/KGKPDxS5q/Lm/ry5e06i7/SBi5HHd5izxVI/nqIpcM6aXL1WW+1z7v6SPyJ0I7RMJvl+sgP+H9uLihviFvp5FDmNhrL096/34+2Jf3cgBYw8TuAfI3/OiHu8MXl+tsMM97ee3lKBr7AT1JuVuwG+Sp2EvkcSMvR1+/PqbO9Bw5MIn38rgTu69rP6fFeJd2hzwFn/OJPU6XO5gNX5VTy6iNk66QA4+KLqoCY5nYay0L4bs6YedN1e5EJ5fRdogu60dM7DE+/SZk+lIqxmMzrl5br2wzxrvbCA5Ad9FlraTLay2vJ3YV2DS0Rds4VzuYI7isQ1q9TNG6l79uzsK/8ldAyffhYRoRwz0qJgLIgT6CC/uHMcjpck/0c8Gl9aHLbUIO/FN5aflEbhfyOoJBfrlEbhNyydf5C0jnvdwm5MAY5eWtInK7kAOzlRc4mYndLuTAq8pL7KGMMTzUXTGGdrj6qc2KS7yq7O27E1fYxx4ufaK4yCOK41M0ofg7dYHIRVIh2xr3gyBdbpxUW8+8ozh+PV0ePqkmSK1RJPdLhrj890Qu1ynFxa6PeXRTQ76X871cS6rPqh/GPDrLiJc0ulxTqgVtj8U8OglneS8Pn9RrHjaMefwbvJeHT4vj/JY+iMjDJ/UQip8oIqyNcewyJnYT9T3lpf9NEaEJPqvlyEV0uZnqKpjVkqWIkV3DTuKlmusfE3kClYwzygaYIIiSi03XxuA7OIF5aE7kJuttZRPsQpIoUga64W601l75mF0xCZdkYdvBPtZP5AGom6Ahtvu2brnfiZ3IXfbKye7rdHmo9AtBc5zyYftIujxAtRONcduIFLrcJm3wpdmDdfm/iDy2BgqbZnpoXE7kSiUJOy8qMNWD2nJwlC43QY+Km+i5OF/fHhD0ARJ5grpjt4qbaT1auM4oU1DGxG6Oev2/71xdCpEr7Jqtro5YpwWELk+AXtZqsHz01ojdDHM1PU7kCVEznNDEko8RuEXQ0bsAJZqRiTxhGqQ5FdGBg3NYgsfRpoZoDTEIv8N/tCNGDnlSwPU/hxkujyzCPhzBOZQiBY3QFB3i6Lidp7lhZSbe0VorcyVGoZwer1JdbHHlTC8LE3vC1US8CLg/xf+XtDqEfLPa4BiRR0/dBXsGhzOxE3kMdcGXCUc+h8iDT/IFCQR+BROJ3ARlaw5DcF8uYAiRm6J6yHPRXaNb9mhvUknkPmuocuGC+MoS1Cdy89QSK3wCvg8PaZ8NkSdM/YT7hsvLRcwSfKwh8kBVB08LN/JSlxIscNUzT+QBKBlDsC1O4OeR53LkDZEHqN7Ic9VRW4a3kav92EbkxigF38BcbEO5CMBhLME45Tz3yCJPChn8dPRBF7RHB3RARrVtvC6hGIewHwUowBYcirMW/e/lubhCZybunyALmR7/6zKxR05ETuRETuRETuRsNCKniJwicorIKSKniJwicorIKSKniJyqGfnHmvsyE3nIlRJzHxi63ErlEXnUNI6JPWrKUO7rTJdbp98QedSUjWIm9qjpGSKPnrYysUdNzYRLEBO5RRrLxF6p5AhB7yz4zUqMtn+CUpSgZyt/sZpz0mzTWuXU5sbRaIgoOT1T8fdCnCZ026RC2lJzQ25CD4EKFX9PwWLUI/RoQQe+hbdcrEBFGazRovf0tdFwe1SUJVyx5u90u03aKOx7J3aLNEP8lY1J3ho10hg3Q7dbo59pjJwhdkvUAMeJPXr6jtY2Ary3W6Jfaw2CptutUJLmJgLEboXSsUkLO5O8JQ9079LtxE7sxE7sxE7sFqkhH+mIXV1WhG43DMoD7OPZZNHD/gWnPUUR+4BwX2wyeQMAijEYH4h/fS+hRw97c0K3B/tAvCf6ZRmh26OLGCpy+wE2VfQe6XLYTFHD/h6bKGrYy9CDDWQr9vwakV/FE2wce5WGl29CfgrD2TC2qy+W4/w14Hsxy5aVKvjFSN1CLVAPp1DEpqAoiqIoyiz9D9lYMumhgrvLAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDI1LTExLTI3VDA5OjEyOjQxKzAwOjAwvIZCxQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyNS0xMS0yN1QwOToxMjo0MSswMDowMM3b+nkAAAAASUVORK5CYII=";
6021
6164
  function McpLogo({ className }) {
6022
6165
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -8022,17 +8165,47 @@ function ProviderTestDetails({ result }) {
8022
8165
  function ProviderFormatTestStatus({
8023
8166
  results
8024
8167
  }) {
8025
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-col gap-2", children: [
8026
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [
8168
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid min-w-0 gap-2 sm:grid-cols-2", children: [
8169
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 rounded-md border border-border/60 bg-muted/20 px-2 py-1.5", children: [
8027
8170
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] text-muted-foreground", children: "Non-stream" }),
8028
8171
  /* @__PURE__ */ jsxRuntimeExports.jsx(TestStatus, { result: results.nonStreaming })
8029
8172
  ] }),
8030
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [
8173
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 rounded-md border border-border/60 bg-muted/20 px-2 py-1.5", children: [
8031
8174
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] text-muted-foreground", children: "Stream" }),
8032
8175
  /* @__PURE__ */ jsxRuntimeExports.jsx(TestStatus, { result: results.streaming })
8033
8176
  ] })
8034
8177
  ] });
8035
8178
  }
8179
+ function EndpointDiagnosticLine({
8180
+ diagnostic
8181
+ }) {
8182
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: diagnostic.severity === "warning" ? "text-amber-200" : "text-muted-foreground", children: diagnostic.message });
8183
+ }
8184
+ function ProviderEndpointSummary({
8185
+ label,
8186
+ baseUrl,
8187
+ endpoint,
8188
+ providerName,
8189
+ children
8190
+ }) {
8191
+ const preview = previewUpstreamUrl(baseUrl, endpoint, { providerName });
8192
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-col gap-2 border-t border-border/60 pt-2 first:border-t-0 first:pt-0", children: [
8193
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid min-w-0 gap-1 text-xs sm:grid-cols-[104px_minmax(0,1fr)]", children: [
8194
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium text-muted-foreground", children: label }),
8195
+ /* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "min-w-0 break-all font-mono text-foreground/80", children: baseUrl }),
8196
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] uppercase text-muted-foreground/80", children: "Final" }),
8197
+ /* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "min-w-0 break-all font-mono text-foreground", children: preview.finalUrl })
8198
+ ] }),
8199
+ preview.diagnostics.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1 text-xs", children: preview.diagnostics.map((diagnostic) => /* @__PURE__ */ jsxRuntimeExports.jsx(
8200
+ EndpointDiagnosticLine,
8201
+ {
8202
+ diagnostic
8203
+ },
8204
+ `${diagnostic.severity}:${diagnostic.message}`
8205
+ )) }),
8206
+ children
8207
+ ] });
8208
+ }
8036
8209
  function getErrorIcon(type) {
8037
8210
  const iconProps = { className: "size-3", strokeWidth: 2 };
8038
8211
  switch (type) {
@@ -8130,8 +8303,8 @@ function TestStatus({ result }) {
8130
8303
  displayTiming.push(timingParts[i]);
8131
8304
  }
8132
8305
  return /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
8133
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 text-xs text-green-600 shrink-0", children: [
8134
- /* @__PURE__ */ jsxRuntimeExports.jsx(CircleCheckBig, { className: "size-3" }),
8306
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 text-xs text-cyan-100 shrink-0", children: [
8307
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CircleCheckBig, { className: "size-3 text-cyan-300" }),
8135
8308
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Connected" }),
8136
8309
  tokenParts.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground", children: [
8137
8310
  "(",
@@ -8233,6 +8406,13 @@ function ProviderCard({
8233
8406
  const hasContextMetadata = providerHasContextMetadata(provider);
8234
8407
  const canRefreshMetadata = provider.modelMetadataUrl !== void 0 && provider.modelMetadataUrl.trim() !== "";
8235
8408
  const metadataImportLabel = canRefreshMetadata ? "Refresh" : "Import defaults";
8409
+ const providerSourceBadge = provider.source === "company" ? /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
8410
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0 rounded border border-cyan-300/20 bg-cyan-300/[0.08] px-1.5 py-0.5 text-xs text-cyan-100", children: "Company" }) }),
8411
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Company-provided API key" })
8412
+ ] }) }) : provider.source === "personal" ? /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
8413
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0 rounded border border-violet-300/20 bg-violet-300/[0.08] px-1.5 py-0.5 text-xs text-violet-100", children: "Personal" }) }),
8414
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Your personal API key" })
8415
+ ] }) }) : null;
8236
8416
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
8237
8417
  "div",
8238
8418
  {
@@ -8241,11 +8421,12 @@ function ProviderCard({
8241
8421
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
8242
8422
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [
8243
8423
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium truncate", children: provider.name }),
8244
- provider.source === "company" && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
8424
+ providerSourceBadge,
8425
+ providerSourceBadge === null && provider.source === "company" && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
8245
8426
  /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs px-1.5 py-0.5 rounded bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400 shrink-0", children: "公司" }) }),
8246
8427
  /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Company-provided API key" })
8247
8428
  ] }) }),
8248
- provider.source === "personal" && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
8429
+ providerSourceBadge === null && provider.source === "personal" && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
8249
8430
  /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs px-1.5 py-0.5 rounded bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400 shrink-0", children: "个人" }) }),
8250
8431
  /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Your personal API key" })
8251
8432
  ] }) })
@@ -8344,31 +8525,40 @@ function ProviderCard({
8344
8525
  onClick: handleCopy,
8345
8526
  className: "text-muted-foreground hover:text-foreground transition-colors p-1",
8346
8527
  "aria-label": "Copy API key",
8347
- children: copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-4 text-green-500" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-4" })
8528
+ children: copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-4 text-cyan-300" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-4" })
8348
8529
  }
8349
8530
  )
8350
8531
  ] }),
8351
- provider.anthropicBaseUrl !== void 0 && provider.anthropicBaseUrl !== "" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-col gap-2", children: [
8352
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 text-xs text-muted-foreground", children: [
8353
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium", children: "Anthropic:" }),
8354
- " ",
8355
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate", children: provider.anthropicBaseUrl })
8356
- ] }),
8357
- testResults !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: testResults.anthropic })
8358
- ] }),
8359
- provider.openaiBaseUrl !== void 0 && provider.openaiBaseUrl !== "" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-col gap-2", children: [
8360
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 text-xs text-muted-foreground", children: [
8361
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium", children: "OpenAI Chat:" }),
8362
- " ",
8363
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate", children: provider.openaiBaseUrl })
8364
- ] }),
8365
- testResults !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: testResults.openai })
8366
- ] }),
8367
- 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: [
8368
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium", children: "OpenAI Responses:" }),
8369
- " ",
8370
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate", children: provider.openaiResponsesBaseUrl })
8371
- ] }) }),
8532
+ provider.anthropicBaseUrl !== void 0 && provider.anthropicBaseUrl !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx(
8533
+ ProviderEndpointSummary,
8534
+ {
8535
+ label: "Anthropic",
8536
+ baseUrl: provider.anthropicBaseUrl,
8537
+ endpoint: PATH_V1_MESSAGES,
8538
+ providerName: provider.name,
8539
+ children: testResults !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: testResults.anthropic })
8540
+ }
8541
+ ),
8542
+ provider.openaiBaseUrl !== void 0 && provider.openaiBaseUrl !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx(
8543
+ ProviderEndpointSummary,
8544
+ {
8545
+ label: "OpenAI Chat",
8546
+ baseUrl: provider.openaiBaseUrl,
8547
+ endpoint: PATH_V1_CHAT_COMPLETIONS,
8548
+ providerName: provider.name,
8549
+ children: testResults !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: testResults.openaiChat })
8550
+ }
8551
+ ),
8552
+ provider.openaiResponsesBaseUrl !== void 0 && provider.openaiResponsesBaseUrl !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx(
8553
+ ProviderEndpointSummary,
8554
+ {
8555
+ label: "OpenAI Responses",
8556
+ baseUrl: provider.openaiResponsesBaseUrl,
8557
+ endpoint: PATH_V1_RESPONSES,
8558
+ providerName: provider.name,
8559
+ children: testResults !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: testResults.openaiResponses })
8560
+ }
8561
+ ),
8372
8562
  testResults?.testedAt !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-xs text-muted-foreground flex items-center gap-1", children: [
8373
8563
  /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "size-3" }),
8374
8564
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
@@ -8395,12 +8585,14 @@ function ProviderCard({
8395
8585
  /* @__PURE__ */ jsxRuntimeExports.jsx("thead", { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("tr", { className: "border-b border-border", children: [
8396
8586
  /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "text-left py-1 px-2 font-medium text-muted-foreground", children: "Model" }),
8397
8587
  provider.anthropicBaseUrl !== void 0 && provider.anthropicBaseUrl !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "text-left py-1 px-2 font-medium text-muted-foreground", children: "Anthropic" }),
8398
- provider.openaiBaseUrl !== void 0 && provider.openaiBaseUrl !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "text-left py-1 px-2 font-medium text-muted-foreground", children: "OpenAI" })
8588
+ provider.openaiBaseUrl !== void 0 && provider.openaiBaseUrl !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "text-left py-1 px-2 font-medium text-muted-foreground", children: "Chat" }),
8589
+ provider.openaiResponsesBaseUrl !== void 0 && provider.openaiResponsesBaseUrl !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "text-left py-1 px-2 font-medium text-muted-foreground", children: "Responses" })
8399
8590
  ] }) }),
8400
8591
  /* @__PURE__ */ jsxRuntimeExports.jsx("tbody", { children: Object.entries(testResults.models).map(([modelName, modelResult]) => /* @__PURE__ */ jsxRuntimeExports.jsxs("tr", { className: "border-b border-border/50 last:border-0", children: [
8401
8592
  /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-1 px-2 font-medium", children: modelName }),
8402
8593
  provider.anthropicBaseUrl !== void 0 && provider.anthropicBaseUrl !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-1 px-2 align-top", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: modelResult.anthropic }) }),
8403
- provider.openaiBaseUrl !== void 0 && provider.openaiBaseUrl !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-1 px-2 align-top", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: modelResult.openai }) })
8594
+ provider.openaiBaseUrl !== void 0 && provider.openaiBaseUrl !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-1 px-2 align-top", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: modelResult.openaiChat }) }),
8595
+ provider.openaiResponsesBaseUrl !== void 0 && provider.openaiResponsesBaseUrl !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-1 px-2 align-top", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: modelResult.openaiResponses }) })
8404
8596
  ] }, modelName)) })
8405
8597
  ] }) })
8406
8598
  ] }),
@@ -8460,9 +8652,9 @@ const ZHIPU_CODING_PROVIDER_KEYWORDS = [
8460
8652
  "z.ai coding",
8461
8653
  "zai coding"
8462
8654
  ];
8463
- const ANTHROPIC_MESSAGES_ENDPOINT = "/v1/messages";
8464
- const OPENAI_CHAT_COMPLETIONS_ENDPOINT = "/v1/chat/completions";
8465
- const OPENAI_RESPONSES_ENDPOINT = "/v1/responses";
8655
+ const ANTHROPIC_MESSAGES_ENDPOINT = PATH_V1_MESSAGES;
8656
+ const OPENAI_CHAT_COMPLETIONS_ENDPOINT = PATH_V1_CHAT_COMPLETIONS;
8657
+ const OPENAI_RESPONSES_ENDPOINT = PATH_V1_RESPONSES;
8466
8658
  const KNOWN_PROVIDER_PRESETS = {
8467
8659
  deepseek: {
8468
8660
  openaiBaseUrl: "https://api.deepseek.com"
@@ -8650,19 +8842,28 @@ function stripEndpointSuffix(value, endpoint) {
8650
8842
  const normalized = trimmed.replace(/\/+$/, "");
8651
8843
  return normalized.endsWith(endpoint) ? normalized.slice(0, -endpoint.length).replace(/\/+$/, "") : trimmed;
8652
8844
  }
8653
- function previewEndpointUrl(baseUrl, endpoint) {
8845
+ function previewEndpointUrl(baseUrl, endpoint, providerName) {
8654
8846
  const trimmed = baseUrl.trim();
8655
- return trimmed === "" ? null : buildUpstreamUrl(trimmed, endpoint);
8847
+ return trimmed === "" ? null : previewUpstreamUrl(trimmed, endpoint, { providerName });
8656
8848
  }
8657
8849
  function EndpointUrlPreview({
8658
8850
  baseUrl,
8659
- endpoint
8851
+ endpoint,
8852
+ providerName
8660
8853
  }) {
8661
- const finalUrl = previewEndpointUrl(baseUrl, endpoint);
8662
- if (finalUrl === null) return null;
8854
+ const preview = previewEndpointUrl(baseUrl, endpoint, providerName);
8855
+ if (preview === null) return null;
8663
8856
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border border-border bg-muted/40 rounded-md px-3 py-2 text-xs", children: [
8664
8857
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-muted-foreground", children: "Final URL" }),
8665
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "break-all font-mono text-foreground", children: finalUrl })
8858
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "break-all font-mono text-foreground", children: preview.finalUrl }),
8859
+ preview.diagnostics.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 space-y-1", children: preview.diagnostics.map((diagnostic) => /* @__PURE__ */ jsxRuntimeExports.jsx(
8860
+ "div",
8861
+ {
8862
+ className: diagnostic.severity === "warning" ? "text-amber-200" : "text-muted-foreground",
8863
+ children: diagnostic.message
8864
+ },
8865
+ `${diagnostic.severity}:${diagnostic.message}`
8866
+ )) })
8666
8867
  ] });
8667
8868
  }
8668
8869
  function ProviderForm({ provider, onSubmit, onCancel }) {
@@ -9037,7 +9238,7 @@ function ProviderForm({ provider, onSubmit, onCancel }) {
9037
9238
  onClick: handleCopy,
9038
9239
  className: "text-muted-foreground hover:text-foreground transition-colors p-1 shrink-0",
9039
9240
  "aria-label": "Copy API key",
9040
- children: copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-4 text-green-500" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-4" })
9241
+ children: copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-4 text-cyan-300" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-4" })
9041
9242
  }
9042
9243
  )
9043
9244
  ] }),
@@ -9263,7 +9464,14 @@ function ProviderForm({ provider, onSubmit, onCancel }) {
9263
9464
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0 select-none border-l border-white/10 bg-white/[0.04] px-3 py-2 font-mono text-xs text-muted-foreground", children: ANTHROPIC_MESSAGES_ENDPOINT })
9264
9465
  ] }),
9265
9466
  errors.anthropicBaseUrl !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-destructive", children: errors.anthropicBaseUrl }),
9266
- /* @__PURE__ */ jsxRuntimeExports.jsx(EndpointUrlPreview, { baseUrl: anthropicBaseUrl, endpoint: ANTHROPIC_MESSAGES_ENDPOINT }),
9467
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
9468
+ EndpointUrlPreview,
9469
+ {
9470
+ baseUrl: anthropicBaseUrl,
9471
+ endpoint: ANTHROPIC_MESSAGES_ENDPOINT,
9472
+ providerName: name
9473
+ }
9474
+ ),
9267
9475
  /* @__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." })
9268
9476
  ] }),
9269
9477
  activeTab === "openai" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
@@ -9291,7 +9499,8 @@ function ProviderForm({ provider, onSubmit, onCancel }) {
9291
9499
  EndpointUrlPreview,
9292
9500
  {
9293
9501
  baseUrl: openaiBaseUrl,
9294
- endpoint: OPENAI_CHAT_COMPLETIONS_ENDPOINT
9502
+ endpoint: OPENAI_CHAT_COMPLETIONS_ENDPOINT,
9503
+ providerName: name
9295
9504
  }
9296
9505
  ),
9297
9506
  /* @__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." })
@@ -9320,7 +9529,8 @@ function ProviderForm({ provider, onSubmit, onCancel }) {
9320
9529
  EndpointUrlPreview,
9321
9530
  {
9322
9531
  baseUrl: openaiResponsesBaseUrl,
9323
- endpoint: OPENAI_RESPONSES_ENDPOINT
9532
+ endpoint: OPENAI_RESPONSES_ENDPOINT,
9533
+ providerName: name
9324
9534
  }
9325
9535
  ),
9326
9536
  /* @__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." })
@@ -9851,7 +10061,7 @@ function ProvidersPanel({
9851
10061
  },
9852
10062
  className: "shrink-0 ml-auto text-muted-foreground hover:text-foreground transition-colors",
9853
10063
  "aria-label": configPathCopied ? "Copied config file path" : "Copy config file path",
9854
- children: configPathCopied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-3 text-green-500" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-3" })
10064
+ children: configPathCopied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-3 text-cyan-300" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-3" })
9855
10065
  }
9856
10066
  ) }),
9857
10067
  /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Copy config file path to clipboard" })
@@ -12141,97 +12351,348 @@ function getModelLabel(logs) {
12141
12351
  if (sorted.length === 1) return sorted[0] ?? "Model unknown";
12142
12352
  return `${sorted.length} models`;
12143
12353
  }
12354
+ function getProviderLabel(logs) {
12355
+ const providers = /* @__PURE__ */ new Set();
12356
+ for (const log of logs) {
12357
+ if (log.providerName !== null && log.providerName !== void 0 && log.providerName.length > 0) {
12358
+ providers.add(log.providerName);
12359
+ }
12360
+ }
12361
+ const sorted = [...providers].sort();
12362
+ if (sorted.length === 0) return "Provider unknown";
12363
+ if (sorted.length === 1) return sorted[0] ?? "Provider unknown";
12364
+ return `${sorted.length} providers`;
12365
+ }
12366
+ function formatElapsedMs(ms) {
12367
+ if (ms < 1e3) return `${ms}ms`;
12368
+ if (ms < 6e4) {
12369
+ const seconds2 = ms / 1e3;
12370
+ return `${seconds2 < 10 ? seconds2.toFixed(1) : seconds2.toFixed(0)}s`;
12371
+ }
12372
+ const totalSeconds = Math.round(ms / 1e3);
12373
+ const minutes = Math.floor(totalSeconds / 60);
12374
+ const seconds = totalSeconds % 60;
12375
+ return `${minutes}m ${seconds}s`;
12376
+ }
12377
+ function formatTokenPair(inputTokens, outputTokens) {
12378
+ return `${formatTokens(inputTokens)} in / ${formatTokens(outputTokens)} out`;
12379
+ }
12380
+ function countSessionTurns(logs, conversationGroups) {
12381
+ if (logs.length === 0) return 0;
12382
+ if (conversationGroups.length === 0) return buildTurnGroups(logs).length;
12383
+ let turns = 0;
12384
+ for (const group of conversationGroups) {
12385
+ turns += buildTurnGroups(group.logs).length;
12386
+ }
12387
+ return turns;
12388
+ }
12389
+ function summarizeFinishReason({
12390
+ stopReason,
12391
+ pending,
12392
+ lastFailureLogNumber
12393
+ }) {
12394
+ if (pending > 0) {
12395
+ return {
12396
+ label: "In flight",
12397
+ detail: `${pending} request${pending === 1 ? "" : "s"} pending`,
12398
+ tone: "cool"
12399
+ };
12400
+ }
12401
+ if (lastFailureLogNumber !== null && stopReason === null) {
12402
+ return {
12403
+ label: "Error",
12404
+ detail: `Last failed request #${lastFailureLogNumber}`,
12405
+ tone: "danger"
12406
+ };
12407
+ }
12408
+ switch (stopReason) {
12409
+ case "end_turn":
12410
+ return { label: "End turn", detail: "Assistant completed the turn", tone: "neutral" };
12411
+ case "stop":
12412
+ return { label: "Stop", detail: "Model reached a stop condition", tone: "neutral" };
12413
+ case "length":
12414
+ return { label: "Output limit", detail: "Turn ended at max output tokens", tone: "watch" };
12415
+ case "tool_use":
12416
+ return { label: "Tool call", detail: "Assistant requested a tool", tone: "cool" };
12417
+ case null:
12418
+ return { label: "Unknown", detail: "No finish reason captured", tone: "neutral" };
12419
+ }
12420
+ }
12421
+ function isClientAbortError(error) {
12422
+ if (error === null) return false;
12423
+ const lower = error.toLowerCase();
12424
+ return lower.includes("abort") || lower.includes("cancel") || lower.includes("client disconnected") || lower.includes("stream disconnected") || lower.includes("connection closed");
12425
+ }
12426
+ function summarizeSessionOutcome({
12427
+ pending,
12428
+ failures,
12429
+ lengthStops,
12430
+ stopReason,
12431
+ lastFailure
12432
+ }) {
12433
+ if (lastFailure !== null && (lastFailure.status === 499 || isClientAbortError(lastFailure.error))) {
12434
+ return {
12435
+ label: "Client aborted",
12436
+ detail: `Request #${lastFailure.logNumber} ended before completion`,
12437
+ tone: "watch"
12438
+ };
12439
+ }
12440
+ if (pending > 0) {
12441
+ return {
12442
+ label: "In flight",
12443
+ detail: `${pending} request${pending === 1 ? "" : "s"} still running`,
12444
+ tone: "cool"
12445
+ };
12446
+ }
12447
+ if (lastFailure !== null && lastFailure.status !== null && lastFailure.status >= 500) {
12448
+ return {
12449
+ label: "Provider error",
12450
+ detail: `Request #${lastFailure.logNumber} returned HTTP ${lastFailure.status}`,
12451
+ tone: "danger"
12452
+ };
12453
+ }
12454
+ if (failures > 0 && lastFailure !== null) {
12455
+ return {
12456
+ label: "Failed",
12457
+ detail: `Request #${lastFailure.logNumber} needs attention`,
12458
+ tone: "danger"
12459
+ };
12460
+ }
12461
+ if (lengthStops > 0 || stopReason === "length") {
12462
+ return {
12463
+ label: "Output limited",
12464
+ detail: "Model stopped at the output token limit",
12465
+ tone: "watch"
12466
+ };
12467
+ }
12468
+ switch (stopReason) {
12469
+ case "end_turn":
12470
+ case "stop":
12471
+ return { label: "Completed", detail: "Assistant completed normally", tone: "neutral" };
12472
+ case "tool_use":
12473
+ return { label: "Tool requested", detail: "Assistant handed off to a tool", tone: "cool" };
12474
+ case null:
12475
+ return { label: "Unknown", detail: "No terminal signal captured", tone: "neutral" };
12476
+ }
12477
+ }
12144
12478
  function buildSessionSlateStats({
12145
12479
  logs,
12480
+ conversationGroups,
12146
12481
  isLoading,
12147
12482
  timeDisplayFormat,
12148
12483
  slowResponseThresholdSeconds
12149
12484
  }) {
12150
12485
  let failures = 0;
12486
+ let pending = 0;
12151
12487
  let slow = 0;
12488
+ let lengthStops = 0;
12152
12489
  let totalIn = 0;
12153
12490
  let totalOut = 0;
12491
+ let terminalStopReason = null;
12492
+ let lastFailureLogNumber = null;
12493
+ let lastFailure = null;
12494
+ let slowestMs = null;
12495
+ let slowestLogNumber = null;
12496
+ let heaviestTokens = 0;
12497
+ let heaviestInputTokens = 0;
12498
+ let heaviestOutputTokens = 0;
12499
+ let heaviestLogNumber = null;
12154
12500
  const slowThresholdMs = slowResponseThresholdSeconds * 1e3;
12155
- for (const log of logs) {
12156
- if (hasLogFailure(log)) failures += 1;
12501
+ for (let index = 0; index < logs.length; index += 1) {
12502
+ const log = logs[index];
12503
+ if (log === void 0) continue;
12504
+ const logNumber = index + 1;
12505
+ const stopReason = extractStopReason(log);
12506
+ if (stopReason !== null) terminalStopReason = stopReason;
12507
+ if (stopReason === "length") lengthStops += 1;
12508
+ if (hasLogFailure(log)) {
12509
+ failures += 1;
12510
+ lastFailureLogNumber = logNumber;
12511
+ lastFailure = {
12512
+ logNumber,
12513
+ status: log.responseStatus,
12514
+ error: log.error ?? null
12515
+ };
12516
+ }
12517
+ if (log.responseStatus === null) pending += 1;
12157
12518
  if (slowResponseThresholdSeconds > 0 && log.elapsedMs !== null && log.elapsedMs >= slowThresholdMs) {
12158
12519
  slow += 1;
12159
12520
  }
12160
12521
  if (log.inputTokens !== null) totalIn += log.inputTokens;
12161
12522
  if (log.outputTokens !== null) totalOut += log.outputTokens;
12523
+ if (log.elapsedMs !== null && (slowestMs === null || log.elapsedMs > slowestMs)) {
12524
+ slowestMs = log.elapsedMs;
12525
+ slowestLogNumber = logNumber;
12526
+ }
12527
+ const inputTokens = log.inputTokens ?? 0;
12528
+ const outputTokens = log.outputTokens ?? 0;
12529
+ const requestTokens = inputTokens + outputTokens;
12530
+ if (requestTokens > heaviestTokens) {
12531
+ heaviestTokens = requestTokens;
12532
+ heaviestInputTokens = inputTokens;
12533
+ heaviestOutputTokens = outputTokens;
12534
+ heaviestLogNumber = logNumber;
12535
+ }
12162
12536
  }
12163
- const status = isLoading ? "rolling" : failures > 0 ? "failed" : slow > 0 ? "watch" : "clear";
12537
+ const status = isLoading || pending > 0 && failures === 0 ? "rolling" : failures > 0 ? "failed" : slow > 0 || lengthStops > 0 ? "watch" : "clear";
12164
12538
  const statusLabel2 = status === "rolling" ? "Rolling" : status === "failed" ? "Failure" : status === "watch" ? "Watch" : "Clear";
12539
+ const finish = summarizeFinishReason({
12540
+ stopReason: terminalStopReason,
12541
+ pending,
12542
+ lastFailureLogNumber
12543
+ });
12544
+ const outcome = summarizeSessionOutcome({
12545
+ pending,
12546
+ failures,
12547
+ lengthStops,
12548
+ stopReason: terminalStopReason,
12549
+ lastFailure
12550
+ });
12165
12551
  return {
12166
12552
  status,
12167
12553
  statusLabel: statusLabel2,
12168
12554
  modelLabel: getModelLabel(logs),
12555
+ providerLabel: getProviderLabel(logs),
12169
12556
  requests: logs.length,
12557
+ turns: countSessionTurns(logs, conversationGroups),
12170
12558
  failures,
12559
+ pending,
12171
12560
  slow,
12561
+ lengthStops,
12172
12562
  timeRange: formatTimeRange(logs, timeDisplayFormat),
12173
- tokenLabel: `${formatTokens(totalIn)} in / ${formatTokens(totalOut)} out`
12563
+ tokenLabel: `${formatTokens(totalIn)} in / ${formatTokens(totalOut)} out`,
12564
+ finishLabel: finish.label,
12565
+ finishDetail: finish.detail,
12566
+ finishTone: finish.tone,
12567
+ outcomeLabel: outcome.label,
12568
+ outcomeDetail: outcome.detail,
12569
+ outcomeTone: outcome.tone,
12570
+ slowestLabel: slowestMs === null ? "n/a" : formatElapsedMs(slowestMs),
12571
+ slowestDetail: slowestLogNumber === null ? "Latency pending" : `Request #${slowestLogNumber}`,
12572
+ heaviestDetail: heaviestLogNumber === null ? "Tokens pending" : `#${heaviestLogNumber} ${formatTokenPair(heaviestInputTokens, heaviestOutputTokens)}`
12174
12573
  };
12175
12574
  }
12176
- function slateStatusClass(status) {
12575
+ function slateMetricToneClass(tone) {
12576
+ switch (tone) {
12577
+ case "cool":
12578
+ return "text-cyan-100";
12579
+ case "danger":
12580
+ return "text-red-100";
12581
+ case "watch":
12582
+ return "text-amber-100";
12583
+ case "neutral":
12584
+ return "text-foreground";
12585
+ }
12586
+ }
12587
+ function statusMetricTone(status) {
12177
12588
  switch (status) {
12178
12589
  case "rolling":
12179
- return "border-cyan-400/35 bg-cyan-500/10 text-cyan-200";
12590
+ return "cool";
12180
12591
  case "failed":
12181
- return "border-red-400/35 bg-red-500/10 text-red-100";
12592
+ return "danger";
12182
12593
  case "watch":
12183
- return "border-amber-300/35 bg-amber-400/10 text-amber-100";
12594
+ return "watch";
12184
12595
  case "clear":
12185
- return "border-slate-300/20 bg-slate-300/[0.08] text-slate-100";
12596
+ return "neutral";
12186
12597
  }
12187
12598
  }
12599
+ function requestHealthDetail(stats) {
12600
+ if (stats.pending > 0) return `${stats.pending} pending / ${stats.failures} failed`;
12601
+ if (stats.lengthStops > 0) return `${stats.lengthStops} output limit / ${stats.failures} failed`;
12602
+ return `${stats.failures} failed / ${stats.slow} slow`;
12603
+ }
12604
+ function SessionSlateMetric({
12605
+ label,
12606
+ value,
12607
+ detail,
12608
+ icon,
12609
+ tone = "neutral"
12610
+ }) {
12611
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 border-t border-white/10 px-4 py-3", children: [
12612
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 text-[10px] uppercase text-muted-foreground", children: [
12613
+ icon,
12614
+ label
12615
+ ] }),
12616
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: cn("mt-2 font-mono text-sm font-semibold", slateMetricToneClass(tone)), children: value }),
12617
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1 font-mono text-[11px] leading-snug text-muted-foreground", children: detail })
12618
+ ] });
12619
+ }
12188
12620
  function SessionOpeningSlate({ stats }) {
12189
12621
  if (stats.requests === 0) return null;
12190
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "border border-border bg-card shadow-sm mb-4 rounded-[8px]", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-0 md:grid-cols-[minmax(220px,1.2fr)_repeat(4,minmax(120px,1fr))]", children: [
12191
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "col-span-2 border-b border-white/10 px-4 py-3 md:col-span-1 md:border-b-0 md:border-r", children: [
12192
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-[10px] font-semibold uppercase text-muted-foreground", children: [
12193
- /* @__PURE__ */ jsxRuntimeExports.jsx(Clapperboard, { className: "size-3.5 text-cyan-300" }),
12194
- "Opening Slate"
12622
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border border-border bg-card shadow-sm mb-4 overflow-hidden rounded-[8px]", children: [
12623
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-4 py-3", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-end justify-between gap-3", children: [
12624
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0", children: [
12625
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-[10px] font-semibold uppercase text-muted-foreground", children: [
12626
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Clapperboard, { className: "size-3.5 text-slate-300" }),
12627
+ "Flight Recorder"
12628
+ ] }),
12629
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 min-w-0 font-mono text-sm font-semibold text-foreground", children: stats.modelLabel })
12195
12630
  ] }),
12196
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 min-w-0 truncate font-mono text-sm font-semibold text-foreground", children: stats.modelLabel }),
12197
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1 truncate font-mono text-[11px] text-muted-foreground", children: stats.timeRange ?? "Timeline pending" })
12198
- ] }),
12199
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-r border-b border-white/10 px-4 py-3 md:border-b-0", children: [
12200
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[10px] uppercase text-muted-foreground", children: "Status" }),
12631
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-x-4 gap-y-1 text-[11px] text-muted-foreground", children: [
12632
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0 font-mono", children: stats.providerLabel }),
12633
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0 font-mono", children: stats.timeRange ?? "Timeline pending" })
12634
+ ] })
12635
+ ] }) }),
12636
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 border-t border-white/10 md:grid-cols-3 2xl:grid-cols-6", children: [
12201
12637
  /* @__PURE__ */ jsxRuntimeExports.jsx(
12202
- "div",
12638
+ SessionSlateMetric,
12203
12639
  {
12204
- className: cn(
12205
- "mt-2 inline-flex h-7 items-center rounded-md border px-2.5 font-mono text-xs font-semibold",
12206
- slateStatusClass(stats.status)
12207
- ),
12208
- children: stats.statusLabel
12640
+ label: "Status",
12641
+ value: stats.statusLabel,
12642
+ detail: requestHealthDetail(stats),
12643
+ tone: statusMetricTone(stats.status)
12644
+ }
12645
+ ),
12646
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
12647
+ SessionSlateMetric,
12648
+ {
12649
+ label: "Turns",
12650
+ value: String(stats.turns),
12651
+ detail: stats.finishLabel,
12652
+ icon: /* @__PURE__ */ jsxRuntimeExports.jsx(Flag, { className: "size-3 text-muted-foreground" }),
12653
+ tone: stats.finishTone
12654
+ }
12655
+ ),
12656
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
12657
+ SessionSlateMetric,
12658
+ {
12659
+ label: "Requests",
12660
+ value: String(stats.requests),
12661
+ detail: `${stats.failures} failed / ${stats.slow} slow`,
12662
+ icon: /* @__PURE__ */ jsxRuntimeExports.jsx(Siren, { className: "size-3 text-muted-foreground" }),
12663
+ tone: stats.failures > 0 ? "danger" : "neutral"
12664
+ }
12665
+ ),
12666
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
12667
+ SessionSlateMetric,
12668
+ {
12669
+ label: "Peak",
12670
+ value: stats.slowestLabel,
12671
+ detail: stats.slowestDetail,
12672
+ icon: /* @__PURE__ */ jsxRuntimeExports.jsx(Timer, { className: "size-3 text-muted-foreground" }),
12673
+ tone: stats.slow > 0 ? "watch" : "neutral"
12674
+ }
12675
+ ),
12676
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
12677
+ SessionSlateMetric,
12678
+ {
12679
+ label: "Tokens",
12680
+ value: stats.tokenLabel,
12681
+ detail: stats.heaviestDetail,
12682
+ icon: /* @__PURE__ */ jsxRuntimeExports.jsx(Gauge, { className: "size-3 text-muted-foreground" })
12683
+ }
12684
+ ),
12685
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
12686
+ SessionSlateMetric,
12687
+ {
12688
+ label: "Outcome",
12689
+ value: stats.outcomeLabel,
12690
+ detail: stats.outcomeDetail,
12691
+ tone: stats.outcomeTone
12209
12692
  }
12210
12693
  )
12211
- ] }),
12212
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-b border-white/10 px-4 py-3 md:border-b-0 md:border-r", children: [
12213
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[10px] uppercase text-muted-foreground", children: "Requests" }),
12214
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 font-mono text-xl font-semibold text-foreground", children: stats.requests })
12215
- ] }),
12216
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-r border-white/10 px-4 py-3 md:border-r", children: [
12217
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 text-[10px] uppercase text-muted-foreground", children: [
12218
- /* @__PURE__ */ jsxRuntimeExports.jsx(Siren, { className: "size-3 text-red-300" }),
12219
- "Failure"
12220
- ] }),
12221
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 font-mono text-xl font-semibold text-red-100", children: stats.failures })
12222
- ] }),
12223
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-3", children: [
12224
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 text-[10px] uppercase text-muted-foreground", children: [
12225
- /* @__PURE__ */ jsxRuntimeExports.jsx(Gauge, { className: "size-3 text-amber-200" }),
12226
- "Tempo"
12227
- ] }),
12228
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-2 font-mono text-sm font-semibold text-foreground", children: [
12229
- stats.slow,
12230
- " slow"
12231
- ] }),
12232
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1 truncate font-mono text-[11px] text-muted-foreground", children: stats.tokenLabel })
12233
12694
  ] })
12234
- ] }) });
12695
+ ] });
12235
12696
  }
12236
12697
  function resolveSessionContextScope({
12237
12698
  pinnedSessionId,
@@ -13193,11 +13654,12 @@ function ProxyViewer({
13193
13654
  const slateStats = reactExports.useMemo(
13194
13655
  () => buildSessionSlateStats({
13195
13656
  logs,
13657
+ conversationGroups: groups,
13196
13658
  isLoading,
13197
13659
  timeDisplayFormat,
13198
13660
  slowResponseThresholdSeconds
13199
13661
  }),
13200
- [isLoading, logs, slowResponseThresholdSeconds, timeDisplayFormat]
13662
+ [groups, isLoading, logs, slowResponseThresholdSeconds, timeDisplayFormat]
13201
13663
  );
13202
13664
  const handleCompareWithPrevious = reactExports.useCallback(
13203
13665
  (log) => {