@tonyclaw/agent-inspector 2.0.29 → 2.0.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/{CompareDrawer-DcqxlgSQ.js → CompareDrawer-tIUf2EJm.js} +1 -1
  3. package/.output/public/assets/ProxyViewerContainer-BxRaXhKR.js +115 -0
  4. package/.output/public/assets/{ReplayDialog-CBcnPgx1.js → ReplayDialog-D6v1xcuC.js} +1 -1
  5. package/.output/public/assets/{RequestAnatomy-DSgSqCYt.js → RequestAnatomy-D6PniTlx.js} +1 -1
  6. package/.output/public/assets/{ResponseView-CjqzBSoF.js → ResponseView-Sx8PjuvU.js} +1 -1
  7. package/.output/public/assets/{StreamingChunkSequence-DdBBKolI.js → StreamingChunkSequence-D-Rbfnxh.js} +1 -1
  8. package/.output/public/assets/_sessionId-BhNTuZ31.js +1 -0
  9. package/.output/public/assets/index-Byk60-jA.css +1 -0
  10. package/.output/public/assets/index-Kxptlkpg.js +1 -0
  11. package/.output/public/assets/{main-B6OLZCp9.js → main-B1kdhY98.js} +2 -2
  12. package/.output/server/_libs/lucide-react.mjs +159 -134
  13. package/.output/server/{_sessionId-CCfKJJ19.mjs → _sessionId-BceHFKf4.mjs} +3 -3
  14. package/.output/server/_ssr/{CompareDrawer-uaPI5R6e.mjs → CompareDrawer-uSxK5Ei5.mjs} +3 -3
  15. package/.output/server/_ssr/{ProxyViewerContainer-BV2nIxXy.mjs → ProxyViewerContainer-_npQ_f2i.mjs} +566 -17
  16. package/.output/server/_ssr/{ReplayDialog-eE2Hy2Nl.mjs → ReplayDialog-BHAzSLCT.mjs} +4 -4
  17. package/.output/server/_ssr/{RequestAnatomy-B7vwWo57.mjs → RequestAnatomy-DjlZLXBd.mjs} +3 -3
  18. package/.output/server/_ssr/{ResponseView-Bm6Qp8mo.mjs → ResponseView-BuDEJ3fl.mjs} +3 -3
  19. package/.output/server/_ssr/{StreamingChunkSequence-CbAJKJQx.mjs → StreamingChunkSequence-DFcu0bD8.mjs} +3 -3
  20. package/.output/server/_ssr/{index-u14_Aj60.mjs → index-Bw6Fw33c.mjs} +2 -2
  21. package/.output/server/_ssr/index.mjs +2 -2
  22. package/.output/server/_ssr/{router-qgeGUp1k.mjs → router-D90tMCb3.mjs} +1236 -143
  23. package/.output/server/_tanstack-start-manifest_v-BVM4AUlx.mjs +4 -0
  24. package/.output/server/index.mjs +60 -60
  25. package/README.md +24 -1
  26. package/package.json +1 -1
  27. package/src/components/ProxyViewer.tsx +9 -2
  28. package/src/components/groups/GroupsDialog.tsx +732 -0
  29. package/src/lib/groupContract.ts +148 -0
  30. package/src/lib/runContract.ts +2 -0
  31. package/src/lib/useGroupEvidence.ts +33 -0
  32. package/src/lib/useGroups.ts +28 -0
  33. package/src/mcp/server.ts +282 -1
  34. package/src/mcp/toolHandlers.ts +123 -0
  35. package/src/proxy/groupEvidenceExporter.ts +354 -0
  36. package/src/proxy/groupStore.ts +259 -0
  37. package/src/routes/api/groups.$groupId.evidence.ts +74 -0
  38. package/src/routes/api/groups.$groupId.sessions.ts +50 -0
  39. package/src/routes/api/groups.$groupId.ts +50 -0
  40. package/src/routes/api/groups.ts +39 -0
  41. package/.output/public/assets/ProxyViewerContainer-D650kQlv.js +0 -115
  42. package/.output/public/assets/_sessionId-wctOoGh_.js +0 -1
  43. package/.output/public/assets/index-BhQGSdhG.js +0 -1
  44. package/.output/public/assets/index-CwlHPmgL.css +0 -1
  45. package/.output/server/_tanstack-start-manifest_v-BrfUXnre.mjs +0 -4
@@ -1,5 +1,5 @@
1
1
  import { r as reactExports, j as jsxRuntimeExports, a as React } from "../_libs/react.mjs";
