@tonyclaw/agent-inspector 3.0.22 → 3.0.24
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-CaDAbX9q.js → CompareDrawer-BC52FYwn.js} +1 -1
- package/.output/public/assets/ProxyViewerContainer-WuChOrSS.js +127 -0
- package/.output/public/assets/{ReplayDialog-C5kb1Bj4.js → ReplayDialog-BcKsarKt.js} +1 -1
- package/.output/public/assets/{RequestAnatomy-CbPNLnlL.js → RequestAnatomy-DR0uGpCj.js} +1 -1
- package/.output/public/assets/{ResponseView-DyzW0Zfo.js → ResponseView-kxAAPfmn.js} +2 -2
- package/.output/public/assets/{StreamingChunkSequence-Cl8zJu0w.js → StreamingChunkSequence-YQR0PjQj.js} +1 -1
- package/.output/public/assets/{_sessionId-BeN8-5Ho.js → _sessionId-DRl-Y9om.js} +1 -1
- package/.output/public/assets/{index-BCHWOmF2.js → index-CQbrc-hi.js} +71 -7
- package/.output/public/assets/{index-DcFtdKF3.js → index-CcSIBI4L.js} +1 -1
- package/.output/public/assets/index-DQeXi4Rv.css +1 -0
- package/.output/public/assets/{index-Pz9T7cS9.js → index-ZrMgyEZV.js} +1 -1
- package/.output/public/assets/{json-viewer-PNvFrOUw.js → json-viewer-CS5pwnEA.js} +1 -1
- package/.output/server/_libs/lucide-react.mjs +266 -234
- package/.output/server/{_sessionId-CIvbZsmt.mjs → _sessionId-BLk2xPkR.mjs} +2 -2
- package/.output/server/_ssr/{CompareDrawer-CtWPZP5T.mjs → CompareDrawer-Cw7Dseo3.mjs} +3 -3
- package/.output/server/_ssr/{ProxyViewerContainer-Dnm-Hup3.mjs → ProxyViewerContainer-D8SB0zyQ.mjs} +1124 -877
- package/.output/server/_ssr/{ReplayDialog-BYii7Q2m.mjs → ReplayDialog-B-YMhZkE.mjs} +4 -4
- package/.output/server/_ssr/{RequestAnatomy-CC6brPZr.mjs → RequestAnatomy-a9d8UTYZ.mjs} +2 -2
- package/.output/server/_ssr/{ResponseView-CwwkL_0d.mjs → ResponseView-PzaZS4CN.mjs} +3 -3
- package/.output/server/_ssr/{StreamingChunkSequence-CFsJzBLS.mjs → StreamingChunkSequence-C21_TCXk.mjs} +2 -2
- package/.output/server/_ssr/{index-B-Mm06YB.mjs → index-CrCeNP7H.mjs} +2 -2
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{json-viewer-D2MGmYZ0.mjs → json-viewer-Di2gxs9H.mjs} +3 -3
- package/.output/server/_ssr/{router-BwvN4eYE.mjs → router-BJzdUbcH.mjs} +296 -91
- package/.output/server/{_tanstack-start-manifest_v-Dpk8cafb.mjs → _tanstack-start-manifest_v-CGBTdAYC.mjs} +1 -1
- package/.output/server/index.mjs +64 -64
- package/package.json +6 -2
- package/src/components/ProxyViewer.tsx +136 -460
- package/src/components/ProxyViewerContainer.tsx +5 -47
- package/src/components/alerts/AlertsDialog.tsx +6 -2
- package/src/components/providers/ProviderCard.tsx +20 -579
- package/src/components/providers/ProviderTestResultsView.tsx +732 -0
- package/src/components/proxy-viewer/LogEntry.tsx +5 -0
- package/src/components/proxy-viewer/LogEntryHeader.tsx +7 -0
- package/src/components/proxy-viewer/ToolTraceEvents.tsx +33 -36
- package/src/components/proxy-viewer/TurnGroup.tsx +1 -5
- package/src/components/proxy-viewer/proxyViewerContainerLogic.ts +46 -0
- package/src/components/proxy-viewer/proxyViewerLogic.ts +469 -0
- package/src/lib/themeMode.ts +45 -0
- package/src/lib/uiScale.ts +112 -0
- package/src/lib/useThemeMode.ts +40 -0
- package/src/lib/useUiScale.ts +52 -0
- package/src/routes/__root.tsx +78 -1
- package/styles/globals.css +305 -23
- package/.output/public/assets/ProxyViewerContainer-7ugZIMW0.js +0 -127
- package/.output/public/assets/index-SqCROi0s.css +0 -1
package/.output/server/_ssr/{ProxyViewerContainer-Dnm-Hup3.mjs → ProxyViewerContainer-D8SB0zyQ.mjs}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { r as reactExports, j as jsxRuntimeExports, R as React } from "../_libs/react.mjs";
|
|
2
|
-
import { C as CapturedLogSchema,
|
|
2
|
+
import { C as CapturedLogSchema, z as DeleteInspectorGroupsResponseSchema, 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, g as readStoredUiScalePreference, h as persistUiScalePreference, i as applyUiScalePreference, w as extractStopReason, p as packageJson, P as ProviderConfigSchema, U as UI_SCALE_STORAGE_KEY, j as normalizeUiScalePreference, q as apiFormatForPath, B as GroupEvidenceExportResultSchema, E as DeleteInspectorGroupResponseSchema, $ as PiAgentResponseSchema, v as isTurnBoundary, r as readStoredThemeMode, e as applyThemeMode, f as persistThemeMode, a2 as formatUiScale, x as AlertSummarySchema, y as AlertListResponseSchema, I as InspectorGroupsListResponseSchema, G as GroupEvidenceReadResponseSchema, V as createPendingProviderTestResults, W as ProviderTestResultsSchema, X as createFailedProviderTestResults, Y as MAX_SLOW_RESPONSE_THRESHOLD_SECONDS, Z as MAX_PROVIDER_TEST_TIMEOUT_SECONDS, _ as TimeDisplayFormatSchema, T as THEME_MODE_STORAGE_KEY, n as normalizeThemeMode, H as maskApiKey, M as PATH_V1_MESSAGES, N as PATH_V1_CHAT_COMPLETIONS, Q as PATH_V1_RESPONSES, F as providerHasContextMetadata, l as parseOpenAIResponse, m as parseOpenAIResponsesResponse, O as OpenAIRequestSchema, o as OpenAIResponsesRequestSchema, A as AnthropicResponseSchema$1, k as AnthropicRequestSchema, s as safeGetOwnProperty, a0 as resolveProviderContextWindow, t as getSessionPath, J as findProviderModelMetadata, S as previewUpstreamUrl, K as KnowledgeCandidateSchema, a1 as isPlainRecord, u as stripClaudeCodeBillingHeader, L as LogBodyChunkSchema } from "./router-BJzdUbcH.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";
|
|
@@ -7,7 +7,7 @@ import { t as twMerge } from "../_libs/tailwind-merge.mjs";
|
|
|
7
7
|
import { c as cva } from "../_libs/class-variance-authority.mjs";
|
|
8
8
|
import { u as useWindowVirtualizer, a as useVirtualizer } from "../_libs/tanstack__react-virtual.mjs";
|
|
9
9
|
import { d as diffJson, a as diffLines } from "../_libs/diff.mjs";
|
|
10
|
-
import { T as TriangleAlert, C as CircleCheck, X, I as Info, a as ChevronDown, b as Check, P as PanelRightOpen, c as PanelRightClose, S as Search, U as Upload, D as Download, F as FileBraces, R as RefreshCw, d as Trash2, e as Plus, B as BrainCircuit, L as LoaderCircle, f as Send, A as ArrowLeft, g as ChevronUp, h as Copy, i as ChevronsLeft, j as ChevronLeft, k as ChevronRight, l as ChevronsRight, m as Clapperboard, n as Flag, o as Siren, p as Timer, G as Gauge, q as
|
|
10
|
+
import { T as TriangleAlert, C as CircleCheck, X, I as Info, a as ChevronDown, b as Check, P as PanelRightOpen, c as PanelRightClose, S as Search, U as Upload, D as Download, F as FileBraces, R as RefreshCw, d as Trash2, e as Plus, B as BrainCircuit, L as LoaderCircle, f as Send, A as ArrowLeft, g as ChevronUp, h as Copy, i as ChevronsLeft, j as ChevronLeft, k as ChevronRight, l as ChevronsRight, m as Clapperboard, n as Flag, o as Siren, p as Timer, G as Gauge, q as Sun, E as Eye, M as Moon, r as ALargeSmall, s as Layers, t as FlaskConical, u as Sparkles, v as Activity, w as Beaker, N as Network, x as Terminal, y as Settings, z as Monitor, H as Rocket, J as PackageCheck, K as History, O as Scan, Q as CircleAlert, V as ArrowUpRight, W as ArrowDownRight, Y as Cpu, Z as FolderOpen, _ as Bell, $ as Clock3, a0 as ShieldAlert, a1 as EyeOff, a2 as ExternalLink, a3 as Clock, a4 as RotateCw, a5 as Pencil, a6 as MessageSquare, a7 as Zap, a8 as Wrench, a9 as Brain, aa as CircleCheckBig, ab as Minus, ac as CircleX, ad as ShieldCheck, ae as Save, af as FileSearch, ag as CloudUpload, ah as CircleQuestionMark, ai as Server, aj as Lock, ak as Wifi, al as WifiOff, am as OctagonAlert, an as Radio, ao as Globe, ap as FileTerminal, aq as ChevronsUp, ar as ChevronsDown, as as FileDiff, at as RotateCcw, au as GitCompareArrows, av as ArrowUp, aw as ArrowDown, ax as Ellipsis, ay as CodeXml, az as Blocks, aA as MousePointerClick, aB as FileText, aC as Rows3, aD as Columns2 } from "../_libs/lucide-react.mjs";
|
|
11
11
|
import { u as union, o as object, e as array, l as literal, n as number, d as boolean, b as string, _ as _enum } from "../_libs/zod.mjs";
|
|
12
12
|
import { S as Select$1, a as SelectTrigger$1, b as SelectIcon, c as SelectValue$1, d as SelectPortal, e as SelectContent$1, f as SelectViewport, g as SelectItem$1, h as SelectItemIndicator, i as SelectItemText, j as SelectScrollUpButton$1, k as SelectScrollDownButton$1 } from "../_libs/radix-ui__react-select.mjs";
|
|
13
13
|
import { D as Dialog$1, a as DialogContent$1, b as DialogClose, c as DialogTitle$1, d as DialogDescription$1, e as DialogPortal$1, f as DialogOverlay$1, g as DialogTrigger$1 } from "../_libs/radix-ui__react-dialog.mjs";
|
|
@@ -625,6 +625,59 @@ function getStatusCategory(status) {
|
|
|
625
625
|
if (status >= 500) return "server_error";
|
|
626
626
|
return "pending";
|
|
627
627
|
}
|
|
628
|
+
function useThemeMode() {
|
|
629
|
+
const [themeMode, setThemeModeState] = reactExports.useState(readStoredThemeMode);
|
|
630
|
+
const setThemeMode = reactExports.useCallback((nextThemeMode) => {
|
|
631
|
+
setThemeModeState(nextThemeMode);
|
|
632
|
+
applyThemeMode(nextThemeMode);
|
|
633
|
+
persistThemeMode(nextThemeMode);
|
|
634
|
+
}, []);
|
|
635
|
+
reactExports.useEffect(() => {
|
|
636
|
+
applyThemeMode(themeMode);
|
|
637
|
+
}, [themeMode]);
|
|
638
|
+
reactExports.useEffect(() => {
|
|
639
|
+
function handleStorage(event) {
|
|
640
|
+
if (event.key !== THEME_MODE_STORAGE_KEY) return;
|
|
641
|
+
const nextThemeMode = normalizeThemeMode(event.newValue);
|
|
642
|
+
setThemeModeState(nextThemeMode);
|
|
643
|
+
applyThemeMode(nextThemeMode);
|
|
644
|
+
}
|
|
645
|
+
window.addEventListener("storage", handleStorage);
|
|
646
|
+
return () => window.removeEventListener("storage", handleStorage);
|
|
647
|
+
}, []);
|
|
648
|
+
return { themeMode, setThemeMode };
|
|
649
|
+
}
|
|
650
|
+
function useUiScale() {
|
|
651
|
+
const [uiScalePreference, setUiScalePreferenceState] = reactExports.useState(
|
|
652
|
+
readStoredUiScalePreference
|
|
653
|
+
);
|
|
654
|
+
const [resolvedUiScale, setResolvedUiScale] = reactExports.useState(1);
|
|
655
|
+
const setUiScalePreference = reactExports.useCallback((nextPreference) => {
|
|
656
|
+
setUiScalePreferenceState(nextPreference);
|
|
657
|
+
persistUiScalePreference(nextPreference);
|
|
658
|
+
setResolvedUiScale(applyUiScalePreference(nextPreference));
|
|
659
|
+
}, []);
|
|
660
|
+
reactExports.useEffect(() => {
|
|
661
|
+
const refreshScale = () => {
|
|
662
|
+
setResolvedUiScale(applyUiScalePreference(uiScalePreference));
|
|
663
|
+
};
|
|
664
|
+
refreshScale();
|
|
665
|
+
if (uiScalePreference !== "auto") return;
|
|
666
|
+
window.addEventListener("resize", refreshScale);
|
|
667
|
+
return () => window.removeEventListener("resize", refreshScale);
|
|
668
|
+
}, [uiScalePreference]);
|
|
669
|
+
reactExports.useEffect(() => {
|
|
670
|
+
const handleStorage = (event) => {
|
|
671
|
+
if (event.key !== UI_SCALE_STORAGE_KEY) return;
|
|
672
|
+
const nextPreference = normalizeUiScalePreference(event.newValue);
|
|
673
|
+
setUiScalePreferenceState(nextPreference);
|
|
674
|
+
setResolvedUiScale(applyUiScalePreference(nextPreference));
|
|
675
|
+
};
|
|
676
|
+
window.addEventListener("storage", handleStorage);
|
|
677
|
+
return () => window.removeEventListener("storage", handleStorage);
|
|
678
|
+
}, []);
|
|
679
|
+
return { uiScalePreference, resolvedUiScale, setUiScalePreference };
|
|
680
|
+
}
|
|
628
681
|
async function fetcher(url) {
|
|
629
682
|
return fetchJson(
|
|
630
683
|
url,
|
|
@@ -2472,27 +2525,27 @@ function useCopyFeedback(text) {
|
|
|
2472
2525
|
return { copied, copy };
|
|
2473
2526
|
}
|
|
2474
2527
|
const LazyCompareDrawer = reactExports.lazy(
|
|
2475
|
-
() => import("./CompareDrawer-
|
|
2528
|
+
() => import("./CompareDrawer-Cw7Dseo3.mjs").then((m) => ({ default: m.CompareDrawer }))
|
|
2476
2529
|
);
|
|
2477
2530
|
const LazyReplayDialog = reactExports.lazy(
|
|
2478
|
-
() => import("./ReplayDialog-
|
|
2531
|
+
() => import("./ReplayDialog-B-YMhZkE.mjs").then((m) => ({ default: m.ReplayDialog }))
|
|
2479
2532
|
);
|
|
2480
2533
|
const LazyRequestAnatomy = reactExports.lazy(
|
|
2481
|
-
() => import("./RequestAnatomy-
|
|
2534
|
+
() => import("./RequestAnatomy-a9d8UTYZ.mjs").then((m) => ({ default: m.RequestAnatomy }))
|
|
2482
2535
|
);
|
|
2483
2536
|
const LazyResponseView = reactExports.lazy(
|
|
2484
|
-
() => import("./ResponseView-
|
|
2537
|
+
() => import("./ResponseView-PzaZS4CN.mjs").then((m) => ({ default: m.ResponseView }))
|
|
2485
2538
|
);
|
|
2486
2539
|
const LazyStreamingChunkSequence = reactExports.lazy(
|
|
2487
|
-
() => import("./StreamingChunkSequence-
|
|
2540
|
+
() => import("./StreamingChunkSequence-C21_TCXk.mjs").then((m) => ({
|
|
2488
2541
|
default: m.StreamingChunkSequence
|
|
2489
2542
|
}))
|
|
2490
2543
|
);
|
|
2491
2544
|
const LazyJsonViewer = reactExports.lazy(
|
|
2492
|
-
() => import("./json-viewer-
|
|
2545
|
+
() => import("./json-viewer-Di2gxs9H.mjs").then((m) => ({ default: m.JsonViewer }))
|
|
2493
2546
|
);
|
|
2494
2547
|
const LazyJsonViewerFromString = reactExports.lazy(
|
|
2495
|
-
() => import("./json-viewer-
|
|
2548
|
+
() => import("./json-viewer-Di2gxs9H.mjs").then((m) => ({ default: m.JsonViewerFromString }))
|
|
2496
2549
|
);
|
|
2497
2550
|
const HIGHLIGHT_DURATION_MS = 1200;
|
|
2498
2551
|
const MAX_HIGHLIGHT_ATTEMPTS = 12;
|
|
@@ -2951,6 +3004,58 @@ function Badge({
|
|
|
2951
3004
|
}
|
|
2952
3005
|
);
|
|
2953
3006
|
}
|
|
3007
|
+
const VISIBLE_TOOL_LIMIT = 3;
|
|
3008
|
+
function ToolTraceEventChip({ event }) {
|
|
3009
|
+
const handleClick = (clickEvent) => {
|
|
3010
|
+
clickEvent.stopPropagation();
|
|
3011
|
+
dispatchLogFocusRequest({
|
|
3012
|
+
logId: event.logId,
|
|
3013
|
+
tab: "response",
|
|
3014
|
+
toolCallIndex: event.index
|
|
3015
|
+
});
|
|
3016
|
+
};
|
|
3017
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3018
|
+
"button",
|
|
3019
|
+
{
|
|
3020
|
+
type: "button",
|
|
3021
|
+
className: "inline-flex h-5 min-w-0 max-w-[8.5rem] items-center rounded px-1.5 text-[10px] text-muted-foreground transition-colors hover:bg-background/65 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
3022
|
+
onClick: handleClick,
|
|
3023
|
+
onKeyDown: (keyEvent) => keyEvent.stopPropagation(),
|
|
3024
|
+
"aria-label": `Open response tool call ${event.name}`,
|
|
3025
|
+
title: event.name,
|
|
3026
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0 truncate font-mono font-semibold", children: event.name })
|
|
3027
|
+
}
|
|
3028
|
+
);
|
|
3029
|
+
}
|
|
3030
|
+
function ToolTraceEvents({ events }) {
|
|
3031
|
+
if (events.length === 0) return null;
|
|
3032
|
+
const visibleEvents = events.slice(0, VISIBLE_TOOL_LIMIT);
|
|
3033
|
+
const hiddenCount = Math.max(0, events.length - visibleEvents.length);
|
|
3034
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
3035
|
+
"span",
|
|
3036
|
+
{
|
|
3037
|
+
className: "inline-flex h-7 min-w-0 max-w-full items-center gap-1 overflow-hidden rounded-md border border-cyan-300/10 bg-cyan-300/[0.055] px-1 sm:max-w-[26rem]",
|
|
3038
|
+
role: "group",
|
|
3039
|
+
"aria-label": `${events.length} response tool ${events.length === 1 ? "call" : "calls"}`,
|
|
3040
|
+
onClick: (clickEvent) => clickEvent.stopPropagation(),
|
|
3041
|
+
onKeyDown: (keyEvent) => keyEvent.stopPropagation(),
|
|
3042
|
+
children: [
|
|
3043
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex h-5 shrink-0 items-center gap-1 px-1 font-mono text-[9px] font-semibold uppercase text-cyan-300", children: [
|
|
3044
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Wrench, { className: "size-3" }),
|
|
3045
|
+
"Call ",
|
|
3046
|
+
events.length
|
|
3047
|
+
] }),
|
|
3048
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 flex-1 items-center gap-0.5 overflow-hidden", children: [
|
|
3049
|
+
visibleEvents.map((event) => /* @__PURE__ */ jsxRuntimeExports.jsx(ToolTraceEventChip, { event }, event.id)),
|
|
3050
|
+
hiddenCount > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex h-5 shrink-0 items-center rounded px-1 font-mono text-[10px] font-semibold text-muted-foreground", children: [
|
|
3051
|
+
"+",
|
|
3052
|
+
hiddenCount
|
|
3053
|
+
] })
|
|
3054
|
+
] })
|
|
3055
|
+
]
|
|
3056
|
+
}
|
|
3057
|
+
);
|
|
3058
|
+
}
|
|
2954
3059
|
const STATUS_BADGE_CLASSES = {
|
|
2955
3060
|
success: "bg-slate-300/[0.08] text-slate-100 border-transparent",
|
|
2956
3061
|
client_error: "bg-amber-300/[0.10] text-amber-100 border-transparent",
|
|
@@ -3011,6 +3116,7 @@ const LogEntryHeader = reactExports.memo(function({
|
|
|
3011
3116
|
displayNumber,
|
|
3012
3117
|
messageCount = null,
|
|
3013
3118
|
toolCount = null,
|
|
3119
|
+
toolEvents = [],
|
|
3014
3120
|
expanded,
|
|
3015
3121
|
onToggle,
|
|
3016
3122
|
cacheTrend = null,
|
|
@@ -3195,6 +3301,7 @@ const LogEntryHeader = reactExports.memo(function({
|
|
|
3195
3301
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Wrench, { className: "size-3" }),
|
|
3196
3302
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", children: toolCount })
|
|
3197
3303
|
] }),
|
|
3304
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ToolTraceEvents, { events: toolEvents }),
|
|
3198
3305
|
log.origin !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
3199
3306
|
"span",
|
|
3200
3307
|
{
|
|
@@ -3869,7 +3976,8 @@ const LogEntry = reactExports.memo(function({
|
|
|
3869
3976
|
timeDisplayFormat,
|
|
3870
3977
|
cacheTrend = null,
|
|
3871
3978
|
onCompareWithPrevious,
|
|
3872
|
-
showClientMetadata = true
|
|
3979
|
+
showClientMetadata = true,
|
|
3980
|
+
toolEvents = []
|
|
3873
3981
|
}) {
|
|
3874
3982
|
const [expanded, setExpanded] = reactExports.useState(false);
|
|
3875
3983
|
const [replayOpen, setReplayOpen] = reactExports.useState(false);
|
|
@@ -4217,6 +4325,7 @@ const LogEntry = reactExports.memo(function({
|
|
|
4217
4325
|
displayNumber,
|
|
4218
4326
|
messageCount: requestAnalysis.messageCount,
|
|
4219
4327
|
toolCount: requestAnalysis.toolCount,
|
|
4328
|
+
toolEvents,
|
|
4220
4329
|
expanded,
|
|
4221
4330
|
onToggle: handleToggleExpanded,
|
|
4222
4331
|
cacheTrend,
|
|
@@ -4600,52 +4709,6 @@ function ThreadConnector({
|
|
|
4600
4709
|
) })
|
|
4601
4710
|
] });
|
|
4602
4711
|
}
|
|
4603
|
-
const VISIBLE_TOOL_LIMIT = 4;
|
|
4604
|
-
function ToolTraceEventChip({ event }) {
|
|
4605
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
4606
|
-
"button",
|
|
4607
|
-
{
|
|
4608
|
-
type: "button",
|
|
4609
|
-
className: "inline-flex h-6 max-w-[11rem] min-w-0 items-center gap-1 rounded-md bg-white/[0.028] px-1.5 text-[11px] text-muted-foreground transition-colors hover:bg-sky-400/[0.08] hover:text-sky-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
4610
|
-
onClick: () => dispatchLogFocusRequest({
|
|
4611
|
-
logId: event.logId,
|
|
4612
|
-
tab: "response",
|
|
4613
|
-
toolCallIndex: event.index
|
|
4614
|
-
}),
|
|
4615
|
-
"aria-label": `Open response tool call ${event.name}`,
|
|
4616
|
-
children: [
|
|
4617
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(Wrench, { className: "size-3 shrink-0 text-sky-400/65" }),
|
|
4618
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0 truncate font-mono font-semibold", children: event.name })
|
|
4619
|
-
]
|
|
4620
|
-
},
|
|
4621
|
-
event.id
|
|
4622
|
-
);
|
|
4623
|
-
}
|
|
4624
|
-
function ToolTraceEvents({
|
|
4625
|
-
events,
|
|
4626
|
-
warnings = []
|
|
4627
|
-
}) {
|
|
4628
|
-
if (events.length === 0 && warnings.length === 0) return null;
|
|
4629
|
-
const visibleEvents = events.slice(0, VISIBLE_TOOL_LIMIT);
|
|
4630
|
-
const hiddenCount = Math.max(0, events.length - visibleEvents.length);
|
|
4631
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mx-3 mb-2 flex min-w-0 items-center gap-1.5 overflow-hidden rounded-md bg-black/[0.10] px-2 py-1 shadow-[inset_0_1px_0_rgba(255,255,255,0.025)]", children: [
|
|
4632
|
-
events.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex h-6 shrink-0 items-center gap-1 rounded-md px-1.5 font-mono text-[10px] font-semibold uppercase tracking-[0.12em] text-sky-300/70", children: [
|
|
4633
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(Wrench, { className: "size-3" }),
|
|
4634
|
-
events.length
|
|
4635
|
-
] }),
|
|
4636
|
-
warnings.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex h-6 shrink-0 items-center gap-1 rounded-md border border-amber-300/20 bg-amber-300/[0.08] px-1.5 font-mono text-[10px] font-semibold text-amber-100", children: [
|
|
4637
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(TriangleAlert, { className: "size-3" }),
|
|
4638
|
-
warnings.length
|
|
4639
|
-
] }),
|
|
4640
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-1 overflow-hidden", children: [
|
|
4641
|
-
visibleEvents.map((event) => /* @__PURE__ */ jsxRuntimeExports.jsx(ToolTraceEventChip, { event }, event.id)),
|
|
4642
|
-
hiddenCount > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex h-6 shrink-0 items-center rounded-md bg-white/[0.025] px-1.5 font-mono text-[11px] font-semibold text-muted-foreground", children: [
|
|
4643
|
-
"+",
|
|
4644
|
-
hiddenCount
|
|
4645
|
-
] })
|
|
4646
|
-
] })
|
|
4647
|
-
] });
|
|
4648
|
-
}
|
|
4649
4712
|
const PREVIEW_LIMIT = 180;
|
|
4650
4713
|
const toolTraceCache = /* @__PURE__ */ new WeakMap();
|
|
4651
4714
|
function responseMayContainToolTrace(log, format) {
|
|
@@ -5161,29 +5224,21 @@ const TurnGroup = reactExports.memo(function TurnGroup2({
|
|
|
5161
5224
|
onToggle: toggleCollapse
|
|
5162
5225
|
}
|
|
5163
5226
|
),
|
|
5164
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
5172
|
-
|
|
5173
|
-
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5180
|
-
ToolTraceEvents,
|
|
5181
|
-
{
|
|
5182
|
-
events: toolEventsByLogId.get(log.id) ?? [],
|
|
5183
|
-
warnings: log.warnings ?? []
|
|
5184
|
-
}
|
|
5185
|
-
)
|
|
5186
|
-
] })
|
|
5227
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: cn("flex-1 min-w-0 mb-0.5 rounded-[8px]", bgClass), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5228
|
+
LogEntry,
|
|
5229
|
+
{
|
|
5230
|
+
log,
|
|
5231
|
+
displayNumber: entry.sessionLogNumber,
|
|
5232
|
+
viewMode,
|
|
5233
|
+
strip,
|
|
5234
|
+
slowResponseThresholdSeconds,
|
|
5235
|
+
timeDisplayFormat,
|
|
5236
|
+
cacheTrend: cacheTrends?.get(log.id) ?? null,
|
|
5237
|
+
showClientMetadata: showLogClientMetadata,
|
|
5238
|
+
toolEvents: toolEventsByLogId.get(log.id),
|
|
5239
|
+
onCompareWithPrevious: comparisonPredecessors.has(log.id) ? onCompareWithPrevious : void 0
|
|
5240
|
+
}
|
|
5241
|
+
) })
|
|
5187
5242
|
] }, log.id);
|
|
5188
5243
|
})
|
|
5189
5244
|
)
|
|
@@ -5314,7 +5369,7 @@ function formatElapsed$1(ms) {
|
|
|
5314
5369
|
if (ms < 1e3) return `${String(ms)}ms`;
|
|
5315
5370
|
return `${(ms / 1e3).toFixed(1)}s`;
|
|
5316
5371
|
}
|
|
5317
|
-
function formatTimeRange$
|
|
5372
|
+
function formatTimeRange$2(startedAt, endedAt, timeDisplayFormat) {
|
|
5318
5373
|
if (startedAt === null || endedAt === null) return null;
|
|
5319
5374
|
return formatTimestampRange(startedAt, endedAt, timeDisplayFormat);
|
|
5320
5375
|
}
|
|
@@ -5801,7 +5856,7 @@ function AgentTraceSummary({
|
|
|
5801
5856
|
);
|
|
5802
5857
|
const showElapsedSummary = showRollupMetrics || summary.maxElapsedMs !== null;
|
|
5803
5858
|
const timeRange = reactExports.useMemo(
|
|
5804
|
-
() => formatTimeRange$
|
|
5859
|
+
() => formatTimeRange$2(summary.startedAt, summary.endedAt, timeDisplayFormat),
|
|
5805
5860
|
[summary.endedAt, summary.startedAt, timeDisplayFormat]
|
|
5806
5861
|
);
|
|
5807
5862
|
const createCandidates = reactExports.useCallback(() => {
|
|
@@ -6167,152 +6222,451 @@ const ConversationGroup = reactExports.memo(function({
|
|
|
6167
6222
|
] })
|
|
6168
6223
|
] });
|
|
6169
6224
|
});
|
|
6170
|
-
function
|
|
6171
|
-
return
|
|
6172
|
-
"svg",
|
|
6173
|
-
{
|
|
6174
|
-
viewBox: "0 0 24 24",
|
|
6175
|
-
fill: "none",
|
|
6176
|
-
stroke: "currentColor",
|
|
6177
|
-
strokeWidth: "1.5",
|
|
6178
|
-
strokeLinecap: "round",
|
|
6179
|
-
strokeLinejoin: "round",
|
|
6180
|
-
"aria-hidden": "true",
|
|
6181
|
-
className: cn("inline-block size-5", className),
|
|
6182
|
-
children: [
|
|
6183
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M5 13 C5 9 8 7 12 7 C16 7 19 9 19 13 C19 16 16 18 12 18 C8 18 5 16 5 13 Z" }),
|
|
6184
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M5 11 C3.5 9.5 1.5 10 2 12.5 C2.5 14 4 13.5 5 12.5" }),
|
|
6185
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M19 11 C20.5 9.5 22.5 10 22 12.5 C21.5 14 20 13.5 19 12.5" }),
|
|
6186
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10", y1: "7", x2: "9.5", y2: "5" }),
|
|
6187
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14", y1: "7", x2: "14.5", y2: "5" }),
|
|
6188
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "9.5", cy: "4.5", r: "0.9", fill: "currentColor", stroke: "none" }),
|
|
6189
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "14.5", cy: "4.5", r: "0.9", fill: "currentColor", stroke: "none" }),
|
|
6190
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "6.5", y1: "16", x2: "4.5", y2: "19.5" }),
|
|
6191
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "9", y1: "17.5", x2: "8", y2: "20.5" }),
|
|
6192
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "15", y1: "17.5", x2: "16", y2: "20.5" }),
|
|
6193
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "17.5", y1: "16", x2: "19.5", y2: "19.5" })
|
|
6194
|
-
]
|
|
6195
|
-
}
|
|
6196
|
-
);
|
|
6225
|
+
function shouldShowRawExport(captureMode) {
|
|
6226
|
+
return captureMode === "full";
|
|
6197
6227
|
}
|
|
6198
|
-
|
|
6199
|
-
|
|
6200
|
-
return
|
|
6201
|
-
|
|
6202
|
-
|
|
6203
|
-
|
|
6204
|
-
alt: "Model Context Protocol",
|
|
6205
|
-
"aria-hidden": "true",
|
|
6206
|
-
className: cn("inline-block size-8 object-contain invert", className)
|
|
6207
|
-
}
|
|
6208
|
-
);
|
|
6228
|
+
function getExportActionVisibility(captureMode, logCount) {
|
|
6229
|
+
const hasLogs = logCount > 0;
|
|
6230
|
+
return {
|
|
6231
|
+
redacted: hasLogs,
|
|
6232
|
+
raw: hasLogs && shouldShowRawExport(captureMode)
|
|
6233
|
+
};
|
|
6209
6234
|
}
|
|
6210
|
-
function
|
|
6211
|
-
|
|
6212
|
-
|
|
6213
|
-
|
|
6235
|
+
function formatTimeRange$1(logs, timeDisplayFormat) {
|
|
6236
|
+
const first = logs[0];
|
|
6237
|
+
const last = logs[logs.length - 1];
|
|
6238
|
+
if (first === void 0 || last === void 0) return null;
|
|
6239
|
+
return formatTimestampRange(first.timestamp, last.timestamp, timeDisplayFormat);
|
|
6214
6240
|
}
|
|
6215
|
-
function
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue$1, { "data-slot": "select-value", ...props });
|
|
6241
|
+
function hasLogFailure(log) {
|
|
6242
|
+
if (log.error !== null && log.error !== void 0 && log.error.length > 0) return true;
|
|
6243
|
+
return log.responseStatus !== null && log.responseStatus >= 400;
|
|
6219
6244
|
}
|
|
6220
|
-
function
|
|
6221
|
-
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
|
|
6225
|
-
}) {
|
|
6226
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
6227
|
-
SelectTrigger$1,
|
|
6228
|
-
{
|
|
6229
|
-
"data-slot": "select-trigger",
|
|
6230
|
-
"data-size": size,
|
|
6231
|
-
className: cn(
|
|
6232
|
-
"border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
6233
|
-
className
|
|
6234
|
-
),
|
|
6235
|
-
...props,
|
|
6236
|
-
children: [
|
|
6237
|
-
children,
|
|
6238
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectIcon, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-4 opacity-50" }) })
|
|
6239
|
-
]
|
|
6245
|
+
function getModelLabel(logs) {
|
|
6246
|
+
const models = /* @__PURE__ */ new Set();
|
|
6247
|
+
for (const log of logs) {
|
|
6248
|
+
if (log.model !== null && log.model.length > 0) {
|
|
6249
|
+
models.add(log.model);
|
|
6240
6250
|
}
|
|
6241
|
-
|
|
6251
|
+
}
|
|
6252
|
+
const sorted = [...models].sort();
|
|
6253
|
+
if (sorted.length === 0) return "Model unknown";
|
|
6254
|
+
if (sorted.length === 1) return sorted[0] ?? "Model unknown";
|
|
6255
|
+
return `${sorted.length} models`;
|
|
6242
6256
|
}
|
|
6243
|
-
function
|
|
6244
|
-
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6248
|
-
...props
|
|
6249
|
-
}) {
|
|
6250
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(SelectPortal, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
6251
|
-
SelectContent$1,
|
|
6252
|
-
{
|
|
6253
|
-
"data-slot": "select-content",
|
|
6254
|
-
className: cn(
|
|
6255
|
-
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md",
|
|
6256
|
-
position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
|
6257
|
-
className
|
|
6258
|
-
),
|
|
6259
|
-
position,
|
|
6260
|
-
align,
|
|
6261
|
-
...props,
|
|
6262
|
-
children: [
|
|
6263
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectScrollUpButton, {}),
|
|
6264
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
6265
|
-
SelectViewport,
|
|
6266
|
-
{
|
|
6267
|
-
className: cn(
|
|
6268
|
-
"p-1",
|
|
6269
|
-
position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1"
|
|
6270
|
-
),
|
|
6271
|
-
children
|
|
6272
|
-
}
|
|
6273
|
-
),
|
|
6274
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectScrollDownButton, {})
|
|
6275
|
-
]
|
|
6257
|
+
function getProviderLabel(logs) {
|
|
6258
|
+
const providers = /* @__PURE__ */ new Set();
|
|
6259
|
+
for (const log of logs) {
|
|
6260
|
+
if (log.providerName !== null && log.providerName !== void 0 && log.providerName.length > 0) {
|
|
6261
|
+
providers.add(log.providerName);
|
|
6276
6262
|
}
|
|
6277
|
-
|
|
6263
|
+
}
|
|
6264
|
+
const sorted = [...providers].sort();
|
|
6265
|
+
if (sorted.length === 0) return "Provider unknown";
|
|
6266
|
+
if (sorted.length === 1) return sorted[0] ?? "Provider unknown";
|
|
6267
|
+
return `${sorted.length} providers`;
|
|
6278
6268
|
}
|
|
6279
|
-
function
|
|
6280
|
-
|
|
6281
|
-
|
|
6282
|
-
|
|
6283
|
-
|
|
6284
|
-
|
|
6285
|
-
|
|
6286
|
-
|
|
6287
|
-
|
|
6288
|
-
|
|
6289
|
-
"focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
|
|
6290
|
-
className
|
|
6291
|
-
),
|
|
6292
|
-
...props,
|
|
6293
|
-
children: [
|
|
6294
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "absolute right-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItemIndicator, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-4" }) }) }),
|
|
6295
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectItemText, { children })
|
|
6296
|
-
]
|
|
6297
|
-
}
|
|
6298
|
-
);
|
|
6269
|
+
function formatElapsedMs(ms) {
|
|
6270
|
+
if (ms < 1e3) return `${ms}ms`;
|
|
6271
|
+
if (ms < 6e4) {
|
|
6272
|
+
const seconds2 = ms / 1e3;
|
|
6273
|
+
return `${seconds2 < 10 ? seconds2.toFixed(1) : seconds2.toFixed(0)}s`;
|
|
6274
|
+
}
|
|
6275
|
+
const totalSeconds = Math.round(ms / 1e3);
|
|
6276
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
6277
|
+
const seconds = totalSeconds % 60;
|
|
6278
|
+
return `${minutes}m ${seconds}s`;
|
|
6299
6279
|
}
|
|
6300
|
-
function
|
|
6301
|
-
|
|
6302
|
-
...props
|
|
6303
|
-
}) {
|
|
6304
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
6305
|
-
SelectScrollUpButton$1,
|
|
6306
|
-
{
|
|
6307
|
-
"data-slot": "select-scroll-up-button",
|
|
6308
|
-
className: cn("flex cursor-default items-center justify-center py-1", className),
|
|
6309
|
-
...props,
|
|
6310
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronUp, { className: "size-4" })
|
|
6311
|
-
}
|
|
6312
|
-
);
|
|
6280
|
+
function formatTokenPair(inputTokens, outputTokens) {
|
|
6281
|
+
return `${formatTokens(inputTokens)} in / ${formatTokens(outputTokens)} out`;
|
|
6313
6282
|
}
|
|
6314
|
-
function
|
|
6315
|
-
|
|
6283
|
+
function countSessionTurns(logs, conversationGroups) {
|
|
6284
|
+
if (logs.length === 0) return 0;
|
|
6285
|
+
if (conversationGroups.length === 0) return buildTurnGroups(logs).length;
|
|
6286
|
+
let turns = 0;
|
|
6287
|
+
for (const group of conversationGroups) {
|
|
6288
|
+
turns += buildTurnGroups(group.logs).length;
|
|
6289
|
+
}
|
|
6290
|
+
return turns;
|
|
6291
|
+
}
|
|
6292
|
+
function summarizeFinishReason({
|
|
6293
|
+
stopReason,
|
|
6294
|
+
pending,
|
|
6295
|
+
lastFailureLogNumber
|
|
6296
|
+
}) {
|
|
6297
|
+
if (pending > 0) {
|
|
6298
|
+
return {
|
|
6299
|
+
label: "In flight",
|
|
6300
|
+
detail: `${pending} request${pending === 1 ? "" : "s"} pending`,
|
|
6301
|
+
tone: "cool"
|
|
6302
|
+
};
|
|
6303
|
+
}
|
|
6304
|
+
if (lastFailureLogNumber !== null && stopReason === null) {
|
|
6305
|
+
return {
|
|
6306
|
+
label: "Error",
|
|
6307
|
+
detail: `Last failed request #${lastFailureLogNumber}`,
|
|
6308
|
+
tone: "danger"
|
|
6309
|
+
};
|
|
6310
|
+
}
|
|
6311
|
+
switch (stopReason) {
|
|
6312
|
+
case "end_turn":
|
|
6313
|
+
return { label: "End turn", detail: "Assistant completed the turn", tone: "neutral" };
|
|
6314
|
+
case "stop":
|
|
6315
|
+
return { label: "Stop", detail: "Model reached a stop condition", tone: "neutral" };
|
|
6316
|
+
case "length":
|
|
6317
|
+
return { label: "Output limit", detail: "Turn ended at max output tokens", tone: "watch" };
|
|
6318
|
+
case "tool_use":
|
|
6319
|
+
return { label: "Tool call", detail: "Assistant requested a tool", tone: "cool" };
|
|
6320
|
+
case null:
|
|
6321
|
+
return { label: "Unknown", detail: "No finish reason captured", tone: "neutral" };
|
|
6322
|
+
}
|
|
6323
|
+
}
|
|
6324
|
+
function isClientAbortError(error) {
|
|
6325
|
+
if (error === null) return false;
|
|
6326
|
+
const lower = error.toLowerCase();
|
|
6327
|
+
return lower.includes("abort") || lower.includes("cancel") || lower.includes("client disconnected") || lower.includes("stream disconnected") || lower.includes("connection closed");
|
|
6328
|
+
}
|
|
6329
|
+
function summarizeSessionOutcome({
|
|
6330
|
+
pending,
|
|
6331
|
+
failures,
|
|
6332
|
+
lengthStops,
|
|
6333
|
+
stopReason,
|
|
6334
|
+
lastFailure
|
|
6335
|
+
}) {
|
|
6336
|
+
if (lastFailure !== null && (lastFailure.status === 499 || isClientAbortError(lastFailure.error))) {
|
|
6337
|
+
return {
|
|
6338
|
+
label: "Client aborted",
|
|
6339
|
+
detail: `Request #${lastFailure.logNumber} ended before completion`,
|
|
6340
|
+
tone: "watch"
|
|
6341
|
+
};
|
|
6342
|
+
}
|
|
6343
|
+
if (pending > 0) {
|
|
6344
|
+
return {
|
|
6345
|
+
label: "In flight",
|
|
6346
|
+
detail: `${pending} request${pending === 1 ? "" : "s"} still running`,
|
|
6347
|
+
tone: "cool"
|
|
6348
|
+
};
|
|
6349
|
+
}
|
|
6350
|
+
if (lastFailure !== null && lastFailure.status !== null && lastFailure.status >= 500) {
|
|
6351
|
+
return {
|
|
6352
|
+
label: "Provider error",
|
|
6353
|
+
detail: `Request #${lastFailure.logNumber} returned HTTP ${lastFailure.status}`,
|
|
6354
|
+
tone: "danger"
|
|
6355
|
+
};
|
|
6356
|
+
}
|
|
6357
|
+
if (failures > 0 && lastFailure !== null) {
|
|
6358
|
+
return {
|
|
6359
|
+
label: "Failed",
|
|
6360
|
+
detail: `Request #${lastFailure.logNumber} needs attention`,
|
|
6361
|
+
tone: "danger"
|
|
6362
|
+
};
|
|
6363
|
+
}
|
|
6364
|
+
if (lengthStops > 0 || stopReason === "length") {
|
|
6365
|
+
return {
|
|
6366
|
+
label: "Output limited",
|
|
6367
|
+
detail: "Model stopped at the output token limit",
|
|
6368
|
+
tone: "watch"
|
|
6369
|
+
};
|
|
6370
|
+
}
|
|
6371
|
+
switch (stopReason) {
|
|
6372
|
+
case "end_turn":
|
|
6373
|
+
case "stop":
|
|
6374
|
+
return { label: "Completed", detail: "Assistant completed normally", tone: "neutral" };
|
|
6375
|
+
case "tool_use":
|
|
6376
|
+
return { label: "Tool requested", detail: "Assistant handed off to a tool", tone: "cool" };
|
|
6377
|
+
case null:
|
|
6378
|
+
return { label: "Unknown", detail: "No terminal signal captured", tone: "neutral" };
|
|
6379
|
+
}
|
|
6380
|
+
}
|
|
6381
|
+
function buildSessionSlateStats({
|
|
6382
|
+
logs,
|
|
6383
|
+
conversationGroups,
|
|
6384
|
+
isLoading,
|
|
6385
|
+
timeDisplayFormat,
|
|
6386
|
+
slowResponseThresholdSeconds
|
|
6387
|
+
}) {
|
|
6388
|
+
let failures = 0;
|
|
6389
|
+
let pending = 0;
|
|
6390
|
+
let slow = 0;
|
|
6391
|
+
let lengthStops = 0;
|
|
6392
|
+
let totalIn = 0;
|
|
6393
|
+
let totalOut = 0;
|
|
6394
|
+
let terminalStopReason = null;
|
|
6395
|
+
let lastFailureLogNumber = null;
|
|
6396
|
+
let lastFailure = null;
|
|
6397
|
+
let slowestMs = null;
|
|
6398
|
+
let slowestLogNumber = null;
|
|
6399
|
+
let heaviestTokens = 0;
|
|
6400
|
+
let heaviestInputTokens = 0;
|
|
6401
|
+
let heaviestOutputTokens = 0;
|
|
6402
|
+
let heaviestLogNumber = null;
|
|
6403
|
+
const slowThresholdMs = slowResponseThresholdSeconds * 1e3;
|
|
6404
|
+
for (let index = 0; index < logs.length; index += 1) {
|
|
6405
|
+
const log = logs[index];
|
|
6406
|
+
if (log === void 0) continue;
|
|
6407
|
+
const logNumber = index + 1;
|
|
6408
|
+
const stopReason = extractStopReason(log);
|
|
6409
|
+
if (stopReason !== null) terminalStopReason = stopReason;
|
|
6410
|
+
if (stopReason === "length") lengthStops += 1;
|
|
6411
|
+
if (hasLogFailure(log)) {
|
|
6412
|
+
failures += 1;
|
|
6413
|
+
lastFailureLogNumber = logNumber;
|
|
6414
|
+
lastFailure = {
|
|
6415
|
+
logNumber,
|
|
6416
|
+
status: log.responseStatus,
|
|
6417
|
+
error: log.error ?? null
|
|
6418
|
+
};
|
|
6419
|
+
}
|
|
6420
|
+
if (log.responseStatus === null) pending += 1;
|
|
6421
|
+
if (slowResponseThresholdSeconds > 0 && log.elapsedMs !== null && log.elapsedMs >= slowThresholdMs) {
|
|
6422
|
+
slow += 1;
|
|
6423
|
+
}
|
|
6424
|
+
if (log.inputTokens !== null) totalIn += log.inputTokens;
|
|
6425
|
+
if (log.outputTokens !== null) totalOut += log.outputTokens;
|
|
6426
|
+
if (log.elapsedMs !== null && (slowestMs === null || log.elapsedMs > slowestMs)) {
|
|
6427
|
+
slowestMs = log.elapsedMs;
|
|
6428
|
+
slowestLogNumber = logNumber;
|
|
6429
|
+
}
|
|
6430
|
+
const inputTokens = log.inputTokens ?? 0;
|
|
6431
|
+
const outputTokens = log.outputTokens ?? 0;
|
|
6432
|
+
const requestTokens = inputTokens + outputTokens;
|
|
6433
|
+
if (requestTokens > heaviestTokens) {
|
|
6434
|
+
heaviestTokens = requestTokens;
|
|
6435
|
+
heaviestInputTokens = inputTokens;
|
|
6436
|
+
heaviestOutputTokens = outputTokens;
|
|
6437
|
+
heaviestLogNumber = logNumber;
|
|
6438
|
+
}
|
|
6439
|
+
}
|
|
6440
|
+
const status = isLoading || pending > 0 && failures === 0 ? "rolling" : failures > 0 ? "failed" : slow > 0 || lengthStops > 0 ? "watch" : "clear";
|
|
6441
|
+
const statusLabel2 = status === "rolling" ? "Rolling" : status === "failed" ? "Failure" : status === "watch" ? "Watch" : "Clear";
|
|
6442
|
+
const finish = summarizeFinishReason({
|
|
6443
|
+
stopReason: terminalStopReason,
|
|
6444
|
+
pending,
|
|
6445
|
+
lastFailureLogNumber
|
|
6446
|
+
});
|
|
6447
|
+
const outcome = summarizeSessionOutcome({
|
|
6448
|
+
pending,
|
|
6449
|
+
failures,
|
|
6450
|
+
lengthStops,
|
|
6451
|
+
stopReason: terminalStopReason,
|
|
6452
|
+
lastFailure
|
|
6453
|
+
});
|
|
6454
|
+
return {
|
|
6455
|
+
status,
|
|
6456
|
+
statusLabel: statusLabel2,
|
|
6457
|
+
modelLabel: getModelLabel(logs),
|
|
6458
|
+
providerLabel: getProviderLabel(logs),
|
|
6459
|
+
requests: logs.length,
|
|
6460
|
+
turns: countSessionTurns(logs, conversationGroups),
|
|
6461
|
+
failures,
|
|
6462
|
+
pending,
|
|
6463
|
+
slow,
|
|
6464
|
+
lengthStops,
|
|
6465
|
+
timeRange: formatTimeRange$1(logs, timeDisplayFormat),
|
|
6466
|
+
tokenLabel: `${formatTokens(totalIn)} in / ${formatTokens(totalOut)} out`,
|
|
6467
|
+
finishLabel: finish.label,
|
|
6468
|
+
finishDetail: finish.detail,
|
|
6469
|
+
finishTone: finish.tone,
|
|
6470
|
+
outcomeLabel: outcome.label,
|
|
6471
|
+
outcomeDetail: outcome.detail,
|
|
6472
|
+
outcomeTone: outcome.tone,
|
|
6473
|
+
slowestLabel: slowestMs === null ? "n/a" : formatElapsedMs(slowestMs),
|
|
6474
|
+
slowestDetail: slowestLogNumber === null ? "Latency pending" : `Request #${slowestLogNumber}`,
|
|
6475
|
+
heaviestDetail: heaviestLogNumber === null ? "Tokens pending" : `#${heaviestLogNumber} ${formatTokenPair(heaviestInputTokens, heaviestOutputTokens)}`
|
|
6476
|
+
};
|
|
6477
|
+
}
|
|
6478
|
+
function resolveSessionContextScope({
|
|
6479
|
+
pinnedSessionId,
|
|
6480
|
+
selectedSession,
|
|
6481
|
+
sessions,
|
|
6482
|
+
logs
|
|
6483
|
+
}) {
|
|
6484
|
+
if (pinnedSessionId !== void 0) {
|
|
6485
|
+
const scopedLogs = logs.filter((log) => log.sessionId === pinnedSessionId);
|
|
6486
|
+
if (scopedLogs.length === 0) return null;
|
|
6487
|
+
return { label: pinnedSessionId, logs: scopedLogs, showBackLink: true };
|
|
6488
|
+
}
|
|
6489
|
+
if (selectedSession !== "__all__") {
|
|
6490
|
+
const scopedLogs = logs.filter((log) => log.sessionId === selectedSession);
|
|
6491
|
+
if (scopedLogs.length === 0) return null;
|
|
6492
|
+
return { label: selectedSession, logs: scopedLogs, showBackLink: true };
|
|
6493
|
+
}
|
|
6494
|
+
const singleSessionId = sessions.length === 1 ? sessions[0] ?? null : null;
|
|
6495
|
+
if (singleSessionId !== null) {
|
|
6496
|
+
const allVisibleLogsBelongToSession = logs.every((log) => log.sessionId === singleSessionId);
|
|
6497
|
+
if (allVisibleLogsBelongToSession) {
|
|
6498
|
+
return { label: singleSessionId, logs: [...logs], showBackLink: false };
|
|
6499
|
+
}
|
|
6500
|
+
}
|
|
6501
|
+
const allVisibleLogsAreSessionless = sessions.length === 0 && logs.length > 0 && logs.every((log) => log.sessionId === null);
|
|
6502
|
+
if (allVisibleLogsAreSessionless) {
|
|
6503
|
+
return { label: "Visible requests", logs: [...logs], showBackLink: false };
|
|
6504
|
+
}
|
|
6505
|
+
return null;
|
|
6506
|
+
}
|
|
6507
|
+
function formatPaginationStatus({
|
|
6508
|
+
logs,
|
|
6509
|
+
pagination
|
|
6510
|
+
}) {
|
|
6511
|
+
if (pagination.isLoading && logs.length === 0) return "Loading logs...";
|
|
6512
|
+
if (logs.length === 0) return "No logs on this page";
|
|
6513
|
+
const first = logs[0];
|
|
6514
|
+
const last = logs[logs.length - 1];
|
|
6515
|
+
const range = first === void 0 || last === void 0 ? "Current page" : `#${first.id}-#${last.id}`;
|
|
6516
|
+
if (pagination.total === null) {
|
|
6517
|
+
return `Showing ${logs.length} logs (${range})`;
|
|
6518
|
+
}
|
|
6519
|
+
if (pagination.total <= logs.length) {
|
|
6520
|
+
return `Showing all ${pagination.total} logs`;
|
|
6521
|
+
}
|
|
6522
|
+
return `Showing ${logs.length} of ${pagination.total} logs (${range})`;
|
|
6523
|
+
}
|
|
6524
|
+
function CrabLogo({ className }) {
|
|
6525
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
6526
|
+
"svg",
|
|
6527
|
+
{
|
|
6528
|
+
viewBox: "0 0 24 24",
|
|
6529
|
+
fill: "none",
|
|
6530
|
+
stroke: "currentColor",
|
|
6531
|
+
strokeWidth: "1.5",
|
|
6532
|
+
strokeLinecap: "round",
|
|
6533
|
+
strokeLinejoin: "round",
|
|
6534
|
+
"aria-hidden": "true",
|
|
6535
|
+
className: cn("inline-block size-5", className),
|
|
6536
|
+
children: [
|
|
6537
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M5 13 C5 9 8 7 12 7 C16 7 19 9 19 13 C19 16 16 18 12 18 C8 18 5 16 5 13 Z" }),
|
|
6538
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M5 11 C3.5 9.5 1.5 10 2 12.5 C2.5 14 4 13.5 5 12.5" }),
|
|
6539
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M19 11 C20.5 9.5 22.5 10 22 12.5 C21.5 14 20 13.5 19 12.5" }),
|
|
6540
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10", y1: "7", x2: "9.5", y2: "5" }),
|
|
6541
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14", y1: "7", x2: "14.5", y2: "5" }),
|
|
6542
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "9.5", cy: "4.5", r: "0.9", fill: "currentColor", stroke: "none" }),
|
|
6543
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "14.5", cy: "4.5", r: "0.9", fill: "currentColor", stroke: "none" }),
|
|
6544
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "6.5", y1: "16", x2: "4.5", y2: "19.5" }),
|
|
6545
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "9", y1: "17.5", x2: "8", y2: "20.5" }),
|
|
6546
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "15", y1: "17.5", x2: "16", y2: "20.5" }),
|
|
6547
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "17.5", y1: "16", x2: "19.5", y2: "19.5" })
|
|
6548
|
+
]
|
|
6549
|
+
}
|
|
6550
|
+
);
|
|
6551
|
+
}
|
|
6552
|
+
const McpLogoPng = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6CAQAAAAi5ZK2AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfpCxsJDCnsge2KAAAM2ElEQVR42u2de3AW1RnGnyQQDARDwiUFpHIVMHIpYgFRB2nLxQrC0FIDiCKDWNqBUqBlai8wvciIpaRTWh3QDqCDIIjKDL0IaBC5SKlysWJArgqh3BMICYFs/wgpGUi+8579dr89e/Z5zp/59j2755fn3d2z5wJQFEVRFEVRoVQSm+AG1UFrtEdT1EcjNEA5SlCMIhxDAQoJ3S4lIwf9cD+6ozXq1vKbYuzHNmxEPo6xwcKtungIS3EajkYpwLPoyqYLp3KwACe1cFcvezATmWzEMOk+rMBV18CrSjHy0IqNGQb1wMa4cV8vZfgzGrNRTVYm8nDFQ+SV5QymIIWNa6ZGaz6y6ZR/I4cNbJrSkOcb8MpyCVPYzCapKz71GXllWY5b2dhm6EGcTwhyBw52oyUbPHgNx6WEIXfg4CDuYKMHq0kevI/rlhP4Ghs+OE1ERcKRO3BwEh3Z+NFC7sDBATQngMRrcoDIHTj4iE/yUXJ5VVlhYsMkWezy+a6urgRbsAP7cRincQGpqI+maI+O6IMuSHYRbwIW0X/mJvZTeAH9ah1CATTCaKxBmWbUi7iTOMxEXoCncIsodgvM1ezo2cFPMebdy89qfyHL0vxSN5FQzHL5ajRxVU8v7NO4cWQRjCnIy/DDOOq6FcvENS0gGjMS+wUMjvvdZ5awrsv4KvEE7/Iz+Lontc4Q1vc8AQXt8rO4x7Oa54hqLOLI2aBdfrenHVyviWqdQUx2uLxS6fhMUO8ugrLD5VXqLfpmfxdh2eHyKi0S1P5b4rLF5ZVqiiJl/Z8SmD0ur9TzgnNoQWi2uLxSt+Gy8ixGEpvZLs9AN3RGqsYRa5Xn8SeCM9XlDfFT7Ll2bDnWYYRwOMZjyjP5kOjMdPkDOHpTjPX4iuDILOWL2znCMxH5IyitMc4+ZAuO3q08nyYEaFpiHxbjYWyDIMm/qDyje4kwPMgdOBihjDBNeU7fJcQwIXewTnBzUJ3Vk8Rozr18mOAtuxT1FFH6KmNMJkhTkH+7lse3G0s7RZyuygjPEGVYEntV6aSIlKOM8CvCDEtirywVyFDE6q2M8WPiDJPLJcMgBiljPEWg4XG5AwfTlfEmKWPkEml4XO7gCBooI85TRvlm8I1ax3CX68w8PYeB2KGFfEWM6Yo3qgy5uKj8VU/lLz5HG2QjHRlIA1CCIhTjBI6ggg43LbGXYYggZj3lgkYVtbwaluITvIlf4gHhNEomdheJXfpeXoX8EVHUAR4sY1CKfEyN5gibMCIHXvJsBYur2IDxSCNy05HXx1mPFy/5L2ZFZb6rGR2uusiByb6sWlOMZ5FOl5vocqAuDvm2XNExjLV5t52wuhyY7vM6Ve+jA11uksuB5glYcLgIY+hyc1yeJBj87E35q6BXkC5PAHJgdgKXI9xlzzt8eF0OjE/wypQH7Li7h9nl4wJYjPQ4utPlwSF/LKD1Z8+gC10eLeQOHHyJ1nR54pGPCniVadmcGyK3xOVVZYvWnNpqb5hBIv+L1hCJAdiuhXyVcpT6dV3GSLylhXyxy7YrxHYU4CBO4yKABmiCNuiIe9DMVbT5mMp7eWJc/rgLl1dgC6bE2NelM6Zim4uoDzOxm5nYS/GicNOuznhJc0X5k2HprIkS8gos1cTSSrgYodFbhkQ5sR/F/a7aqD8Oa9TSny43x+UblDNialcmVovr2WP2qOYoIV8V57tREuaK6/o+E7sJid2bO+00Ya0HTPV6lFy+3LNWmymsMZfIg+1w9fZ5ep6ozp3mjaKjy90rGetF9d5H5Ha4vFLZOB62zYGIPH6NEk2NqEvk4U/s1V/f8gX1DyJye5ADQC/BGfyRyO1I7Nf1rvIcPiZye1xeqaGCua6ZNiMf7sOSAolD3h+v4otrH2RewYPCo1JxWnkmQ4jcROTZNcyGWSMcN7PQ5KUJw4zc33t5G+xHzfu3S7655wqmPRG5ccgPxxjkqN7DvbnyfDYRuVmJvY1iYMQEQYxCxRkVEnlYXF5ZdguibFLEKI/6S9pQg1x+Ow4IYrZSxlmqjJFGl4fF5dLVJBcoYzQl8jDcy3XestV7tbcl8vC43IGD3spo6gEVtxF5mJCXCu7H6u6ZRlFE/nAoE7sDB8sEEd9URqkTfuT2P7FXlSuiZQb2KKKU0OXhcbmDGYKYdZWrTO8l8nDcyx04mCeKqh5IsYaJPRyJ3cEfhHFnePTPQ+ShQQ68r4z1NJEHkdj9Q95KcN7didwmlwOzBC2dTOT2uByoj5PBPcbR5UEgly0tPo3I7XE5kI1zgoVOWhO5PS4HXhHE/IDI7XE5MFIU9QdEbo/LO6NIEPWS98Mn/F04pD+R16oWOCiK+4LXyMf4irwnin1ErrtWzGtGIW+MXcJvdB4v/H87LvqIvL1yWG90XZ6J7UHNpVvoI/KGKPDxS5q/Lm/ry5e06i7/SBi5HHd5izxVI/nqIpcM6aXL1WW+1z7v6SPyJ0I7RMJvl+sgP+H9uLihviFvp5FDmNhrL096/34+2Jf3cgBYw8TuAfI3/OiHu8MXl+tsMM97ee3lKBr7AT1JuVuwG+Sp2EvkcSMvR1+/PqbO9Bw5MIn38rgTu69rP6fFeJd2hzwFn/OJPU6XO5gNX5VTy6iNk66QA4+KLqoCY5nYay0L4bs6YedN1e5EJ5fRdogu60dM7DE+/SZk+lIqxmMzrl5br2wzxrvbCA5Ad9FlraTLay2vJ3YV2DS0Rds4VzuYI7isQ1q9TNG6l79uzsK/8ldAyffhYRoRwz0qJgLIgT6CC/uHMcjpck/0c8Gl9aHLbUIO/FN5aflEbhfyOoJBfrlEbhNyydf5C0jnvdwm5MAY5eWtInK7kAOzlRc4mYndLuTAq8pL7KGMMTzUXTGGdrj6qc2KS7yq7O27E1fYxx4ufaK4yCOK41M0ofg7dYHIRVIh2xr3gyBdbpxUW8+8ozh+PV0ePqkmSK1RJPdLhrj890Qu1ynFxa6PeXRTQ76X871cS6rPqh/GPDrLiJc0ulxTqgVtj8U8OglneS8Pn9RrHjaMefwbvJeHT4vj/JY+iMjDJ/UQip8oIqyNcewyJnYT9T3lpf9NEaEJPqvlyEV0uZnqKpjVkqWIkV3DTuKlmusfE3kClYwzygaYIIiSi03XxuA7OIF5aE7kJuttZRPsQpIoUga64W601l75mF0xCZdkYdvBPtZP5AGom6Ahtvu2brnfiZ3IXfbKye7rdHmo9AtBc5zyYftIujxAtRONcduIFLrcJm3wpdmDdfm/iDy2BgqbZnpoXE7kSiUJOy8qMNWD2nJwlC43QY+Km+i5OF/fHhD0ARJ5grpjt4qbaT1auM4oU1DGxG6Oev2/71xdCpEr7Jqtro5YpwWELk+AXtZqsHz01ojdDHM1PU7kCVEznNDEko8RuEXQ0bsAJZqRiTxhGqQ5FdGBg3NYgsfRpoZoDTEIv8N/tCNGDnlSwPU/hxkujyzCPhzBOZQiBY3QFB3i6Lidp7lhZSbe0VorcyVGoZwer1JdbHHlTC8LE3vC1US8CLg/xf+XtDqEfLPa4BiRR0/dBXsGhzOxE3kMdcGXCUc+h8iDT/IFCQR+BROJ3ARlaw5DcF8uYAiRm6J6yHPRXaNb9mhvUknkPmuocuGC+MoS1Cdy89QSK3wCvg8PaZ8NkSdM/YT7hsvLRcwSfKwh8kBVB08LN/JSlxIscNUzT+QBKBlDsC1O4OeR53LkDZEHqN7Ic9VRW4a3kav92EbkxigF38BcbEO5CMBhLME45Tz3yCJPChn8dPRBF7RHB3RARrVtvC6hGIewHwUowBYcirMW/e/lubhCZybunyALmR7/6zKxR05ETuRETuRETuRsNCKniJwicorIKSKniJwicorIKSKniJyqGfnHmvsyE3nIlRJzHxi63ErlEXnUNI6JPWrKUO7rTJdbp98QedSUjWIm9qjpGSKPnrYysUdNzYRLEBO5RRrLxF6p5AhB7yz4zUqMtn+CUpSgZyt/sZpz0mzTWuXU5sbRaIgoOT1T8fdCnCZ026RC2lJzQ25CD4EKFX9PwWLUI/RoQQe+hbdcrEBFGazRovf0tdFwe1SUJVyx5u90u03aKOx7J3aLNEP8lY1J3ho10hg3Q7dbo59pjJwhdkvUAMeJPXr6jtY2Ary3W6Jfaw2CptutUJLmJgLEboXSsUkLO5O8JQ9079LtxE7sxE7sxE7sFqkhH+mIXV1WhG43DMoD7OPZZNHD/gWnPUUR+4BwX2wyeQMAijEYH4h/fS+hRw97c0K3B/tAvCf6ZRmh26OLGCpy+wE2VfQe6XLYTFHD/h6bKGrYy9CDDWQr9vwakV/FE2wce5WGl29CfgrD2TC2qy+W4/w14Hsxy5aVKvjFSN1CLVAPp1DEpqAoiqIoyiz9D9lYMumhgrvLAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDI1LTExLTI3VDA5OjEyOjQxKzAwOjAwvIZCxQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyNS0xMS0yN1QwOToxMjo0MSswMDowMM3b+nkAAAAASUVORK5CYII=";
|
|
6553
|
+
function McpLogo({ className }) {
|
|
6554
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
6555
|
+
"img",
|
|
6556
|
+
{
|
|
6557
|
+
src: McpLogoPng,
|
|
6558
|
+
alt: "Model Context Protocol",
|
|
6559
|
+
"aria-hidden": "true",
|
|
6560
|
+
className: cn("inline-block size-8 object-contain invert", className)
|
|
6561
|
+
}
|
|
6562
|
+
);
|
|
6563
|
+
}
|
|
6564
|
+
function Select({
|
|
6565
|
+
...props
|
|
6566
|
+
}) {
|
|
6567
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Select$1, { "data-slot": "select", ...props });
|
|
6568
|
+
}
|
|
6569
|
+
function SelectValue({
|
|
6570
|
+
...props
|
|
6571
|
+
}) {
|
|
6572
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue$1, { "data-slot": "select-value", ...props });
|
|
6573
|
+
}
|
|
6574
|
+
function SelectTrigger({
|
|
6575
|
+
className,
|
|
6576
|
+
size = "default",
|
|
6577
|
+
children,
|
|
6578
|
+
...props
|
|
6579
|
+
}) {
|
|
6580
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
6581
|
+
SelectTrigger$1,
|
|
6582
|
+
{
|
|
6583
|
+
"data-slot": "select-trigger",
|
|
6584
|
+
"data-size": size,
|
|
6585
|
+
className: cn(
|
|
6586
|
+
"border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
6587
|
+
className
|
|
6588
|
+
),
|
|
6589
|
+
...props,
|
|
6590
|
+
children: [
|
|
6591
|
+
children,
|
|
6592
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectIcon, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-4 opacity-50" }) })
|
|
6593
|
+
]
|
|
6594
|
+
}
|
|
6595
|
+
);
|
|
6596
|
+
}
|
|
6597
|
+
function SelectContent({
|
|
6598
|
+
className,
|
|
6599
|
+
children,
|
|
6600
|
+
position = "popper",
|
|
6601
|
+
align = "center",
|
|
6602
|
+
...props
|
|
6603
|
+
}) {
|
|
6604
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(SelectPortal, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
6605
|
+
SelectContent$1,
|
|
6606
|
+
{
|
|
6607
|
+
"data-slot": "select-content",
|
|
6608
|
+
className: cn(
|
|
6609
|
+
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md",
|
|
6610
|
+
position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
|
6611
|
+
className
|
|
6612
|
+
),
|
|
6613
|
+
position,
|
|
6614
|
+
align,
|
|
6615
|
+
...props,
|
|
6616
|
+
children: [
|
|
6617
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectScrollUpButton, {}),
|
|
6618
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
6619
|
+
SelectViewport,
|
|
6620
|
+
{
|
|
6621
|
+
className: cn(
|
|
6622
|
+
"p-1",
|
|
6623
|
+
position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1"
|
|
6624
|
+
),
|
|
6625
|
+
children
|
|
6626
|
+
}
|
|
6627
|
+
),
|
|
6628
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectScrollDownButton, {})
|
|
6629
|
+
]
|
|
6630
|
+
}
|
|
6631
|
+
) });
|
|
6632
|
+
}
|
|
6633
|
+
function SelectItem({
|
|
6634
|
+
className,
|
|
6635
|
+
children,
|
|
6636
|
+
...props
|
|
6637
|
+
}) {
|
|
6638
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
6639
|
+
SelectItem$1,
|
|
6640
|
+
{
|
|
6641
|
+
"data-slot": "select-item",
|
|
6642
|
+
className: cn(
|
|
6643
|
+
"focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
|
|
6644
|
+
className
|
|
6645
|
+
),
|
|
6646
|
+
...props,
|
|
6647
|
+
children: [
|
|
6648
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "absolute right-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItemIndicator, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-4" }) }) }),
|
|
6649
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectItemText, { children })
|
|
6650
|
+
]
|
|
6651
|
+
}
|
|
6652
|
+
);
|
|
6653
|
+
}
|
|
6654
|
+
function SelectScrollUpButton({
|
|
6655
|
+
className,
|
|
6656
|
+
...props
|
|
6657
|
+
}) {
|
|
6658
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
6659
|
+
SelectScrollUpButton$1,
|
|
6660
|
+
{
|
|
6661
|
+
"data-slot": "select-scroll-up-button",
|
|
6662
|
+
className: cn("flex cursor-default items-center justify-center py-1", className),
|
|
6663
|
+
...props,
|
|
6664
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronUp, { className: "size-4" })
|
|
6665
|
+
}
|
|
6666
|
+
);
|
|
6667
|
+
}
|
|
6668
|
+
function SelectScrollDownButton({
|
|
6669
|
+
className,
|
|
6316
6670
|
...props
|
|
6317
6671
|
}) {
|
|
6318
6672
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -6719,7 +7073,7 @@ function AlertsDialog() {
|
|
|
6719
7073
|
const criticalCount = summary?.critical ?? 0;
|
|
6720
7074
|
const warningCount = summary?.warning ?? 0;
|
|
6721
7075
|
const noticeCount = summary?.notice ?? 0;
|
|
6722
|
-
const triggerTone = criticalCount > 0 ? "bg-red-
|
|
7076
|
+
const triggerTone = criticalCount > 0 ? "bg-red-600 text-white" : warningCount > 0 ? "bg-amber-400 text-zinc-950" : "bg-sky-400 text-zinc-950";
|
|
6723
7077
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(Dialog, { open, onOpenChange: setOpen, children: [
|
|
6724
7078
|
/* @__PURE__ */ jsxRuntimeExports.jsx(DialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
6725
7079
|
Button,
|
|
@@ -6736,7 +7090,7 @@ function AlertsDialog() {
|
|
|
6736
7090
|
"span",
|
|
6737
7091
|
{
|
|
6738
7092
|
className: cn(
|
|
6739
|
-
"absolute -right-1 -top-1 min-w-4 rounded-full px-1 text-[10px] font-semibold leading-4
|
|
7093
|
+
"absolute -right-1 -top-1 min-w-4 rounded-full px-1 text-[10px] font-semibold leading-4",
|
|
6740
7094
|
triggerTone
|
|
6741
7095
|
),
|
|
6742
7096
|
children: formatCount(totalCount)
|
|
@@ -8181,31 +8535,18 @@ function ImportWizardDialog({
|
|
|
8181
8535
|
] })
|
|
8182
8536
|
] }) });
|
|
8183
8537
|
}
|
|
8184
|
-
const KNOWN_PROVIDER_DOCS = {
|
|
8185
|
-
deepseek: "https://api-docs.deepseek.com/zh-cn/"
|
|
8186
|
-
};
|
|
8187
8538
|
function hasSuccessField(result) {
|
|
8188
8539
|
return Object.prototype.hasOwnProperty.call(result, "success");
|
|
8189
8540
|
}
|
|
8190
8541
|
function isNotConfiguredState(result) {
|
|
8191
8542
|
return Object.prototype.hasOwnProperty.call(result, "notConfigured");
|
|
8192
8543
|
}
|
|
8544
|
+
function providerHasEndpoint$1(value) {
|
|
8545
|
+
return value !== void 0 && value !== "";
|
|
8546
|
+
}
|
|
8193
8547
|
function hasText(value) {
|
|
8194
8548
|
return value !== void 0 && value.trim() !== "";
|
|
8195
8549
|
}
|
|
8196
|
-
function formatHeaders(headers) {
|
|
8197
|
-
if (headers === void 0) {
|
|
8198
|
-
return void 0;
|
|
8199
|
-
}
|
|
8200
|
-
const lines = Object.entries(headers).map(([name, value]) => `${name}: ${value}`);
|
|
8201
|
-
if (lines.length === 0) {
|
|
8202
|
-
return void 0;
|
|
8203
|
-
}
|
|
8204
|
-
return lines.join("\n");
|
|
8205
|
-
}
|
|
8206
|
-
function hasHeaderDetails(headers) {
|
|
8207
|
-
return formatHeaders(headers) !== void 0;
|
|
8208
|
-
}
|
|
8209
8550
|
function formatElapsed(ms) {
|
|
8210
8551
|
if (ms < 1e3) return `${ms}ms`;
|
|
8211
8552
|
return `${(ms / 1e3).toFixed(1)}s`;
|
|
@@ -8214,155 +8555,395 @@ function formatTokenRate(tokensPerSecond) {
|
|
|
8214
8555
|
if (tokensPerSecond >= 10) return `${tokensPerSecond.toFixed(0)}/s`;
|
|
8215
8556
|
return `${tokensPerSecond.toFixed(1)}/s`;
|
|
8216
8557
|
}
|
|
8217
|
-
function
|
|
8218
|
-
|
|
8219
|
-
|
|
8558
|
+
function errorLabel(type) {
|
|
8559
|
+
switch (type) {
|
|
8560
|
+
case "timeout":
|
|
8561
|
+
return "Timeout";
|
|
8562
|
+
case "network_unreachable":
|
|
8563
|
+
return "Offline";
|
|
8564
|
+
case "connection_refused":
|
|
8565
|
+
return "Refused";
|
|
8566
|
+
case "auth_failed":
|
|
8567
|
+
return "Auth";
|
|
8568
|
+
case "rate_limited":
|
|
8569
|
+
return "Rate limit";
|
|
8570
|
+
case "server_error":
|
|
8571
|
+
return "Server";
|
|
8572
|
+
case "invalid_response":
|
|
8573
|
+
return "Invalid";
|
|
8574
|
+
case "unknown":
|
|
8575
|
+
return "Failed";
|
|
8576
|
+
}
|
|
8577
|
+
}
|
|
8578
|
+
function compactSuccessMetric(result) {
|
|
8579
|
+
if (result.firstChunkMs !== void 0 && result.firstChunkMs !== null) {
|
|
8580
|
+
return formatElapsed(result.firstChunkMs);
|
|
8581
|
+
}
|
|
8582
|
+
if (result.latencyMs !== void 0) return formatElapsed(result.latencyMs);
|
|
8583
|
+
if (result.totalStreamMs !== void 0 && result.totalStreamMs !== null) {
|
|
8584
|
+
return formatElapsed(result.totalStreamMs);
|
|
8585
|
+
}
|
|
8586
|
+
if (result.tokensPerSecond !== void 0 && result.tokensPerSecond !== null && result.tokensPerSecond > 0) {
|
|
8587
|
+
return formatTokenRate(result.tokensPerSecond);
|
|
8588
|
+
}
|
|
8589
|
+
return null;
|
|
8590
|
+
}
|
|
8591
|
+
function presentProviderProbe(result) {
|
|
8592
|
+
if (isNotConfiguredState(result)) {
|
|
8593
|
+
return { tone: "quiet", label: "N/A", metric: null, hasDetails: false };
|
|
8594
|
+
}
|
|
8595
|
+
if (!hasSuccessField(result)) {
|
|
8596
|
+
return { tone: "pending", label: "Running", metric: null, hasDetails: false };
|
|
8597
|
+
}
|
|
8598
|
+
if (result.success) {
|
|
8599
|
+
return {
|
|
8600
|
+
tone: "success",
|
|
8601
|
+
label: "Pass",
|
|
8602
|
+
metric: compactSuccessMetric(result),
|
|
8603
|
+
hasDetails: true
|
|
8604
|
+
};
|
|
8605
|
+
}
|
|
8606
|
+
return {
|
|
8607
|
+
tone: "failure",
|
|
8608
|
+
label: errorLabel(result.error?.type ?? "unknown"),
|
|
8609
|
+
metric: null,
|
|
8610
|
+
hasDetails: true
|
|
8611
|
+
};
|
|
8612
|
+
}
|
|
8613
|
+
function configuredFormatResults(provider, testResults) {
|
|
8614
|
+
if (testResults === void 0) return [];
|
|
8615
|
+
const results = [];
|
|
8616
|
+
if (providerHasEndpoint$1(provider.anthropicBaseUrl)) results.push(testResults.anthropic);
|
|
8617
|
+
if (providerHasEndpoint$1(provider.openaiBaseUrl)) results.push(testResults.openaiChat);
|
|
8618
|
+
if (providerHasEndpoint$1(provider.openaiResponsesBaseUrl)) {
|
|
8619
|
+
results.push(testResults.openaiResponses);
|
|
8620
|
+
}
|
|
8621
|
+
return results;
|
|
8622
|
+
}
|
|
8623
|
+
function summarizeProviderTestResults(provider, testResults) {
|
|
8624
|
+
const summary = { total: 0, passed: 0, failed: 0, testing: 0 };
|
|
8625
|
+
for (const results of configuredFormatResults(provider, testResults)) {
|
|
8626
|
+
for (const state of [results.nonStreaming, results.streaming]) {
|
|
8627
|
+
if (isNotConfiguredState(state)) continue;
|
|
8628
|
+
summary.total += 1;
|
|
8629
|
+
if (!hasSuccessField(state)) {
|
|
8630
|
+
summary.testing += 1;
|
|
8631
|
+
} else if (state.success) {
|
|
8632
|
+
summary.passed += 1;
|
|
8633
|
+
} else {
|
|
8634
|
+
summary.failed += 1;
|
|
8635
|
+
}
|
|
8636
|
+
}
|
|
8637
|
+
}
|
|
8638
|
+
return summary;
|
|
8639
|
+
}
|
|
8640
|
+
function formatHeaders(headers) {
|
|
8641
|
+
if (headers === void 0) return void 0;
|
|
8642
|
+
const lines = Object.entries(headers).map(([name, value]) => `${name}: ${value}`);
|
|
8643
|
+
return lines.length === 0 ? void 0 : lines.join("\n");
|
|
8220
8644
|
}
|
|
8221
8645
|
function DiagnosticSection({
|
|
8222
8646
|
title,
|
|
8223
8647
|
children
|
|
8224
8648
|
}) {
|
|
8225
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("
|
|
8226
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("
|
|
8649
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "space-y-1.5", children: [
|
|
8650
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "text-xs font-medium text-foreground/80", children: title }),
|
|
8227
8651
|
children
|
|
8228
8652
|
] });
|
|
8229
8653
|
}
|
|
8230
8654
|
function DiagnosticPre({ value }) {
|
|
8231
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "max-h-
|
|
8655
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "max-h-48 overflow-auto whitespace-pre-wrap break-all rounded-md bg-muted/40 p-3 font-mono text-[11px] leading-relaxed text-foreground/80", children: value });
|
|
8656
|
+
}
|
|
8657
|
+
function ResultMetric({ label, value }) {
|
|
8658
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 rounded-md bg-muted/35 px-3 py-2", children: [
|
|
8659
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("dt", { className: "text-[10px] text-muted-foreground", children: label }),
|
|
8660
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("dd", { className: "mt-1 truncate font-mono text-xs font-semibold text-foreground", title: value, children: value })
|
|
8661
|
+
] });
|
|
8662
|
+
}
|
|
8663
|
+
function ProviderTestMetrics({ result }) {
|
|
8664
|
+
const hasTokens = result.inputTokens !== void 0 || result.outputTokens !== void 0;
|
|
8665
|
+
const hasCache = result.cacheCreationInputTokens !== void 0 || result.cacheReadInputTokens !== void 0;
|
|
8666
|
+
const hasMetrics = hasText(result.model) || hasTokens || hasCache || result.latencyMs !== void 0 || result.firstChunkMs !== void 0 && result.firstChunkMs !== null || result.totalStreamMs !== void 0 && result.totalStreamMs !== null || result.tokensPerSecond !== void 0 && result.tokensPerSecond !== null && result.tokensPerSecond > 0;
|
|
8667
|
+
if (!hasMetrics) return null;
|
|
8668
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("dl", { className: "grid grid-cols-2 gap-2 sm:grid-cols-3 lg:grid-cols-4", children: [
|
|
8669
|
+
hasText(result.model) && /* @__PURE__ */ jsxRuntimeExports.jsx(ResultMetric, { label: "Model", value: result.model }),
|
|
8670
|
+
result.latencyMs !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(ResultMetric, { label: "Latency", value: formatElapsed(result.latencyMs) }),
|
|
8671
|
+
result.firstChunkMs !== void 0 && result.firstChunkMs !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(ResultMetric, { label: "First chunk", value: formatElapsed(result.firstChunkMs) }),
|
|
8672
|
+
result.totalStreamMs !== void 0 && result.totalStreamMs !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(ResultMetric, { label: "Stream total", value: formatElapsed(result.totalStreamMs) }),
|
|
8673
|
+
result.tokensPerSecond !== void 0 && result.tokensPerSecond !== null && result.tokensPerSecond > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
8674
|
+
ResultMetric,
|
|
8675
|
+
{
|
|
8676
|
+
label: "Token rate",
|
|
8677
|
+
value: `${formatTokenRate(result.tokensPerSecond)} tok`
|
|
8678
|
+
}
|
|
8679
|
+
),
|
|
8680
|
+
hasTokens && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
8681
|
+
ResultMetric,
|
|
8682
|
+
{
|
|
8683
|
+
label: "Tokens in / out",
|
|
8684
|
+
value: `${String(result.inputTokens ?? 0)} / ${String(result.outputTokens ?? 0)}`
|
|
8685
|
+
}
|
|
8686
|
+
),
|
|
8687
|
+
hasCache && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
8688
|
+
ResultMetric,
|
|
8689
|
+
{
|
|
8690
|
+
label: "Cache create / read",
|
|
8691
|
+
value: `${String(result.cacheCreationInputTokens ?? 0)} / ${String(result.cacheReadInputTokens ?? 0)}`
|
|
8692
|
+
}
|
|
8693
|
+
)
|
|
8694
|
+
] });
|
|
8232
8695
|
}
|
|
8233
|
-
function
|
|
8696
|
+
function ProviderTestDiagnostics({ result }) {
|
|
8234
8697
|
const debug = result.debug;
|
|
8235
8698
|
const requestUrl = debug?.requestUrl;
|
|
8236
8699
|
const requestMethod = debug?.requestMethod ?? "POST";
|
|
8237
8700
|
const requestHeaders = formatHeaders(debug?.requestHeaders);
|
|
8238
8701
|
const responseHeaders = formatHeaders(debug?.responseHeaders);
|
|
8239
|
-
const responseStatus = debug?.responseStatus
|
|
8702
|
+
const responseStatus = debug?.responseStatus === void 0 ? void 0 : `${String(debug.responseStatus)}${hasText(debug.responseStatusText) ? ` ${debug.responseStatusText}` : ""}`;
|
|
8240
8703
|
const responseBody = debug?.responseBody ?? result.rawResponse;
|
|
8241
|
-
|
|
8242
|
-
|
|
8243
|
-
|
|
8244
|
-
hasText(
|
|
8245
|
-
|
|
8246
|
-
|
|
8247
|
-
|
|
8248
|
-
|
|
8249
|
-
|
|
8250
|
-
|
|
8251
|
-
hasText(
|
|
8252
|
-
responseHeaders !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(DiagnosticSection, { title: "Response Headers", children: /* @__PURE__ */ jsxRuntimeExports.jsx(DiagnosticPre, { value: responseHeaders }) }),
|
|
8253
|
-
hasText(responseBody) && /* @__PURE__ */ jsxRuntimeExports.jsx(DiagnosticSection, { title: "Response Body", children: /* @__PURE__ */ jsxRuntimeExports.jsx(DiagnosticPre, { value: responseBody }) })
|
|
8704
|
+
const hasDiagnostics = hasText(result.error?.hint) || hasText(result.error?.details) || hasText(requestUrl) || requestHeaders !== void 0 || hasText(debug?.requestBody) || hasText(responseStatus) || responseHeaders !== void 0 || hasText(responseBody);
|
|
8705
|
+
if (!hasDiagnostics) return null;
|
|
8706
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4 border-t border-border/70 pt-4 text-xs text-muted-foreground", children: [
|
|
8707
|
+
hasText(result.error?.hint) && /* @__PURE__ */ jsxRuntimeExports.jsx(DiagnosticSection, { title: "Hint", children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "break-words text-foreground/80", children: result.error.hint }) }),
|
|
8708
|
+
hasText(result.error?.details) && /* @__PURE__ */ jsxRuntimeExports.jsx(DiagnosticSection, { title: "Error details", children: /* @__PURE__ */ jsxRuntimeExports.jsx(DiagnosticPre, { value: result.error.details }) }),
|
|
8709
|
+
hasText(requestUrl) && /* @__PURE__ */ jsxRuntimeExports.jsx(DiagnosticSection, { title: "Request", children: /* @__PURE__ */ jsxRuntimeExports.jsx(DiagnosticPre, { value: `${requestMethod} ${requestUrl}` }) }),
|
|
8710
|
+
requestHeaders !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(DiagnosticSection, { title: "Request headers", children: /* @__PURE__ */ jsxRuntimeExports.jsx(DiagnosticPre, { value: requestHeaders }) }),
|
|
8711
|
+
hasText(debug?.requestBody) && /* @__PURE__ */ jsxRuntimeExports.jsx(DiagnosticSection, { title: "Request body", children: /* @__PURE__ */ jsxRuntimeExports.jsx(DiagnosticPre, { value: debug.requestBody }) }),
|
|
8712
|
+
hasText(responseStatus) && /* @__PURE__ */ jsxRuntimeExports.jsx(DiagnosticSection, { title: "Response status", children: /* @__PURE__ */ jsxRuntimeExports.jsx(DiagnosticPre, { value: responseStatus }) }),
|
|
8713
|
+
responseHeaders !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(DiagnosticSection, { title: "Response headers", children: /* @__PURE__ */ jsxRuntimeExports.jsx(DiagnosticPre, { value: responseHeaders }) }),
|
|
8714
|
+
hasText(responseBody) && /* @__PURE__ */ jsxRuntimeExports.jsx(DiagnosticSection, { title: "Response body", children: /* @__PURE__ */ jsxRuntimeExports.jsx(DiagnosticPre, { value: responseBody }) })
|
|
8254
8715
|
] });
|
|
8255
8716
|
}
|
|
8256
|
-
function
|
|
8257
|
-
|
|
8717
|
+
function ProviderTestResultDialog({
|
|
8718
|
+
result,
|
|
8719
|
+
probeLabel,
|
|
8720
|
+
children
|
|
8258
8721
|
}) {
|
|
8259
|
-
|
|
8260
|
-
|
|
8261
|
-
|
|
8262
|
-
|
|
8263
|
-
|
|
8264
|
-
|
|
8265
|
-
|
|
8266
|
-
|
|
8722
|
+
const errorMessage = result.error?.message ?? "Connection failed";
|
|
8723
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(Dialog, { children: [
|
|
8724
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(DialogTrigger, { asChild: true, children }),
|
|
8725
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(DialogContent, { className: "max-h-[82vh] max-w-2xl gap-0 overflow-hidden p-0", children: [
|
|
8726
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(DialogHeader, { className: "border-b border-border/70 px-5 py-4 pr-12", children: [
|
|
8727
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
8728
|
+
result.success ? /* @__PURE__ */ jsxRuntimeExports.jsx(CircleCheckBig, { className: "size-4 text-cyan-300" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "size-4 text-red-300" }),
|
|
8729
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(DialogTitle, { className: "text-base", children: probeLabel })
|
|
8730
|
+
] }),
|
|
8731
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(DialogDescription, { children: result.success ? "Connection probe passed." : errorMessage })
|
|
8732
|
+
] }),
|
|
8733
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4 overflow-y-auto p-5", children: [
|
|
8734
|
+
!result.success && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-md border border-red-400/20 bg-red-400/[0.06] px-3 py-2 text-sm text-red-200", children: [
|
|
8735
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-medium", children: errorLabel(result.error?.type ?? "unknown") }),
|
|
8736
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1 break-words text-xs text-muted-foreground", children: errorMessage })
|
|
8737
|
+
] }),
|
|
8738
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ProviderTestMetrics, { result }),
|
|
8739
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ProviderTestDiagnostics, { result })
|
|
8740
|
+
] })
|
|
8267
8741
|
] })
|
|
8268
8742
|
] });
|
|
8269
8743
|
}
|
|
8270
|
-
function
|
|
8271
|
-
|
|
8272
|
-
|
|
8744
|
+
function errorIcon(type) {
|
|
8745
|
+
const className = "size-3 shrink-0";
|
|
8746
|
+
switch (type) {
|
|
8747
|
+
case "timeout":
|
|
8748
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className });
|
|
8749
|
+
case "network_unreachable":
|
|
8750
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(WifiOff, { className });
|
|
8751
|
+
case "connection_refused":
|
|
8752
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Wifi, { className });
|
|
8753
|
+
case "auth_failed":
|
|
8754
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Lock, { className });
|
|
8755
|
+
case "rate_limited":
|
|
8756
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Gauge, { className });
|
|
8757
|
+
case "server_error":
|
|
8758
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Server, { className });
|
|
8759
|
+
case "invalid_response":
|
|
8760
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(CircleQuestionMark, { className });
|
|
8761
|
+
case "unknown":
|
|
8762
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className });
|
|
8763
|
+
}
|
|
8764
|
+
}
|
|
8765
|
+
const PROBE_TONE_CLASSES = {
|
|
8766
|
+
success: "bg-cyan-300/[0.07] text-cyan-100 hover:bg-cyan-300/[0.11]",
|
|
8767
|
+
failure: "bg-red-400/[0.07] text-red-200 hover:bg-red-400/[0.11]",
|
|
8768
|
+
pending: "bg-muted/40 text-foreground/80",
|
|
8769
|
+
quiet: "bg-transparent text-muted-foreground/70"
|
|
8770
|
+
};
|
|
8771
|
+
function ProviderProbeStatus({
|
|
8772
|
+
result,
|
|
8773
|
+
probeLabel
|
|
8273
8774
|
}) {
|
|
8274
|
-
|
|
8275
|
-
|
|
8276
|
-
|
|
8775
|
+
const presentation = presentProviderProbe(result);
|
|
8776
|
+
const icon = isNotConfiguredState(result) ? /* @__PURE__ */ jsxRuntimeExports.jsx(Minus, { className: "size-3 shrink-0" }) : !hasSuccessField(result) ? /* @__PURE__ */ jsxRuntimeExports.jsx(RotateCw, { className: "size-3 shrink-0 animate-spin" }) : result.success ? /* @__PURE__ */ jsxRuntimeExports.jsx(CircleCheckBig, { className: "size-3 shrink-0" }) : errorIcon(result.error?.type ?? "unknown");
|
|
8777
|
+
const content = /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
8778
|
+
icon,
|
|
8779
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0 truncate", children: presentation.label }),
|
|
8780
|
+
presentation.metric !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ml-auto shrink-0 font-mono text-[10px] opacity-75", children: presentation.metric })
|
|
8277
8781
|
] });
|
|
8278
|
-
|
|
8279
|
-
|
|
8280
|
-
|
|
8281
|
-
|
|
8282
|
-
|
|
8283
|
-
|
|
8284
|
-
|
|
8285
|
-
|
|
8286
|
-
|
|
8287
|
-
|
|
8288
|
-
|
|
8289
|
-
|
|
8290
|
-
|
|
8291
|
-
|
|
8782
|
+
const className = cn(
|
|
8783
|
+
"inline-flex h-7 w-full min-w-0 items-center gap-1.5 rounded-md px-2 text-left text-xs transition-colors",
|
|
8784
|
+
PROBE_TONE_CLASSES[presentation.tone]
|
|
8785
|
+
);
|
|
8786
|
+
if (hasSuccessField(result) && presentation.hasDetails) {
|
|
8787
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderTestResultDialog, { result, probeLabel, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
8788
|
+
"button",
|
|
8789
|
+
{
|
|
8790
|
+
type: "button",
|
|
8791
|
+
className,
|
|
8792
|
+
"aria-label": `Open ${probeLabel} result: ${presentation.label}`,
|
|
8793
|
+
children: content
|
|
8794
|
+
}
|
|
8795
|
+
) });
|
|
8292
8796
|
}
|
|
8293
|
-
return
|
|
8797
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className, children: content });
|
|
8798
|
+
}
|
|
8799
|
+
function ProbePlaceholder({ label }) {
|
|
8800
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "inline-flex h-7 w-full min-w-0 items-center gap-1.5 rounded-md px-2 text-xs text-muted-foreground/70", children: [
|
|
8801
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Minus, { className: "size-3 shrink-0" }),
|
|
8802
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate", children: label })
|
|
8803
|
+
] });
|
|
8294
8804
|
}
|
|
8295
|
-
function
|
|
8805
|
+
function ProviderFormatRow({
|
|
8296
8806
|
label,
|
|
8297
|
-
|
|
8298
|
-
|
|
8807
|
+
results,
|
|
8808
|
+
configured = true
|
|
8299
8809
|
}) {
|
|
8300
|
-
|
|
8301
|
-
|
|
8302
|
-
|
|
8303
|
-
label
|
|
8810
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid min-w-0 grid-cols-[minmax(6.5rem,1fr)_minmax(6rem,0.9fr)_minmax(6rem,0.9fr)] items-center gap-2 border-t border-border/60 px-2 py-2", children: [
|
|
8811
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "min-w-0 truncate text-xs font-medium text-foreground/85", title: label, children: label }),
|
|
8812
|
+
configured && results !== void 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderProbeStatus, { result: results.nonStreaming, probeLabel: `${label} non-stream` }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ProbePlaceholder, { label: configured ? "Not tested" : "Off" }),
|
|
8813
|
+
configured && results !== void 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderProbeStatus, { result: results.streaming, probeLabel: `${label} stream` }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ProbePlaceholder, { label: configured ? "Not tested" : "Off" })
|
|
8304
8814
|
] });
|
|
8305
8815
|
}
|
|
8306
|
-
function
|
|
8307
|
-
|
|
8308
|
-
|
|
8309
|
-
|
|
8816
|
+
function ProviderTestMatrix({
|
|
8817
|
+
provider,
|
|
8818
|
+
results
|
|
8819
|
+
}) {
|
|
8820
|
+
const hasAnthropic = providerHasEndpoint$1(provider.anthropicBaseUrl);
|
|
8821
|
+
const hasChat = providerHasEndpoint$1(provider.openaiBaseUrl);
|
|
8822
|
+
const hasResponses = providerHasEndpoint$1(provider.openaiResponsesBaseUrl);
|
|
8310
8823
|
if (!hasAnthropic && !hasChat && !hasResponses) {
|
|
8311
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-muted-foreground", children: "
|
|
8312
|
-
}
|
|
8313
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-1.5 text-xs text-muted-foreground", children: [
|
|
8314
|
-
hasAnthropic && /* @__PURE__ */ jsxRuntimeExports.jsx(CapabilityChip, { label: "Anthropic", enabled: true }),
|
|
8315
|
-
hasChat && /* @__PURE__ */ jsxRuntimeExports.jsx(CapabilityChip, { label: "OpenAI Chat", enabled: true }),
|
|
8316
|
-
hasResponses && /* @__PURE__ */ jsxRuntimeExports.jsx(CapabilityChip, { label: "OpenAI Responses", enabled: true })
|
|
8317
|
-
] });
|
|
8318
|
-
}
|
|
8319
|
-
function configuredFormatResults(provider, testResults) {
|
|
8320
|
-
if (testResults === void 0) return [];
|
|
8321
|
-
const results = [];
|
|
8322
|
-
if (providerHasEndpoint(provider.anthropicBaseUrl)) {
|
|
8323
|
-
results.push(testResults.anthropic);
|
|
8824
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-muted-foreground", children: "No testable endpoint configured." });
|
|
8324
8825
|
}
|
|
8325
|
-
|
|
8326
|
-
|
|
8327
|
-
|
|
8328
|
-
|
|
8329
|
-
|
|
8330
|
-
|
|
8331
|
-
|
|
8826
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "min-w-0 overflow-x-auto rounded-md border border-border/70", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-[20rem]", children: [
|
|
8827
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-[minmax(6.5rem,1fr)_minmax(6rem,0.9fr)_minmax(6rem,0.9fr)] gap-2 bg-muted/25 px-2 py-1.5 text-[10px] text-muted-foreground", children: [
|
|
8828
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Protocol" }),
|
|
8829
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Non-stream" }),
|
|
8830
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Stream" })
|
|
8831
|
+
] }),
|
|
8832
|
+
hasAnthropic && /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatRow, { label: "Anthropic", results: results?.anthropic }),
|
|
8833
|
+
hasChat && /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatRow, { label: "OpenAI Chat", results: results?.openaiChat }),
|
|
8834
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
8835
|
+
ProviderFormatRow,
|
|
8836
|
+
{
|
|
8837
|
+
label: "OpenAI Responses",
|
|
8838
|
+
results: results?.openaiResponses,
|
|
8839
|
+
configured: hasResponses
|
|
8840
|
+
}
|
|
8841
|
+
)
|
|
8842
|
+
] }) });
|
|
8332
8843
|
}
|
|
8333
|
-
function
|
|
8844
|
+
function summarizeFormat(results) {
|
|
8334
8845
|
const summary = { total: 0, passed: 0, failed: 0, testing: 0 };
|
|
8335
|
-
for (const
|
|
8336
|
-
|
|
8337
|
-
|
|
8338
|
-
|
|
8339
|
-
|
|
8340
|
-
|
|
8341
|
-
summary.passed += 1;
|
|
8342
|
-
} else {
|
|
8343
|
-
summary.failed += 1;
|
|
8344
|
-
}
|
|
8345
|
-
} else {
|
|
8346
|
-
summary.testing += 1;
|
|
8347
|
-
}
|
|
8348
|
-
}
|
|
8846
|
+
for (const state of [results.nonStreaming, results.streaming]) {
|
|
8847
|
+
if (isNotConfiguredState(state)) continue;
|
|
8848
|
+
summary.total += 1;
|
|
8849
|
+
if (!hasSuccessField(state)) summary.testing += 1;
|
|
8850
|
+
else if (state.success) summary.passed += 1;
|
|
8851
|
+
else summary.failed += 1;
|
|
8349
8852
|
}
|
|
8350
8853
|
return summary;
|
|
8351
8854
|
}
|
|
8855
|
+
function FormatSummaryBadge({
|
|
8856
|
+
label,
|
|
8857
|
+
results
|
|
8858
|
+
}) {
|
|
8859
|
+
const summary = summarizeFormat(results);
|
|
8860
|
+
const className = summary.failed > 0 ? "border-red-400/20 bg-red-400/[0.06] text-red-200" : summary.testing > 0 ? "border-amber-300/20 bg-amber-300/[0.06] text-amber-100" : summary.total > 0 && summary.passed === summary.total ? "border-cyan-300/20 bg-cyan-300/[0.06] text-cyan-100" : "border-border/60 bg-transparent text-muted-foreground";
|
|
8861
|
+
const value = summary.failed > 0 ? `${summary.failed} fail` : summary.testing > 0 ? "running" : summary.total === 0 ? "off" : `${summary.passed}/${summary.total}`;
|
|
8862
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: cn("rounded border px-1.5 py-0.5 text-[10px]", className), children: [
|
|
8863
|
+
label,
|
|
8864
|
+
" ",
|
|
8865
|
+
value
|
|
8866
|
+
] });
|
|
8867
|
+
}
|
|
8868
|
+
function ModelResultRow({
|
|
8869
|
+
provider,
|
|
8870
|
+
modelName,
|
|
8871
|
+
results,
|
|
8872
|
+
expanded,
|
|
8873
|
+
onToggle
|
|
8874
|
+
}) {
|
|
8875
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0", children: [
|
|
8876
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
8877
|
+
"button",
|
|
8878
|
+
{
|
|
8879
|
+
type: "button",
|
|
8880
|
+
onClick: onToggle,
|
|
8881
|
+
className: "flex w-full min-w-0 flex-wrap items-center gap-2 px-2 py-2 text-left transition-colors hover:bg-muted/20",
|
|
8882
|
+
"aria-expanded": expanded,
|
|
8883
|
+
children: [
|
|
8884
|
+
expanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-3.5 shrink-0 text-muted-foreground" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-3.5 shrink-0 text-muted-foreground" }),
|
|
8885
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-[8rem] flex-1 truncate text-xs font-medium", title: modelName, children: modelName }),
|
|
8886
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex flex-wrap items-center justify-end gap-1", children: [
|
|
8887
|
+
providerHasEndpoint$1(provider.anthropicBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsx(FormatSummaryBadge, { label: "A", results: results.anthropic }),
|
|
8888
|
+
providerHasEndpoint$1(provider.openaiBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsx(FormatSummaryBadge, { label: "Chat", results: results.openaiChat }),
|
|
8889
|
+
providerHasEndpoint$1(provider.openaiResponsesBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsx(FormatSummaryBadge, { label: "Resp", results: results.openaiResponses })
|
|
8890
|
+
] })
|
|
8891
|
+
]
|
|
8892
|
+
}
|
|
8893
|
+
),
|
|
8894
|
+
expanded && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-2 pb-3", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderTestMatrix, { provider, results }) })
|
|
8895
|
+
] });
|
|
8896
|
+
}
|
|
8897
|
+
function ProviderModelTestResultsView({
|
|
8898
|
+
provider,
|
|
8899
|
+
testResults
|
|
8900
|
+
}) {
|
|
8901
|
+
const entries = Object.entries(testResults.models ?? {});
|
|
8902
|
+
const [showModels, setShowModels] = reactExports.useState(false);
|
|
8903
|
+
const [expandedModelName, setExpandedModelName] = reactExports.useState(null);
|
|
8904
|
+
if (entries.length === 0) return null;
|
|
8905
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "space-y-2", children: [
|
|
8906
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
8907
|
+
"button",
|
|
8908
|
+
{
|
|
8909
|
+
type: "button",
|
|
8910
|
+
onClick: () => setShowModels((value) => !value),
|
|
8911
|
+
className: "flex w-full items-center gap-1.5 text-left text-xs font-medium text-foreground/80 transition-colors hover:text-foreground",
|
|
8912
|
+
"aria-expanded": showModels,
|
|
8913
|
+
children: [
|
|
8914
|
+
showModels ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-3.5" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-3.5" }),
|
|
8915
|
+
"Model probes",
|
|
8916
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "rounded bg-muted/50 px-1.5 py-0.5 font-mono text-[10px] text-muted-foreground", children: entries.length })
|
|
8917
|
+
]
|
|
8918
|
+
}
|
|
8919
|
+
),
|
|
8920
|
+
showModels && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "min-w-0 divide-y divide-border/60 rounded-md border border-border/70", children: entries.map(([modelName, modelResults]) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
8921
|
+
ModelResultRow,
|
|
8922
|
+
{
|
|
8923
|
+
provider,
|
|
8924
|
+
modelName,
|
|
8925
|
+
results: modelResults,
|
|
8926
|
+
expanded: expandedModelName === modelName,
|
|
8927
|
+
onToggle: () => setExpandedModelName((current) => current === modelName ? null : modelName)
|
|
8928
|
+
},
|
|
8929
|
+
modelName
|
|
8930
|
+
)) })
|
|
8931
|
+
] });
|
|
8932
|
+
}
|
|
8352
8933
|
function ProviderTestPill({
|
|
8353
8934
|
provider,
|
|
8354
8935
|
testResults,
|
|
8355
8936
|
isTesting
|
|
8356
8937
|
}) {
|
|
8357
|
-
const
|
|
8358
|
-
const summary =
|
|
8938
|
+
const hasEndpoint = providerHasEndpoint$1(provider.anthropicBaseUrl) || providerHasEndpoint$1(provider.openaiBaseUrl) || providerHasEndpoint$1(provider.openaiResponsesBaseUrl);
|
|
8939
|
+
const summary = summarizeProviderTestResults(provider, testResults);
|
|
8359
8940
|
if (isTesting) {
|
|
8360
8941
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1 rounded border border-cyan-300/25 bg-cyan-300/[0.08] px-2 py-1 text-xs text-cyan-100", children: [
|
|
8361
8942
|
/* @__PURE__ */ jsxRuntimeExports.jsx(RotateCw, { className: "size-3 animate-spin" }),
|
|
8362
8943
|
"Testing"
|
|
8363
8944
|
] });
|
|
8364
8945
|
}
|
|
8365
|
-
if (
|
|
8946
|
+
if (!hasEndpoint) {
|
|
8366
8947
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "rounded border border-border/70 bg-muted/20 px-2 py-1 text-xs text-muted-foreground", children: "No endpoint" });
|
|
8367
8948
|
}
|
|
8368
8949
|
if (testResults === void 0 || summary.total === 0) {
|
|
@@ -8371,15 +8952,12 @@ function ProviderTestPill({
|
|
|
8371
8952
|
if (summary.failed > 0) {
|
|
8372
8953
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1 rounded border border-red-400/25 bg-red-500/[0.08] px-2 py-1 text-xs text-red-200", children: [
|
|
8373
8954
|
/* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "size-3" }),
|
|
8374
|
-
summary.
|
|
8375
|
-
"
|
|
8376
|
-
summary.total,
|
|
8377
|
-
" passed"
|
|
8955
|
+
summary.failed,
|
|
8956
|
+
" failed"
|
|
8378
8957
|
] });
|
|
8379
8958
|
}
|
|
8380
8959
|
if (summary.testing > 0 || summary.passed < summary.total) {
|
|
8381
8960
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "rounded border border-amber-300/25 bg-amber-400/[0.08] px-2 py-1 text-xs text-amber-100", children: [
|
|
8382
|
-
"Partial ",
|
|
8383
8961
|
summary.passed,
|
|
8384
8962
|
"/",
|
|
8385
8963
|
summary.total
|
|
@@ -8387,12 +8965,36 @@ function ProviderTestPill({
|
|
|
8387
8965
|
}
|
|
8388
8966
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1 rounded border border-cyan-300/25 bg-cyan-300/[0.08] px-2 py-1 text-xs text-cyan-100", children: [
|
|
8389
8967
|
/* @__PURE__ */ jsxRuntimeExports.jsx(CircleCheckBig, { className: "size-3" }),
|
|
8390
|
-
"OK ",
|
|
8391
8968
|
summary.passed,
|
|
8392
8969
|
"/",
|
|
8393
8970
|
summary.total
|
|
8394
8971
|
] });
|
|
8395
8972
|
}
|
|
8973
|
+
const KNOWN_PROVIDER_DOCS = {
|
|
8974
|
+
deepseek: "https://api-docs.deepseek.com/zh-cn/"
|
|
8975
|
+
};
|
|
8976
|
+
function providerHasEndpoint(value) {
|
|
8977
|
+
return value !== void 0 && value !== "";
|
|
8978
|
+
}
|
|
8979
|
+
function CapabilityChip({ label }) {
|
|
8980
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1 rounded border border-border/70 bg-muted/25 px-1.5 py-0.5 text-foreground/80", children: [
|
|
8981
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(CircleCheckBig, { className: "size-3" }),
|
|
8982
|
+
label
|
|
8983
|
+
] });
|
|
8984
|
+
}
|
|
8985
|
+
function ProviderCapabilitySummary({ provider }) {
|
|
8986
|
+
const hasAnthropic = providerHasEndpoint(provider.anthropicBaseUrl);
|
|
8987
|
+
const hasChat = providerHasEndpoint(provider.openaiBaseUrl);
|
|
8988
|
+
const hasResponses = providerHasEndpoint(provider.openaiResponsesBaseUrl);
|
|
8989
|
+
if (!hasAnthropic && !hasChat && !hasResponses) {
|
|
8990
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-muted-foreground", children: "Test requires at least one configured endpoint." });
|
|
8991
|
+
}
|
|
8992
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-1.5 text-xs text-muted-foreground", children: [
|
|
8993
|
+
hasAnthropic && /* @__PURE__ */ jsxRuntimeExports.jsx(CapabilityChip, { label: "Anthropic" }),
|
|
8994
|
+
hasChat && /* @__PURE__ */ jsxRuntimeExports.jsx(CapabilityChip, { label: "OpenAI Chat" }),
|
|
8995
|
+
hasResponses && /* @__PURE__ */ jsxRuntimeExports.jsx(CapabilityChip, { label: "OpenAI Responses" })
|
|
8996
|
+
] });
|
|
8997
|
+
}
|
|
8396
8998
|
function compactModelLabel(provider) {
|
|
8397
8999
|
const models = provider.models ?? [];
|
|
8398
9000
|
if (models.length === 0) return "No models configured";
|
|
@@ -8422,143 +9024,6 @@ function ModelChip({ provider, model }) {
|
|
|
8422
9024
|
] }) })
|
|
8423
9025
|
] });
|
|
8424
9026
|
}
|
|
8425
|
-
function getErrorIcon(type) {
|
|
8426
|
-
const iconProps = { className: "size-3", strokeWidth: 2 };
|
|
8427
|
-
switch (type) {
|
|
8428
|
-
case "timeout":
|
|
8429
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { ...iconProps });
|
|
8430
|
-
case "network_unreachable":
|
|
8431
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(WifiOff, { ...iconProps });
|
|
8432
|
-
case "connection_refused":
|
|
8433
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(Wifi, { ...iconProps });
|
|
8434
|
-
case "auth_failed":
|
|
8435
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(Lock, { ...iconProps });
|
|
8436
|
-
case "rate_limited":
|
|
8437
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(Gauge, { ...iconProps });
|
|
8438
|
-
case "server_error":
|
|
8439
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(Server, { ...iconProps });
|
|
8440
|
-
case "invalid_response":
|
|
8441
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(CircleQuestionMark, { ...iconProps });
|
|
8442
|
-
case "unknown":
|
|
8443
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { ...iconProps });
|
|
8444
|
-
default:
|
|
8445
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { ...iconProps });
|
|
8446
|
-
}
|
|
8447
|
-
}
|
|
8448
|
-
function TestStatus({ result }) {
|
|
8449
|
-
const [showDetails, setShowDetails] = reactExports.useState(false);
|
|
8450
|
-
if (!hasSuccessField(result)) {
|
|
8451
|
-
if (isNotConfiguredState(result)) {
|
|
8452
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 text-xs text-muted-foreground shrink-0", children: [
|
|
8453
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(Minus, { className: "size-3" }),
|
|
8454
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Not configured" })
|
|
8455
|
-
] });
|
|
8456
|
-
}
|
|
8457
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 text-xs text-muted-foreground shrink-0", children: [
|
|
8458
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(RotateCw, { className: "size-3 animate-spin" }),
|
|
8459
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Testing..." })
|
|
8460
|
-
] });
|
|
8461
|
-
}
|
|
8462
|
-
if (result.success) {
|
|
8463
|
-
const tokenParts = [];
|
|
8464
|
-
const timingParts = [];
|
|
8465
|
-
if (result.inputTokens !== void 0) {
|
|
8466
|
-
tokenParts.push(/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
8467
|
-
result.inputTokens,
|
|
8468
|
-
" in"
|
|
8469
|
-
] }, "in"));
|
|
8470
|
-
}
|
|
8471
|
-
if (result.outputTokens !== void 0) {
|
|
8472
|
-
tokenParts.push(/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
8473
|
-
result.outputTokens,
|
|
8474
|
-
" out"
|
|
8475
|
-
] }, "out"));
|
|
8476
|
-
}
|
|
8477
|
-
if (result.cacheCreationInputTokens !== void 0 && result.cacheCreationInputTokens > 0) {
|
|
8478
|
-
tokenParts.push(
|
|
8479
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono tabular-nums text-emerald-400", children: [
|
|
8480
|
-
"KV Cache +",
|
|
8481
|
-
result.cacheCreationInputTokens
|
|
8482
|
-
] }, "cache-create")
|
|
8483
|
-
);
|
|
8484
|
-
}
|
|
8485
|
-
if (result.cacheReadInputTokens !== void 0 && result.cacheReadInputTokens > 0) {
|
|
8486
|
-
tokenParts.push(
|
|
8487
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono tabular-nums text-purple-400", children: [
|
|
8488
|
-
"KV Cache ~",
|
|
8489
|
-
result.cacheReadInputTokens
|
|
8490
|
-
] }, "cache-read")
|
|
8491
|
-
);
|
|
8492
|
-
}
|
|
8493
|
-
if (result.firstChunkMs !== void 0 && result.firstChunkMs !== null) {
|
|
8494
|
-
timingParts.push(/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
8495
|
-
"first ",
|
|
8496
|
-
formatElapsed(result.firstChunkMs)
|
|
8497
|
-
] }, "first"));
|
|
8498
|
-
}
|
|
8499
|
-
if (result.totalStreamMs !== void 0 && result.totalStreamMs !== null) {
|
|
8500
|
-
timingParts.push(/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
8501
|
-
"total ",
|
|
8502
|
-
formatElapsed(result.totalStreamMs)
|
|
8503
|
-
] }, "total"));
|
|
8504
|
-
}
|
|
8505
|
-
if (result.tokensPerSecond !== void 0 && result.tokensPerSecond !== null && result.tokensPerSecond > 0) {
|
|
8506
|
-
timingParts.push(/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
8507
|
-
formatTokenRate(result.tokensPerSecond),
|
|
8508
|
-
" tok/s"
|
|
8509
|
-
] }, "rate"));
|
|
8510
|
-
}
|
|
8511
|
-
const displayTokens = [];
|
|
8512
|
-
for (let i = 0; i < tokenParts.length; i++) {
|
|
8513
|
-
if (i > 0) displayTokens.push(", ");
|
|
8514
|
-
displayTokens.push(tokenParts[i]);
|
|
8515
|
-
}
|
|
8516
|
-
const displayTiming = [];
|
|
8517
|
-
for (let i = 0; i < timingParts.length; i++) {
|
|
8518
|
-
if (i > 0) displayTiming.push(", ");
|
|
8519
|
-
displayTiming.push(timingParts[i]);
|
|
8520
|
-
}
|
|
8521
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex shrink-0 items-center gap-1 text-xs text-cyan-100", children: [
|
|
8522
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(CircleCheckBig, { className: "size-3 text-cyan-300" }),
|
|
8523
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Connected" }),
|
|
8524
|
-
tokenParts.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground", children: [
|
|
8525
|
-
"(",
|
|
8526
|
-
displayTokens,
|
|
8527
|
-
")"
|
|
8528
|
-
] }),
|
|
8529
|
-
timingParts.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "hidden text-muted-foreground lg:inline", children: [
|
|
8530
|
-
"(",
|
|
8531
|
-
displayTiming,
|
|
8532
|
-
")"
|
|
8533
|
-
] })
|
|
8534
|
-
] });
|
|
8535
|
-
}
|
|
8536
|
-
const error = result.error;
|
|
8537
|
-
const errorMessage = error?.message ?? "Connection failed";
|
|
8538
|
-
const errorType = error?.type ?? "unknown";
|
|
8539
|
-
const hasDetails = hasDiagnosticDetails(result);
|
|
8540
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1 shrink-0", children: [
|
|
8541
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 text-xs text-red-600 max-w-[200px]", children: [
|
|
8542
|
-
getErrorIcon(errorType),
|
|
8543
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate", children: errorMessage }),
|
|
8544
|
-
hasDetails && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
8545
|
-
"button",
|
|
8546
|
-
{
|
|
8547
|
-
type: "button",
|
|
8548
|
-
onClick: () => setShowDetails((value) => !value),
|
|
8549
|
-
"aria-expanded": showDetails,
|
|
8550
|
-
"aria-label": showDetails ? "Hide provider test diagnostics" : "Show provider test diagnostics",
|
|
8551
|
-
className: "inline-flex h-5 shrink-0 items-center gap-1 rounded border border-border/70 bg-background/70 px-1.5 text-[10px] text-muted-foreground transition-colors hover:text-foreground",
|
|
8552
|
-
children: [
|
|
8553
|
-
showDetails ? /* @__PURE__ */ jsxRuntimeExports.jsx(EyeOff, { className: "size-3" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Eye, { className: "size-3" }),
|
|
8554
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: showDetails ? "Hide" : "Details" })
|
|
8555
|
-
]
|
|
8556
|
-
}
|
|
8557
|
-
)
|
|
8558
|
-
] }),
|
|
8559
|
-
showDetails && hasDetails && /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderTestDetails, { result })
|
|
8560
|
-
] });
|
|
8561
|
-
}
|
|
8562
9027
|
function formatTimeAgo(isoString) {
|
|
8563
9028
|
const now = Date.now();
|
|
8564
9029
|
const then = new Date(isoString).getTime();
|
|
@@ -8603,7 +9068,6 @@ function ProviderCard({
|
|
|
8603
9068
|
const [showApiKey, setShowApiKey] = reactExports.useState(false);
|
|
8604
9069
|
const [copied, setCopied] = reactExports.useState(false);
|
|
8605
9070
|
const [showDetails, setShowDetails] = reactExports.useState(false);
|
|
8606
|
-
const [showModelResults, setShowModelResults] = reactExports.useState(false);
|
|
8607
9071
|
function handleCopy() {
|
|
8608
9072
|
void copyTextToClipboard(provider.apiKey).then((success) => {
|
|
8609
9073
|
if (!success) return;
|
|
@@ -8622,6 +9086,7 @@ function ProviderCard({
|
|
|
8622
9086
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
8623
9087
|
"div",
|
|
8624
9088
|
{
|
|
9089
|
+
"data-provider-id": provider.id,
|
|
8625
9090
|
className: `flex flex-col gap-3 rounded-[8px] border border-border bg-card p-4 shadow-sm transition-all duration-500 ${isHighlighted === true ? "ring-2 ring-primary shadow-md" : ""}`,
|
|
8626
9091
|
children: [
|
|
8627
9092
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-start justify-between gap-2", children: [
|
|
@@ -8720,51 +9185,11 @@ function ProviderCard({
|
|
|
8720
9185
|
)
|
|
8721
9186
|
] }),
|
|
8722
9187
|
provider.models !== void 0 && provider.models.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-wrap gap-1", children: provider.models.map((model) => /* @__PURE__ */ jsxRuntimeExports.jsx(ModelChip, { provider, model }, model)) }),
|
|
8723
|
-
|
|
8724
|
-
|
|
8725
|
-
|
|
8726
|
-
testResults === void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-muted-foreground", children: "Not tested yet" })
|
|
8727
|
-
] }),
|
|
8728
|
-
providerHasEndpoint(provider.openaiBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsxs(ProviderFormatStatusBlock, { label: "OpenAI Chat", children: [
|
|
8729
|
-
testResults !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: testResults.openaiChat }),
|
|
8730
|
-
testResults === void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-muted-foreground", children: "Not tested yet" })
|
|
8731
|
-
] }),
|
|
8732
|
-
providerHasEndpoint(provider.openaiResponsesBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsxs(ProviderFormatStatusBlock, { label: "OpenAI Responses", children: [
|
|
8733
|
-
testResults !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: testResults.openaiResponses }),
|
|
8734
|
-
testResults === void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-muted-foreground", children: "Not tested yet" })
|
|
8735
|
-
] }),
|
|
8736
|
-
!providerHasEndpoint(provider.openaiResponsesBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "min-w-0 rounded-md border border-border/50 bg-transparent p-2 text-xs text-muted-foreground/75", children: "OpenAI Responses not configured" })
|
|
9188
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "space-y-2", children: [
|
|
9189
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "text-xs font-medium text-foreground/80", children: "Connection probes" }),
|
|
9190
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ProviderTestMatrix, { provider, results: testResults })
|
|
8737
9191
|
] }),
|
|
8738
|
-
testResults
|
|
8739
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
8740
|
-
"button",
|
|
8741
|
-
{
|
|
8742
|
-
type: "button",
|
|
8743
|
-
onClick: () => setShowModelResults((value) => !value),
|
|
8744
|
-
className: "flex items-center gap-1 text-xs text-muted-foreground transition-colors hover:text-foreground",
|
|
8745
|
-
children: [
|
|
8746
|
-
showModelResults ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-3" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-3" }),
|
|
8747
|
-
"Model Test Results (",
|
|
8748
|
-
Object.keys(testResults.models).length,
|
|
8749
|
-
")"
|
|
8750
|
-
]
|
|
8751
|
-
}
|
|
8752
|
-
),
|
|
8753
|
-
showModelResults && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 overflow-x-auto", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("table", { className: "w-full border-collapse text-xs", children: [
|
|
8754
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("thead", { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("tr", { className: "border-b border-border", children: [
|
|
8755
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "px-2 py-1 text-left font-medium text-muted-foreground", children: "Model" }),
|
|
8756
|
-
providerHasEndpoint(provider.anthropicBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "px-2 py-1 text-left font-medium text-muted-foreground", children: "Anthropic" }),
|
|
8757
|
-
providerHasEndpoint(provider.openaiBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "px-2 py-1 text-left font-medium text-muted-foreground", children: "Chat" }),
|
|
8758
|
-
providerHasEndpoint(provider.openaiResponsesBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "px-2 py-1 text-left font-medium text-muted-foreground", children: "Responses" })
|
|
8759
|
-
] }) }),
|
|
8760
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("tbody", { children: Object.entries(testResults.models).map(([modelName, modelResult]) => /* @__PURE__ */ jsxRuntimeExports.jsxs("tr", { className: "border-b border-border/50 last:border-0", children: [
|
|
8761
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "px-2 py-1 font-medium", children: modelName }),
|
|
8762
|
-
providerHasEndpoint(provider.anthropicBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "px-2 py-1 align-top", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: modelResult.anthropic }) }),
|
|
8763
|
-
providerHasEndpoint(provider.openaiBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "px-2 py-1 align-top", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: modelResult.openaiChat }) }),
|
|
8764
|
-
providerHasEndpoint(provider.openaiResponsesBaseUrl) && /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "px-2 py-1 align-top", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderFormatTestStatus, { results: modelResult.openaiResponses }) })
|
|
8765
|
-
] }, modelName)) })
|
|
8766
|
-
] }) })
|
|
8767
|
-
] })
|
|
9192
|
+
testResults !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderModelTestResultsView, { provider, testResults })
|
|
8768
9193
|
] }),
|
|
8769
9194
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-2 border-t pt-1 sm:flex-row sm:items-center sm:justify-between", children: [
|
|
8770
9195
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
@@ -13341,288 +13766,41 @@ function truncateSessionId(id) {
|
|
|
13341
13766
|
return `${id.slice(0, 12)}...${id.slice(-12)}`;
|
|
13342
13767
|
}
|
|
13343
13768
|
function buildDisplayNumberByLogId(groups) {
|
|
13344
|
-
const result = /* @__PURE__ */ new Map();
|
|
13345
|
-
for (const group of groups) {
|
|
13346
|
-
for (let index = 0; index < group.logs.length; index += 1) {
|
|
13347
|
-
const log = group.logs[index];
|
|
13348
|
-
if (log === void 0) continue;
|
|
13349
|
-
result.set(log.id, index + 1);
|
|
13350
|
-
}
|
|
13351
|
-
}
|
|
13352
|
-
return result;
|
|
13353
|
-
}
|
|
13354
|
-
function displayNumberForLog(log, displayNumberByLogId) {
|
|
13355
|
-
return displayNumberByLogId.get(log.id) ?? log.id;
|
|
13356
|
-
}
|
|
13357
|
-
function shouldShowRawExport(captureMode) {
|
|
13358
|
-
return captureMode === "full";
|
|
13359
|
-
}
|
|
13360
|
-
function getExportActionVisibility(captureMode, logCount) {
|
|
13361
|
-
const hasLogs = logCount > 0;
|
|
13362
|
-
return {
|
|
13363
|
-
redacted: hasLogs,
|
|
13364
|
-
raw: hasLogs && shouldShowRawExport(captureMode)
|
|
13365
|
-
};
|
|
13366
|
-
}
|
|
13367
|
-
function computeTokenSummary(logs) {
|
|
13368
|
-
let totalIn = 0;
|
|
13369
|
-
let totalOut = 0;
|
|
13370
|
-
for (const log of logs) {
|
|
13371
|
-
if (log.inputTokens !== null) totalIn += log.inputTokens;
|
|
13372
|
-
if (log.outputTokens !== null) totalOut += log.outputTokens;
|
|
13373
|
-
}
|
|
13374
|
-
return { totalIn, totalOut };
|
|
13375
|
-
}
|
|
13376
|
-
function formatTimeRange(logs, timeDisplayFormat) {
|
|
13377
|
-
const first = logs[0];
|
|
13378
|
-
const last = logs[logs.length - 1];
|
|
13379
|
-
if (first === void 0 || last === void 0) return null;
|
|
13380
|
-
return formatTimestampRange(first.timestamp, last.timestamp, timeDisplayFormat);
|
|
13381
|
-
}
|
|
13382
|
-
function getFirstUserAgent(logs) {
|
|
13383
|
-
for (const log of logs) {
|
|
13384
|
-
if (log.userAgent !== null && log.userAgent !== void 0 && log.userAgent !== "") {
|
|
13385
|
-
return log.userAgent;
|
|
13386
|
-
}
|
|
13387
|
-
}
|
|
13388
|
-
return null;
|
|
13389
|
-
}
|
|
13390
|
-
function hasLogFailure(log) {
|
|
13391
|
-
if (log.error !== null && log.error !== void 0 && log.error.length > 0) return true;
|
|
13392
|
-
return log.responseStatus !== null && log.responseStatus >= 400;
|
|
13393
|
-
}
|
|
13394
|
-
function getModelLabel(logs) {
|
|
13395
|
-
const models = /* @__PURE__ */ new Set();
|
|
13396
|
-
for (const log of logs) {
|
|
13397
|
-
if (log.model !== null && log.model.length > 0) {
|
|
13398
|
-
models.add(log.model);
|
|
13399
|
-
}
|
|
13400
|
-
}
|
|
13401
|
-
const sorted = [...models].sort();
|
|
13402
|
-
if (sorted.length === 0) return "Model unknown";
|
|
13403
|
-
if (sorted.length === 1) return sorted[0] ?? "Model unknown";
|
|
13404
|
-
return `${sorted.length} models`;
|
|
13405
|
-
}
|
|
13406
|
-
function getProviderLabel(logs) {
|
|
13407
|
-
const providers = /* @__PURE__ */ new Set();
|
|
13408
|
-
for (const log of logs) {
|
|
13409
|
-
if (log.providerName !== null && log.providerName !== void 0 && log.providerName.length > 0) {
|
|
13410
|
-
providers.add(log.providerName);
|
|
13411
|
-
}
|
|
13412
|
-
}
|
|
13413
|
-
const sorted = [...providers].sort();
|
|
13414
|
-
if (sorted.length === 0) return "Provider unknown";
|
|
13415
|
-
if (sorted.length === 1) return sorted[0] ?? "Provider unknown";
|
|
13416
|
-
return `${sorted.length} providers`;
|
|
13417
|
-
}
|
|
13418
|
-
function formatElapsedMs(ms) {
|
|
13419
|
-
if (ms < 1e3) return `${ms}ms`;
|
|
13420
|
-
if (ms < 6e4) {
|
|
13421
|
-
const seconds2 = ms / 1e3;
|
|
13422
|
-
return `${seconds2 < 10 ? seconds2.toFixed(1) : seconds2.toFixed(0)}s`;
|
|
13423
|
-
}
|
|
13424
|
-
const totalSeconds = Math.round(ms / 1e3);
|
|
13425
|
-
const minutes = Math.floor(totalSeconds / 60);
|
|
13426
|
-
const seconds = totalSeconds % 60;
|
|
13427
|
-
return `${minutes}m ${seconds}s`;
|
|
13428
|
-
}
|
|
13429
|
-
function formatTokenPair(inputTokens, outputTokens) {
|
|
13430
|
-
return `${formatTokens(inputTokens)} in / ${formatTokens(outputTokens)} out`;
|
|
13431
|
-
}
|
|
13432
|
-
function countSessionTurns(logs, conversationGroups) {
|
|
13433
|
-
if (logs.length === 0) return 0;
|
|
13434
|
-
if (conversationGroups.length === 0) return buildTurnGroups(logs).length;
|
|
13435
|
-
let turns = 0;
|
|
13436
|
-
for (const group of conversationGroups) {
|
|
13437
|
-
turns += buildTurnGroups(group.logs).length;
|
|
13438
|
-
}
|
|
13439
|
-
return turns;
|
|
13440
|
-
}
|
|
13441
|
-
function summarizeFinishReason({
|
|
13442
|
-
stopReason,
|
|
13443
|
-
pending,
|
|
13444
|
-
lastFailureLogNumber
|
|
13445
|
-
}) {
|
|
13446
|
-
if (pending > 0) {
|
|
13447
|
-
return {
|
|
13448
|
-
label: "In flight",
|
|
13449
|
-
detail: `${pending} request${pending === 1 ? "" : "s"} pending`,
|
|
13450
|
-
tone: "cool"
|
|
13451
|
-
};
|
|
13452
|
-
}
|
|
13453
|
-
if (lastFailureLogNumber !== null && stopReason === null) {
|
|
13454
|
-
return {
|
|
13455
|
-
label: "Error",
|
|
13456
|
-
detail: `Last failed request #${lastFailureLogNumber}`,
|
|
13457
|
-
tone: "danger"
|
|
13458
|
-
};
|
|
13459
|
-
}
|
|
13460
|
-
switch (stopReason) {
|
|
13461
|
-
case "end_turn":
|
|
13462
|
-
return { label: "End turn", detail: "Assistant completed the turn", tone: "neutral" };
|
|
13463
|
-
case "stop":
|
|
13464
|
-
return { label: "Stop", detail: "Model reached a stop condition", tone: "neutral" };
|
|
13465
|
-
case "length":
|
|
13466
|
-
return { label: "Output limit", detail: "Turn ended at max output tokens", tone: "watch" };
|
|
13467
|
-
case "tool_use":
|
|
13468
|
-
return { label: "Tool call", detail: "Assistant requested a tool", tone: "cool" };
|
|
13469
|
-
case null:
|
|
13470
|
-
return { label: "Unknown", detail: "No finish reason captured", tone: "neutral" };
|
|
13471
|
-
}
|
|
13472
|
-
}
|
|
13473
|
-
function isClientAbortError(error) {
|
|
13474
|
-
if (error === null) return false;
|
|
13475
|
-
const lower = error.toLowerCase();
|
|
13476
|
-
return lower.includes("abort") || lower.includes("cancel") || lower.includes("client disconnected") || lower.includes("stream disconnected") || lower.includes("connection closed");
|
|
13477
|
-
}
|
|
13478
|
-
function summarizeSessionOutcome({
|
|
13479
|
-
pending,
|
|
13480
|
-
failures,
|
|
13481
|
-
lengthStops,
|
|
13482
|
-
stopReason,
|
|
13483
|
-
lastFailure
|
|
13484
|
-
}) {
|
|
13485
|
-
if (lastFailure !== null && (lastFailure.status === 499 || isClientAbortError(lastFailure.error))) {
|
|
13486
|
-
return {
|
|
13487
|
-
label: "Client aborted",
|
|
13488
|
-
detail: `Request #${lastFailure.logNumber} ended before completion`,
|
|
13489
|
-
tone: "watch"
|
|
13490
|
-
};
|
|
13491
|
-
}
|
|
13492
|
-
if (pending > 0) {
|
|
13493
|
-
return {
|
|
13494
|
-
label: "In flight",
|
|
13495
|
-
detail: `${pending} request${pending === 1 ? "" : "s"} still running`,
|
|
13496
|
-
tone: "cool"
|
|
13497
|
-
};
|
|
13498
|
-
}
|
|
13499
|
-
if (lastFailure !== null && lastFailure.status !== null && lastFailure.status >= 500) {
|
|
13500
|
-
return {
|
|
13501
|
-
label: "Provider error",
|
|
13502
|
-
detail: `Request #${lastFailure.logNumber} returned HTTP ${lastFailure.status}`,
|
|
13503
|
-
tone: "danger"
|
|
13504
|
-
};
|
|
13505
|
-
}
|
|
13506
|
-
if (failures > 0 && lastFailure !== null) {
|
|
13507
|
-
return {
|
|
13508
|
-
label: "Failed",
|
|
13509
|
-
detail: `Request #${lastFailure.logNumber} needs attention`,
|
|
13510
|
-
tone: "danger"
|
|
13511
|
-
};
|
|
13512
|
-
}
|
|
13513
|
-
if (lengthStops > 0 || stopReason === "length") {
|
|
13514
|
-
return {
|
|
13515
|
-
label: "Output limited",
|
|
13516
|
-
detail: "Model stopped at the output token limit",
|
|
13517
|
-
tone: "watch"
|
|
13518
|
-
};
|
|
13519
|
-
}
|
|
13520
|
-
switch (stopReason) {
|
|
13521
|
-
case "end_turn":
|
|
13522
|
-
case "stop":
|
|
13523
|
-
return { label: "Completed", detail: "Assistant completed normally", tone: "neutral" };
|
|
13524
|
-
case "tool_use":
|
|
13525
|
-
return { label: "Tool requested", detail: "Assistant handed off to a tool", tone: "cool" };
|
|
13526
|
-
case null:
|
|
13527
|
-
return { label: "Unknown", detail: "No terminal signal captured", tone: "neutral" };
|
|
13769
|
+
const result = /* @__PURE__ */ new Map();
|
|
13770
|
+
for (const group of groups) {
|
|
13771
|
+
for (let index = 0; index < group.logs.length; index += 1) {
|
|
13772
|
+
const log = group.logs[index];
|
|
13773
|
+
if (log === void 0) continue;
|
|
13774
|
+
result.set(log.id, index + 1);
|
|
13775
|
+
}
|
|
13528
13776
|
}
|
|
13777
|
+
return result;
|
|
13529
13778
|
}
|
|
13530
|
-
function
|
|
13531
|
-
|
|
13532
|
-
|
|
13533
|
-
|
|
13534
|
-
timeDisplayFormat,
|
|
13535
|
-
slowResponseThresholdSeconds
|
|
13536
|
-
}) {
|
|
13537
|
-
let failures = 0;
|
|
13538
|
-
let pending = 0;
|
|
13539
|
-
let slow = 0;
|
|
13540
|
-
let lengthStops = 0;
|
|
13779
|
+
function displayNumberForLog(log, displayNumberByLogId) {
|
|
13780
|
+
return displayNumberByLogId.get(log.id) ?? log.id;
|
|
13781
|
+
}
|
|
13782
|
+
function computeTokenSummary(logs) {
|
|
13541
13783
|
let totalIn = 0;
|
|
13542
13784
|
let totalOut = 0;
|
|
13543
|
-
|
|
13544
|
-
let lastFailureLogNumber = null;
|
|
13545
|
-
let lastFailure = null;
|
|
13546
|
-
let slowestMs = null;
|
|
13547
|
-
let slowestLogNumber = null;
|
|
13548
|
-
let heaviestTokens = 0;
|
|
13549
|
-
let heaviestInputTokens = 0;
|
|
13550
|
-
let heaviestOutputTokens = 0;
|
|
13551
|
-
let heaviestLogNumber = null;
|
|
13552
|
-
const slowThresholdMs = slowResponseThresholdSeconds * 1e3;
|
|
13553
|
-
for (let index = 0; index < logs.length; index += 1) {
|
|
13554
|
-
const log = logs[index];
|
|
13555
|
-
if (log === void 0) continue;
|
|
13556
|
-
const logNumber = index + 1;
|
|
13557
|
-
const stopReason = extractStopReason(log);
|
|
13558
|
-
if (stopReason !== null) terminalStopReason = stopReason;
|
|
13559
|
-
if (stopReason === "length") lengthStops += 1;
|
|
13560
|
-
if (hasLogFailure(log)) {
|
|
13561
|
-
failures += 1;
|
|
13562
|
-
lastFailureLogNumber = logNumber;
|
|
13563
|
-
lastFailure = {
|
|
13564
|
-
logNumber,
|
|
13565
|
-
status: log.responseStatus,
|
|
13566
|
-
error: log.error ?? null
|
|
13567
|
-
};
|
|
13568
|
-
}
|
|
13569
|
-
if (log.responseStatus === null) pending += 1;
|
|
13570
|
-
if (slowResponseThresholdSeconds > 0 && log.elapsedMs !== null && log.elapsedMs >= slowThresholdMs) {
|
|
13571
|
-
slow += 1;
|
|
13572
|
-
}
|
|
13785
|
+
for (const log of logs) {
|
|
13573
13786
|
if (log.inputTokens !== null) totalIn += log.inputTokens;
|
|
13574
13787
|
if (log.outputTokens !== null) totalOut += log.outputTokens;
|
|
13575
|
-
|
|
13576
|
-
|
|
13577
|
-
|
|
13578
|
-
|
|
13579
|
-
|
|
13580
|
-
|
|
13581
|
-
|
|
13582
|
-
if (requestTokens > heaviestTokens) {
|
|
13583
|
-
heaviestTokens = requestTokens;
|
|
13584
|
-
heaviestInputTokens = inputTokens;
|
|
13585
|
-
heaviestOutputTokens = outputTokens;
|
|
13586
|
-
heaviestLogNumber = logNumber;
|
|
13788
|
+
}
|
|
13789
|
+
return { totalIn, totalOut };
|
|
13790
|
+
}
|
|
13791
|
+
function getFirstUserAgent(logs) {
|
|
13792
|
+
for (const log of logs) {
|
|
13793
|
+
if (log.userAgent !== null && log.userAgent !== void 0 && log.userAgent !== "") {
|
|
13794
|
+
return log.userAgent;
|
|
13587
13795
|
}
|
|
13588
13796
|
}
|
|
13589
|
-
|
|
13590
|
-
|
|
13591
|
-
|
|
13592
|
-
|
|
13593
|
-
|
|
13594
|
-
|
|
13595
|
-
|
|
13596
|
-
const outcome = summarizeSessionOutcome({
|
|
13597
|
-
pending,
|
|
13598
|
-
failures,
|
|
13599
|
-
lengthStops,
|
|
13600
|
-
stopReason: terminalStopReason,
|
|
13601
|
-
lastFailure
|
|
13602
|
-
});
|
|
13603
|
-
return {
|
|
13604
|
-
status,
|
|
13605
|
-
statusLabel: statusLabel2,
|
|
13606
|
-
modelLabel: getModelLabel(logs),
|
|
13607
|
-
providerLabel: getProviderLabel(logs),
|
|
13608
|
-
requests: logs.length,
|
|
13609
|
-
turns: countSessionTurns(logs, conversationGroups),
|
|
13610
|
-
failures,
|
|
13611
|
-
pending,
|
|
13612
|
-
slow,
|
|
13613
|
-
lengthStops,
|
|
13614
|
-
timeRange: formatTimeRange(logs, timeDisplayFormat),
|
|
13615
|
-
tokenLabel: `${formatTokens(totalIn)} in / ${formatTokens(totalOut)} out`,
|
|
13616
|
-
finishLabel: finish.label,
|
|
13617
|
-
finishDetail: finish.detail,
|
|
13618
|
-
finishTone: finish.tone,
|
|
13619
|
-
outcomeLabel: outcome.label,
|
|
13620
|
-
outcomeDetail: outcome.detail,
|
|
13621
|
-
outcomeTone: outcome.tone,
|
|
13622
|
-
slowestLabel: slowestMs === null ? "n/a" : formatElapsedMs(slowestMs),
|
|
13623
|
-
slowestDetail: slowestLogNumber === null ? "Latency pending" : `Request #${slowestLogNumber}`,
|
|
13624
|
-
heaviestDetail: heaviestLogNumber === null ? "Tokens pending" : `#${heaviestLogNumber} ${formatTokenPair(heaviestInputTokens, heaviestOutputTokens)}`
|
|
13625
|
-
};
|
|
13797
|
+
return null;
|
|
13798
|
+
}
|
|
13799
|
+
function formatTimeRange(logs, timeDisplayFormat) {
|
|
13800
|
+
const first = logs[0];
|
|
13801
|
+
const last = logs[logs.length - 1];
|
|
13802
|
+
if (first === void 0 || last === void 0) return null;
|
|
13803
|
+
return formatTimestampRange(first.timestamp, last.timestamp, timeDisplayFormat);
|
|
13626
13804
|
}
|
|
13627
13805
|
function slateMetricToneClass(tone) {
|
|
13628
13806
|
switch (tone) {
|
|
@@ -13746,35 +13924,6 @@ function SessionOpeningSlate({ stats }) {
|
|
|
13746
13924
|
] })
|
|
13747
13925
|
] });
|
|
13748
13926
|
}
|
|
13749
|
-
function resolveSessionContextScope({
|
|
13750
|
-
pinnedSessionId,
|
|
13751
|
-
selectedSession,
|
|
13752
|
-
sessions,
|
|
13753
|
-
logs
|
|
13754
|
-
}) {
|
|
13755
|
-
if (pinnedSessionId !== void 0) {
|
|
13756
|
-
const scopedLogs = logs.filter((log) => log.sessionId === pinnedSessionId);
|
|
13757
|
-
if (scopedLogs.length === 0) return null;
|
|
13758
|
-
return { label: pinnedSessionId, logs: scopedLogs, showBackLink: true };
|
|
13759
|
-
}
|
|
13760
|
-
if (selectedSession !== "__all__") {
|
|
13761
|
-
const scopedLogs = logs.filter((log) => log.sessionId === selectedSession);
|
|
13762
|
-
if (scopedLogs.length === 0) return null;
|
|
13763
|
-
return { label: selectedSession, logs: scopedLogs, showBackLink: true };
|
|
13764
|
-
}
|
|
13765
|
-
const singleSessionId = sessions.length === 1 ? sessions[0] ?? null : null;
|
|
13766
|
-
if (singleSessionId !== null) {
|
|
13767
|
-
const allVisibleLogsBelongToSession = logs.every((log) => log.sessionId === singleSessionId);
|
|
13768
|
-
if (allVisibleLogsBelongToSession) {
|
|
13769
|
-
return { label: singleSessionId, logs: [...logs], showBackLink: false };
|
|
13770
|
-
}
|
|
13771
|
-
}
|
|
13772
|
-
const allVisibleLogsAreSessionless = sessions.length === 0 && logs.length > 0 && logs.every((log) => log.sessionId === null);
|
|
13773
|
-
if (allVisibleLogsAreSessionless) {
|
|
13774
|
-
return { label: "Visible requests", logs: [...logs], showBackLink: false };
|
|
13775
|
-
}
|
|
13776
|
-
return null;
|
|
13777
|
-
}
|
|
13778
13927
|
function formatPercent(value) {
|
|
13779
13928
|
if (value === null) return "Unknown";
|
|
13780
13929
|
const percent = value * 100;
|
|
@@ -13971,23 +14120,6 @@ function SessionMembershipPanel({
|
|
|
13971
14120
|
}) })
|
|
13972
14121
|
] });
|
|
13973
14122
|
}
|
|
13974
|
-
function formatPaginationStatus({
|
|
13975
|
-
logs,
|
|
13976
|
-
pagination
|
|
13977
|
-
}) {
|
|
13978
|
-
if (pagination.isLoading && logs.length === 0) return "Loading logs...";
|
|
13979
|
-
if (logs.length === 0) return "No logs on this page";
|
|
13980
|
-
const first = logs[0];
|
|
13981
|
-
const last = logs[logs.length - 1];
|
|
13982
|
-
const range = first === void 0 || last === void 0 ? "Current page" : `#${first.id}-#${last.id}`;
|
|
13983
|
-
if (pagination.total === null) {
|
|
13984
|
-
return `Showing ${logs.length} logs (${range})`;
|
|
13985
|
-
}
|
|
13986
|
-
if (pagination.total <= logs.length) {
|
|
13987
|
-
return `Showing all ${pagination.total} logs`;
|
|
13988
|
-
}
|
|
13989
|
-
return `Showing ${logs.length} of ${pagination.total} logs (${range})`;
|
|
13990
|
-
}
|
|
13991
14123
|
function LogPaginationButton({
|
|
13992
14124
|
label,
|
|
13993
14125
|
title,
|
|
@@ -14261,11 +14393,107 @@ function CrabFamily({
|
|
|
14261
14393
|
}) })
|
|
14262
14394
|
] });
|
|
14263
14395
|
}
|
|
14396
|
+
function ThemeModeToggle() {
|
|
14397
|
+
const { themeMode, setThemeMode } = useThemeMode();
|
|
14398
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
14399
|
+
"div",
|
|
14400
|
+
{
|
|
14401
|
+
className: "border-border/70 bg-muted/70 inline-flex h-8 items-center rounded-md border p-0.5 shadow-sm",
|
|
14402
|
+
"aria-label": "Theme mode",
|
|
14403
|
+
role: "group",
|
|
14404
|
+
children: [
|
|
14405
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
14406
|
+
"button",
|
|
14407
|
+
{
|
|
14408
|
+
type: "button",
|
|
14409
|
+
onClick: () => setThemeMode("light"),
|
|
14410
|
+
className: cn(
|
|
14411
|
+
"inline-flex size-7 items-center justify-center rounded-[6px] text-muted-foreground transition-colors hover:text-foreground",
|
|
14412
|
+
themeMode === "light" && "bg-background text-foreground shadow-sm"
|
|
14413
|
+
),
|
|
14414
|
+
"aria-label": "Use light mode",
|
|
14415
|
+
"aria-pressed": themeMode === "light",
|
|
14416
|
+
title: "Light mode",
|
|
14417
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(Sun, { className: "size-3.5" })
|
|
14418
|
+
}
|
|
14419
|
+
),
|
|
14420
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
14421
|
+
"button",
|
|
14422
|
+
{
|
|
14423
|
+
type: "button",
|
|
14424
|
+
onClick: () => setThemeMode("eye-care"),
|
|
14425
|
+
className: cn(
|
|
14426
|
+
"inline-flex size-7 items-center justify-center rounded-[6px] text-muted-foreground transition-colors hover:text-foreground",
|
|
14427
|
+
themeMode === "eye-care" && "bg-background text-foreground shadow-sm"
|
|
14428
|
+
),
|
|
14429
|
+
"aria-label": "Use eye care mode",
|
|
14430
|
+
"aria-pressed": themeMode === "eye-care",
|
|
14431
|
+
title: "Eye care mode",
|
|
14432
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(Eye, { className: "size-3.5" })
|
|
14433
|
+
}
|
|
14434
|
+
),
|
|
14435
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
14436
|
+
"button",
|
|
14437
|
+
{
|
|
14438
|
+
type: "button",
|
|
14439
|
+
onClick: () => setThemeMode("dark"),
|
|
14440
|
+
className: cn(
|
|
14441
|
+
"inline-flex size-7 items-center justify-center rounded-[6px] text-muted-foreground transition-colors hover:text-foreground",
|
|
14442
|
+
themeMode === "dark" && "bg-background text-foreground shadow-sm"
|
|
14443
|
+
),
|
|
14444
|
+
"aria-label": "Use dark mode",
|
|
14445
|
+
"aria-pressed": themeMode === "dark",
|
|
14446
|
+
title: "Dark mode",
|
|
14447
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(Moon, { className: "size-3.5" })
|
|
14448
|
+
}
|
|
14449
|
+
)
|
|
14450
|
+
]
|
|
14451
|
+
}
|
|
14452
|
+
);
|
|
14453
|
+
}
|
|
14454
|
+
function UiScaleControl({
|
|
14455
|
+
preference,
|
|
14456
|
+
resolvedScale,
|
|
14457
|
+
onChange
|
|
14458
|
+
}) {
|
|
14459
|
+
const resolvedLabel = formatUiScale(resolvedScale);
|
|
14460
|
+
const currentLabel = preference === "auto" ? `Auto (${resolvedLabel})` : `${preference}%`;
|
|
14461
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
14462
|
+
Select,
|
|
14463
|
+
{
|
|
14464
|
+
value: preference,
|
|
14465
|
+
onValueChange: (value) => onChange(normalizeUiScalePreference(value)),
|
|
14466
|
+
children: [
|
|
14467
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
14468
|
+
SelectTrigger,
|
|
14469
|
+
{
|
|
14470
|
+
size: "sm",
|
|
14471
|
+
className: "bg-white/[0.035] hover:bg-white/[0.065] h-8 min-w-[4rem] justify-center gap-1 border-0 px-2 py-0 text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] [&>svg:last-child]:hidden",
|
|
14472
|
+
"aria-label": `Interface size: ${currentLabel}`,
|
|
14473
|
+
children: [
|
|
14474
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ALargeSmall, { className: "size-3.5" }),
|
|
14475
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-[10px] font-semibold tabular-nums", children: resolvedLabel })
|
|
14476
|
+
]
|
|
14477
|
+
}
|
|
14478
|
+
),
|
|
14479
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(SelectContent, { align: "end", children: [
|
|
14480
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: "auto", children: "Auto" }),
|
|
14481
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: "100", children: "100%" }),
|
|
14482
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: "125", children: "125%" }),
|
|
14483
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: "150", children: "150%" })
|
|
14484
|
+
] })
|
|
14485
|
+
]
|
|
14486
|
+
}
|
|
14487
|
+
);
|
|
14488
|
+
}
|
|
14264
14489
|
function BrandHeader({
|
|
14265
14490
|
compact,
|
|
14266
14491
|
crabEntrancePhase,
|
|
14267
14492
|
currentSessionId,
|
|
14268
|
-
logCount
|
|
14493
|
+
logCount,
|
|
14494
|
+
uiScalePreference,
|
|
14495
|
+
resolvedUiScale,
|
|
14496
|
+
onUiScaleChange
|
|
14269
14497
|
}) {
|
|
14270
14498
|
if (compact) {
|
|
14271
14499
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "bg-white/[0.035] shadow-[inset_0_1px_0_rgba(255,255,255,0.045),0_16px_44px_rgba(0,0,0,0.18)] rounded-[8px] p-3", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [
|
|
@@ -14283,6 +14511,15 @@ function BrandHeader({
|
|
|
14283
14511
|
] })
|
|
14284
14512
|
] }),
|
|
14285
14513
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [
|
|
14514
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ThemeModeToggle, {}),
|
|
14515
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
14516
|
+
UiScaleControl,
|
|
14517
|
+
{
|
|
14518
|
+
preference: uiScalePreference,
|
|
14519
|
+
resolvedScale: resolvedUiScale,
|
|
14520
|
+
onChange: onUiScaleChange
|
|
14521
|
+
}
|
|
14522
|
+
),
|
|
14286
14523
|
/* @__PURE__ */ jsxRuntimeExports.jsx(AlertsDialog, {}),
|
|
14287
14524
|
/* @__PURE__ */ jsxRuntimeExports.jsx(GroupsDialog, {}),
|
|
14288
14525
|
/* @__PURE__ */ jsxRuntimeExports.jsx(AgentLabDialog, { currentSessionId, logCount }),
|
|
@@ -14308,6 +14545,15 @@ function BrandHeader({
|
|
|
14308
14545
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "max-w-full text-sm font-semibold text-muted-foreground", children: "Local First. Evidence First." })
|
|
14309
14546
|
] }),
|
|
14310
14547
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-1 justify-end gap-1", children: [
|
|
14548
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ThemeModeToggle, {}),
|
|
14549
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
14550
|
+
UiScaleControl,
|
|
14551
|
+
{
|
|
14552
|
+
preference: uiScalePreference,
|
|
14553
|
+
resolvedScale: resolvedUiScale,
|
|
14554
|
+
onChange: onUiScaleChange
|
|
14555
|
+
}
|
|
14556
|
+
),
|
|
14311
14557
|
/* @__PURE__ */ jsxRuntimeExports.jsx(AlertsDialog, {}),
|
|
14312
14558
|
/* @__PURE__ */ jsxRuntimeExports.jsx(GroupsDialog, {}),
|
|
14313
14559
|
/* @__PURE__ */ jsxRuntimeExports.jsx(AgentLabDialog, { currentSessionId, logCount }),
|
|
@@ -14881,6 +15127,7 @@ function ProxyViewer({
|
|
|
14881
15127
|
}) {
|
|
14882
15128
|
const { totalIn, totalOut } = reactExports.useMemo(() => computeTokenSummary(logs), [logs]);
|
|
14883
15129
|
const { providers } = useProviders();
|
|
15130
|
+
const { uiScalePreference, resolvedUiScale, setUiScalePreference } = useUiScale();
|
|
14884
15131
|
const [exporting, setExporting] = reactExports.useState(null);
|
|
14885
15132
|
const [exportError, setExportError] = reactExports.useState(null);
|
|
14886
15133
|
const [importing, setImporting] = reactExports.useState(false);
|
|
@@ -15122,7 +15369,7 @@ function ProxyViewer({
|
|
|
15122
15369
|
onClick: toggleDetailsPanelCollapsed,
|
|
15123
15370
|
className: cn(
|
|
15124
15371
|
"group fixed top-1/2 right-3 z-40 inline-flex h-14 w-7 -translate-y-1/2 items-center justify-center rounded-l-md border border-white/[0.08] bg-background/90 text-muted-foreground shadow-[0_12px_34px_rgba(0,0,0,0.26),inset_0_1px_0_rgba(255,255,255,0.06)] backdrop-blur transition-[right,background-color,color,border-color] duration-200 hover:border-white/[0.16] hover:bg-white/[0.07] hover:text-foreground focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none",
|
|
15125
|
-
detailsPanelCollapsed ? "right-3" : "lg:right-[
|
|
15372
|
+
detailsPanelCollapsed ? "right-3" : "lg:right-[calc(21.25rem-0.875rem)] xl:right-[calc(22.5rem-0.875rem)]"
|
|
15126
15373
|
),
|
|
15127
15374
|
"aria-label": detailsPanelCollapsed ? "Show details panel" : "Hide details panel",
|
|
15128
15375
|
title: detailsPanelCollapsed ? "Show details panel" : "Hide details panel",
|
|
@@ -15138,7 +15385,7 @@ function ProxyViewer({
|
|
|
15138
15385
|
{
|
|
15139
15386
|
className: cn(
|
|
15140
15387
|
"grid w-full min-w-0 grid-cols-1 lg:min-h-0 lg:flex-1 lg:overflow-hidden",
|
|
15141
|
-
detailsPanelCollapsed ? "lg:grid-cols-[minmax(0,1fr)]" : "lg:grid-cols-[minmax(0,1fr)
|
|
15388
|
+
detailsPanelCollapsed ? "lg:grid-cols-[minmax(0,1fr)]" : "lg:grid-cols-[minmax(0,1fr)_21.25rem] xl:grid-cols-[minmax(0,1fr)_22.5rem]"
|
|
15142
15389
|
),
|
|
15143
15390
|
children: [
|
|
15144
15391
|
!detailsPanelCollapsed && /* @__PURE__ */ jsxRuntimeExports.jsx("aside", { className: "bg-background/95 order-1 border-b border-white/[0.045] lg:order-2 lg:h-full lg:overflow-y-auto lg:border-b-0 lg:border-l lg:border-white/[0.055] inspector-scrollbar", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4 p-4", children: [
|
|
@@ -15148,7 +15395,10 @@ function ProxyViewer({
|
|
|
15148
15395
|
compact: true,
|
|
15149
15396
|
crabEntrancePhase,
|
|
15150
15397
|
currentSessionId: labSessionId,
|
|
15151
|
-
logCount: logs.length
|
|
15398
|
+
logCount: logs.length,
|
|
15399
|
+
uiScalePreference,
|
|
15400
|
+
resolvedUiScale,
|
|
15401
|
+
onUiScaleChange: setUiScalePreference
|
|
15152
15402
|
}
|
|
15153
15403
|
),
|
|
15154
15404
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(SidebarPanel, { label: "Session", children: [
|
|
@@ -15489,6 +15739,32 @@ function ProxyViewer({
|
|
|
15489
15739
|
) })
|
|
15490
15740
|
] });
|
|
15491
15741
|
}
|
|
15742
|
+
function filterLogs(logs, selectedSession, selectedModel) {
|
|
15743
|
+
if (selectedSession === "__all__" && selectedModel === "__all__") return logs;
|
|
15744
|
+
return logs.filter((l) => {
|
|
15745
|
+
if (selectedSession !== "__all__" && l.sessionId !== selectedSession) return false;
|
|
15746
|
+
if (selectedModel !== "__all__" && l.model !== selectedModel) return false;
|
|
15747
|
+
return true;
|
|
15748
|
+
});
|
|
15749
|
+
}
|
|
15750
|
+
function mergeLogsById(previousLogs, incomingLogs) {
|
|
15751
|
+
if (previousLogs.length === 0) return [...incomingLogs];
|
|
15752
|
+
if (incomingLogs.length === 0) return [...previousLogs];
|
|
15753
|
+
const byId = /* @__PURE__ */ new Map();
|
|
15754
|
+
for (const log of previousLogs) byId.set(log.id, log);
|
|
15755
|
+
for (const log of incomingLogs) byId.set(log.id, log);
|
|
15756
|
+
return [...byId.values()].toSorted((left, right) => left.id - right.id);
|
|
15757
|
+
}
|
|
15758
|
+
function mergeSessionIds(previousSessions, incomingSessions) {
|
|
15759
|
+
const merged = /* @__PURE__ */ new Set();
|
|
15760
|
+
for (const session of previousSessions) {
|
|
15761
|
+
if (session !== "") merged.add(session);
|
|
15762
|
+
}
|
|
15763
|
+
for (const session of incomingSessions) {
|
|
15764
|
+
if (session !== "") merged.add(session);
|
|
15765
|
+
}
|
|
15766
|
+
return [...merged].sort();
|
|
15767
|
+
}
|
|
15492
15768
|
const SSEUpdateSchema = union([
|
|
15493
15769
|
object({
|
|
15494
15770
|
type: literal("init"),
|
|
@@ -15549,14 +15825,6 @@ function extractModels(logs) {
|
|
|
15549
15825
|
}
|
|
15550
15826
|
return [...set];
|
|
15551
15827
|
}
|
|
15552
|
-
function filterLogs(logs, selectedSession, selectedModel) {
|
|
15553
|
-
if (selectedSession === "__all__" && selectedModel === "__all__") return logs;
|
|
15554
|
-
return logs.filter((l) => {
|
|
15555
|
-
if (selectedSession !== "__all__" && l.sessionId !== selectedSession) return false;
|
|
15556
|
-
if (selectedModel !== "__all__" && l.model !== selectedModel) return false;
|
|
15557
|
-
return true;
|
|
15558
|
-
});
|
|
15559
|
-
}
|
|
15560
15828
|
const DEBOUNCE_MS = 100;
|
|
15561
15829
|
const HASH_SCROLL_ATTEMPTS = 12;
|
|
15562
15830
|
const HASH_HIGHLIGHT_MS = 1800;
|
|
@@ -15641,27 +15909,6 @@ async function deleteAllGroupsForFullHistoryDelete() {
|
|
|
15641
15909
|
return { deleted: 0, ok: false };
|
|
15642
15910
|
}
|
|
15643
15911
|
}
|
|
15644
|
-
function mergeLogsById(previousLogs, incomingLogs) {
|
|
15645
|
-
if (incomingLogs.length === 0) return [...previousLogs];
|
|
15646
|
-
const byId = /* @__PURE__ */ new Map();
|
|
15647
|
-
for (const log of previousLogs) {
|
|
15648
|
-
byId.set(log.id, log);
|
|
15649
|
-
}
|
|
15650
|
-
for (const log of incomingLogs) {
|
|
15651
|
-
byId.set(log.id, log);
|
|
15652
|
-
}
|
|
15653
|
-
return [...byId.values()].sort((left, right) => left.id - right.id);
|
|
15654
|
-
}
|
|
15655
|
-
function mergeSessionIds(previousSessions, incomingSessions) {
|
|
15656
|
-
const sessions = /* @__PURE__ */ new Set();
|
|
15657
|
-
for (const session of previousSessions) {
|
|
15658
|
-
if (session !== "") sessions.add(session);
|
|
15659
|
-
}
|
|
15660
|
-
for (const session of incomingSessions) {
|
|
15661
|
-
if (session !== "") sessions.add(session);
|
|
15662
|
-
}
|
|
15663
|
-
return [...sessions].sort();
|
|
15664
|
-
}
|
|
15665
15912
|
function ProxyViewerContainer({
|
|
15666
15913
|
initialSessionId
|
|
15667
15914
|
} = {}) {
|