@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.
- package/.output/nitro.json +1 -1
- package/.output/public/assets/{CompareDrawer-DcqxlgSQ.js → CompareDrawer-tIUf2EJm.js} +1 -1
- package/.output/public/assets/ProxyViewerContainer-BxRaXhKR.js +115 -0
- package/.output/public/assets/{ReplayDialog-CBcnPgx1.js → ReplayDialog-D6v1xcuC.js} +1 -1
- package/.output/public/assets/{RequestAnatomy-DSgSqCYt.js → RequestAnatomy-D6PniTlx.js} +1 -1
- package/.output/public/assets/{ResponseView-CjqzBSoF.js → ResponseView-Sx8PjuvU.js} +1 -1
- package/.output/public/assets/{StreamingChunkSequence-DdBBKolI.js → StreamingChunkSequence-D-Rbfnxh.js} +1 -1
- package/.output/public/assets/_sessionId-BhNTuZ31.js +1 -0
- package/.output/public/assets/index-Byk60-jA.css +1 -0
- package/.output/public/assets/index-Kxptlkpg.js +1 -0
- package/.output/public/assets/{main-B6OLZCp9.js → main-B1kdhY98.js} +2 -2
- package/.output/server/_libs/lucide-react.mjs +159 -134
- package/.output/server/{_sessionId-CCfKJJ19.mjs → _sessionId-BceHFKf4.mjs} +3 -3
- package/.output/server/_ssr/{CompareDrawer-uaPI5R6e.mjs → CompareDrawer-uSxK5Ei5.mjs} +3 -3
- package/.output/server/_ssr/{ProxyViewerContainer-BV2nIxXy.mjs → ProxyViewerContainer-_npQ_f2i.mjs} +566 -17
- package/.output/server/_ssr/{ReplayDialog-eE2Hy2Nl.mjs → ReplayDialog-BHAzSLCT.mjs} +4 -4
- package/.output/server/_ssr/{RequestAnatomy-B7vwWo57.mjs → RequestAnatomy-DjlZLXBd.mjs} +3 -3
- package/.output/server/_ssr/{ResponseView-Bm6Qp8mo.mjs → ResponseView-BuDEJ3fl.mjs} +3 -3
- package/.output/server/_ssr/{StreamingChunkSequence-CbAJKJQx.mjs → StreamingChunkSequence-DFcu0bD8.mjs} +3 -3
- package/.output/server/_ssr/{index-u14_Aj60.mjs → index-Bw6Fw33c.mjs} +2 -2
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{router-qgeGUp1k.mjs → router-D90tMCb3.mjs} +1236 -143
- package/.output/server/_tanstack-start-manifest_v-BVM4AUlx.mjs +4 -0
- package/.output/server/index.mjs +60 -60
- package/README.md +24 -1
- package/package.json +1 -1
- package/src/components/ProxyViewer.tsx +9 -2
- package/src/components/groups/GroupsDialog.tsx +732 -0
- package/src/lib/groupContract.ts +148 -0
- package/src/lib/runContract.ts +2 -0
- package/src/lib/useGroupEvidence.ts +33 -0
- package/src/lib/useGroups.ts +28 -0
- package/src/mcp/server.ts +282 -1
- package/src/mcp/toolHandlers.ts +123 -0
- package/src/proxy/groupEvidenceExporter.ts +354 -0
- package/src/proxy/groupStore.ts +259 -0
- package/src/routes/api/groups.$groupId.evidence.ts +74 -0
- package/src/routes/api/groups.$groupId.sessions.ts +50 -0
- package/src/routes/api/groups.$groupId.ts +50 -0
- package/src/routes/api/groups.ts +39 -0
- package/.output/public/assets/ProxyViewerContainer-D650kQlv.js +0 -115
- package/.output/public/assets/_sessionId-wctOoGh_.js +0 -1
- package/.output/public/assets/index-BhQGSdhG.js +0 -1
- package/.output/public/assets/index-CwlHPmgL.css +0 -1
- package/.output/server/_tanstack-start-manifest_v-BrfUXnre.mjs +0 -4
package/.output/server/_ssr/{ProxyViewerContainer-BV2nIxXy.mjs → ProxyViewerContainer-_npQ_f2i.mjs}
RENAMED
|
@@ -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,
|
|
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,
|
|
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-
|
|
1575
|
+
() => import("./CompareDrawer-uSxK5Ei5.mjs").then((m) => ({ default: m.CompareDrawer }))
|
|
1580
1576
|
);
|
|
1581
1577
|
const LazyReplayDialog = reactExports.lazy(
|
|
1582
|
-
() => import("./ReplayDialog-
|
|
1578
|
+
() => import("./ReplayDialog-BHAzSLCT.mjs").then((m) => ({ default: m.ReplayDialog }))
|
|
1583
1579
|
);
|
|
1584
1580
|
const LazyRequestAnatomy = reactExports.lazy(
|
|
1585
|
-
() => import("./RequestAnatomy-
|
|
1581
|
+
() => import("./RequestAnatomy-DjlZLXBd.mjs").then((m) => ({ default: m.RequestAnatomy }))
|
|
1586
1582
|
);
|
|
1587
1583
|
const LazyResponseView = reactExports.lazy(
|
|
1588
|
-
() => import("./ResponseView-
|
|
1584
|
+
() => import("./ResponseView-BuDEJ3fl.mjs").then((m) => ({ default: m.ResponseView }))
|
|
1589
1585
|
);
|
|
1590
1586
|
const LazyStreamingChunkSequence = reactExports.lazy(
|
|
1591
|
-
() => import("./StreamingChunkSequence-
|
|
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.
|
|
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",
|