@tonyclaw/agent-inspector 2.0.30 → 2.0.32
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-BDzfRSt1.js → CompareDrawer-Dgi0hhg5.js} +1 -1
- package/.output/public/assets/ProxyViewerContainer-4dG0nLRp.js +115 -0
- package/.output/public/assets/{ReplayDialog-p-5TKg75.js → ReplayDialog-BL6BwDuI.js} +1 -1
- package/.output/public/assets/{RequestAnatomy-G0dV8-D_.js → RequestAnatomy-DZMmiIiD.js} +1 -1
- package/.output/public/assets/{ResponseView-D2wE6lD-.js → ResponseView-DJLOiTYq.js} +1 -1
- package/.output/public/assets/{StreamingChunkSequence-D8JRK-j_.js → StreamingChunkSequence--SxZ5cxc.js} +1 -1
- package/.output/public/assets/_sessionId-C4z6gu9i.js +1 -0
- package/.output/public/assets/index-Drpb2qR5.js +1 -0
- package/.output/public/assets/index-fUUi8iQF.css +1 -0
- package/.output/public/assets/{main-XHHZsOBK.js → main-CbRIHhJ5.js} +2 -2
- package/.output/server/_libs/lucide-react.mjs +160 -135
- package/.output/server/{_sessionId-CK9QEhkB.mjs → _sessionId-DNfumR8F.mjs} +2 -2
- package/.output/server/_ssr/{CompareDrawer-BJVPFMIx.mjs → CompareDrawer-CzgjhnUa.mjs} +3 -3
- package/.output/server/_ssr/{ProxyViewerContainer-DhbmJ2zj.mjs → ProxyViewerContainer-BqOcZ7en.mjs} +737 -17
- package/.output/server/_ssr/{ReplayDialog-DXRj95Gj.mjs → ReplayDialog-DmEknIL8.mjs} +4 -4
- package/.output/server/_ssr/{RequestAnatomy-CrYJTXdJ.mjs → RequestAnatomy-DNoiMudY.mjs} +3 -3
- package/.output/server/_ssr/{ResponseView-4ESqSITr.mjs → ResponseView-C_cRrleT.mjs} +3 -3
- package/.output/server/_ssr/{StreamingChunkSequence-Czdko5n_.mjs → StreamingChunkSequence-DHZ9Q_dL.mjs} +3 -3
- package/.output/server/_ssr/{index-bei0I7qL.mjs → index-coYS9XyS.mjs} +2 -2
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{router-sQh4Gk8J.mjs → router-DUb5lKw1.mjs} +174 -40
- package/.output/server/{_tanstack-start-manifest_v-C0fdSWnA.mjs → _tanstack-start-manifest_v-xcG1o8Vt.mjs} +1 -1
- package/.output/server/index.mjs +60 -60
- package/package.json +1 -1
- package/src/components/ProxyViewer.tsx +9 -2
- package/src/components/groups/GroupsDialog.tsx +945 -0
- package/src/lib/groupContract.ts +24 -2
- 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 +20 -1
- package/src/mcp/toolHandlers.ts +22 -0
- package/src/proxy/groupEvidenceExporter.ts +13 -0
- package/src/proxy/groupStore.ts +52 -2
- package/src/routes/api/groups.$groupId.evidence.ts +14 -2
- package/src/routes/api/groups.$groupId.ts +38 -1
- package/.output/public/assets/ProxyViewerContainer-NtOD8Ex_.js +0 -115
- package/.output/public/assets/_sessionId-zimzVrJE.js +0 -1
- package/.output/public/assets/index-Cv5vPgpr.js +0 -1
- package/.output/public/assets/index-CwlHPmgL.css +0 -1
package/.output/server/_ssr/{ProxyViewerContainer-DhbmJ2zj.mjs → ProxyViewerContainer-BqOcZ7en.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, v as packageJson, h as GroupEvidenceExportResultSchema, i as DeleteInspectorGroupResponseSchema, d as RuntimeConfigSchema, P as ProviderConfigSchema, r as requestFormatForPath, l as createPendingProviderTestResults, n as ProviderTestResultsSchema, o as createFailedProviderTestResults, M as MAX_SLOW_RESPONSE_THRESHOLD_SECONDS, q as MAX_PROVIDER_TEST_TIMEOUT_SECONDS, T as TimeDisplayFormatSchema, m as maskApiKey, j as providerHasContextMetadata, k as findProviderModelMetadata, g as getSessionPath, p as parseOpenAIResponse, O as OpenAIRequestSchema, A as AnthropicResponseSchema$1, e as AnthropicRequestSchema, s as safeGetOwnProperty, t as resolveProviderContextWindow, K as KnowledgeCandidateSchema, f as stripClaudeCodeBillingHeader, u as isPlainRecord, G as GroupEvidenceReadResponseSchema$1, I as InspectorGroupsListResponseSchema } from "./router-DUb5lKw1.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, T as Trash2, U as Upload, d as Scan, e as CircleAlert, f as Terminal, g as ChevronUp, E as EyeOff, h as Eye, i as ExternalLink, j as RotateCw, k as Clock, l as ChevronRight, m as Pencil, 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.30";
|
|
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-CzgjhnUa.mjs").then((m) => ({ default: m.CompareDrawer }))
|
|
1580
1576
|
);
|
|
1581
1577
|
const LazyReplayDialog = reactExports.lazy(
|
|
1582
|
-
() => import("./ReplayDialog-
|
|
1578
|
+
() => import("./ReplayDialog-DmEknIL8.mjs").then((m) => ({ default: m.ReplayDialog }))
|
|
1583
1579
|
);
|
|
1584
1580
|
const LazyRequestAnatomy = reactExports.lazy(
|
|
1585
|
-
() => import("./RequestAnatomy-
|
|
1581
|
+
() => import("./RequestAnatomy-DNoiMudY.mjs").then((m) => ({ default: m.RequestAnatomy }))
|
|
1586
1582
|
);
|
|
1587
1583
|
const LazyResponseView = reactExports.lazy(
|
|
1588
|
-
() => import("./ResponseView-
|
|
1584
|
+
() => import("./ResponseView-C_cRrleT.mjs").then((m) => ({ default: m.ResponseView }))
|
|
1589
1585
|
);
|
|
1590
1586
|
const LazyStreamingChunkSequence = reactExports.lazy(
|
|
1591
|
-
() => import("./StreamingChunkSequence-
|
|
1587
|
+
() => import("./StreamingChunkSequence-DHZ9Q_dL.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,723 @@ 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 groupDeletePath(groupId, deleteEvidence) {
|
|
5453
|
+
const path = `/api/groups/${encodeURIComponent(groupId)}`;
|
|
5454
|
+
return deleteEvidence ? `${path}?deleteEvidence=1` : path;
|
|
5455
|
+
}
|
|
5456
|
+
function summarizeGroup(group) {
|
|
5457
|
+
let completedMembers = 0;
|
|
5458
|
+
let failedMembers = 0;
|
|
5459
|
+
let runningMembers = 0;
|
|
5460
|
+
let missingStatusMembers = 0;
|
|
5461
|
+
for (const member of group.members) {
|
|
5462
|
+
switch (member.status) {
|
|
5463
|
+
case "completed":
|
|
5464
|
+
completedMembers += 1;
|
|
5465
|
+
break;
|
|
5466
|
+
case "failed":
|
|
5467
|
+
case "cancelled":
|
|
5468
|
+
failedMembers += 1;
|
|
5469
|
+
break;
|
|
5470
|
+
case "running":
|
|
5471
|
+
runningMembers += 1;
|
|
5472
|
+
break;
|
|
5473
|
+
case "created":
|
|
5474
|
+
break;
|
|
5475
|
+
case null:
|
|
5476
|
+
missingStatusMembers += 1;
|
|
5477
|
+
break;
|
|
5478
|
+
}
|
|
5479
|
+
}
|
|
5480
|
+
return {
|
|
5481
|
+
memberCount: group.members.length,
|
|
5482
|
+
completedMembers,
|
|
5483
|
+
failedMembers,
|
|
5484
|
+
runningMembers,
|
|
5485
|
+
missingStatusMembers
|
|
5486
|
+
};
|
|
5487
|
+
}
|
|
5488
|
+
function buildGroupMemberRows(group, exportResult) {
|
|
5489
|
+
if (exportResult !== null && exportResult.group.id === group.id) {
|
|
5490
|
+
return exportResult.members.map((exportMember) => ({
|
|
5491
|
+
member: exportMember.member,
|
|
5492
|
+
exportMember
|
|
5493
|
+
}));
|
|
5494
|
+
}
|
|
5495
|
+
return group.members.map((member) => ({ member, exportMember: null }));
|
|
5496
|
+
}
|
|
5497
|
+
function statusClassName(status) {
|
|
5498
|
+
switch (status) {
|
|
5499
|
+
case "completed":
|
|
5500
|
+
return "border-emerald-200 bg-emerald-50 text-emerald-700";
|
|
5501
|
+
case "failed":
|
|
5502
|
+
case "cancelled":
|
|
5503
|
+
return "border-red-200 bg-red-50 text-red-700";
|
|
5504
|
+
case "running":
|
|
5505
|
+
return "border-sky-200 bg-sky-50 text-sky-700";
|
|
5506
|
+
case "created":
|
|
5507
|
+
return "border-zinc-200 bg-zinc-50 text-zinc-600";
|
|
5508
|
+
case null:
|
|
5509
|
+
return "border-zinc-200 bg-zinc-50 text-zinc-500";
|
|
5510
|
+
}
|
|
5511
|
+
}
|
|
5512
|
+
function statusLabel(status) {
|
|
5513
|
+
return status ?? "unknown";
|
|
5514
|
+
}
|
|
5515
|
+
function reportStatusClassName(status) {
|
|
5516
|
+
switch (status) {
|
|
5517
|
+
case "PASS":
|
|
5518
|
+
return "border-emerald-200 bg-emerald-50 text-emerald-700";
|
|
5519
|
+
case "FAIL":
|
|
5520
|
+
return "border-red-200 bg-red-50 text-red-700";
|
|
5521
|
+
case "RUNNING":
|
|
5522
|
+
return "border-sky-200 bg-sky-50 text-sky-700";
|
|
5523
|
+
case "UNKNOWN":
|
|
5524
|
+
return "border-zinc-200 bg-zinc-50 text-zinc-600";
|
|
5525
|
+
}
|
|
5526
|
+
}
|
|
5527
|
+
function displayText(value) {
|
|
5528
|
+
if (value === null || value.trim().length === 0) return "-";
|
|
5529
|
+
return value;
|
|
5530
|
+
}
|
|
5531
|
+
function formatNumber(value) {
|
|
5532
|
+
return value.toLocaleString();
|
|
5533
|
+
}
|
|
5534
|
+
function formatMs(value) {
|
|
5535
|
+
if (value === null || value === void 0) return "-";
|
|
5536
|
+
if (value < 1e3) return `${formatNumber(value)} ms`;
|
|
5537
|
+
return `${(value / 1e3).toFixed(1)} s`;
|
|
5538
|
+
}
|
|
5539
|
+
function formatTimestamp(value) {
|
|
5540
|
+
const millis = Date.parse(value);
|
|
5541
|
+
if (!Number.isFinite(millis)) return value;
|
|
5542
|
+
return new Intl.DateTimeFormat(void 0, {
|
|
5543
|
+
month: "short",
|
|
5544
|
+
day: "2-digit",
|
|
5545
|
+
hour: "2-digit",
|
|
5546
|
+
minute: "2-digit",
|
|
5547
|
+
hour12: false
|
|
5548
|
+
}).format(new Date(millis));
|
|
5549
|
+
}
|
|
5550
|
+
function firstNonEmpty(...values) {
|
|
5551
|
+
for (const value of values) {
|
|
5552
|
+
if (value !== null && value.trim().length > 0) return value;
|
|
5553
|
+
}
|
|
5554
|
+
return "-";
|
|
5555
|
+
}
|
|
5556
|
+
function providerModel(member) {
|
|
5557
|
+
const provider = member.provider;
|
|
5558
|
+
const model = member.model;
|
|
5559
|
+
if (provider !== null && provider.length > 0 && model !== null && model.length > 0) {
|
|
5560
|
+
return `${provider} / ${model}`;
|
|
5561
|
+
}
|
|
5562
|
+
return firstNonEmpty(provider, model);
|
|
5563
|
+
}
|
|
5564
|
+
function selectedGroupFrom(groups, selectedGroupId) {
|
|
5565
|
+
if (selectedGroupId !== null) {
|
|
5566
|
+
const selected = groups.find((group) => group.id === selectedGroupId);
|
|
5567
|
+
if (selected !== void 0) return selected;
|
|
5568
|
+
}
|
|
5569
|
+
return groups[0] ?? null;
|
|
5570
|
+
}
|
|
5571
|
+
function latestLog(row) {
|
|
5572
|
+
const logs = row.exportMember?.session?.latestLogs ?? [];
|
|
5573
|
+
return logs[0] ?? null;
|
|
5574
|
+
}
|
|
5575
|
+
function evidenceFor(group, exportResult) {
|
|
5576
|
+
if (exportResult !== null && exportResult.group.id === group.id) return exportResult.evidence;
|
|
5577
|
+
return group.evidence;
|
|
5578
|
+
}
|
|
5579
|
+
function exportSummaryFor(group, exportResult, evidenceResponse) {
|
|
5580
|
+
if (exportResult !== null && exportResult.group.id === group.id) return exportResult.summary;
|
|
5581
|
+
if (evidenceResponse !== null && evidenceResponse.group.id === group.id) {
|
|
5582
|
+
return evidenceResponse.summary;
|
|
5583
|
+
}
|
|
5584
|
+
return null;
|
|
5585
|
+
}
|
|
5586
|
+
function evidenceReportFor(group, exportResult, evidenceResponse) {
|
|
5587
|
+
if (exportResult !== null && exportResult.group.id === group.id) {
|
|
5588
|
+
return exportResult.jenkinsReport;
|
|
5589
|
+
}
|
|
5590
|
+
if (evidenceResponse !== null && evidenceResponse.group.id === group.id) {
|
|
5591
|
+
return evidenceResponse.report;
|
|
5592
|
+
}
|
|
5593
|
+
return null;
|
|
5594
|
+
}
|
|
5595
|
+
function GroupsDialog() {
|
|
5596
|
+
const [open, setOpen] = reactExports.useState(false);
|
|
5597
|
+
const [selectedGroupId, setSelectedGroupId] = reactExports.useState(null);
|
|
5598
|
+
const [exportingGroupId, setExportingGroupId] = reactExports.useState(null);
|
|
5599
|
+
const [exportError, setExportError] = reactExports.useState(null);
|
|
5600
|
+
const [exportResult, setExportResult] = reactExports.useState(null);
|
|
5601
|
+
const [deleteTarget, setDeleteTarget] = reactExports.useState(null);
|
|
5602
|
+
const [deleteEvidence, setDeleteEvidence] = reactExports.useState(false);
|
|
5603
|
+
const [deletingGroupId, setDeletingGroupId] = reactExports.useState(null);
|
|
5604
|
+
const [deleteError, setDeleteError] = reactExports.useState(null);
|
|
5605
|
+
const { groups, isLoading, error, mutate } = useGroups();
|
|
5606
|
+
const selectedGroup = reactExports.useMemo(
|
|
5607
|
+
() => selectedGroupFrom(groups, selectedGroupId),
|
|
5608
|
+
[groups, selectedGroupId]
|
|
5609
|
+
);
|
|
5610
|
+
reactExports.useEffect(() => {
|
|
5611
|
+
if (!open) return;
|
|
5612
|
+
const hasSelected = selectedGroupId !== null && groups.some((group) => group.id === selectedGroupId);
|
|
5613
|
+
if (hasSelected) return;
|
|
5614
|
+
setSelectedGroupId(groups[0]?.id ?? null);
|
|
5615
|
+
}, [groups, open, selectedGroupId]);
|
|
5616
|
+
const selectedExportResult = selectedGroup !== null && exportResult !== null && exportResult.group.id === selectedGroup.id ? exportResult : null;
|
|
5617
|
+
const {
|
|
5618
|
+
evidenceResponse,
|
|
5619
|
+
isLoading: evidenceLoading,
|
|
5620
|
+
error: evidenceError,
|
|
5621
|
+
mutate: mutateEvidence
|
|
5622
|
+
} = useGroupEvidence(selectedGroup);
|
|
5623
|
+
const handleRefresh = reactExports.useCallback(() => {
|
|
5624
|
+
void mutate();
|
|
5625
|
+
}, [mutate]);
|
|
5626
|
+
const handleExport = reactExports.useCallback(
|
|
5627
|
+
async (group) => {
|
|
5628
|
+
setExportingGroupId(group.id);
|
|
5629
|
+
setExportError(null);
|
|
5630
|
+
try {
|
|
5631
|
+
const response = await fetch(`/api/groups/${encodeURIComponent(group.id)}/evidence`, {
|
|
5632
|
+
method: "POST",
|
|
5633
|
+
headers: { "content-type": "application/json" },
|
|
5634
|
+
body: JSON.stringify({ latestLogLimit: 10 })
|
|
5635
|
+
});
|
|
5636
|
+
if (!response.ok) {
|
|
5637
|
+
setExportError(
|
|
5638
|
+
await readApiError(response, `Export failed with status ${String(response.status)}`)
|
|
5639
|
+
);
|
|
5640
|
+
return;
|
|
5641
|
+
}
|
|
5642
|
+
const parsed = await parseJsonResponse$1(response, GroupEvidenceExportResultSchema);
|
|
5643
|
+
setExportResult(parsed);
|
|
5644
|
+
await mutate();
|
|
5645
|
+
await mutateEvidence();
|
|
5646
|
+
} catch (err) {
|
|
5647
|
+
setExportError(err instanceof Error ? err.message : String(err));
|
|
5648
|
+
} finally {
|
|
5649
|
+
setExportingGroupId(null);
|
|
5650
|
+
}
|
|
5651
|
+
},
|
|
5652
|
+
[mutate, mutateEvidence]
|
|
5653
|
+
);
|
|
5654
|
+
const handleRequestDelete = reactExports.useCallback((group) => {
|
|
5655
|
+
setDeleteTarget(group);
|
|
5656
|
+
setDeleteEvidence(false);
|
|
5657
|
+
setDeleteError(null);
|
|
5658
|
+
}, []);
|
|
5659
|
+
const handleDeleteDialogOpenChange = reactExports.useCallback(
|
|
5660
|
+
(nextOpen) => {
|
|
5661
|
+
if (nextOpen || deletingGroupId !== null) return;
|
|
5662
|
+
setDeleteTarget(null);
|
|
5663
|
+
setDeleteEvidence(false);
|
|
5664
|
+
setDeleteError(null);
|
|
5665
|
+
},
|
|
5666
|
+
[deletingGroupId]
|
|
5667
|
+
);
|
|
5668
|
+
const handleDelete = reactExports.useCallback(async () => {
|
|
5669
|
+
const group = deleteTarget;
|
|
5670
|
+
if (group === null) return;
|
|
5671
|
+
setDeletingGroupId(group.id);
|
|
5672
|
+
setDeleteError(null);
|
|
5673
|
+
try {
|
|
5674
|
+
const response = await fetch(groupDeletePath(group.id, deleteEvidence), {
|
|
5675
|
+
method: "DELETE"
|
|
5676
|
+
});
|
|
5677
|
+
if (!response.ok) {
|
|
5678
|
+
setDeleteError(
|
|
5679
|
+
await readApiError(response, `Delete failed with status ${String(response.status)}`)
|
|
5680
|
+
);
|
|
5681
|
+
return;
|
|
5682
|
+
}
|
|
5683
|
+
await parseJsonResponse$1(response, DeleteInspectorGroupResponseSchema);
|
|
5684
|
+
setExportResult(
|
|
5685
|
+
(current) => current !== null && current.group.id === group.id ? null : current
|
|
5686
|
+
);
|
|
5687
|
+
setSelectedGroupId((current) => current === group.id ? null : current);
|
|
5688
|
+
setDeleteTarget(null);
|
|
5689
|
+
setDeleteEvidence(false);
|
|
5690
|
+
await mutate();
|
|
5691
|
+
await mutateEvidence();
|
|
5692
|
+
} catch (err) {
|
|
5693
|
+
setDeleteError(err instanceof Error ? err.message : String(err));
|
|
5694
|
+
} finally {
|
|
5695
|
+
setDeletingGroupId(null);
|
|
5696
|
+
}
|
|
5697
|
+
}, [deleteEvidence, deleteTarget, mutate, mutateEvidence]);
|
|
5698
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
5699
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(Dialog, { open, onOpenChange: setOpen, children: [
|
|
5700
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(DialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
5701
|
+
Button,
|
|
5702
|
+
{
|
|
5703
|
+
type: "button",
|
|
5704
|
+
variant: "ghost",
|
|
5705
|
+
size: "icon",
|
|
5706
|
+
className: "relative size-8",
|
|
5707
|
+
"aria-label": "Evaluation groups",
|
|
5708
|
+
title: "Evaluation groups",
|
|
5709
|
+
children: [
|
|
5710
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Layers, { className: "size-4" }),
|
|
5711
|
+
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,
|
|
5712
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sr-only", children: "Evaluation groups" })
|
|
5713
|
+
]
|
|
5714
|
+
}
|
|
5715
|
+
) }),
|
|
5716
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(DialogContent, { className: "flex max-h-[85vh] max-w-5xl flex-col overflow-hidden", children: [
|
|
5717
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(DialogHeader, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogTitle, { className: "flex items-center gap-2 pr-8", children: [
|
|
5718
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Layers, { className: "size-5 text-muted-foreground" }),
|
|
5719
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Groups" }),
|
|
5720
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { variant: "outline", children: formatNumber(groups.length) })
|
|
5721
|
+
] }) }),
|
|
5722
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-h-0 items-center justify-between gap-3 border-b border-border pb-3", children: [
|
|
5723
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: "Evaluation batches, model runs, and exported evidence packs." }),
|
|
5724
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
5725
|
+
Button,
|
|
5726
|
+
{
|
|
5727
|
+
type: "button",
|
|
5728
|
+
variant: "outline",
|
|
5729
|
+
size: "sm",
|
|
5730
|
+
className: "shrink-0",
|
|
5731
|
+
onClick: handleRefresh,
|
|
5732
|
+
children: [
|
|
5733
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: "size-3.5" }),
|
|
5734
|
+
"Refresh"
|
|
5735
|
+
]
|
|
5736
|
+
}
|
|
5737
|
+
)
|
|
5738
|
+
] }),
|
|
5739
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid min-h-0 flex-1 gap-4 md:grid-cols-[260px_minmax(0,1fr)]", children: [
|
|
5740
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5741
|
+
GroupList,
|
|
5742
|
+
{
|
|
5743
|
+
groups,
|
|
5744
|
+
selectedGroupId: selectedGroup?.id ?? null,
|
|
5745
|
+
isLoading,
|
|
5746
|
+
error,
|
|
5747
|
+
onSelect: setSelectedGroupId
|
|
5748
|
+
}
|
|
5749
|
+
),
|
|
5750
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5751
|
+
GroupDetails,
|
|
5752
|
+
{
|
|
5753
|
+
group: selectedGroup,
|
|
5754
|
+
exportResult: selectedExportResult,
|
|
5755
|
+
evidenceResponse,
|
|
5756
|
+
evidenceLoading,
|
|
5757
|
+
evidenceError,
|
|
5758
|
+
exportError,
|
|
5759
|
+
deleteError,
|
|
5760
|
+
exportingGroupId,
|
|
5761
|
+
deletingGroupId,
|
|
5762
|
+
onExport: handleExport,
|
|
5763
|
+
onRequestDelete: handleRequestDelete
|
|
5764
|
+
}
|
|
5765
|
+
)
|
|
5766
|
+
] })
|
|
5767
|
+
] })
|
|
5768
|
+
] }),
|
|
5769
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5770
|
+
DeleteGroupDialog,
|
|
5771
|
+
{
|
|
5772
|
+
group: deleteTarget,
|
|
5773
|
+
open: deleteTarget !== null,
|
|
5774
|
+
deleteEvidence,
|
|
5775
|
+
isDeleting: deleteTarget !== null && deletingGroupId === deleteTarget.id,
|
|
5776
|
+
error: deleteError,
|
|
5777
|
+
onDeleteEvidenceChange: setDeleteEvidence,
|
|
5778
|
+
onOpenChange: handleDeleteDialogOpenChange,
|
|
5779
|
+
onConfirm: () => void handleDelete()
|
|
5780
|
+
}
|
|
5781
|
+
)
|
|
5782
|
+
] });
|
|
5783
|
+
}
|
|
5784
|
+
function GroupList({
|
|
5785
|
+
groups,
|
|
5786
|
+
selectedGroupId,
|
|
5787
|
+
isLoading,
|
|
5788
|
+
error,
|
|
5789
|
+
onSelect
|
|
5790
|
+
}) {
|
|
5791
|
+
if (isLoading) {
|
|
5792
|
+
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..." });
|
|
5793
|
+
}
|
|
5794
|
+
if (error !== void 0) {
|
|
5795
|
+
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 });
|
|
5796
|
+
}
|
|
5797
|
+
if (groups.length === 0) {
|
|
5798
|
+
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." });
|
|
5799
|
+
}
|
|
5800
|
+
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) => {
|
|
5801
|
+
const summary = summarizeGroup(group);
|
|
5802
|
+
const selected = selectedGroupId === group.id;
|
|
5803
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
5804
|
+
"button",
|
|
5805
|
+
{
|
|
5806
|
+
type: "button",
|
|
5807
|
+
onClick: () => onSelect(group.id),
|
|
5808
|
+
className: cn(
|
|
5809
|
+
"w-full rounded-md border px-3 py-2 text-left text-xs transition-colors",
|
|
5810
|
+
selected ? "border-primary bg-primary/5" : "border-border bg-background hover:bg-muted/50"
|
|
5811
|
+
),
|
|
5812
|
+
children: [
|
|
5813
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center justify-between gap-2", children: [
|
|
5814
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0 truncate text-sm font-medium", children: group.title }),
|
|
5815
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { variant: "outline", className: statusClassName(group.status), children: statusLabel(group.status) })
|
|
5816
|
+
] }),
|
|
5817
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-1 flex items-center gap-2 text-muted-foreground", children: [
|
|
5818
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
5819
|
+
summary.memberCount,
|
|
5820
|
+
" sessions"
|
|
5821
|
+
] }),
|
|
5822
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: formatTimestamp(group.updatedAt) })
|
|
5823
|
+
] })
|
|
5824
|
+
]
|
|
5825
|
+
},
|
|
5826
|
+
group.id
|
|
5827
|
+
);
|
|
5828
|
+
}) }) });
|
|
5829
|
+
}
|
|
5830
|
+
function GroupDetails({
|
|
5831
|
+
group,
|
|
5832
|
+
exportResult,
|
|
5833
|
+
evidenceResponse,
|
|
5834
|
+
evidenceLoading,
|
|
5835
|
+
evidenceError,
|
|
5836
|
+
exportError,
|
|
5837
|
+
deleteError,
|
|
5838
|
+
exportingGroupId,
|
|
5839
|
+
deletingGroupId,
|
|
5840
|
+
onExport,
|
|
5841
|
+
onRequestDelete
|
|
5842
|
+
}) {
|
|
5843
|
+
if (group === null) {
|
|
5844
|
+
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." });
|
|
5845
|
+
}
|
|
5846
|
+
const summary = summarizeGroup(group);
|
|
5847
|
+
const exportedSummary = exportSummaryFor(group, exportResult, evidenceResponse);
|
|
5848
|
+
const evidenceReport = evidenceReportFor(group, exportResult, evidenceResponse);
|
|
5849
|
+
const evidence = evidenceFor(group, exportResult);
|
|
5850
|
+
const rows = buildGroupMemberRows(group, exportResult);
|
|
5851
|
+
const isExporting = exportingGroupId === group.id;
|
|
5852
|
+
const isDeleting = deletingGroupId === group.id;
|
|
5853
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "min-h-0 overflow-y-auto pr-1", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
|
|
5854
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-col gap-3 sm:flex-row sm:items-start sm:justify-between", children: [
|
|
5855
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 space-y-1", children: [
|
|
5856
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-2", children: [
|
|
5857
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "min-w-0 truncate text-base font-semibold", children: group.title }),
|
|
5858
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { variant: "outline", className: statusClassName(group.status), children: statusLabel(group.status) }),
|
|
5859
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { variant: "outline", children: group.kind })
|
|
5860
|
+
] }),
|
|
5861
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-2 text-xs text-muted-foreground", children: [
|
|
5862
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: displayText(group.project) }),
|
|
5863
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
5864
|
+
"updated ",
|
|
5865
|
+
formatTimestamp(group.updatedAt)
|
|
5866
|
+
] })
|
|
5867
|
+
] })
|
|
5868
|
+
] }),
|
|
5869
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
5870
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5871
|
+
Button,
|
|
5872
|
+
{
|
|
5873
|
+
type: "button",
|
|
5874
|
+
variant: "outline",
|
|
5875
|
+
size: "icon",
|
|
5876
|
+
className: "size-8 text-red-600 hover:text-red-700",
|
|
5877
|
+
"aria-label": "Delete group",
|
|
5878
|
+
title: "Delete group",
|
|
5879
|
+
disabled: isDeleting,
|
|
5880
|
+
onClick: () => onRequestDelete(group),
|
|
5881
|
+
children: isDeleting ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-3.5 animate-spin" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" })
|
|
5882
|
+
}
|
|
5883
|
+
),
|
|
5884
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
5885
|
+
Button,
|
|
5886
|
+
{
|
|
5887
|
+
type: "button",
|
|
5888
|
+
variant: "default",
|
|
5889
|
+
size: "sm",
|
|
5890
|
+
className: "shrink-0",
|
|
5891
|
+
disabled: isExporting || isDeleting,
|
|
5892
|
+
onClick: () => void onExport(group),
|
|
5893
|
+
children: [
|
|
5894
|
+
isExporting ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-3.5 animate-spin" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Download, { className: "size-3.5" }),
|
|
5895
|
+
"Export evidence"
|
|
5896
|
+
]
|
|
5897
|
+
}
|
|
5898
|
+
)
|
|
5899
|
+
] })
|
|
5900
|
+
] }),
|
|
5901
|
+
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 }),
|
|
5902
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid gap-2 sm:grid-cols-4", children: [
|
|
5903
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SummaryStat, { label: "Members", value: summary.memberCount }),
|
|
5904
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SummaryStat, { label: "Done", value: summary.completedMembers }),
|
|
5905
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SummaryStat, { label: "Failed", value: summary.failedMembers }),
|
|
5906
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SummaryStat, { label: "Running", value: summary.runningMembers })
|
|
5907
|
+
] }),
|
|
5908
|
+
exportedSummary !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid gap-2 sm:grid-cols-4", children: [
|
|
5909
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SummaryStat, { label: "Requests", value: exportedSummary.requestCount }),
|
|
5910
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SummaryStat, { label: "Errors", value: exportedSummary.errorCount }),
|
|
5911
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SummaryStat, { label: "Tokens", value: exportedSummary.tokenUsage.total }),
|
|
5912
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SummaryStat, { label: "Missing", value: exportedSummary.missingSessions })
|
|
5913
|
+
] }),
|
|
5914
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5915
|
+
EvidenceReportCard,
|
|
5916
|
+
{
|
|
5917
|
+
report: evidenceReport,
|
|
5918
|
+
loading: evidenceLoading,
|
|
5919
|
+
error: evidenceError,
|
|
5920
|
+
hasEvidence: evidence !== null
|
|
5921
|
+
}
|
|
5922
|
+
),
|
|
5923
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(EvidencePaths, { evidence }),
|
|
5924
|
+
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 }),
|
|
5925
|
+
deleteError !== 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: deleteError }),
|
|
5926
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(MemberTable, { rows })
|
|
5927
|
+
] }) });
|
|
5928
|
+
}
|
|
5929
|
+
function DeleteGroupDialog({
|
|
5930
|
+
group,
|
|
5931
|
+
open,
|
|
5932
|
+
deleteEvidence,
|
|
5933
|
+
isDeleting,
|
|
5934
|
+
error,
|
|
5935
|
+
onDeleteEvidenceChange,
|
|
5936
|
+
onOpenChange,
|
|
5937
|
+
onConfirm
|
|
5938
|
+
}) {
|
|
5939
|
+
const title = group?.title ?? "this group";
|
|
5940
|
+
const hasEvidence = group?.evidence !== null && group?.evidence !== void 0;
|
|
5941
|
+
const evidencePath = group?.evidence?.markdownPath ?? "No evidence pack exported.";
|
|
5942
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogContent, { className: "max-w-md", children: [
|
|
5943
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(DialogHeader, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogTitle, { className: "flex items-center gap-2 pr-8", children: [
|
|
5944
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-5 text-red-600" }),
|
|
5945
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Delete group" })
|
|
5946
|
+
] }) }),
|
|
5947
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-3", children: [
|
|
5948
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-sm text-muted-foreground", children: [
|
|
5949
|
+
"Delete ",
|
|
5950
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium text-foreground", children: title }),
|
|
5951
|
+
"? Session logs and run records stay intact."
|
|
5952
|
+
] }),
|
|
5953
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
5954
|
+
"label",
|
|
5955
|
+
{
|
|
5956
|
+
className: cn(
|
|
5957
|
+
"flex items-start gap-3 rounded-md border border-border bg-muted/20 px-3 py-2 text-sm",
|
|
5958
|
+
hasEvidence ? "cursor-pointer" : "opacity-60"
|
|
5959
|
+
),
|
|
5960
|
+
children: [
|
|
5961
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5962
|
+
"input",
|
|
5963
|
+
{
|
|
5964
|
+
type: "checkbox",
|
|
5965
|
+
className: "mt-0.5 size-4",
|
|
5966
|
+
checked: deleteEvidence,
|
|
5967
|
+
disabled: !hasEvidence || isDeleting,
|
|
5968
|
+
onChange: (event) => onDeleteEvidenceChange(event.currentTarget.checked)
|
|
5969
|
+
}
|
|
5970
|
+
),
|
|
5971
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "min-w-0", children: [
|
|
5972
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "block font-medium", children: "Also delete exported evidence files" }),
|
|
5973
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "mt-1 block truncate font-mono text-[11px] text-muted-foreground", children: evidencePath })
|
|
5974
|
+
] })
|
|
5975
|
+
]
|
|
5976
|
+
}
|
|
5977
|
+
),
|
|
5978
|
+
error !== 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: error })
|
|
5979
|
+
] }),
|
|
5980
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-end gap-2 pt-1", children: [
|
|
5981
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5982
|
+
Button,
|
|
5983
|
+
{
|
|
5984
|
+
type: "button",
|
|
5985
|
+
variant: "outline",
|
|
5986
|
+
size: "sm",
|
|
5987
|
+
disabled: isDeleting,
|
|
5988
|
+
onClick: () => onOpenChange(false),
|
|
5989
|
+
children: "Cancel"
|
|
5990
|
+
}
|
|
5991
|
+
),
|
|
5992
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
5993
|
+
Button,
|
|
5994
|
+
{
|
|
5995
|
+
type: "button",
|
|
5996
|
+
variant: "destructive",
|
|
5997
|
+
size: "sm",
|
|
5998
|
+
disabled: isDeleting || group === null,
|
|
5999
|
+
onClick: onConfirm,
|
|
6000
|
+
children: [
|
|
6001
|
+
isDeleting ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-3.5 animate-spin" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" }),
|
|
6002
|
+
"Delete"
|
|
6003
|
+
]
|
|
6004
|
+
}
|
|
6005
|
+
)
|
|
6006
|
+
] })
|
|
6007
|
+
] }) });
|
|
6008
|
+
}
|
|
6009
|
+
function SummaryStat({ label, value }) {
|
|
6010
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-md border border-border bg-muted/20 px-3 py-2", children: [
|
|
6011
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[11px] font-medium uppercase text-muted-foreground", children: label }),
|
|
6012
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1 font-mono text-sm font-semibold", children: formatNumber(value) })
|
|
6013
|
+
] });
|
|
6014
|
+
}
|
|
6015
|
+
function EvidenceReportCard({
|
|
6016
|
+
report,
|
|
6017
|
+
loading,
|
|
6018
|
+
error,
|
|
6019
|
+
hasEvidence
|
|
6020
|
+
}) {
|
|
6021
|
+
const { copied, copy } = useCopyFeedback(report?.markdown ?? null);
|
|
6022
|
+
if (report === null && !loading && error === void 0) return null;
|
|
6023
|
+
if (loading) {
|
|
6024
|
+
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: [
|
|
6025
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-3.5 animate-spin" }),
|
|
6026
|
+
"Loading evidence report..."
|
|
6027
|
+
] });
|
|
6028
|
+
}
|
|
6029
|
+
if (error !== void 0 && hasEvidence) {
|
|
6030
|
+
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: [
|
|
6031
|
+
"Failed to load evidence report: ",
|
|
6032
|
+
error.message
|
|
6033
|
+
] });
|
|
6034
|
+
}
|
|
6035
|
+
if (report === null) return null;
|
|
6036
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-md border border-border bg-muted/20 px-3 py-2", children: [
|
|
6037
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center justify-between gap-2", children: [
|
|
6038
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
6039
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs font-semibold", children: "Evidence report" }),
|
|
6040
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { variant: "outline", className: reportStatusClassName(report.status), children: report.status })
|
|
6041
|
+
] }),
|
|
6042
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
6043
|
+
Button,
|
|
6044
|
+
{
|
|
6045
|
+
type: "button",
|
|
6046
|
+
variant: "ghost",
|
|
6047
|
+
size: "icon",
|
|
6048
|
+
className: "size-7 shrink-0",
|
|
6049
|
+
"aria-label": copied ? "Copied evidence report" : "Copy evidence report",
|
|
6050
|
+
onClick: copy,
|
|
6051
|
+
children: copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-3.5 text-emerald-500" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-3.5" })
|
|
6052
|
+
}
|
|
6053
|
+
)
|
|
6054
|
+
] }),
|
|
6055
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: report.summary })
|
|
6056
|
+
] });
|
|
6057
|
+
}
|
|
6058
|
+
function EvidencePaths({ evidence }) {
|
|
6059
|
+
if (evidence === null) {
|
|
6060
|
+
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." });
|
|
6061
|
+
}
|
|
6062
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2 rounded-md border border-border bg-muted/20 px-3 py-2", children: [
|
|
6063
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
6064
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs font-semibold", children: "Evidence paths" }),
|
|
6065
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] text-muted-foreground", children: formatTimestamp(evidence.exportedAt) })
|
|
6066
|
+
] }),
|
|
6067
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid gap-2", children: [
|
|
6068
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(CopyPathRow, { label: "JSON", value: evidence.jsonPath }),
|
|
6069
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(CopyPathRow, { label: "Markdown", value: evidence.markdownPath }),
|
|
6070
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(CopyPathRow, { label: "HTML", value: evidence.htmlPath })
|
|
6071
|
+
] })
|
|
6072
|
+
] });
|
|
6073
|
+
}
|
|
6074
|
+
function CopyPathRow({ label, value }) {
|
|
6075
|
+
const { copied, copy } = useCopyFeedback(value);
|
|
6076
|
+
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: [
|
|
6077
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-16 shrink-0 text-[11px] font-medium text-muted-foreground", children: label }),
|
|
6078
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "min-w-0 flex-1 truncate font-mono text-xs", children: value }),
|
|
6079
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
6080
|
+
Button,
|
|
6081
|
+
{
|
|
6082
|
+
type: "button",
|
|
6083
|
+
variant: "ghost",
|
|
6084
|
+
size: "icon",
|
|
6085
|
+
className: "size-7 shrink-0",
|
|
6086
|
+
"aria-label": copied ? `Copied ${label} path` : `Copy ${label} path`,
|
|
6087
|
+
onClick: copy,
|
|
6088
|
+
children: copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-3.5 text-emerald-500" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-3.5" })
|
|
6089
|
+
}
|
|
6090
|
+
)
|
|
6091
|
+
] });
|
|
6092
|
+
}
|
|
6093
|
+
function MemberTable({ rows }) {
|
|
6094
|
+
if (rows.length === 0) {
|
|
6095
|
+
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." });
|
|
6096
|
+
}
|
|
6097
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "overflow-hidden rounded-md border border-border", children: [
|
|
6098
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "border-b border-border bg-muted/30 px-3 py-2 text-xs font-semibold", children: "Members" }),
|
|
6099
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("table", { className: "w-full min-w-[760px] text-left text-xs", children: [
|
|
6100
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("thead", { className: "border-b border-border bg-muted/20 text-muted-foreground", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("tr", { children: [
|
|
6101
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "px-3 py-2 font-medium", children: "Session" }),
|
|
6102
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "px-3 py-2 font-medium", children: "Provider / Model" }),
|
|
6103
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "px-3 py-2 font-medium", children: "Status" }),
|
|
6104
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "px-3 py-2 font-medium", children: "Requests" }),
|
|
6105
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "px-3 py-2 font-medium", children: "Errors" }),
|
|
6106
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "px-3 py-2 font-medium", children: "First chunk" }),
|
|
6107
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "px-3 py-2 font-medium", children: "Tokens" })
|
|
6108
|
+
] }) }),
|
|
6109
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("tbody", { children: rows.map((row) => /* @__PURE__ */ jsxRuntimeExports.jsx(MemberRow, { row }, row.member.id)) })
|
|
6110
|
+
] }) })
|
|
6111
|
+
] });
|
|
6112
|
+
}
|
|
6113
|
+
function MemberRow({ row }) {
|
|
6114
|
+
const member = row.member;
|
|
6115
|
+
const session = row.exportMember?.session ?? null;
|
|
6116
|
+
const log = latestLog(row);
|
|
6117
|
+
const sessionPath = session?.inspectorPath ?? getSessionPath(member.sessionId);
|
|
6118
|
+
const requests = session?.requestCount ?? null;
|
|
6119
|
+
const errors = session?.errorCount ?? null;
|
|
6120
|
+
const tokens = session?.tokenUsage.total ?? null;
|
|
6121
|
+
const firstChunkMs = log?.firstChunkMs ?? null;
|
|
6122
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("tr", { className: "border-b border-border last:border-0", children: [
|
|
6123
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("td", { className: "max-w-56 px-3 py-2", children: [
|
|
6124
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
6125
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
6126
|
+
"a",
|
|
6127
|
+
{
|
|
6128
|
+
href: sessionPath,
|
|
6129
|
+
target: "_blank",
|
|
6130
|
+
rel: "noreferrer",
|
|
6131
|
+
className: "min-w-0 truncate font-mono text-xs text-primary hover:underline",
|
|
6132
|
+
children: firstNonEmpty(member.label, member.sessionId)
|
|
6133
|
+
}
|
|
6134
|
+
),
|
|
6135
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ExternalLink, { className: "size-3 shrink-0 text-muted-foreground" })
|
|
6136
|
+
] }),
|
|
6137
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-0.5 truncate text-[11px] text-muted-foreground", children: displayText(member.agent) })
|
|
6138
|
+
] }),
|
|
6139
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "max-w-52 px-3 py-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "block truncate", children: providerModel(member) }) }),
|
|
6140
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "px-3 py-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { variant: "outline", className: statusClassName(member.status), children: statusLabel(member.status) }) }),
|
|
6141
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "px-3 py-2 font-mono", children: requests === null ? "-" : formatNumber(requests) }),
|
|
6142
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "px-3 py-2 font-mono", children: errors === null ? "-" : formatNumber(errors) }),
|
|
6143
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "px-3 py-2 font-mono", children: formatMs(firstChunkMs) }),
|
|
6144
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "px-3 py-2 font-mono", children: tokens === null ? "-" : formatNumber(tokens) })
|
|
6145
|
+
] });
|
|
6146
|
+
}
|
|
5434
6147
|
function ClaudeCodeIcon() {
|
|
5435
6148
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
5436
6149
|
"svg",
|
|
@@ -9215,6 +9928,9 @@ function truncateSessionId(id) {
|
|
|
9215
9928
|
if (id.length <= 30) return id;
|
|
9216
9929
|
return `${id.slice(0, 12)}...${id.slice(-12)}`;
|
|
9217
9930
|
}
|
|
9931
|
+
function shouldShowRawExport(captureMode) {
|
|
9932
|
+
return captureMode === "full";
|
|
9933
|
+
}
|
|
9218
9934
|
function computeTokenSummary(logs) {
|
|
9219
9935
|
let totalIn = 0;
|
|
9220
9936
|
let totalOut = 0;
|
|
@@ -9784,6 +10500,7 @@ function ProxyViewer({
|
|
|
9784
10500
|
);
|
|
9785
10501
|
const cacheTrends = reactExports.useMemo(() => computeCacheTrends(groups), [groups]);
|
|
9786
10502
|
const comparisonPredecessors = reactExports.useMemo(() => buildValidPredecessors(groups), [groups]);
|
|
10503
|
+
const showRawExport = shouldShowRawExport(captureMode);
|
|
9787
10504
|
const handleCompareWithPrevious = reactExports.useCallback(
|
|
9788
10505
|
(log) => {
|
|
9789
10506
|
const predecessor = comparisonPredecessors.get(log.id);
|
|
@@ -9848,7 +10565,10 @@ function ProxyViewer({
|
|
|
9848
10565
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "max-w-[calc(100vw-7rem)] text-sm font-semibold text-muted-foreground", children: "Local First. Evidence First." }),
|
|
9849
10566
|
/* @__PURE__ */ jsxRuntimeExports.jsx(McpReadyBadge, {})
|
|
9850
10567
|
] }),
|
|
9851
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
10568
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "justify-self-end flex items-center gap-1", children: [
|
|
10569
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(GroupsDialog, {}),
|
|
10570
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SettingsDialog, {})
|
|
10571
|
+
] })
|
|
9852
10572
|
] }),
|
|
9853
10573
|
hasSessionContext && sessionContextScope !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
9854
10574
|
SessionContextBar,
|
|
@@ -9904,7 +10624,7 @@ function ProxyViewer({
|
|
|
9904
10624
|
logs.length !== 1 ? "s" : "",
|
|
9905
10625
|
totalIn > 0 || totalOut > 0 ? ` - ${formatTokens(totalIn)} in / ${formatTokens(totalOut)} out` : ""
|
|
9906
10626
|
] }),
|
|
9907
|
-
logs.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10627
|
+
logs.length > 0 && showRawExport && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
9908
10628
|
"button",
|
|
9909
10629
|
{
|
|
9910
10630
|
type: "button",
|