2
- import { C as CapturedLogSchema, D as DEFAULT_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 ProviderConfigSchema, r as requestFormatForPath, j as createPendingProviderTestResults, k as ProviderTestResultsSchema, l as createFailedProviderTestResults, M as MAX_SLOW_RESPONSE_THRESHOLD_SECONDS, n as MAX_PROVIDER_TEST_TIMEOUT_SECONDS, T as TimeDisplayFormatSchema, m as maskApiKey, h as providerHasContextMetadata, i as findProviderModelMetadata, g as getSessionPath, p as parseOpenAIResponse, O as OpenAIRequestSchema, A as AnthropicResponseSchema$1, e as AnthropicRequestSchema, s as safeGetOwnProperty, o as resolveProviderContextWindow, K as KnowledgeCandidateSchema, f as stripClaudeCodeBillingHeader, q as isPlainRecord } from "./router-qgeGUp1k.mjs";
2
+ import { C as CapturedLogSchema, D as DEFAULT_CAPTURE_MODE, a as DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS, b as DEFAULT_PROVIDER_TEST_TIMEOUT_SECONDS, c as DEFAULT_TIME_DISPLAY_FORMAT, u as packageJson, h as GroupEvidenceExportResultSchema, d as RuntimeConfigSchema, P as ProviderConfigSchema, r as requestFormatForPath, k as createPendingProviderTestResults, l as ProviderTestResultsSchema, n as createFailedProviderTestResults, M as MAX_SLOW_RESPONSE_THRESHOLD_SECONDS, o as MAX_PROVIDER_TEST_TIMEOUT_SECONDS, T as TimeDisplayFormatSchema, m as maskApiKey, i as providerHasContextMetadata, j as findProviderModelMetadata, g as getSessionPath, p as parseOpenAIResponse, O as OpenAIRequestSchema, A as AnthropicResponseSchema$1, e as AnthropicRequestSchema, s as safeGetOwnProperty, q as resolveProviderContextWindow, K as KnowledgeCandidateSchema, f as stripClaudeCodeBillingHeader, t as isPlainRecord, G as GroupEvidenceReadResponseSchema$1, I as InspectorGroupsListResponseSchema } from "./router-D90tMCb3.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,12 +9,12 @@ import { R as Root, T as Trigger$2, C as Content, a as Close, b as Title, P as P
9
9
  import { d as diffJson, a as diffLines } from "../_libs/diff.mjs";
10
10
  import { u as useWindowVirtualizer, a as useVirtualizer } from "../_libs/tanstack__react-virtual.mjs";
11
11
  import { R as Root2, T as Trigger, I as Icon, V as Value, P as Portal, C as Content2, a as Viewport, b as Item, c as ItemIndicator, d as ItemText, S as ScrollUpButton, e as ScrollDownButton } from "../_libs/radix-ui__react-select.mjs";
12
- import { C as Check, X, P as Plus, D as Download, S as Settings, A as ArrowLeft, a as Copy, b as ChevronDown, U as Upload, c as Scan, d as CircleAlert, T as Terminal, e as ChevronUp, E as EyeOff, f as Eye, g as ExternalLink, R as RotateCw, h as Clock, i as ChevronRight, j as Pencil, k as Trash2, L as LoaderCircle, l as ArrowUpRight, m as ArrowDownRight, n as User, M as MessageSquare, Z as Zap, W as Wrench, o as TriangleAlert, B as Brain, p as Minus, q as CircleCheckBig, r as CircleX, s as ShieldCheck, t as RefreshCw, u as Save, F as FileSearch, v as CircleCheck, w as CloudUpload, O as OctagonAlert, x as Radio, G as Gauge, y as Globe, z as FileTerminal, H as ChevronsUp, I as ChevronsDown, J as FileDiff, K as History, N as RotateCcw, Q as Search, V as GitCompareArrows, Y as CircleQuestionMark, _ as Server, $ as Lock, a0 as Wifi, a1 as WifiOff, a2 as ArrowUp, a3 as ArrowDown, a4 as Ellipsis, a5 as CodeXml, a6 as Blocks, a7 as MousePointerClick, a8 as FileText, a9 as Rows3, aa as Columns2 } from "../_libs/lucide-react.mjs";
12
+ import { C as Check, X, P as Plus, D as Download, L as Layers, a as LoaderCircle, R as RefreshCw, S as Settings, A as ArrowLeft, b as Copy, c as ChevronDown, U as Upload, d as Scan, e as CircleAlert, T as Terminal, f as ChevronUp, E as EyeOff, g as Eye, h as ExternalLink, i as RotateCw, j as Clock, k as ChevronRight, l as Pencil, m as Trash2, n as ArrowUpRight, o as ArrowDownRight, p as User, M as MessageSquare, Z as Zap, W as Wrench, q as TriangleAlert, B as Brain, r as Minus, s as CircleCheckBig, t as CircleX, u as ShieldCheck, v as Save, F as FileSearch, w as CircleCheck, x as CloudUpload, O as OctagonAlert, y as Radio, G as Gauge, z as Globe, H as FileTerminal, I as ChevronsUp, J as ChevronsDown, K as FileDiff, N as History, Q as RotateCcw, V as Search, Y as GitCompareArrows, _ as CircleQuestionMark, $ as Server, a0 as Lock, a1 as Wifi, a2 as WifiOff, a3 as ArrowUp, a4 as ArrowDown, a5 as Ellipsis, a6 as CodeXml, a7 as Blocks, a8 as MousePointerClick, a9 as FileText, aa as Rows3, ab as Columns2 } from "../_libs/lucide-react.mjs";
13
13
  import { M as Markdown } from "../_libs/react-markdown.mjs";
14
14
  import { u as union, d as object, a as array, l as literal, b as string, n as number, c as boolean, _ as _enum } from "../_libs/zod.mjs";
15
15
  import { P as Provider, R as Root3, T as Trigger$1, a as Portal$1, C as Content2$1, A as Arrow2 } from "../_libs/radix-ui__react-tooltip.mjs";
16
- import { R as Root2$1, L as List, T as Trigger$3, C as Content$1 } from "../_libs/radix-ui__react-tabs.mjs";
17
16
  import { S as Slot } from "../_libs/radix-ui__react-slot.mjs";
17
+ import { R as Root2$1, L as List, T as Trigger$3, C as Content$1 } from "../_libs/radix-ui__react-tabs.mjs";
18
18
  import { R as Root$1, C as CollapsibleContent$1, a as CollapsibleTrigger$1 } from "../_libs/radix-ui__react-collapsible.mjs";
19
19
  import { R as Root$2, V as Viewport$1, C as Corner, S as ScrollAreaScrollbar, a as ScrollAreaThumb } from "../_libs/radix-ui__react-scroll-area.mjs";
20
20
  const ApiErrorSchema = object({
@@ -414,7 +414,7 @@ async function exportLogsAsZip(logs, mode = "redacted") {
414
414
  URL.revokeObjectURL(url);
415
415
  return { ok: true };
416
416
  }
417
- function formatTimestamp(iso, format) {
417
+ function formatTimestamp$1(iso, format) {
418
418
  switch (format) {
419
419
  case "full":
420
420
  return iso;
@@ -427,7 +427,7 @@ function formatTimestamp(iso, format) {
427
427
  }
428
428
  }
429
429
  function formatTimestampRange(startedAt, endedAt, format) {
430
- return `${formatTimestamp(startedAt, format)} - ${formatTimestamp(endedAt, format)}`;
430
+ return `${formatTimestamp$1(startedAt, format)} - ${formatTimestamp$1(endedAt, format)}`;
431
431
  }
432
432
  function cn(...inputs) {
433
433
  return twMerge(clsx(inputs));
@@ -515,10 +515,6 @@ function useProviders() {
515
515
  mutate: response.mutate
516
516
  };
517
517
  }
518
- const version = "2.0.29";
519
- const packageJson = {
520
- version
521
- };
522
518
  const badgeVariants = cva(
523
519
  "inline-flex items-center justify-center rounded-full border border-transparent px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
524
520
  {
@@ -1576,19 +1572,19 @@ function useCopyFeedback(text) {
1576
1572
  return { copied, copy };
1577
1573
  }
1578
1574
  const LazyCompareDrawer = reactExports.lazy(
1579
- () => import("./CompareDrawer-uaPI5R6e.mjs").then((m) => ({ default: m.CompareDrawer }))
1575
+ () => import("./CompareDrawer-uSxK5Ei5.mjs").then((m) => ({ default: m.CompareDrawer }))
1580
1576
  );
1581
1577
  const LazyReplayDialog = reactExports.lazy(
1582
- () => import("./ReplayDialog-eE2Hy2Nl.mjs").then((m) => ({ default: m.ReplayDialog }))
1578
+ () => import("./ReplayDialog-BHAzSLCT.mjs").then((m) => ({ default: m.ReplayDialog }))
1583
1579
  );
1584
1580
  const LazyRequestAnatomy = reactExports.lazy(
1585
- () => import("./RequestAnatomy-B7vwWo57.mjs").then((m) => ({ default: m.RequestAnatomy }))
1581
+ () => import("./RequestAnatomy-DjlZLXBd.mjs").then((m) => ({ default: m.RequestAnatomy }))
1586
1582
  );
1587
1583
  const LazyResponseView = reactExports.lazy(
1588
- () => import("./ResponseView-Bm6Qp8mo.mjs").then((m) => ({ default: m.ResponseView }))
1584
+ () => import("./ResponseView-BuDEJ3fl.mjs").then((m) => ({ default: m.ResponseView }))
1589
1585
  );
1590
1586
  const LazyStreamingChunkSequence = reactExports.lazy(
1591
- () => import("./StreamingChunkSequence-CbAJKJQx.mjs").then((m) => ({
1587
+ () => import("./StreamingChunkSequence-DFcu0bD8.mjs").then((m) => ({
1592
1588
  default: m.StreamingChunkSequence
1593
1589
  }))
1594
1590
  );
@@ -2059,7 +2055,7 @@ const LogEntryHeader = reactExports.memo(function({
2059
2055
  ] }),
2060
2056
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1 text-muted-foreground text-xs shrink-0", children: [
2061
2057
  /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "size-3" }),
2062
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", title: log.timestamp, children: formatTimestamp(log.timestamp, timeDisplayFormat) })
2058
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", title: log.timestamp, children: formatTimestamp$1(log.timestamp, timeDisplayFormat) })
2063
2059
  ] }),
2064
2060
  log.model !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
2065
2061
  /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderLogo, { provider: detectProvider(log.model), className: "size-4" }) }) }),
@@ -5431,6 +5427,552 @@ function SelectScrollDownButton({
5431
5427
  }
5432
5428
  );
5433
5429
  }
5430
+ function evidenceKey(group) {
5431
+ if (group === null || group.evidence === null) return null;
5432
+ return `/api/groups/${encodeURIComponent(group.id)}/evidence`;
5433
+ }
5434
+ function useGroupEvidence(group) {
5435
+ const response = useSWR(evidenceKey(group), (url) => fetchJson(url, GroupEvidenceReadResponseSchema$1));
5436
+ return {
5437
+ evidenceResponse: response.data ?? null,
5438
+ isLoading: response.isLoading,
5439
+ error: response.error,
5440
+ mutate: response.mutate
5441
+ };
5442
+ }
5443
+ function useGroups() {
5444
+ const response = useSWR("/api/groups", (url) => fetchJson(url, InspectorGroupsListResponseSchema));
5445
+ return {
5446
+ groups: response.data?.groups ?? [],
5447
+ isLoading: response.isLoading,
5448
+ error: response.error,
5449
+ mutate: response.mutate
5450
+ };
5451
+ }
5452
+ function summarizeGroup(group) {
5453
+ let completedMembers = 0;
5454
+ let failedMembers = 0;
5455
+ let runningMembers = 0;
5456
+ let missingStatusMembers = 0;
5457
+ for (const member of group.members) {
5458
+ switch (member.status) {
5459
+ case "completed":
5460
+ completedMembers += 1;
5461
+ break;
5462
+ case "failed":
5463
+ case "cancelled":
5464
+ failedMembers += 1;
5465
+ break;
5466
+ case "running":
5467
+ runningMembers += 1;
5468
+ break;
5469
+ case "created":
5470
+ break;
5471
+ case null:
5472
+ missingStatusMembers += 1;
5473
+ break;
5474
+ }
5475
+ }
5476
+ return {
5477
+ memberCount: group.members.length,
5478
+ completedMembers,
5479
+ failedMembers,
5480
+ runningMembers,
5481
+ missingStatusMembers
5482
+ };
5483
+ }
5484
+ function buildGroupMemberRows(group, exportResult) {
5485
+ if (exportResult !== null && exportResult.group.id === group.id) {
5486
+ return exportResult.members.map((exportMember) => ({
5487
+ member: exportMember.member,
5488
+ exportMember
5489
+ }));
5490
+ }
5491
+ return group.members.map((member) => ({ member, exportMember: null }));
5492
+ }
5493
+ function statusClassName(status) {
5494
+ switch (status) {
5495
+ case "completed":
5496
+ return "border-emerald-200 bg-emerald-50 text-emerald-700";
5497
+ case "failed":
5498
+ case "cancelled":
5499
+ return "border-red-200 bg-red-50 text-red-700";
5500
+ case "running":
5501
+ return "border-sky-200 bg-sky-50 text-sky-700";
5502
+ case "created":
5503
+ return "border-zinc-200 bg-zinc-50 text-zinc-600";
5504
+ case null:
5505
+ return "border-zinc-200 bg-zinc-50 text-zinc-500";
5506
+ }
5507
+ }
5508
+ function statusLabel(status) {
5509
+ return status ?? "unknown";
5510
+ }
5511
+ function reportStatusClassName(status) {
5512
+ switch (status) {
5513
+ case "PASS":
5514
+ return "border-emerald-200 bg-emerald-50 text-emerald-700";
5515
+ case "FAIL":
5516
+ return "border-red-200 bg-red-50 text-red-700";
5517
+ case "RUNNING":
5518
+ return "border-sky-200 bg-sky-50 text-sky-700";
5519
+ case "UNKNOWN":
5520
+ return "border-zinc-200 bg-zinc-50 text-zinc-600";
5521
+ }
5522
+ }
5523
+ function displayText(value) {
5524
+ if (value === null || value.trim().length === 0) return "-";
5525
+ return value;
5526
+ }
5527
+ function formatNumber(value) {
5528
+ return value.toLocaleString();
5529
+ }
5530
+ function formatMs(value) {
5531
+ if (value === null || value === void 0) return "-";
5532
+ if (value < 1e3) return `${formatNumber(value)} ms`;
5533
+ return `${(value / 1e3).toFixed(1)} s`;
5534
+ }
5535
+ function formatTimestamp(value) {
5536
+ const millis = Date.parse(value);
5537
+ if (!Number.isFinite(millis)) return value;
5538
+ return new Intl.DateTimeFormat(void 0, {
5539
+ month: "short",
5540
+ day: "2-digit",
5541
+ hour: "2-digit",
5542
+ minute: "2-digit",
5543
+ hour12: false
5544
+ }).format(new Date(millis));
5545
+ }
5546
+ function firstNonEmpty(...values) {
5547
+ for (const value of values) {
5548
+ if (value !== null && value.trim().length > 0) return value;
5549
+ }
5550
+ return "-";
5551
+ }
5552
+ function providerModel(member) {
5553
+ const provider = member.provider;
5554
+ const model = member.model;
5555
+ if (provider !== null && provider.length > 0 && model !== null && model.length > 0) {
5556
+ return `${provider} / ${model}`;
5557
+ }
5558
+ return firstNonEmpty(provider, model);
5559
+ }
5560
+ function selectedGroupFrom(groups, selectedGroupId) {
5561
+ if (selectedGroupId !== null) {
5562
+ const selected = groups.find((group) => group.id === selectedGroupId);
5563
+ if (selected !== void 0) return selected;
5564
+ }
5565
+ return groups[0] ?? null;
5566
+ }
5567
+ function latestLog(row) {
5568
+ const logs = row.exportMember?.session?.latestLogs ?? [];
5569
+ return logs[0] ?? null;
5570
+ }
5571
+ function evidenceFor(group, exportResult) {
5572
+ if (exportResult !== null && exportResult.group.id === group.id) return exportResult.evidence;
5573
+ return group.evidence;
5574
+ }
5575
+ function exportSummaryFor(group, exportResult, evidenceResponse) {
5576
+ if (exportResult !== null && exportResult.group.id === group.id) return exportResult.summary;
5577
+ if (evidenceResponse !== null && evidenceResponse.group.id === group.id) {
5578
+ return evidenceResponse.summary;
5579
+ }
5580
+ return null;
5581
+ }
5582
+ function evidenceReportFor(group, exportResult, evidenceResponse) {
5583
+ if (exportResult !== null && exportResult.group.id === group.id) {
5584
+ return exportResult.jenkinsReport;
5585
+ }
5586
+ if (evidenceResponse !== null && evidenceResponse.group.id === group.id) {
5587
+ return evidenceResponse.report;
5588
+ }
5589
+ return null;
5590
+ }
5591
+ function GroupsDialog() {
5592
+ const [open, setOpen] = reactExports.useState(false);
5593
+ const [selectedGroupId, setSelectedGroupId] = reactExports.useState(null);
5594
+ const [exportingGroupId, setExportingGroupId] = reactExports.useState(null);
5595
+ const [exportError, setExportError] = reactExports.useState(null);
5596
+ const [exportResult, setExportResult] = reactExports.useState(null);
5597
+ const { groups, isLoading, error, mutate } = useGroups();
5598
+ const selectedGroup = reactExports.useMemo(
5599
+ () => selectedGroupFrom(groups, selectedGroupId),
5600
+ [groups, selectedGroupId]
5601
+ );
5602
+ reactExports.useEffect(() => {
5603
+ if (!open) return;
5604
+ const hasSelected = selectedGroupId !== null && groups.some((group) => group.id === selectedGroupId);
5605
+ if (hasSelected) return;
5606
+ setSelectedGroupId(groups[0]?.id ?? null);
5607
+ }, [groups, open, selectedGroupId]);
5608
+ const selectedExportResult = selectedGroup !== null && exportResult !== null && exportResult.group.id === selectedGroup.id ? exportResult : null;
5609
+ const {
5610
+ evidenceResponse,
5611
+ isLoading: evidenceLoading,
5612
+ error: evidenceError,
5613
+ mutate: mutateEvidence
5614
+ } = useGroupEvidence(selectedGroup);
5615
+ const handleRefresh = reactExports.useCallback(() => {
5616
+ void mutate();
5617
+ }, [mutate]);
5618
+ const handleExport = reactExports.useCallback(
5619
+ async (group) => {
5620
+ setExportingGroupId(group.id);
5621
+ setExportError(null);
5622
+ try {
5623
+ const response = await fetch(`/api/groups/${encodeURIComponent(group.id)}/evidence`, {
5624
+ method: "POST",
5625
+ headers: { "content-type": "application/json" },
5626
+ body: JSON.stringify({ latestLogLimit: 10 })
5627
+ });
5628
+ if (!response.ok) {
5629
+ setExportError(
5630
+ await readApiError(response, `Export failed with status ${String(response.status)}`)
5631
+ );
5632
+ return;
5633
+ }
5634
+ const parsed = await parseJsonResponse$1(response, GroupEvidenceExportResultSchema);
5635
+ setExportResult(parsed);
5636
+ await mutate();
5637
+ await mutateEvidence();
5638
+ } catch (err) {
5639
+ setExportError(err instanceof Error ? err.message : String(err));
5640
+ } finally {
5641
+ setExportingGroupId(null);
5642
+ }
5643
+ },
5644
+ [mutate, mutateEvidence]
5645
+ );
5646
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(Dialog, { open, onOpenChange: setOpen, children: [
5647
+ /* @__PURE__ */ jsxRuntimeExports.jsx(DialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
5648
+ Button,
5649
+ {
5650
+ type: "button",
5651
+ variant: "ghost",
5652
+ size: "icon",
5653
+ className: "relative size-8",
5654
+ "aria-label": "Evaluation groups",
5655
+ title: "Evaluation groups",
5656
+ children: [
5657
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Layers, { className: "size-4" }),
5658
+ isLoading ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "absolute -right-0.5 -top-0.5 size-3 animate-spin text-muted-foreground" }) : groups.length > 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "absolute -right-1 -top-1 min-w-4 rounded-full bg-primary px-1 text-[10px] leading-4 text-primary-foreground", children: groups.length }) : null,
5659
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sr-only", children: "Evaluation groups" })
5660
+ ]
5661
+ }
5662
+ ) }),
5663
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogContent, { className: "flex max-h-[85vh] max-w-5xl flex-col overflow-hidden", children: [
5664
+ /* @__PURE__ */ jsxRuntimeExports.jsx(DialogHeader, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogTitle, { className: "flex items-center gap-2 pr-8", children: [
5665
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Layers, { className: "size-5 text-muted-foreground" }),
5666
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Groups" }),
5667
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { variant: "outline", children: formatNumber(groups.length) })
5668
+ ] }) }),
5669
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-h-0 items-center justify-between gap-3 border-b border-border pb-3", children: [
5670
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: "Evaluation batches, model runs, and exported evidence packs." }),
5671
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
5672
+ Button,
5673
+ {
5674
+ type: "button",
5675
+ variant: "outline",
5676
+ size: "sm",
5677
+ className: "shrink-0",
5678
+ onClick: handleRefresh,
5679
+ children: [
5680
+ /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: "size-3.5" }),
5681
+ "Refresh"
5682
+ ]
5683
+ }
5684
+ )
5685
+ ] }),
5686
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid min-h-0 flex-1 gap-4 md:grid-cols-[260px_minmax(0,1fr)]", children: [
5687
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
5688
+ GroupList,
5689
+ {
5690
+ groups,
5691
+ selectedGroupId: selectedGroup?.id ?? null,
5692
+ isLoading,
5693
+ error,
5694
+ onSelect: setSelectedGroupId
5695
+ }
5696
+ ),
5697
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
5698
+ GroupDetails,
5699
+ {
5700
+ group: selectedGroup,
5701
+ exportResult: selectedExportResult,
5702
+ evidenceResponse,
5703
+ evidenceLoading,
5704
+ evidenceError,
5705
+ exportError,
5706
+ exportingGroupId,
5707
+ onExport: handleExport
5708
+ }
5709
+ )
5710
+ ] })
5711
+ ] })
5712
+ ] });
5713
+ }
5714
+ function GroupList({
5715
+ groups,
5716
+ selectedGroupId,
5717
+ isLoading,
5718
+ error,
5719
+ onSelect
5720
+ }) {
5721
+ if (isLoading) {
5722
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex min-h-48 items-center justify-center rounded-md border border-dashed border-border text-xs text-muted-foreground", children: "Loading groups..." });
5723
+ }
5724
+ if (error !== void 0) {
5725
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "rounded-md border border-red-200 bg-red-50 px-3 py-2 text-xs text-red-700", children: error.message });
5726
+ }
5727
+ if (groups.length === 0) {
5728
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "rounded-md border border-dashed border-border px-3 py-8 text-center text-xs text-muted-foreground", children: "No groups yet." });
5729
+ }
5730
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "min-h-0 overflow-y-auto pr-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-2", children: groups.map((group) => {
5731
+ const summary = summarizeGroup(group);
5732
+ const selected = selectedGroupId === group.id;
5733
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
5734
+ "button",
5735
+ {
5736
+ type: "button",
5737
+ onClick: () => onSelect(group.id),
5738
+ className: cn(
5739
+ "w-full rounded-md border px-3 py-2 text-left text-xs transition-colors",
5740
+ selected ? "border-primary bg-primary/5" : "border-border bg-background hover:bg-muted/50"
5741
+ ),
5742
+ children: [
5743
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center justify-between gap-2", children: [
5744
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0 truncate text-sm font-medium", children: group.title }),
5745
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { variant: "outline", className: statusClassName(group.status), children: statusLabel(group.status) })
5746
+ ] }),
5747
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-1 flex items-center gap-2 text-muted-foreground", children: [
5748
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
5749
+ summary.memberCount,
5750
+ " sessions"
5751
+ ] }),
5752
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: formatTimestamp(group.updatedAt) })
5753
+ ] })
5754
+ ]
5755
+ },
5756
+ group.id
5757
+ );
5758
+ }) }) });
5759
+ }
5760
+ function GroupDetails({
5761
+ group,
5762
+ exportResult,
5763
+ evidenceResponse,
5764
+ evidenceLoading,
5765
+ evidenceError,
5766
+ exportError,
5767
+ exportingGroupId,
5768
+ onExport
5769
+ }) {
5770
+ if (group === null) {
5771
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex min-h-48 items-center justify-center rounded-md border border-dashed border-border text-xs text-muted-foreground", children: "Select a group to inspect." });
5772
+ }
5773
+ const summary = summarizeGroup(group);
5774
+ const exportedSummary = exportSummaryFor(group, exportResult, evidenceResponse);
5775
+ const evidenceReport = evidenceReportFor(group, exportResult, evidenceResponse);
5776
+ const evidence = evidenceFor(group, exportResult);
5777
+ const rows = buildGroupMemberRows(group, exportResult);
5778
+ const isExporting = exportingGroupId === group.id;
5779
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "min-h-0 overflow-y-auto pr-1", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
5780
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-col gap-3 sm:flex-row sm:items-start sm:justify-between", children: [
5781
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 space-y-1", children: [
5782
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-2", children: [
5783
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "min-w-0 truncate text-base font-semibold", children: group.title }),
5784
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { variant: "outline", className: statusClassName(group.status), children: statusLabel(group.status) }),
5785
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { variant: "outline", children: group.kind })
5786
+ ] }),
5787
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-2 text-xs text-muted-foreground", children: [
5788
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: displayText(group.project) }),
5789
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
5790
+ "updated ",
5791
+ formatTimestamp(group.updatedAt)
5792
+ ] })
5793
+ ] })
5794
+ ] }),
5795
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
5796
+ Button,
5797
+ {
5798
+ type: "button",
5799
+ variant: "default",
5800
+ size: "sm",
5801
+ className: "shrink-0",
5802
+ disabled: isExporting,
5803
+ onClick: () => void onExport(group),
5804
+ children: [
5805
+ isExporting ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-3.5 animate-spin" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Download, { className: "size-3.5" }),
5806
+ "Export evidence"
5807
+ ]
5808
+ }
5809
+ )
5810
+ ] }),
5811
+ group.task !== null && group.task.trim().length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "rounded-md border border-border bg-muted/20 px-3 py-2 text-xs text-muted-foreground", children: group.task }),
5812
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid gap-2 sm:grid-cols-4", children: [
5813
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SummaryStat, { label: "Members", value: summary.memberCount }),
5814
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SummaryStat, { label: "Done", value: summary.completedMembers }),
5815
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SummaryStat, { label: "Failed", value: summary.failedMembers }),
5816
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SummaryStat, { label: "Running", value: summary.runningMembers })
5817
+ ] }),
5818
+ exportedSummary !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid gap-2 sm:grid-cols-4", children: [
5819
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SummaryStat, { label: "Requests", value: exportedSummary.requestCount }),
5820
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SummaryStat, { label: "Errors", value: exportedSummary.errorCount }),
5821
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SummaryStat, { label: "Tokens", value: exportedSummary.tokenUsage.total }),
5822
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SummaryStat, { label: "Missing", value: exportedSummary.missingSessions })
5823
+ ] }),
5824
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
5825
+ EvidenceReportCard,
5826
+ {
5827
+ report: evidenceReport,
5828
+ loading: evidenceLoading,
5829
+ error: evidenceError,
5830
+ hasEvidence: evidence !== null
5831
+ }
5832
+ ),
5833
+ /* @__PURE__ */ jsxRuntimeExports.jsx(EvidencePaths, { evidence }),
5834
+ exportError !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "rounded-md border border-red-200 bg-red-50 px-3 py-2 text-xs text-red-700", children: exportError }),
5835
+ /* @__PURE__ */ jsxRuntimeExports.jsx(MemberTable, { rows })
5836
+ ] }) });
5837
+ }
5838
+ function SummaryStat({ label, value }) {
5839
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-md border border-border bg-muted/20 px-3 py-2", children: [
5840
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[11px] font-medium uppercase text-muted-foreground", children: label }),
5841
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1 font-mono text-sm font-semibold", children: formatNumber(value) })
5842
+ ] });
5843
+ }
5844
+ function EvidenceReportCard({
5845
+ report,
5846
+ loading,
5847
+ error,
5848
+ hasEvidence
5849
+ }) {
5850
+ const { copied, copy } = useCopyFeedback(report?.markdown ?? null);
5851
+ if (report === null && !loading && error === void 0) return null;
5852
+ if (loading) {
5853
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 rounded-md border border-border bg-muted/20 px-3 py-2 text-xs text-muted-foreground", children: [
5854
+ /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-3.5 animate-spin" }),
5855
+ "Loading evidence report..."
5856
+ ] });
5857
+ }
5858
+ if (error !== void 0 && hasEvidence) {
5859
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-md border border-red-200 bg-red-50 px-3 py-2 text-xs text-red-700", children: [
5860
+ "Failed to load evidence report: ",
5861
+ error.message
5862
+ ] });
5863
+ }
5864
+ if (report === null) return null;
5865
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-md border border-border bg-muted/20 px-3 py-2", children: [
5866
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center justify-between gap-2", children: [
5867
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
5868
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs font-semibold", children: "Evidence report" }),
5869
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { variant: "outline", className: reportStatusClassName(report.status), children: report.status })
5870
+ ] }),
5871
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
5872
+ Button,
5873
+ {
5874
+ type: "button",
5875
+ variant: "ghost",
5876
+ size: "icon",
5877
+ className: "size-7 shrink-0",
5878
+ "aria-label": copied ? "Copied evidence report" : "Copy evidence report",
5879
+ onClick: copy,
5880
+ children: copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-3.5 text-emerald-500" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-3.5" })
5881
+ }
5882
+ )
5883
+ ] }),
5884
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: report.summary })
5885
+ ] });
5886
+ }
5887
+ function EvidencePaths({ evidence }) {
5888
+ if (evidence === null) {
5889
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "rounded-md border border-dashed border-border px-3 py-2 text-xs text-muted-foreground", children: "No evidence pack exported yet." });
5890
+ }
5891
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2 rounded-md border border-border bg-muted/20 px-3 py-2", children: [
5892
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
5893
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs font-semibold", children: "Evidence paths" }),
5894
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] text-muted-foreground", children: formatTimestamp(evidence.exportedAt) })
5895
+ ] }),
5896
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid gap-2", children: [
5897
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CopyPathRow, { label: "JSON", value: evidence.jsonPath }),
5898
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CopyPathRow, { label: "Markdown", value: evidence.markdownPath }),
5899
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CopyPathRow, { label: "HTML", value: evidence.htmlPath })
5900
+ ] })
5901
+ ] });
5902
+ }
5903
+ function CopyPathRow({ label, value }) {
5904
+ const { copied, copy } = useCopyFeedback(value);
5905
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center gap-2 rounded-md border border-border bg-background px-2 py-1.5", children: [
5906
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-16 shrink-0 text-[11px] font-medium text-muted-foreground", children: label }),
5907
+ /* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "min-w-0 flex-1 truncate font-mono text-xs", children: value }),
5908
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
5909
+ Button,
5910
+ {
5911
+ type: "button",
5912
+ variant: "ghost",
5913
+ size: "icon",
5914
+ className: "size-7 shrink-0",
5915
+ "aria-label": copied ? `Copied ${label} path` : `Copy ${label} path`,
5916
+ onClick: copy,
5917
+ children: copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-3.5 text-emerald-500" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-3.5" })
5918
+ }
5919
+ )
5920
+ ] });
5921
+ }
5922
+ function MemberTable({ rows }) {
5923
+ if (rows.length === 0) {
5924
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "rounded-md border border-dashed border-border px-3 py-8 text-center text-xs text-muted-foreground", children: "No sessions attached." });
5925
+ }
5926
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "overflow-hidden rounded-md border border-border", children: [
5927
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "border-b border-border bg-muted/30 px-3 py-2 text-xs font-semibold", children: "Members" }),
5928
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("table", { className: "w-full min-w-[760px] text-left text-xs", children: [
5929
+ /* @__PURE__ */ jsxRuntimeExports.jsx("thead", { className: "border-b border-border bg-muted/20 text-muted-foreground", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("tr", { children: [
5930
+ /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "px-3 py-2 font-medium", children: "Session" }),
5931
+ /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "px-3 py-2 font-medium", children: "Provider / Model" }),
5932
+ /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "px-3 py-2 font-medium", children: "Status" }),
5933
+ /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "px-3 py-2 font-medium", children: "Requests" }),
5934
+ /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "px-3 py-2 font-medium", children: "Errors" }),
5935
+ /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "px-3 py-2 font-medium", children: "First chunk" }),
5936
+ /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "px-3 py-2 font-medium", children: "Tokens" })
5937
+ ] }) }),
5938
+ /* @__PURE__ */ jsxRuntimeExports.jsx("tbody", { children: rows.map((row) => /* @__PURE__ */ jsxRuntimeExports.jsx(MemberRow, { row }, row.member.id)) })
5939
+ ] }) })
5940
+ ] });
5941
+ }
5942
+ function MemberRow({ row }) {
5943
+ const member = row.member;
5944
+ const session = row.exportMember?.session ?? null;
5945
+ const log = latestLog(row);
5946
+ const sessionPath = session?.inspectorPath ?? getSessionPath(member.sessionId);
5947
+ const requests = session?.requestCount ?? null;
5948
+ const errors = session?.errorCount ?? null;
5949
+ const tokens = session?.tokenUsage.total ?? null;
5950
+ const firstChunkMs = log?.firstChunkMs ?? null;
5951
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("tr", { className: "border-b border-border last:border-0", children: [
5952
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("td", { className: "max-w-56 px-3 py-2", children: [
5953
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
5954
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
5955
+ "a",
5956
+ {
5957
+ href: sessionPath,
5958
+ target: "_blank",
5959
+ rel: "noreferrer",
5960
+ className: "min-w-0 truncate font-mono text-xs text-primary hover:underline",
5961
+ children: firstNonEmpty(member.label, member.sessionId)
5962
+ }
5963
+ ),
5964
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ExternalLink, { className: "size-3 shrink-0 text-muted-foreground" })
5965
+ ] }),
5966
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-0.5 truncate text-[11px] text-muted-foreground", children: displayText(member.agent) })
5967
+ ] }),
5968
+ /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "max-w-52 px-3 py-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "block truncate", children: providerModel(member) }) }),
5969
+ /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "px-3 py-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { variant: "outline", className: statusClassName(member.status), children: statusLabel(member.status) }) }),
5970
+ /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "px-3 py-2 font-mono", children: requests === null ? "-" : formatNumber(requests) }),
5971
+ /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "px-3 py-2 font-mono", children: errors === null ? "-" : formatNumber(errors) }),
5972
+ /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "px-3 py-2 font-mono", children: formatMs(firstChunkMs) }),
5973
+ /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "px-3 py-2 font-mono", children: tokens === null ? "-" : formatNumber(tokens) })
5974
+ ] });
5975
+ }
5434
5976
  function ClaudeCodeIcon() {
5435
5977
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
5436
5978
  "svg",
@@ -9215,6 +9757,9 @@ function truncateSessionId(id) {
9215
9757
  if (id.length <= 30) return id;
9216
9758
  return `${id.slice(0, 12)}...${id.slice(-12)}`;
9217
9759
  }
9760
+ function shouldShowRawExport(captureMode) {
9761
+ return captureMode === "full";
9762
+ }
9218
9763
  function computeTokenSummary(logs) {
9219
9764
  let totalIn = 0;
9220
9765
  let totalOut = 0;
@@ -9784,6 +10329,7 @@ function ProxyViewer({
9784
10329
  );
9785
10330
  const cacheTrends = reactExports.useMemo(() => computeCacheTrends(groups), [groups]);
9786
10331
  const comparisonPredecessors = reactExports.useMemo(() => buildValidPredecessors(groups), [groups]);
10332
+ const showRawExport = shouldShowRawExport(captureMode);
9787
10333
  const handleCompareWithPrevious = reactExports.useCallback(
9788
10334
  (log) => {
9789
10335
  const predecessor = comparisonPredecessors.get(log.id);
@@ -9848,7 +10394,10 @@ function ProxyViewer({
9848
10394
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "max-w-[calc(100vw-7rem)] text-sm font-semibold text-muted-foreground", children: "Local First. Evidence First." }),
9849
10395
  /* @__PURE__ */ jsxRuntimeExports.jsx(McpReadyBadge, {})
9850
10396
  ] }),
9851
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "justify-self-end", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SettingsDialog, {}) })
10397
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "justify-self-end flex items-center gap-1", children: [
10398
+ /* @__PURE__ */ jsxRuntimeExports.jsx(GroupsDialog, {}),
10399
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SettingsDialog, {})
10400
+ ] })
9852
10401
  ] }),
9853
10402
  hasSessionContext && sessionContextScope !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(
9854
10403
  SessionContextBar,
@@ -9904,7 +10453,7 @@ function ProxyViewer({
9904
10453
  logs.length !== 1 ? "s" : "",
9905
10454
  totalIn > 0 || totalOut > 0 ? ` - ${formatTokens(totalIn)} in / ${formatTokens(totalOut)} out` : ""
9906
10455
  ] }),
9907
- logs.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(
10456
+ logs.length > 0 && showRawExport && /* @__PURE__ */ jsxRuntimeExports.jsx(
9908
10457
  "button",
9909
10458
  {
9910
10459
  type: "button",