@tonyclaw/agent-inspector 3.0.23 → 3.0.25
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-CFedvZHU.js → CompareDrawer-BnvOPwpe.js} +1 -1
- package/.output/public/assets/ProxyViewerContainer-DcqFqo1m.js +127 -0
- package/.output/public/assets/{ReplayDialog-X-fRSKAu.js → ReplayDialog-BJgoQWdW.js} +1 -1
- package/.output/public/assets/{RequestAnatomy-S8qB5nVg.js → RequestAnatomy-CpBZEHnM.js} +1 -1
- package/.output/public/assets/{ResponseView-_rcOWSwJ.js → ResponseView-CWmyRb2M.js} +2 -2
- package/.output/public/assets/{StreamingChunkSequence-Bc15AVpN.js → StreamingChunkSequence-BWhC8bwx.js} +1 -1
- package/.output/public/assets/{_sessionId-Cz-HW2Wf.js → _sessionId-Cq-2OqUU.js} +1 -1
- package/.output/public/assets/{index-CEgwWY3E.js → index-BKi9IRtV.js} +71 -7
- package/.output/public/assets/index-BMYuDL5X.css +1 -0
- package/.output/public/assets/{index-CXYBU0j8.js → index-Cf8O0Oos.js} +1 -1
- package/.output/public/assets/{index-ClKXooQd.js → index-DdgTJ4QJ.js} +1 -1
- package/.output/public/assets/{json-viewer-QfU4qGdd.js → json-viewer-Bqu_4hmm.js} +1 -1
- package/.output/server/_libs/lucide-react.mjs +306 -246
- package/.output/server/{_sessionId-9FAmYZVf.mjs → _sessionId-Ba7H3Gjw.mjs} +2 -2
- package/.output/server/_ssr/{CompareDrawer-BLKjOzwD.mjs → CompareDrawer-aH59Ab6x.mjs} +3 -3
- package/.output/server/_ssr/{ProxyViewerContainer-Dcs2Mq8l.mjs → ProxyViewerContainer-By-I0tJv.mjs} +1791 -1259
- package/.output/server/_ssr/{ReplayDialog-oyiF4LIo.mjs → ReplayDialog-BO4Vy0et.mjs} +4 -4
- package/.output/server/_ssr/{RequestAnatomy-DkyQXSuj.mjs → RequestAnatomy-FtOr7vSS.mjs} +3 -3
- package/.output/server/_ssr/{ResponseView-3NTDEiDh.mjs → ResponseView-cvw6ajue.mjs} +3 -3
- package/.output/server/_ssr/{StreamingChunkSequence-DRq-5Bgn.mjs → StreamingChunkSequence-Oc8S2kD6.mjs} +3 -3
- package/.output/server/_ssr/{index-dtMiNUa1.mjs → index-BDRlQheR.mjs} +2 -2
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{json-viewer-BhUwicvp.mjs → json-viewer-Cd6trhQr.mjs} +3 -3
- package/.output/server/_ssr/{router-DO0OntUK.mjs → router-bofP-Ekl.mjs} +296 -91
- package/.output/server/{_tanstack-start-manifest_v-DO5v3BHY.mjs → _tanstack-start-manifest_v-BPuf86qB.mjs} +1 -1
- package/.output/server/index.mjs +76 -76
- package/package.json +3 -2
- package/src/components/ProxyViewer.tsx +138 -740
- package/src/components/ProxyViewerContainer.tsx +5 -47
- package/src/components/alerts/AlertsDialog.tsx +6 -2
- package/src/components/inspector-pet/InspectorPet.tsx +390 -0
- package/src/components/inspector-pet/inspectorPetLogic.ts +273 -0
- 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 +403 -24
- package/.output/public/assets/ProxyViewerContainer-BlCrBvdm.js +0 -127
- package/.output/public/assets/index-B_SIQ47i.css +0 -1
package/.output/server/_ssr/{ProxyViewerContainer-Dcs2Mq8l.mjs → ProxyViewerContainer-By-I0tJv.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-bofP-Ekl.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,
|
|
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, H as Heart, e as Pause, f as Play, g as Plus, B as BrainCircuit, L as LoaderCircle, h as Send, A as ArrowLeft, i as ChevronUp, j as Copy, k as ChevronsLeft, l as ChevronLeft, m as ChevronRight, n as ChevronsRight, o as Clapperboard, p as Flag, q as Siren, r as Timer, G as Gauge, s as Sun, E as Eye, M as Moon, t as ALargeSmall, u as Layers, v as FlaskConical, w as Sparkles, x as Activity, y as Beaker, N as Network, z as Terminal, J as Settings, K as Monitor, O as Rocket, Q as PackageCheck, V as History, W as Scan, Y as CircleAlert, Z as ArrowUpRight, _ as ArrowDownRight, $ as Cpu, a0 as FolderOpen, a1 as Bell, a2 as Clock3, a3 as ShieldAlert, a4 as EyeOff, a5 as ExternalLink, a6 as Clock, a7 as RotateCw, a8 as Pencil, a9 as MessageSquare, aa as Zap, ab as Wrench, ac as Brain, ad as CircleCheckBig, ae as Minus, af as CircleX, ag as ShieldCheck, ah as Save, ai as FileSearch, aj as CloudUpload, ak as CircleQuestionMark, al as Server, am as Lock, an as Wifi, ao as WifiOff, ap as OctagonAlert, aq as Radio, ar as Globe, as as FileTerminal, at as ChevronsUp, au as ChevronsDown, av as FileDiff, aw as RotateCcw, ax as GitCompareArrows, ay as ArrowUp, az as ArrowDown, aA as Ellipsis, aB as CodeXml, aC as Blocks, aD as MousePointerClick, aE as FileText, aF as Rows3, aG 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-aH59Ab6x.mjs").then((m) => ({ default: m.CompareDrawer }))
|
|
2476
2529
|
);
|
|
2477
2530
|
const LazyReplayDialog = reactExports.lazy(
|
|
2478
|
-
() => import("./ReplayDialog-
|
|
2531
|
+
() => import("./ReplayDialog-BO4Vy0et.mjs").then((m) => ({ default: m.ReplayDialog }))
|
|
2479
2532
|
);
|
|
2480
2533
|
const LazyRequestAnatomy = reactExports.lazy(
|
|
2481
|
-
() => import("./RequestAnatomy-
|
|
2534
|
+
() => import("./RequestAnatomy-FtOr7vSS.mjs").then((m) => ({ default: m.RequestAnatomy }))
|
|
2482
2535
|
);
|
|
2483
2536
|
const LazyResponseView = reactExports.lazy(
|
|
2484
|
-
() => import("./ResponseView-
|
|
2537
|
+
() => import("./ResponseView-cvw6ajue.mjs").then((m) => ({ default: m.ResponseView }))
|
|
2485
2538
|
);
|
|
2486
2539
|
const LazyStreamingChunkSequence = reactExports.lazy(
|
|
2487
|
-
() => import("./StreamingChunkSequence-
|
|
2540
|
+
() => import("./StreamingChunkSequence-Oc8S2kD6.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-Cd6trhQr.mjs").then((m) => ({ default: m.JsonViewer }))
|
|
2493
2546
|
);
|
|
2494
2547
|
const LazyJsonViewerFromString = reactExports.lazy(
|
|
2495
|
-
() => import("./json-viewer-
|
|
2548
|
+
() => import("./json-viewer-Cd6trhQr.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);
|
|
8324
|
-
}
|
|
8325
|
-
if (providerHasEndpoint(provider.openaiBaseUrl)) {
|
|
8326
|
-
results.push(testResults.openaiChat);
|
|
8327
|
-
}
|
|
8328
|
-
if (providerHasEndpoint(provider.openaiResponsesBaseUrl)) {
|
|
8329
|
-
results.push(testResults.openaiResponses);
|
|
8824
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-muted-foreground", children: "No testable endpoint configured." });
|
|
8330
8825
|
}
|
|
8331
|
-
return
|
|
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,176 +8965,63 @@ 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
|
}
|
|
8396
|
-
|
|
8397
|
-
|
|
8398
|
-
|
|
8399
|
-
|
|
8400
|
-
|
|
8401
|
-
return hiddenCount > 0 ? `${visible} +${hiddenCount} more` : visible;
|
|
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 !== "";
|
|
8402
8978
|
}
|
|
8403
|
-
function
|
|
8404
|
-
|
|
8405
|
-
|
|
8406
|
-
|
|
8407
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: model }),
|
|
8408
|
-
metadata !== null && metadata.contextWindow !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-foreground/80", children: formatContextWindowTokens(metadata.contextWindow) }),
|
|
8409
|
-
sourceLink !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
8410
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
8411
|
-
"a",
|
|
8412
|
-
{
|
|
8413
|
-
href: sourceLink.url,
|
|
8414
|
-
target: "_blank",
|
|
8415
|
-
rel: "noopener noreferrer",
|
|
8416
|
-
className: "inline-flex items-center gap-0.5 rounded border border-border/70 bg-background/70 px-1 font-mono text-[10px] leading-4 text-muted-foreground transition-colors hover:text-foreground",
|
|
8417
|
-
"aria-label": sourceLink.title,
|
|
8418
|
-
children: sourceLink.label
|
|
8419
|
-
}
|
|
8420
|
-
) }),
|
|
8421
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: sourceLink.title })
|
|
8422
|
-
] }) })
|
|
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
|
|
8423
8983
|
] });
|
|
8424
8984
|
}
|
|
8425
|
-
function
|
|
8426
|
-
const
|
|
8427
|
-
|
|
8428
|
-
|
|
8429
|
-
|
|
8430
|
-
|
|
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
|
-
] });
|
|
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." });
|
|
8535
8991
|
}
|
|
8536
|
-
|
|
8537
|
-
|
|
8538
|
-
|
|
8539
|
-
|
|
8540
|
-
|
|
8541
|
-
|
|
8542
|
-
|
|
8543
|
-
|
|
8544
|
-
|
|
8545
|
-
|
|
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
|
+
}
|
|
8998
|
+
function compactModelLabel(provider) {
|
|
8999
|
+
const models = provider.models ?? [];
|
|
9000
|
+
if (models.length === 0) return "No models configured";
|
|
9001
|
+
const visible = models.slice(0, 2).join(", ");
|
|
9002
|
+
const hiddenCount = models.length - 2;
|
|
9003
|
+
return hiddenCount > 0 ? `${visible} +${hiddenCount} more` : visible;
|
|
9004
|
+
}
|
|
9005
|
+
function ModelChip({ provider, model }) {
|
|
9006
|
+
const metadata = findProviderModelMetadata(provider, model);
|
|
9007
|
+
const sourceLink = getModelSourceLink(metadata?.sourceUrl);
|
|
9008
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1 rounded bg-muted px-1.5 py-0.5 text-xs text-muted-foreground", children: [
|
|
9009
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: model }),
|
|
9010
|
+
metadata !== null && metadata.contextWindow !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-foreground/80", children: formatContextWindowTokens(metadata.contextWindow) }),
|
|
9011
|
+
sourceLink !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
9012
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
9013
|
+
"a",
|
|
8546
9014
|
{
|
|
8547
|
-
|
|
8548
|
-
|
|
8549
|
-
"
|
|
8550
|
-
"
|
|
8551
|
-
|
|
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
|
-
]
|
|
9015
|
+
href: sourceLink.url,
|
|
9016
|
+
target: "_blank",
|
|
9017
|
+
rel: "noopener noreferrer",
|
|
9018
|
+
className: "inline-flex items-center gap-0.5 rounded border border-border/70 bg-background/70 px-1 font-mono text-[10px] leading-4 text-muted-foreground transition-colors hover:text-foreground",
|
|
9019
|
+
"aria-label": sourceLink.title,
|
|
9020
|
+
children: sourceLink.label
|
|
8556
9021
|
}
|
|
8557
|
-
)
|
|
8558
|
-
|
|
8559
|
-
|
|
9022
|
+
) }),
|
|
9023
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: sourceLink.title })
|
|
9024
|
+
] }) })
|
|
8560
9025
|
] });
|
|
8561
9026
|
}
|
|
8562
9027
|
function formatTimeAgo(isoString) {
|
|
@@ -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(
|
|
@@ -11651,62 +12076,591 @@ function AgentLabDialog({ currentSessionId, logCount }) {
|
|
|
11651
12076
|
response.isLoading && runnerPresets.length === 0 && [0, 1, 2, 3].map((index) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
11652
12077
|
"div",
|
|
11653
12078
|
{
|
|
11654
|
-
className: "h-32 animate-pulse rounded-lg bg-white/[0.025] shadow-[inset_0_0_0_1px_rgba(255,255,255,0.055)]"
|
|
11655
|
-
},
|
|
11656
|
-
index
|
|
11657
|
-
))
|
|
11658
|
-
] })
|
|
11659
|
-
] }),
|
|
11660
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "mt-3", children: [
|
|
11661
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-2 flex items-center justify-between gap-3", children: [
|
|
11662
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm font-semibold", children: "TonyClaw packages" }),
|
|
11663
|
-
response.isLoading && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-mono text-[11px] text-muted-foreground", children: "checking npm..." })
|
|
12079
|
+
className: "h-32 animate-pulse rounded-lg bg-white/[0.025] shadow-[inset_0_0_0_1px_rgba(255,255,255,0.055)]"
|
|
12080
|
+
},
|
|
12081
|
+
index
|
|
12082
|
+
))
|
|
12083
|
+
] })
|
|
12084
|
+
] }),
|
|
12085
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "mt-3", children: [
|
|
12086
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-2 flex items-center justify-between gap-3", children: [
|
|
12087
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm font-semibold", children: "TonyClaw packages" }),
|
|
12088
|
+
response.isLoading && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-mono text-[11px] text-muted-foreground", children: "checking npm..." })
|
|
12089
|
+
] }),
|
|
12090
|
+
response.error !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "rounded-lg bg-red-500/8 p-3 text-xs text-red-100 shadow-[inset_0_0_0_1px_rgba(248,113,113,0.16)]", children: "Package status is temporarily unavailable." }),
|
|
12091
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid gap-3 md:grid-cols-3", children: [
|
|
12092
|
+
packages.map((pkg) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
12093
|
+
PackageStatusCard,
|
|
12094
|
+
{
|
|
12095
|
+
pkg,
|
|
12096
|
+
activeTask,
|
|
12097
|
+
onStartTask: handleStartTask
|
|
12098
|
+
},
|
|
12099
|
+
pkg.id
|
|
12100
|
+
)),
|
|
12101
|
+
response.isLoading && packages.length === 0 && [0, 1, 2].map((index) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
12102
|
+
"div",
|
|
12103
|
+
{
|
|
12104
|
+
className: "h-36 animate-pulse rounded-lg bg-white/[0.025] shadow-[inset_0_0_0_1px_rgba(255,255,255,0.055)]"
|
|
12105
|
+
},
|
|
12106
|
+
index
|
|
12107
|
+
))
|
|
12108
|
+
] })
|
|
12109
|
+
] }),
|
|
12110
|
+
taskError !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-3 rounded-lg bg-red-500/8 p-3 text-xs text-red-100 shadow-[inset_0_0_0_1px_rgba(248,113,113,0.16)]", children: taskError }),
|
|
12111
|
+
recentTasks.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "mt-3", children: [
|
|
12112
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-2 flex items-center justify-between gap-3", children: [
|
|
12113
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm font-semibold", children: "Recent Lab runs" }),
|
|
12114
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "hidden font-mono text-[11px] text-muted-foreground sm:block", children: [
|
|
12115
|
+
"last ",
|
|
12116
|
+
String(recentTasks.length)
|
|
12117
|
+
] })
|
|
12118
|
+
] }),
|
|
12119
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grid gap-2 md:grid-cols-2", children: recentTasks.map((task) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
12120
|
+
RecentTaskRow,
|
|
12121
|
+
{
|
|
12122
|
+
task,
|
|
12123
|
+
selected: activeTaskId === task.id,
|
|
12124
|
+
onSelect: (selectedTask) => {
|
|
12125
|
+
setActiveTaskId(selectedTask.id);
|
|
12126
|
+
void activeTaskResponse.mutate({ task: selectedTask }, { revalidate: true });
|
|
12127
|
+
}
|
|
12128
|
+
},
|
|
12129
|
+
task.id
|
|
12130
|
+
)) })
|
|
12131
|
+
] }),
|
|
12132
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TaskConsole, { task: activeTask })
|
|
12133
|
+
] })
|
|
12134
|
+
] })
|
|
12135
|
+
] });
|
|
12136
|
+
}
|
|
12137
|
+
const INSPECTOR_PET_SIZE = 56;
|
|
12138
|
+
const INSPECTOR_PET_MARGIN = 14;
|
|
12139
|
+
const INSPECTOR_PET_EDGE_PEEK = 18;
|
|
12140
|
+
const INSPECTOR_PET_MIN_STEP = 72;
|
|
12141
|
+
const INSPECTOR_PET_MAX_STEP = 156;
|
|
12142
|
+
const INSPECTOR_PET_SLEEP_AFTER_MS = 45e3;
|
|
12143
|
+
const INSPECTOR_PET_PANEL_WIDTH = 192;
|
|
12144
|
+
const INSPECTOR_PET_PANEL_HEIGHT = 68;
|
|
12145
|
+
const INSPECTOR_PET_PANEL_GAP = 10;
|
|
12146
|
+
const INSPECTOR_PET_VERTICAL_SAFE_MARGIN = 78;
|
|
12147
|
+
function viewportScale(viewport) {
|
|
12148
|
+
const scale = viewport.scale ?? 1;
|
|
12149
|
+
return Number.isFinite(scale) && scale > 0 ? scale : 1;
|
|
12150
|
+
}
|
|
12151
|
+
function scaledMetric(value, viewport) {
|
|
12152
|
+
return value * viewportScale(viewport);
|
|
12153
|
+
}
|
|
12154
|
+
function clampUnit(value) {
|
|
12155
|
+
return Math.min(Math.max(value, 0), 1);
|
|
12156
|
+
}
|
|
12157
|
+
function maximumPetX(viewport) {
|
|
12158
|
+
const edgePeek = scaledMetric(INSPECTOR_PET_EDGE_PEEK, viewport);
|
|
12159
|
+
return Math.max(
|
|
12160
|
+
-edgePeek,
|
|
12161
|
+
viewport.width - scaledMetric(INSPECTOR_PET_SIZE, viewport) + edgePeek
|
|
12162
|
+
);
|
|
12163
|
+
}
|
|
12164
|
+
function maximumPetY(viewport) {
|
|
12165
|
+
const edgePeek = scaledMetric(INSPECTOR_PET_EDGE_PEEK, viewport);
|
|
12166
|
+
return Math.max(
|
|
12167
|
+
-edgePeek,
|
|
12168
|
+
viewport.height - scaledMetric(INSPECTOR_PET_SIZE, viewport) + edgePeek
|
|
12169
|
+
);
|
|
12170
|
+
}
|
|
12171
|
+
function clampInspectorPetPosition(position, viewport) {
|
|
12172
|
+
const edgePeek = scaledMetric(INSPECTOR_PET_EDGE_PEEK, viewport);
|
|
12173
|
+
return {
|
|
12174
|
+
x: Math.min(Math.max(position.x, -edgePeek), maximumPetX(viewport)),
|
|
12175
|
+
y: Math.min(Math.max(position.y, -edgePeek), maximumPetY(viewport))
|
|
12176
|
+
};
|
|
12177
|
+
}
|
|
12178
|
+
function nearestInspectorPetEdge(position, viewport) {
|
|
12179
|
+
const clamped = clampInspectorPetPosition(position, viewport);
|
|
12180
|
+
const edgePeek = scaledMetric(INSPECTOR_PET_EDGE_PEEK, viewport);
|
|
12181
|
+
const distances = [
|
|
12182
|
+
{ edge: "left", distance: clamped.x + edgePeek },
|
|
12183
|
+
{ edge: "right", distance: maximumPetX(viewport) - clamped.x },
|
|
12184
|
+
{ edge: "top", distance: clamped.y + INSPECTOR_PET_EDGE_PEEK },
|
|
12185
|
+
{ edge: "bottom", distance: maximumPetY(viewport) - clamped.y }
|
|
12186
|
+
];
|
|
12187
|
+
return distances.reduce((best, current) => current.distance < best.distance ? current : best).edge;
|
|
12188
|
+
}
|
|
12189
|
+
function snapInspectorPetToEdge(position, viewport) {
|
|
12190
|
+
const clamped = clampInspectorPetPosition(position, viewport);
|
|
12191
|
+
const edge = nearestInspectorPetEdge(clamped, viewport);
|
|
12192
|
+
const edgePeek = scaledMetric(INSPECTOR_PET_EDGE_PEEK, viewport);
|
|
12193
|
+
switch (edge) {
|
|
12194
|
+
case "left":
|
|
12195
|
+
return { x: -edgePeek, y: clamped.y };
|
|
12196
|
+
case "right":
|
|
12197
|
+
return { x: maximumPetX(viewport), y: clamped.y };
|
|
12198
|
+
case "top":
|
|
12199
|
+
return { x: clamped.x, y: -edgePeek };
|
|
12200
|
+
case "bottom":
|
|
12201
|
+
return { x: clamped.x, y: maximumPetY(viewport) };
|
|
12202
|
+
}
|
|
12203
|
+
}
|
|
12204
|
+
function randomInspectorPetEdgePosition(viewport, edgeSample, ySample) {
|
|
12205
|
+
const maxX = maximumPetX(viewport);
|
|
12206
|
+
const maxY = maximumPetY(viewport);
|
|
12207
|
+
const edgePeek = scaledMetric(INSPECTOR_PET_EDGE_PEEK, viewport);
|
|
12208
|
+
const minimumSafeY = Math.min(scaledMetric(INSPECTOR_PET_VERTICAL_SAFE_MARGIN, viewport), maxY);
|
|
12209
|
+
const randomY = minimumSafeY + clampUnit(ySample) * (maxY - minimumSafeY);
|
|
12210
|
+
const edgeIndex = Math.min(1, Math.floor(clampUnit(edgeSample) * 2));
|
|
12211
|
+
switch (edgeIndex) {
|
|
12212
|
+
case 0:
|
|
12213
|
+
return { x: -edgePeek, y: randomY };
|
|
12214
|
+
case 1:
|
|
12215
|
+
return { x: maxX, y: randomY };
|
|
12216
|
+
default:
|
|
12217
|
+
return { x: maxX, y: maxY };
|
|
12218
|
+
}
|
|
12219
|
+
}
|
|
12220
|
+
function nextInspectorPetWalkingPosition(position, viewport, stepSample, directionSample) {
|
|
12221
|
+
const clamped = snapInspectorPetToEdge(position, viewport);
|
|
12222
|
+
const step = scaledMetric(INSPECTOR_PET_MIN_STEP, viewport) + clampUnit(stepSample) * scaledMetric(INSPECTOR_PET_MAX_STEP - INSPECTOR_PET_MIN_STEP, viewport);
|
|
12223
|
+
const direction = directionSample >= 0.5 ? 1 : -1;
|
|
12224
|
+
const edge = nearestInspectorPetEdge(clamped, viewport);
|
|
12225
|
+
const maxX = maximumPetX(viewport);
|
|
12226
|
+
const maxY = maximumPetY(viewport);
|
|
12227
|
+
const edgePeek = scaledMetric(INSPECTOR_PET_EDGE_PEEK, viewport);
|
|
12228
|
+
const minimumSafeY = Math.min(scaledMetric(INSPECTOR_PET_VERTICAL_SAFE_MARGIN, viewport), maxY);
|
|
12229
|
+
switch (edge) {
|
|
12230
|
+
case "left":
|
|
12231
|
+
return {
|
|
12232
|
+
x: -edgePeek,
|
|
12233
|
+
y: Math.min(Math.max(clamped.y + step * direction, minimumSafeY), maxY)
|
|
12234
|
+
};
|
|
12235
|
+
case "right":
|
|
12236
|
+
return {
|
|
12237
|
+
x: maxX,
|
|
12238
|
+
y: Math.min(Math.max(clamped.y + step * direction, minimumSafeY), maxY)
|
|
12239
|
+
};
|
|
12240
|
+
case "top":
|
|
12241
|
+
return {
|
|
12242
|
+
x: Math.min(Math.max(clamped.x + step * direction, -edgePeek), maxX),
|
|
12243
|
+
y: -edgePeek
|
|
12244
|
+
};
|
|
12245
|
+
case "bottom":
|
|
12246
|
+
return {
|
|
12247
|
+
x: Math.min(Math.max(clamped.x + step * direction, -edgePeek), maxX),
|
|
12248
|
+
y: maxY
|
|
12249
|
+
};
|
|
12250
|
+
}
|
|
12251
|
+
}
|
|
12252
|
+
function inspectorPetPanelPosition(position, viewport) {
|
|
12253
|
+
const edge = nearestInspectorPetEdge(position, viewport);
|
|
12254
|
+
const petSize = scaledMetric(INSPECTOR_PET_SIZE, viewport);
|
|
12255
|
+
const panelWidth = scaledMetric(INSPECTOR_PET_PANEL_WIDTH, viewport);
|
|
12256
|
+
const panelHeight = scaledMetric(INSPECTOR_PET_PANEL_HEIGHT, viewport);
|
|
12257
|
+
const panelGap = scaledMetric(INSPECTOR_PET_PANEL_GAP, viewport);
|
|
12258
|
+
const margin = scaledMetric(INSPECTOR_PET_MARGIN, viewport);
|
|
12259
|
+
let x = position.x + petSize / 2 - panelWidth / 2;
|
|
12260
|
+
let y = position.y + petSize / 2 - panelHeight / 2;
|
|
12261
|
+
switch (edge) {
|
|
12262
|
+
case "left":
|
|
12263
|
+
x = position.x + petSize + panelGap;
|
|
12264
|
+
break;
|
|
12265
|
+
case "right":
|
|
12266
|
+
x = position.x - panelWidth - panelGap;
|
|
12267
|
+
break;
|
|
12268
|
+
case "top":
|
|
12269
|
+
y = position.y + petSize + panelGap;
|
|
12270
|
+
break;
|
|
12271
|
+
case "bottom":
|
|
12272
|
+
y = position.y - panelHeight - panelGap;
|
|
12273
|
+
break;
|
|
12274
|
+
}
|
|
12275
|
+
return {
|
|
12276
|
+
x: Math.min(Math.max(x, margin), Math.max(margin, viewport.width - panelWidth - margin)),
|
|
12277
|
+
y: Math.min(Math.max(y, margin), Math.max(margin, viewport.height - panelHeight - margin))
|
|
12278
|
+
};
|
|
12279
|
+
}
|
|
12280
|
+
function latestCapturedLog(logs) {
|
|
12281
|
+
let latest = null;
|
|
12282
|
+
for (const log of logs) {
|
|
12283
|
+
if (latest === null || log.id > latest.id) latest = log;
|
|
12284
|
+
}
|
|
12285
|
+
return latest;
|
|
12286
|
+
}
|
|
12287
|
+
function logNeedsAttention(log) {
|
|
12288
|
+
const hasHttpError = log.responseStatus !== null && log.responseStatus >= 400;
|
|
12289
|
+
const hasStreamError = log.error !== null && log.error !== void 0 && log.error !== "";
|
|
12290
|
+
return hasHttpError || hasStreamError;
|
|
12291
|
+
}
|
|
12292
|
+
function resolveInspectorPetStatus(logs, nowMs) {
|
|
12293
|
+
const pendingCount = logs.filter((log) => log.responseStatus === null).length;
|
|
12294
|
+
const capturedCount = logs.length;
|
|
12295
|
+
if (pendingCount > 0) {
|
|
12296
|
+
return {
|
|
12297
|
+
mood: "active",
|
|
12298
|
+
label: `${String(pendingCount)} request${pendingCount === 1 ? "" : "s"} in flight`,
|
|
12299
|
+
pendingCount,
|
|
12300
|
+
capturedCount
|
|
12301
|
+
};
|
|
12302
|
+
}
|
|
12303
|
+
const latest = latestCapturedLog(logs);
|
|
12304
|
+
if (latest !== null && logNeedsAttention(latest)) {
|
|
12305
|
+
return {
|
|
12306
|
+
mood: "attention",
|
|
12307
|
+
label: "Latest request needs attention",
|
|
12308
|
+
pendingCount,
|
|
12309
|
+
capturedCount
|
|
12310
|
+
};
|
|
12311
|
+
}
|
|
12312
|
+
if (latest === null) {
|
|
12313
|
+
return {
|
|
12314
|
+
mood: "idle",
|
|
12315
|
+
label: "Waiting for traffic",
|
|
12316
|
+
pendingCount,
|
|
12317
|
+
capturedCount
|
|
12318
|
+
};
|
|
12319
|
+
}
|
|
12320
|
+
const latestTimestamp = Date.parse(latest.timestamp);
|
|
12321
|
+
if (Number.isFinite(latestTimestamp) && nowMs - latestTimestamp >= INSPECTOR_PET_SLEEP_AFTER_MS) {
|
|
12322
|
+
return {
|
|
12323
|
+
mood: "sleeping",
|
|
12324
|
+
label: "All quiet",
|
|
12325
|
+
pendingCount,
|
|
12326
|
+
capturedCount
|
|
12327
|
+
};
|
|
12328
|
+
}
|
|
12329
|
+
return {
|
|
12330
|
+
mood: "idle",
|
|
12331
|
+
label: "Watching the session",
|
|
12332
|
+
pendingCount,
|
|
12333
|
+
capturedCount
|
|
12334
|
+
};
|
|
12335
|
+
}
|
|
12336
|
+
const INSPECTOR_PET_ROAMING_STORAGE_KEY = "agent-inspector.pet.roaming";
|
|
12337
|
+
const INSPECTOR_PET_MIN_DRIFT_MS = 5200;
|
|
12338
|
+
const INSPECTOR_PET_DRIFT_WINDOW_MS = 2400;
|
|
12339
|
+
const INSPECTOR_PET_PANEL_DISMISS_MS = 6e3;
|
|
12340
|
+
const INSPECTOR_PET_REACTION_MS = 760;
|
|
12341
|
+
const INSPECTOR_PET_DRAG_THRESHOLD = 4;
|
|
12342
|
+
function readViewport() {
|
|
12343
|
+
if (typeof window === "undefined") return { width: 1280, height: 720, scale: 1 };
|
|
12344
|
+
const rawScale = window.getComputedStyle(document.documentElement).getPropertyValue("--inspector-ui-scale");
|
|
12345
|
+
const parsedScale = Number.parseFloat(rawScale);
|
|
12346
|
+
const scale = Number.isFinite(parsedScale) && parsedScale > 0 ? parsedScale : 1;
|
|
12347
|
+
return {
|
|
12348
|
+
width: Math.max(window.innerWidth, INSPECTOR_PET_MARGIN * 2),
|
|
12349
|
+
height: Math.max(window.innerHeight, INSPECTOR_PET_MARGIN * 2),
|
|
12350
|
+
scale
|
|
12351
|
+
};
|
|
12352
|
+
}
|
|
12353
|
+
function readStoredRoaming() {
|
|
12354
|
+
if (typeof window === "undefined") return true;
|
|
12355
|
+
try {
|
|
12356
|
+
return window.localStorage.getItem(INSPECTOR_PET_ROAMING_STORAGE_KEY) !== "0";
|
|
12357
|
+
} catch {
|
|
12358
|
+
return true;
|
|
12359
|
+
}
|
|
12360
|
+
}
|
|
12361
|
+
function moodDotClass(mood) {
|
|
12362
|
+
switch (mood) {
|
|
12363
|
+
case "active":
|
|
12364
|
+
return "bg-cyan-400 shadow-[0_0_9px_rgba(34,211,238,0.65)]";
|
|
12365
|
+
case "attention":
|
|
12366
|
+
return "bg-red-500 shadow-[0_0_9px_rgba(239,68,68,0.55)]";
|
|
12367
|
+
case "idle":
|
|
12368
|
+
return "bg-amber-400 shadow-[0_0_8px_rgba(251,191,36,0.45)]";
|
|
12369
|
+
case "sleeping":
|
|
12370
|
+
return "bg-muted-foreground/45";
|
|
12371
|
+
}
|
|
12372
|
+
}
|
|
12373
|
+
function moodMotionClass(mood) {
|
|
12374
|
+
switch (mood) {
|
|
12375
|
+
case "active":
|
|
12376
|
+
return "inspector-pet-active";
|
|
12377
|
+
case "attention":
|
|
12378
|
+
return "inspector-pet-attention";
|
|
12379
|
+
case "idle":
|
|
12380
|
+
return "";
|
|
12381
|
+
case "sleeping":
|
|
12382
|
+
return "inspector-pet-sleeping";
|
|
12383
|
+
}
|
|
12384
|
+
}
|
|
12385
|
+
function InspectorPet({ logs }) {
|
|
12386
|
+
const [viewport, setViewport] = reactExports.useState(readViewport);
|
|
12387
|
+
const [position, setPosition] = reactExports.useState({
|
|
12388
|
+
x: INSPECTOR_PET_MARGIN,
|
|
12389
|
+
y: INSPECTOR_PET_MARGIN
|
|
12390
|
+
});
|
|
12391
|
+
const [clockMs, setClockMs] = reactExports.useState(() => Date.now());
|
|
12392
|
+
const [motionTick, setMotionTick] = reactExports.useState(0);
|
|
12393
|
+
const [panelTick, setPanelTick] = reactExports.useState(0);
|
|
12394
|
+
const [panelVisible, setPanelVisible] = reactExports.useState(false);
|
|
12395
|
+
const [reactionTick, setReactionTick] = reactExports.useState(0);
|
|
12396
|
+
const [reactionVisible, setReactionVisible] = reactExports.useState(false);
|
|
12397
|
+
const [dragging, setDragging] = reactExports.useState(false);
|
|
12398
|
+
const [roaming, setRoaming] = reactExports.useState(readStoredRoaming);
|
|
12399
|
+
const [reduceMotion, setReduceMotion] = reactExports.useState(false);
|
|
12400
|
+
const dragStateRef = reactExports.useRef(null);
|
|
12401
|
+
const dragOccurredRef = reactExports.useRef(false);
|
|
12402
|
+
const status = reactExports.useMemo(() => resolveInspectorPetStatus(logs, clockMs), [clockMs, logs]);
|
|
12403
|
+
const panelPosition = reactExports.useMemo(
|
|
12404
|
+
() => inspectorPetPanelPosition(position, viewport),
|
|
12405
|
+
[position, viewport]
|
|
12406
|
+
);
|
|
12407
|
+
reactExports.useEffect(() => {
|
|
12408
|
+
const nextViewport = readViewport();
|
|
12409
|
+
setViewport(nextViewport);
|
|
12410
|
+
setPosition(randomInspectorPetEdgePosition(nextViewport, Math.random(), Math.random()));
|
|
12411
|
+
}, []);
|
|
12412
|
+
reactExports.useEffect(() => {
|
|
12413
|
+
const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
12414
|
+
const handleChange = (event) => setReduceMotion(event.matches);
|
|
12415
|
+
setReduceMotion(mediaQuery.matches);
|
|
12416
|
+
mediaQuery.addEventListener("change", handleChange);
|
|
12417
|
+
return () => mediaQuery.removeEventListener("change", handleChange);
|
|
12418
|
+
}, []);
|
|
12419
|
+
reactExports.useEffect(() => {
|
|
12420
|
+
const intervalId = window.setInterval(() => setClockMs(Date.now()), 15e3);
|
|
12421
|
+
return () => window.clearInterval(intervalId);
|
|
12422
|
+
}, []);
|
|
12423
|
+
reactExports.useEffect(() => {
|
|
12424
|
+
try {
|
|
12425
|
+
window.localStorage.setItem(INSPECTOR_PET_ROAMING_STORAGE_KEY, roaming ? "1" : "0");
|
|
12426
|
+
} catch {
|
|
12427
|
+
}
|
|
12428
|
+
}, [roaming]);
|
|
12429
|
+
reactExports.useEffect(() => {
|
|
12430
|
+
if (!roaming || dragging || reduceMotion) return void 0;
|
|
12431
|
+
let timeoutId = null;
|
|
12432
|
+
const scheduleDrift = () => {
|
|
12433
|
+
const delay = INSPECTOR_PET_MIN_DRIFT_MS + Math.random() * INSPECTOR_PET_DRIFT_WINDOW_MS;
|
|
12434
|
+
timeoutId = window.setTimeout(() => {
|
|
12435
|
+
setMotionTick((current) => current + 1);
|
|
12436
|
+
setPosition(
|
|
12437
|
+
(current) => nextInspectorPetWalkingPosition(current, viewport, Math.random(), Math.random())
|
|
12438
|
+
);
|
|
12439
|
+
scheduleDrift();
|
|
12440
|
+
}, delay);
|
|
12441
|
+
};
|
|
12442
|
+
scheduleDrift();
|
|
12443
|
+
return () => {
|
|
12444
|
+
if (timeoutId !== null) window.clearTimeout(timeoutId);
|
|
12445
|
+
};
|
|
12446
|
+
}, [dragging, reduceMotion, roaming, viewport]);
|
|
12447
|
+
reactExports.useEffect(() => {
|
|
12448
|
+
const handleResize = () => {
|
|
12449
|
+
const nextViewport = readViewport();
|
|
12450
|
+
setViewport(nextViewport);
|
|
12451
|
+
setPosition((current) => snapInspectorPetToEdge(current, nextViewport));
|
|
12452
|
+
};
|
|
12453
|
+
window.addEventListener("resize", handleResize);
|
|
12454
|
+
return () => window.removeEventListener("resize", handleResize);
|
|
12455
|
+
}, []);
|
|
12456
|
+
reactExports.useEffect(() => {
|
|
12457
|
+
if (!panelVisible) return void 0;
|
|
12458
|
+
const timeoutId = window.setTimeout(
|
|
12459
|
+
() => setPanelVisible(false),
|
|
12460
|
+
INSPECTOR_PET_PANEL_DISMISS_MS
|
|
12461
|
+
);
|
|
12462
|
+
return () => window.clearTimeout(timeoutId);
|
|
12463
|
+
}, [panelTick, panelVisible]);
|
|
12464
|
+
reactExports.useEffect(() => {
|
|
12465
|
+
if (!reactionVisible) return void 0;
|
|
12466
|
+
const timeoutId = window.setTimeout(() => setReactionVisible(false), INSPECTOR_PET_REACTION_MS);
|
|
12467
|
+
return () => window.clearTimeout(timeoutId);
|
|
12468
|
+
}, [reactionTick, reactionVisible]);
|
|
12469
|
+
const handlePet = reactExports.useCallback(() => {
|
|
12470
|
+
if (dragOccurredRef.current) {
|
|
12471
|
+
dragOccurredRef.current = false;
|
|
12472
|
+
return;
|
|
12473
|
+
}
|
|
12474
|
+
setClockMs(Date.now());
|
|
12475
|
+
setPanelTick((current) => current + 1);
|
|
12476
|
+
setPanelVisible(true);
|
|
12477
|
+
setReactionTick((current) => current + 1);
|
|
12478
|
+
setReactionVisible(true);
|
|
12479
|
+
}, []);
|
|
12480
|
+
const handlePointerDown = reactExports.useCallback((event) => {
|
|
12481
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
12482
|
+
dragOccurredRef.current = false;
|
|
12483
|
+
dragStateRef.current = {
|
|
12484
|
+
pointerId: event.pointerId,
|
|
12485
|
+
offsetX: event.clientX - rect.left,
|
|
12486
|
+
offsetY: event.clientY - rect.top,
|
|
12487
|
+
startX: event.clientX,
|
|
12488
|
+
startY: event.clientY,
|
|
12489
|
+
moved: false
|
|
12490
|
+
};
|
|
12491
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
12492
|
+
setPanelVisible(false);
|
|
12493
|
+
setDragging(true);
|
|
12494
|
+
}, []);
|
|
12495
|
+
const handlePointerMove = reactExports.useCallback(
|
|
12496
|
+
(event) => {
|
|
12497
|
+
const dragState = dragStateRef.current;
|
|
12498
|
+
if (dragState === null || dragState.pointerId !== event.pointerId) return;
|
|
12499
|
+
const moved = dragState.moved || Math.abs(event.clientX - dragState.startX) >= INSPECTOR_PET_DRAG_THRESHOLD || Math.abs(event.clientY - dragState.startY) >= INSPECTOR_PET_DRAG_THRESHOLD;
|
|
12500
|
+
dragState.moved = moved;
|
|
12501
|
+
dragOccurredRef.current = moved;
|
|
12502
|
+
setPosition(
|
|
12503
|
+
clampInspectorPetPosition(
|
|
12504
|
+
{
|
|
12505
|
+
x: event.clientX - dragState.offsetX,
|
|
12506
|
+
y: event.clientY - dragState.offsetY
|
|
12507
|
+
},
|
|
12508
|
+
viewport
|
|
12509
|
+
)
|
|
12510
|
+
);
|
|
12511
|
+
},
|
|
12512
|
+
[viewport]
|
|
12513
|
+
);
|
|
12514
|
+
const handlePointerUp = reactExports.useCallback(
|
|
12515
|
+
(event) => {
|
|
12516
|
+
const dragState = dragStateRef.current;
|
|
12517
|
+
if (dragState === null || dragState.pointerId !== event.pointerId) return;
|
|
12518
|
+
if (event.currentTarget.hasPointerCapture(event.pointerId)) {
|
|
12519
|
+
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
12520
|
+
}
|
|
12521
|
+
dragOccurredRef.current = dragState.moved;
|
|
12522
|
+
dragStateRef.current = null;
|
|
12523
|
+
setDragging(false);
|
|
12524
|
+
setPosition((current) => snapInspectorPetToEdge(current, viewport));
|
|
12525
|
+
},
|
|
12526
|
+
[viewport]
|
|
12527
|
+
);
|
|
12528
|
+
const handlePointerCancel = reactExports.useCallback((event) => {
|
|
12529
|
+
if (event.currentTarget.hasPointerCapture(event.pointerId)) {
|
|
12530
|
+
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
12531
|
+
}
|
|
12532
|
+
dragStateRef.current = null;
|
|
12533
|
+
dragOccurredRef.current = false;
|
|
12534
|
+
setDragging(false);
|
|
12535
|
+
}, []);
|
|
12536
|
+
const petStyle = reactExports.useMemo(
|
|
12537
|
+
() => ({
|
|
12538
|
+
transform: `translate3d(${String(position.x)}px, ${String(position.y)}px, 0) rotate(${motionTick % 2 === 0 ? "-4deg" : "5deg"}) scale(${dragging ? "1.08" : "1"})`,
|
|
12539
|
+
transition: dragging ? "none" : "transform 4800ms cubic-bezier(0.33, 1, 0.68, 1)",
|
|
12540
|
+
touchAction: "none"
|
|
12541
|
+
}),
|
|
12542
|
+
[dragging, motionTick, position.x, position.y]
|
|
12543
|
+
);
|
|
12544
|
+
const panelStyle = reactExports.useMemo(
|
|
12545
|
+
() => ({ left: panelPosition.x, top: panelPosition.y }),
|
|
12546
|
+
[panelPosition.x, panelPosition.y]
|
|
12547
|
+
);
|
|
12548
|
+
const roamingLabel = roaming ? "Pause pet roaming" : "Resume pet roaming";
|
|
12549
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
12550
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
12551
|
+
"button",
|
|
12552
|
+
{
|
|
12553
|
+
type: "button",
|
|
12554
|
+
className: cn(
|
|
12555
|
+
"fixed left-0 top-0 z-30 flex size-14 items-center justify-center bg-transparent text-foreground outline-none transition-[filter,opacity] duration-200 hover:opacity-95 hover:drop-shadow-[0_0_24px_rgba(245,158,11,0.36)] focus-visible:drop-shadow-[0_0_12px_rgba(251,191,36,0.72)]",
|
|
12556
|
+
dragging ? "cursor-grabbing" : "cursor-grab"
|
|
12557
|
+
),
|
|
12558
|
+
style: petStyle,
|
|
12559
|
+
"data-pet-mood": status.mood,
|
|
12560
|
+
onClick: handlePet,
|
|
12561
|
+
onPointerDown: handlePointerDown,
|
|
12562
|
+
onPointerMove: handlePointerMove,
|
|
12563
|
+
onPointerUp: handlePointerUp,
|
|
12564
|
+
onPointerCancel: handlePointerCancel,
|
|
12565
|
+
"aria-label": `Inspector pet: ${status.label}`,
|
|
12566
|
+
title: status.label,
|
|
12567
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
12568
|
+
"span",
|
|
12569
|
+
{
|
|
12570
|
+
className: cn(
|
|
12571
|
+
"relative flex size-12 items-center justify-center",
|
|
12572
|
+
reactionVisible && "inspector-pet-patted"
|
|
12573
|
+
),
|
|
12574
|
+
"aria-hidden": "true",
|
|
12575
|
+
children: [
|
|
12576
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
12577
|
+
"span",
|
|
12578
|
+
{
|
|
12579
|
+
className: cn(
|
|
12580
|
+
"relative flex size-12 items-center justify-center",
|
|
12581
|
+
moodMotionClass(status.mood)
|
|
12582
|
+
),
|
|
12583
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
12584
|
+
"span",
|
|
12585
|
+
{
|
|
12586
|
+
className: cn(
|
|
12587
|
+
"relative flex size-12 items-center justify-center",
|
|
12588
|
+
!dragging && "floating-crab-body"
|
|
12589
|
+
),
|
|
12590
|
+
children: [
|
|
12591
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(CrabLogo, { className: "relative z-10 size-11 text-amber-500 drop-shadow-[0_0_15px_rgba(245,158,11,0.30)]" }),
|
|
12592
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "pointer-events-none absolute inset-x-0 bottom-0 z-0 flex items-end justify-center gap-1 text-amber-400/80", children: [0, 1, 2, 3, 4, 5].map((leg) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
12593
|
+
"span",
|
|
12594
|
+
{
|
|
12595
|
+
className: cn(
|
|
12596
|
+
"floating-crab-leg h-2 w-0.5 rounded-full bg-current shadow-[0_0_7px_rgba(245,158,11,0.24)]",
|
|
12597
|
+
leg < 3 ? "floating-crab-leg-left" : "floating-crab-leg-right",
|
|
12598
|
+
dragging && "animate-none"
|
|
12599
|
+
),
|
|
12600
|
+
style: { animationDelay: `${String(leg % 2 === 0 ? 0 : 180)}ms` }
|
|
12601
|
+
},
|
|
12602
|
+
leg
|
|
12603
|
+
)) })
|
|
12604
|
+
]
|
|
12605
|
+
}
|
|
12606
|
+
)
|
|
12607
|
+
}
|
|
12608
|
+
),
|
|
12609
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
12610
|
+
"span",
|
|
12611
|
+
{
|
|
12612
|
+
className: cn(
|
|
12613
|
+
"absolute right-0 top-1 size-2 rounded-full border border-background/90",
|
|
12614
|
+
moodDotClass(status.mood),
|
|
12615
|
+
status.mood === "active" && !reduceMotion && "animate-pulse"
|
|
12616
|
+
)
|
|
12617
|
+
}
|
|
12618
|
+
),
|
|
12619
|
+
reactionVisible && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
12620
|
+
Heart,
|
|
12621
|
+
{
|
|
12622
|
+
className: "inspector-pet-heart absolute -right-1 -top-2 size-3.5 fill-amber-400 text-amber-400"
|
|
12623
|
+
},
|
|
12624
|
+
reactionTick
|
|
12625
|
+
)
|
|
12626
|
+
]
|
|
12627
|
+
}
|
|
12628
|
+
)
|
|
12629
|
+
}
|
|
12630
|
+
),
|
|
12631
|
+
panelVisible && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
12632
|
+
"div",
|
|
12633
|
+
{
|
|
12634
|
+
className: "fixed z-50 w-48 rounded-md border border-border/80 bg-popover/95 px-3 py-2 text-popover-foreground shadow-[0_14px_34px_rgba(0,0,0,0.28)] backdrop-blur",
|
|
12635
|
+
style: panelStyle,
|
|
12636
|
+
role: "status",
|
|
12637
|
+
"aria-live": "polite",
|
|
12638
|
+
children: [
|
|
12639
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
12640
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn("size-2 shrink-0 rounded-full", moodDotClass(status.mood)) }),
|
|
12641
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0 flex-1 truncate text-xs font-medium", children: status.label }),
|
|
12642
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
12643
|
+
"button",
|
|
12644
|
+
{
|
|
12645
|
+
type: "button",
|
|
12646
|
+
className: "inline-flex size-6 shrink-0 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none",
|
|
12647
|
+
onClick: () => setRoaming((current) => !current),
|
|
12648
|
+
"aria-label": roamingLabel,
|
|
12649
|
+
title: roamingLabel,
|
|
12650
|
+
children: roaming ? /* @__PURE__ */ jsxRuntimeExports.jsx(Pause, { className: "size-3.5" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Play, { className: "size-3.5" })
|
|
12651
|
+
}
|
|
12652
|
+
)
|
|
11664
12653
|
] }),
|
|
11665
|
-
|
|
11666
|
-
|
|
11667
|
-
|
|
11668
|
-
|
|
11669
|
-
|
|
11670
|
-
|
|
11671
|
-
activeTask,
|
|
11672
|
-
onStartTask: handleStartTask
|
|
11673
|
-
},
|
|
11674
|
-
pkg.id
|
|
11675
|
-
)),
|
|
11676
|
-
response.isLoading && packages.length === 0 && [0, 1, 2].map((index) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
11677
|
-
"div",
|
|
11678
|
-
{
|
|
11679
|
-
className: "h-36 animate-pulse rounded-lg bg-white/[0.025] shadow-[inset_0_0_0_1px_rgba(255,255,255,0.055)]"
|
|
11680
|
-
},
|
|
11681
|
-
index
|
|
11682
|
-
))
|
|
12654
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-1 flex items-center justify-between gap-3 font-mono text-[10px] text-muted-foreground", children: [
|
|
12655
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
12656
|
+
String(status.capturedCount),
|
|
12657
|
+
" captured"
|
|
12658
|
+
] }),
|
|
12659
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: status.pendingCount > 0 ? `${String(status.pendingCount)} active` : roaming ? "Roaming" : "Resting" })
|
|
11683
12660
|
] })
|
|
11684
|
-
]
|
|
11685
|
-
|
|
11686
|
-
|
|
11687
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-2 flex items-center justify-between gap-3", children: [
|
|
11688
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm font-semibold", children: "Recent Lab runs" }),
|
|
11689
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "hidden font-mono text-[11px] text-muted-foreground sm:block", children: [
|
|
11690
|
-
"last ",
|
|
11691
|
-
String(recentTasks.length)
|
|
11692
|
-
] })
|
|
11693
|
-
] }),
|
|
11694
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grid gap-2 md:grid-cols-2", children: recentTasks.map((task) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
11695
|
-
RecentTaskRow,
|
|
11696
|
-
{
|
|
11697
|
-
task,
|
|
11698
|
-
selected: activeTaskId === task.id,
|
|
11699
|
-
onSelect: (selectedTask) => {
|
|
11700
|
-
setActiveTaskId(selectedTask.id);
|
|
11701
|
-
void activeTaskResponse.mutate({ task: selectedTask }, { revalidate: true });
|
|
11702
|
-
}
|
|
11703
|
-
},
|
|
11704
|
-
task.id
|
|
11705
|
-
)) })
|
|
11706
|
-
] }),
|
|
11707
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(TaskConsole, { task: activeTask })
|
|
11708
|
-
] })
|
|
11709
|
-
] })
|
|
12661
|
+
]
|
|
12662
|
+
}
|
|
12663
|
+
)
|
|
11710
12664
|
] });
|
|
11711
12665
|
}
|
|
11712
12666
|
const DEFAULT_QUESTION = "Analyze the current Inspector session. What looks abnormal, slow, or likely to hang?";
|
|
@@ -13276,353 +14230,106 @@ function riskRank(risk) {
|
|
|
13276
14230
|
return 2;
|
|
13277
14231
|
case "ok":
|
|
13278
14232
|
return 1;
|
|
13279
|
-
}
|
|
13280
|
-
}
|
|
13281
|
-
function compareModelSummary(left, right) {
|
|
13282
|
-
const riskDelta = riskRank(right.latest.riskLevel) - riskRank(left.latest.riskLevel);
|
|
13283
|
-
if (riskDelta !== 0) return riskDelta;
|
|
13284
|
-
const leftPeak = left.peak.usagePercent ?? -1;
|
|
13285
|
-
const rightPeak = right.peak.usagePercent ?? -1;
|
|
13286
|
-
const peakDelta = rightPeak - leftPeak;
|
|
13287
|
-
if (peakDelta !== 0) return peakDelta;
|
|
13288
|
-
return right.latest.logId - left.latest.logId;
|
|
13289
|
-
}
|
|
13290
|
-
function trendPercent(first, latest) {
|
|
13291
|
-
if (first.usagePercent === null || latest.usagePercent === null) return null;
|
|
13292
|
-
return (latest.usagePercent - first.usagePercent) * 100;
|
|
13293
|
-
}
|
|
13294
|
-
function logsInAscendingIdOrder(logs) {
|
|
13295
|
-
for (let index = 1; index < logs.length; index++) {
|
|
13296
|
-
const previous = logs[index - 1];
|
|
13297
|
-
const current = logs[index];
|
|
13298
|
-
if (previous === void 0 || current === void 0) continue;
|
|
13299
|
-
if (previous.id > current.id) return [...logs].sort((left, right) => left.id - right.id);
|
|
13300
|
-
}
|
|
13301
|
-
return logs;
|
|
13302
|
-
}
|
|
13303
|
-
function buildSessionContextSummary(logs, providers = []) {
|
|
13304
|
-
const sortedLogs = logsInAscendingIdOrder(logs);
|
|
13305
|
-
const providersSignature = providerSignature(providers);
|
|
13306
|
-
const byModel = /* @__PURE__ */ new Map();
|
|
13307
|
-
for (const log of sortedLogs) {
|
|
13308
|
-
const snapshot = cachedSnapshotFromLog(log, providers, providersSignature);
|
|
13309
|
-
if (snapshot === null) continue;
|
|
13310
|
-
const existing = byModel.get(snapshot.model);
|
|
13311
|
-
if (existing === void 0) {
|
|
13312
|
-
byModel.set(snapshot.model, {
|
|
13313
|
-
model: snapshot.model,
|
|
13314
|
-
requestCount: 1,
|
|
13315
|
-
first: snapshot,
|
|
13316
|
-
latest: snapshot,
|
|
13317
|
-
peak: snapshot
|
|
13318
|
-
});
|
|
13319
|
-
continue;
|
|
13320
|
-
}
|
|
13321
|
-
byModel.set(snapshot.model, {
|
|
13322
|
-
model: existing.model,
|
|
13323
|
-
requestCount: existing.requestCount + 1,
|
|
13324
|
-
first: existing.first,
|
|
13325
|
-
latest: snapshot,
|
|
13326
|
-
peak: isHigherPeak(snapshot, existing.peak) ? snapshot : existing.peak
|
|
13327
|
-
});
|
|
13328
|
-
}
|
|
13329
|
-
const models = [...byModel.values()].map((entry) => ({
|
|
13330
|
-
model: entry.model,
|
|
13331
|
-
requestCount: entry.requestCount,
|
|
13332
|
-
first: entry.first,
|
|
13333
|
-
latest: entry.latest,
|
|
13334
|
-
peak: entry.peak,
|
|
13335
|
-
trendPercent: trendPercent(entry.first, entry.latest)
|
|
13336
|
-
})).sort(compareModelSummary);
|
|
13337
|
-
return { models };
|
|
13338
|
-
}
|
|
13339
|
-
function truncateSessionId(id) {
|
|
13340
|
-
if (id.length <= 30) return id;
|
|
13341
|
-
return `${id.slice(0, 12)}...${id.slice(-12)}`;
|
|
13342
|
-
}
|
|
13343
|
-
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`;
|
|
14233
|
+
}
|
|
13428
14234
|
}
|
|
13429
|
-
function
|
|
13430
|
-
|
|
14235
|
+
function compareModelSummary(left, right) {
|
|
14236
|
+
const riskDelta = riskRank(right.latest.riskLevel) - riskRank(left.latest.riskLevel);
|
|
14237
|
+
if (riskDelta !== 0) return riskDelta;
|
|
14238
|
+
const leftPeak = left.peak.usagePercent ?? -1;
|
|
14239
|
+
const rightPeak = right.peak.usagePercent ?? -1;
|
|
14240
|
+
const peakDelta = rightPeak - leftPeak;
|
|
14241
|
+
if (peakDelta !== 0) return peakDelta;
|
|
14242
|
+
return right.latest.logId - left.latest.logId;
|
|
13431
14243
|
}
|
|
13432
|
-
function
|
|
13433
|
-
if (
|
|
13434
|
-
|
|
13435
|
-
let turns = 0;
|
|
13436
|
-
for (const group of conversationGroups) {
|
|
13437
|
-
turns += buildTurnGroups(group.logs).length;
|
|
13438
|
-
}
|
|
13439
|
-
return turns;
|
|
14244
|
+
function trendPercent(first, latest) {
|
|
14245
|
+
if (first.usagePercent === null || latest.usagePercent === null) return null;
|
|
14246
|
+
return (latest.usagePercent - first.usagePercent) * 100;
|
|
13440
14247
|
}
|
|
13441
|
-
function
|
|
13442
|
-
|
|
13443
|
-
|
|
13444
|
-
|
|
13445
|
-
|
|
13446
|
-
|
|
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
|
-
};
|
|
14248
|
+
function logsInAscendingIdOrder(logs) {
|
|
14249
|
+
for (let index = 1; index < logs.length; index++) {
|
|
14250
|
+
const previous = logs[index - 1];
|
|
14251
|
+
const current = logs[index];
|
|
14252
|
+
if (previous === void 0 || current === void 0) continue;
|
|
14253
|
+
if (previous.id > current.id) return [...logs].sort((left, right) => left.id - right.id);
|
|
13459
14254
|
}
|
|
13460
|
-
|
|
13461
|
-
|
|
13462
|
-
|
|
13463
|
-
|
|
13464
|
-
|
|
13465
|
-
|
|
13466
|
-
|
|
13467
|
-
|
|
13468
|
-
|
|
13469
|
-
|
|
13470
|
-
|
|
14255
|
+
return logs;
|
|
14256
|
+
}
|
|
14257
|
+
function buildSessionContextSummary(logs, providers = []) {
|
|
14258
|
+
const sortedLogs = logsInAscendingIdOrder(logs);
|
|
14259
|
+
const providersSignature = providerSignature(providers);
|
|
14260
|
+
const byModel = /* @__PURE__ */ new Map();
|
|
14261
|
+
for (const log of sortedLogs) {
|
|
14262
|
+
const snapshot = cachedSnapshotFromLog(log, providers, providersSignature);
|
|
14263
|
+
if (snapshot === null) continue;
|
|
14264
|
+
const existing = byModel.get(snapshot.model);
|
|
14265
|
+
if (existing === void 0) {
|
|
14266
|
+
byModel.set(snapshot.model, {
|
|
14267
|
+
model: snapshot.model,
|
|
14268
|
+
requestCount: 1,
|
|
14269
|
+
first: snapshot,
|
|
14270
|
+
latest: snapshot,
|
|
14271
|
+
peak: snapshot
|
|
14272
|
+
});
|
|
14273
|
+
continue;
|
|
14274
|
+
}
|
|
14275
|
+
byModel.set(snapshot.model, {
|
|
14276
|
+
model: existing.model,
|
|
14277
|
+
requestCount: existing.requestCount + 1,
|
|
14278
|
+
first: existing.first,
|
|
14279
|
+
latest: snapshot,
|
|
14280
|
+
peak: isHigherPeak(snapshot, existing.peak) ? snapshot : existing.peak
|
|
14281
|
+
});
|
|
13471
14282
|
}
|
|
14283
|
+
const models = [...byModel.values()].map((entry) => ({
|
|
14284
|
+
model: entry.model,
|
|
14285
|
+
requestCount: entry.requestCount,
|
|
14286
|
+
first: entry.first,
|
|
14287
|
+
latest: entry.latest,
|
|
14288
|
+
peak: entry.peak,
|
|
14289
|
+
trendPercent: trendPercent(entry.first, entry.latest)
|
|
14290
|
+
})).sort(compareModelSummary);
|
|
14291
|
+
return { models };
|
|
13472
14292
|
}
|
|
13473
|
-
function
|
|
13474
|
-
if (
|
|
13475
|
-
|
|
13476
|
-
return lower.includes("abort") || lower.includes("cancel") || lower.includes("client disconnected") || lower.includes("stream disconnected") || lower.includes("connection closed");
|
|
14293
|
+
function truncateSessionId(id) {
|
|
14294
|
+
if (id.length <= 30) return id;
|
|
14295
|
+
return `${id.slice(0, 12)}...${id.slice(-12)}`;
|
|
13477
14296
|
}
|
|
13478
|
-
function
|
|
13479
|
-
|
|
13480
|
-
|
|
13481
|
-
|
|
13482
|
-
|
|
13483
|
-
|
|
13484
|
-
|
|
13485
|
-
|
|
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" };
|
|
14297
|
+
function buildDisplayNumberByLogId(groups) {
|
|
14298
|
+
const result = /* @__PURE__ */ new Map();
|
|
14299
|
+
for (const group of groups) {
|
|
14300
|
+
for (let index = 0; index < group.logs.length; index += 1) {
|
|
14301
|
+
const log = group.logs[index];
|
|
14302
|
+
if (log === void 0) continue;
|
|
14303
|
+
result.set(log.id, index + 1);
|
|
14304
|
+
}
|
|
13528
14305
|
}
|
|
14306
|
+
return result;
|
|
13529
14307
|
}
|
|
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;
|
|
14308
|
+
function displayNumberForLog(log, displayNumberByLogId) {
|
|
14309
|
+
return displayNumberByLogId.get(log.id) ?? log.id;
|
|
14310
|
+
}
|
|
14311
|
+
function computeTokenSummary(logs) {
|
|
13541
14312
|
let totalIn = 0;
|
|
13542
14313
|
let totalOut = 0;
|
|
13543
|
-
|
|
13544
|
-
|
|
13545
|
-
|
|
13546
|
-
|
|
13547
|
-
|
|
13548
|
-
|
|
13549
|
-
|
|
13550
|
-
|
|
13551
|
-
|
|
13552
|
-
|
|
13553
|
-
|
|
13554
|
-
|
|
13555
|
-
|
|
13556
|
-
|
|
13557
|
-
|
|
13558
|
-
|
|
13559
|
-
|
|
13560
|
-
|
|
13561
|
-
|
|
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
|
-
}
|
|
13573
|
-
if (log.inputTokens !== null) totalIn += log.inputTokens;
|
|
13574
|
-
if (log.outputTokens !== null) totalOut += log.outputTokens;
|
|
13575
|
-
if (log.elapsedMs !== null && (slowestMs === null || log.elapsedMs > slowestMs)) {
|
|
13576
|
-
slowestMs = log.elapsedMs;
|
|
13577
|
-
slowestLogNumber = logNumber;
|
|
13578
|
-
}
|
|
13579
|
-
const inputTokens = log.inputTokens ?? 0;
|
|
13580
|
-
const outputTokens = log.outputTokens ?? 0;
|
|
13581
|
-
const requestTokens = inputTokens + outputTokens;
|
|
13582
|
-
if (requestTokens > heaviestTokens) {
|
|
13583
|
-
heaviestTokens = requestTokens;
|
|
13584
|
-
heaviestInputTokens = inputTokens;
|
|
13585
|
-
heaviestOutputTokens = outputTokens;
|
|
13586
|
-
heaviestLogNumber = logNumber;
|
|
13587
|
-
}
|
|
13588
|
-
}
|
|
13589
|
-
const status = isLoading || pending > 0 && failures === 0 ? "rolling" : failures > 0 ? "failed" : slow > 0 || lengthStops > 0 ? "watch" : "clear";
|
|
13590
|
-
const statusLabel2 = status === "rolling" ? "Rolling" : status === "failed" ? "Failure" : status === "watch" ? "Watch" : "Clear";
|
|
13591
|
-
const finish = summarizeFinishReason({
|
|
13592
|
-
stopReason: terminalStopReason,
|
|
13593
|
-
pending,
|
|
13594
|
-
lastFailureLogNumber
|
|
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
|
-
};
|
|
14314
|
+
for (const log of logs) {
|
|
14315
|
+
if (log.inputTokens !== null) totalIn += log.inputTokens;
|
|
14316
|
+
if (log.outputTokens !== null) totalOut += log.outputTokens;
|
|
14317
|
+
}
|
|
14318
|
+
return { totalIn, totalOut };
|
|
14319
|
+
}
|
|
14320
|
+
function getFirstUserAgent(logs) {
|
|
14321
|
+
for (const log of logs) {
|
|
14322
|
+
if (log.userAgent !== null && log.userAgent !== void 0 && log.userAgent !== "") {
|
|
14323
|
+
return log.userAgent;
|
|
14324
|
+
}
|
|
14325
|
+
}
|
|
14326
|
+
return null;
|
|
14327
|
+
}
|
|
14328
|
+
function formatTimeRange(logs, timeDisplayFormat) {
|
|
14329
|
+
const first = logs[0];
|
|
14330
|
+
const last = logs[logs.length - 1];
|
|
14331
|
+
if (first === void 0 || last === void 0) return null;
|
|
14332
|
+
return formatTimestampRange(first.timestamp, last.timestamp, timeDisplayFormat);
|
|
13626
14333
|
}
|
|
13627
14334
|
function slateMetricToneClass(tone) {
|
|
13628
14335
|
switch (tone) {
|
|
@@ -13746,35 +14453,6 @@ function SessionOpeningSlate({ stats }) {
|
|
|
13746
14453
|
] })
|
|
13747
14454
|
] });
|
|
13748
14455
|
}
|
|
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
14456
|
function formatPercent(value) {
|
|
13779
14457
|
if (value === null) return "Unknown";
|
|
13780
14458
|
const percent = value * 100;
|
|
@@ -13971,23 +14649,6 @@ function SessionMembershipPanel({
|
|
|
13971
14649
|
}) })
|
|
13972
14650
|
] });
|
|
13973
14651
|
}
|
|
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
14652
|
function LogPaginationButton({
|
|
13992
14653
|
label,
|
|
13993
14654
|
title,
|
|
@@ -14261,11 +14922,107 @@ function CrabFamily({
|
|
|
14261
14922
|
}) })
|
|
14262
14923
|
] });
|
|
14263
14924
|
}
|
|
14925
|
+
function ThemeModeToggle() {
|
|
14926
|
+
const { themeMode, setThemeMode } = useThemeMode();
|
|
14927
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
14928
|
+
"div",
|
|
14929
|
+
{
|
|
14930
|
+
className: "border-border/70 bg-muted/70 inline-flex h-8 items-center rounded-md border p-0.5 shadow-sm",
|
|
14931
|
+
"aria-label": "Theme mode",
|
|
14932
|
+
role: "group",
|
|
14933
|
+
children: [
|
|
14934
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
14935
|
+
"button",
|
|
14936
|
+
{
|
|
14937
|
+
type: "button",
|
|
14938
|
+
onClick: () => setThemeMode("light"),
|
|
14939
|
+
className: cn(
|
|
14940
|
+
"inline-flex size-7 items-center justify-center rounded-[6px] text-muted-foreground transition-colors hover:text-foreground",
|
|
14941
|
+
themeMode === "light" && "bg-background text-foreground shadow-sm"
|
|
14942
|
+
),
|
|
14943
|
+
"aria-label": "Use light mode",
|
|
14944
|
+
"aria-pressed": themeMode === "light",
|
|
14945
|
+
title: "Light mode",
|
|
14946
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(Sun, { className: "size-3.5" })
|
|
14947
|
+
}
|
|
14948
|
+
),
|
|
14949
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
14950
|
+
"button",
|
|
14951
|
+
{
|
|
14952
|
+
type: "button",
|
|
14953
|
+
onClick: () => setThemeMode("eye-care"),
|
|
14954
|
+
className: cn(
|
|
14955
|
+
"inline-flex size-7 items-center justify-center rounded-[6px] text-muted-foreground transition-colors hover:text-foreground",
|
|
14956
|
+
themeMode === "eye-care" && "bg-background text-foreground shadow-sm"
|
|
14957
|
+
),
|
|
14958
|
+
"aria-label": "Use eye care mode",
|
|
14959
|
+
"aria-pressed": themeMode === "eye-care",
|
|
14960
|
+
title: "Eye care mode",
|
|
14961
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(Eye, { className: "size-3.5" })
|
|
14962
|
+
}
|
|
14963
|
+
),
|
|
14964
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
14965
|
+
"button",
|
|
14966
|
+
{
|
|
14967
|
+
type: "button",
|
|
14968
|
+
onClick: () => setThemeMode("dark"),
|
|
14969
|
+
className: cn(
|
|
14970
|
+
"inline-flex size-7 items-center justify-center rounded-[6px] text-muted-foreground transition-colors hover:text-foreground",
|
|
14971
|
+
themeMode === "dark" && "bg-background text-foreground shadow-sm"
|
|
14972
|
+
),
|
|
14973
|
+
"aria-label": "Use dark mode",
|
|
14974
|
+
"aria-pressed": themeMode === "dark",
|
|
14975
|
+
title: "Dark mode",
|
|
14976
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(Moon, { className: "size-3.5" })
|
|
14977
|
+
}
|
|
14978
|
+
)
|
|
14979
|
+
]
|
|
14980
|
+
}
|
|
14981
|
+
);
|
|
14982
|
+
}
|
|
14983
|
+
function UiScaleControl({
|
|
14984
|
+
preference,
|
|
14985
|
+
resolvedScale,
|
|
14986
|
+
onChange
|
|
14987
|
+
}) {
|
|
14988
|
+
const resolvedLabel = formatUiScale(resolvedScale);
|
|
14989
|
+
const currentLabel = preference === "auto" ? `Auto (${resolvedLabel})` : `${preference}%`;
|
|
14990
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
14991
|
+
Select,
|
|
14992
|
+
{
|
|
14993
|
+
value: preference,
|
|
14994
|
+
onValueChange: (value) => onChange(normalizeUiScalePreference(value)),
|
|
14995
|
+
children: [
|
|
14996
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
14997
|
+
SelectTrigger,
|
|
14998
|
+
{
|
|
14999
|
+
size: "sm",
|
|
15000
|
+
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",
|
|
15001
|
+
"aria-label": `Interface size: ${currentLabel}`,
|
|
15002
|
+
children: [
|
|
15003
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ALargeSmall, { className: "size-3.5" }),
|
|
15004
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-[10px] font-semibold tabular-nums", children: resolvedLabel })
|
|
15005
|
+
]
|
|
15006
|
+
}
|
|
15007
|
+
),
|
|
15008
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(SelectContent, { align: "end", children: [
|
|
15009
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: "auto", children: "Auto" }),
|
|
15010
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: "100", children: "100%" }),
|
|
15011
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: "125", children: "125%" }),
|
|
15012
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: "150", children: "150%" })
|
|
15013
|
+
] })
|
|
15014
|
+
]
|
|
15015
|
+
}
|
|
15016
|
+
);
|
|
15017
|
+
}
|
|
14264
15018
|
function BrandHeader({
|
|
14265
15019
|
compact,
|
|
14266
15020
|
crabEntrancePhase,
|
|
14267
15021
|
currentSessionId,
|
|
14268
|
-
logCount
|
|
15022
|
+
logCount,
|
|
15023
|
+
uiScalePreference,
|
|
15024
|
+
resolvedUiScale,
|
|
15025
|
+
onUiScaleChange
|
|
14269
15026
|
}) {
|
|
14270
15027
|
if (compact) {
|
|
14271
15028
|
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 +15040,15 @@ function BrandHeader({
|
|
|
14283
15040
|
] })
|
|
14284
15041
|
] }),
|
|
14285
15042
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [
|
|
15043
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ThemeModeToggle, {}),
|
|
15044
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
15045
|
+
UiScaleControl,
|
|
15046
|
+
{
|
|
15047
|
+
preference: uiScalePreference,
|
|
15048
|
+
resolvedScale: resolvedUiScale,
|
|
15049
|
+
onChange: onUiScaleChange
|
|
15050
|
+
}
|
|
15051
|
+
),
|
|
14286
15052
|
/* @__PURE__ */ jsxRuntimeExports.jsx(AlertsDialog, {}),
|
|
14287
15053
|
/* @__PURE__ */ jsxRuntimeExports.jsx(GroupsDialog, {}),
|
|
14288
15054
|
/* @__PURE__ */ jsxRuntimeExports.jsx(AgentLabDialog, { currentSessionId, logCount }),
|
|
@@ -14308,6 +15074,15 @@ function BrandHeader({
|
|
|
14308
15074
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "max-w-full text-sm font-semibold text-muted-foreground", children: "Local First. Evidence First." })
|
|
14309
15075
|
] }),
|
|
14310
15076
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-1 justify-end gap-1", children: [
|
|
15077
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ThemeModeToggle, {}),
|
|
15078
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
15079
|
+
UiScaleControl,
|
|
15080
|
+
{
|
|
15081
|
+
preference: uiScalePreference,
|
|
15082
|
+
resolvedScale: resolvedUiScale,
|
|
15083
|
+
onChange: onUiScaleChange
|
|
15084
|
+
}
|
|
15085
|
+
),
|
|
14311
15086
|
/* @__PURE__ */ jsxRuntimeExports.jsx(AlertsDialog, {}),
|
|
14312
15087
|
/* @__PURE__ */ jsxRuntimeExports.jsx(GroupsDialog, {}),
|
|
14313
15088
|
/* @__PURE__ */ jsxRuntimeExports.jsx(AgentLabDialog, { currentSessionId, logCount }),
|
|
@@ -14315,256 +15090,12 @@ function BrandHeader({
|
|
|
14315
15090
|
] })
|
|
14316
15091
|
] });
|
|
14317
15092
|
}
|
|
14318
|
-
const FLOATING_LOGO_SIZE = 56;
|
|
14319
|
-
const FLOATING_LOGO_MARGIN = 14;
|
|
14320
|
-
const FLOATING_LOGO_MIN_DRIFT_MS = 5200;
|
|
14321
|
-
const FLOATING_LOGO_DRIFT_WINDOW_MS = 2400;
|
|
14322
|
-
const FLOATING_LOGO_MIN_STEP = 72;
|
|
14323
|
-
const FLOATING_LOGO_MAX_STEP = 156;
|
|
14324
15093
|
const DETAILS_PANEL_COLLAPSED_STORAGE_KEY = "agent-inspector.detailsPanelCollapsed";
|
|
14325
15094
|
function readStoredDetailsPanelCollapsed() {
|
|
14326
15095
|
if (typeof window === "undefined") return true;
|
|
14327
15096
|
const stored = window.localStorage.getItem(DETAILS_PANEL_COLLAPSED_STORAGE_KEY);
|
|
14328
15097
|
return stored === null || stored === "1";
|
|
14329
15098
|
}
|
|
14330
|
-
function clampFloatingLogoPosition(position) {
|
|
14331
|
-
const maxX = Math.max(
|
|
14332
|
-
FLOATING_LOGO_MARGIN,
|
|
14333
|
-
window.innerWidth - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
|
|
14334
|
-
);
|
|
14335
|
-
const maxY = Math.max(
|
|
14336
|
-
FLOATING_LOGO_MARGIN,
|
|
14337
|
-
window.innerHeight - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
|
|
14338
|
-
);
|
|
14339
|
-
return {
|
|
14340
|
-
x: Math.min(Math.max(position.x, FLOATING_LOGO_MARGIN), maxX),
|
|
14341
|
-
y: Math.min(Math.max(position.y, FLOATING_LOGO_MARGIN), maxY)
|
|
14342
|
-
};
|
|
14343
|
-
}
|
|
14344
|
-
function snapFloatingLogoToEdge(position) {
|
|
14345
|
-
const clamped = clampFloatingLogoPosition(position);
|
|
14346
|
-
const maxX = Math.max(
|
|
14347
|
-
FLOATING_LOGO_MARGIN,
|
|
14348
|
-
window.innerWidth - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
|
|
14349
|
-
);
|
|
14350
|
-
const maxY = Math.max(
|
|
14351
|
-
FLOATING_LOGO_MARGIN,
|
|
14352
|
-
window.innerHeight - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
|
|
14353
|
-
);
|
|
14354
|
-
const leftDistance = clamped.x - FLOATING_LOGO_MARGIN;
|
|
14355
|
-
const rightDistance = maxX - clamped.x;
|
|
14356
|
-
const topDistance = clamped.y - FLOATING_LOGO_MARGIN;
|
|
14357
|
-
const bottomDistance = maxY - clamped.y;
|
|
14358
|
-
const nearestDistance = Math.min(leftDistance, rightDistance, topDistance, bottomDistance);
|
|
14359
|
-
if (nearestDistance === leftDistance) return { x: FLOATING_LOGO_MARGIN, y: clamped.y };
|
|
14360
|
-
if (nearestDistance === rightDistance) return { x: maxX, y: clamped.y };
|
|
14361
|
-
if (nearestDistance === topDistance) return { x: clamped.x, y: FLOATING_LOGO_MARGIN };
|
|
14362
|
-
return { x: clamped.x, y: maxY };
|
|
14363
|
-
}
|
|
14364
|
-
function randomFloatingLogoEdgePosition() {
|
|
14365
|
-
const maxX = Math.max(
|
|
14366
|
-
FLOATING_LOGO_MARGIN,
|
|
14367
|
-
window.innerWidth - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
|
|
14368
|
-
);
|
|
14369
|
-
const maxY = Math.max(
|
|
14370
|
-
FLOATING_LOGO_MARGIN,
|
|
14371
|
-
window.innerHeight - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
|
|
14372
|
-
);
|
|
14373
|
-
const randomX = FLOATING_LOGO_MARGIN + Math.random() * (maxX - FLOATING_LOGO_MARGIN);
|
|
14374
|
-
const randomY = FLOATING_LOGO_MARGIN + Math.random() * (maxY - FLOATING_LOGO_MARGIN);
|
|
14375
|
-
const edgeIndex = Math.floor(Math.random() * 4);
|
|
14376
|
-
switch (edgeIndex) {
|
|
14377
|
-
case 0:
|
|
14378
|
-
return { x: FLOATING_LOGO_MARGIN, y: randomY };
|
|
14379
|
-
case 1:
|
|
14380
|
-
return { x: maxX, y: randomY };
|
|
14381
|
-
case 2:
|
|
14382
|
-
return { x: randomX, y: FLOATING_LOGO_MARGIN };
|
|
14383
|
-
case 3:
|
|
14384
|
-
return { x: randomX, y: maxY };
|
|
14385
|
-
default:
|
|
14386
|
-
return { x: maxX, y: FLOATING_LOGO_MARGIN };
|
|
14387
|
-
}
|
|
14388
|
-
}
|
|
14389
|
-
function nearestFloatingLogoEdge(position) {
|
|
14390
|
-
const clamped = clampFloatingLogoPosition(position);
|
|
14391
|
-
const maxX = Math.max(
|
|
14392
|
-
FLOATING_LOGO_MARGIN,
|
|
14393
|
-
window.innerWidth - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
|
|
14394
|
-
);
|
|
14395
|
-
const maxY = Math.max(
|
|
14396
|
-
FLOATING_LOGO_MARGIN,
|
|
14397
|
-
window.innerHeight - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
|
|
14398
|
-
);
|
|
14399
|
-
const distances = [
|
|
14400
|
-
{ edge: "left", distance: clamped.x - FLOATING_LOGO_MARGIN },
|
|
14401
|
-
{ edge: "right", distance: maxX - clamped.x },
|
|
14402
|
-
{ edge: "top", distance: clamped.y - FLOATING_LOGO_MARGIN },
|
|
14403
|
-
{ edge: "bottom", distance: maxY - clamped.y }
|
|
14404
|
-
];
|
|
14405
|
-
return distances.reduce((best, current) => current.distance < best.distance ? current : best).edge;
|
|
14406
|
-
}
|
|
14407
|
-
function nextFloatingLogoWalkingPosition(position) {
|
|
14408
|
-
const clamped = snapFloatingLogoToEdge(position);
|
|
14409
|
-
const maxX = Math.max(
|
|
14410
|
-
FLOATING_LOGO_MARGIN,
|
|
14411
|
-
window.innerWidth - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
|
|
14412
|
-
);
|
|
14413
|
-
const maxY = Math.max(
|
|
14414
|
-
FLOATING_LOGO_MARGIN,
|
|
14415
|
-
window.innerHeight - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
|
|
14416
|
-
);
|
|
14417
|
-
const step = FLOATING_LOGO_MIN_STEP + Math.random() * (FLOATING_LOGO_MAX_STEP - FLOATING_LOGO_MIN_STEP);
|
|
14418
|
-
const direction = Math.random() > 0.5 ? 1 : -1;
|
|
14419
|
-
const edge = nearestFloatingLogoEdge(clamped);
|
|
14420
|
-
switch (edge) {
|
|
14421
|
-
case "left": {
|
|
14422
|
-
const nextY = clamped.y + step * direction;
|
|
14423
|
-
if (nextY <= FLOATING_LOGO_MARGIN)
|
|
14424
|
-
return { x: FLOATING_LOGO_MARGIN, y: FLOATING_LOGO_MARGIN };
|
|
14425
|
-
if (nextY >= maxY) return { x: FLOATING_LOGO_MARGIN, y: maxY };
|
|
14426
|
-
return { x: FLOATING_LOGO_MARGIN, y: nextY };
|
|
14427
|
-
}
|
|
14428
|
-
case "right": {
|
|
14429
|
-
const nextY = clamped.y + step * direction;
|
|
14430
|
-
if (nextY <= FLOATING_LOGO_MARGIN) return { x: maxX, y: FLOATING_LOGO_MARGIN };
|
|
14431
|
-
if (nextY >= maxY) return { x: maxX, y: maxY };
|
|
14432
|
-
return { x: maxX, y: nextY };
|
|
14433
|
-
}
|
|
14434
|
-
case "top": {
|
|
14435
|
-
const nextX = clamped.x + step * direction;
|
|
14436
|
-
if (nextX <= FLOATING_LOGO_MARGIN)
|
|
14437
|
-
return { x: FLOATING_LOGO_MARGIN, y: FLOATING_LOGO_MARGIN };
|
|
14438
|
-
if (nextX >= maxX) return { x: maxX, y: FLOATING_LOGO_MARGIN };
|
|
14439
|
-
return { x: nextX, y: FLOATING_LOGO_MARGIN };
|
|
14440
|
-
}
|
|
14441
|
-
case "bottom": {
|
|
14442
|
-
const nextX = clamped.x + step * direction;
|
|
14443
|
-
if (nextX <= FLOATING_LOGO_MARGIN) return { x: FLOATING_LOGO_MARGIN, y: maxY };
|
|
14444
|
-
if (nextX >= maxX) return { x: maxX, y: maxY };
|
|
14445
|
-
return { x: nextX, y: maxY };
|
|
14446
|
-
}
|
|
14447
|
-
}
|
|
14448
|
-
}
|
|
14449
|
-
function FloatingInspectorLogo() {
|
|
14450
|
-
const [position, setPosition] = reactExports.useState({
|
|
14451
|
-
x: FLOATING_LOGO_MARGIN,
|
|
14452
|
-
y: FLOATING_LOGO_MARGIN
|
|
14453
|
-
});
|
|
14454
|
-
const [motionTick, setMotionTick] = reactExports.useState(0);
|
|
14455
|
-
const [dragging, setDragging] = reactExports.useState(false);
|
|
14456
|
-
const dragStateRef = reactExports.useRef(null);
|
|
14457
|
-
reactExports.useEffect(() => {
|
|
14458
|
-
setPosition(randomFloatingLogoEdgePosition());
|
|
14459
|
-
}, []);
|
|
14460
|
-
reactExports.useEffect(() => {
|
|
14461
|
-
if (dragging) return void 0;
|
|
14462
|
-
let timeoutId = null;
|
|
14463
|
-
const scheduleDrift = () => {
|
|
14464
|
-
const delay = FLOATING_LOGO_MIN_DRIFT_MS + Math.random() * FLOATING_LOGO_DRIFT_WINDOW_MS;
|
|
14465
|
-
timeoutId = window.setTimeout(() => {
|
|
14466
|
-
setMotionTick((current) => current + 1);
|
|
14467
|
-
setPosition((current) => nextFloatingLogoWalkingPosition(current));
|
|
14468
|
-
scheduleDrift();
|
|
14469
|
-
}, delay);
|
|
14470
|
-
};
|
|
14471
|
-
scheduleDrift();
|
|
14472
|
-
return () => {
|
|
14473
|
-
if (timeoutId !== null) {
|
|
14474
|
-
window.clearTimeout(timeoutId);
|
|
14475
|
-
}
|
|
14476
|
-
};
|
|
14477
|
-
}, [dragging]);
|
|
14478
|
-
reactExports.useEffect(() => {
|
|
14479
|
-
const handleResize = () => {
|
|
14480
|
-
setPosition((current) => snapFloatingLogoToEdge(current));
|
|
14481
|
-
};
|
|
14482
|
-
window.addEventListener("resize", handleResize);
|
|
14483
|
-
return () => window.removeEventListener("resize", handleResize);
|
|
14484
|
-
}, []);
|
|
14485
|
-
const handlePointerDown = reactExports.useCallback((event) => {
|
|
14486
|
-
const rect = event.currentTarget.getBoundingClientRect();
|
|
14487
|
-
dragStateRef.current = {
|
|
14488
|
-
pointerId: event.pointerId,
|
|
14489
|
-
offsetX: event.clientX - rect.left,
|
|
14490
|
-
offsetY: event.clientY - rect.top
|
|
14491
|
-
};
|
|
14492
|
-
event.currentTarget.setPointerCapture(event.pointerId);
|
|
14493
|
-
setDragging(true);
|
|
14494
|
-
}, []);
|
|
14495
|
-
const handlePointerMove = reactExports.useCallback((event) => {
|
|
14496
|
-
const dragState = dragStateRef.current;
|
|
14497
|
-
if (dragState === null || dragState.pointerId !== event.pointerId) return;
|
|
14498
|
-
setPosition(
|
|
14499
|
-
clampFloatingLogoPosition({
|
|
14500
|
-
x: event.clientX - dragState.offsetX,
|
|
14501
|
-
y: event.clientY - dragState.offsetY
|
|
14502
|
-
})
|
|
14503
|
-
);
|
|
14504
|
-
}, []);
|
|
14505
|
-
const handlePointerUp = reactExports.useCallback((event) => {
|
|
14506
|
-
const dragState = dragStateRef.current;
|
|
14507
|
-
if (dragState === null || dragState.pointerId !== event.pointerId) return;
|
|
14508
|
-
if (event.currentTarget.hasPointerCapture(event.pointerId)) {
|
|
14509
|
-
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
14510
|
-
}
|
|
14511
|
-
dragStateRef.current = null;
|
|
14512
|
-
setDragging(false);
|
|
14513
|
-
setPosition((current) => snapFloatingLogoToEdge(current));
|
|
14514
|
-
}, []);
|
|
14515
|
-
const style = reactExports.useMemo(
|
|
14516
|
-
() => ({
|
|
14517
|
-
transform: `translate3d(${position.x}px, ${position.y}px, 0) rotate(${motionTick % 2 === 0 ? "-4deg" : "5deg"}) scale(${dragging ? "1.08" : "1"})`,
|
|
14518
|
-
transition: dragging ? "none" : "transform 4800ms cubic-bezier(0.33, 1, 0.68, 1)",
|
|
14519
|
-
touchAction: "none"
|
|
14520
|
-
}),
|
|
14521
|
-
[dragging, motionTick, position.x, position.y]
|
|
14522
|
-
);
|
|
14523
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
14524
|
-
"button",
|
|
14525
|
-
{
|
|
14526
|
-
type: "button",
|
|
14527
|
-
className: cn(
|
|
14528
|
-
"fixed left-0 top-0 z-40 flex size-14 items-center justify-center rounded-full bg-transparent text-foreground outline-none transition-[filter,opacity] duration-200 hover:opacity-95 hover:drop-shadow-[0_0_24px_rgba(245,158,11,0.36)] focus-visible:ring-1 focus-visible:ring-amber-300/55",
|
|
14529
|
-
dragging ? "cursor-grabbing" : "cursor-grab"
|
|
14530
|
-
),
|
|
14531
|
-
style,
|
|
14532
|
-
onPointerDown: handlePointerDown,
|
|
14533
|
-
onPointerMove: handlePointerMove,
|
|
14534
|
-
onPointerUp: handlePointerUp,
|
|
14535
|
-
onPointerCancel: handlePointerUp,
|
|
14536
|
-
"aria-label": "Floating Inspector logo",
|
|
14537
|
-
title: "Drag Inspector logo",
|
|
14538
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
14539
|
-
"span",
|
|
14540
|
-
{
|
|
14541
|
-
className: cn(
|
|
14542
|
-
"relative flex size-12 items-center justify-center",
|
|
14543
|
-
!dragging && "floating-crab-body"
|
|
14544
|
-
),
|
|
14545
|
-
"aria-hidden": "true",
|
|
14546
|
-
children: [
|
|
14547
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(CrabLogo, { className: "relative z-10 size-11 text-amber-500 drop-shadow-[0_0_15px_rgba(245,158,11,0.30)]" }),
|
|
14548
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "pointer-events-none absolute inset-x-0 bottom-0 z-0 flex items-end justify-center gap-1 text-amber-400/80", children: [0, 1, 2, 3, 4, 5].map((leg) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
14549
|
-
"span",
|
|
14550
|
-
{
|
|
14551
|
-
className: cn(
|
|
14552
|
-
"floating-crab-leg h-2 w-0.5 rounded-full bg-current shadow-[0_0_7px_rgba(245,158,11,0.24)]",
|
|
14553
|
-
leg < 3 ? "floating-crab-leg-left" : "floating-crab-leg-right",
|
|
14554
|
-
dragging && "animate-none"
|
|
14555
|
-
),
|
|
14556
|
-
style: {
|
|
14557
|
-
animationDelay: `${leg % 2 === 0 ? 0 : 180}ms`
|
|
14558
|
-
}
|
|
14559
|
-
},
|
|
14560
|
-
leg
|
|
14561
|
-
)) })
|
|
14562
|
-
]
|
|
14563
|
-
}
|
|
14564
|
-
)
|
|
14565
|
-
}
|
|
14566
|
-
);
|
|
14567
|
-
}
|
|
14568
15099
|
function SessionContextLogButton({ label, logId }) {
|
|
14569
15100
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
14570
15101
|
"button",
|
|
@@ -14881,6 +15412,7 @@ function ProxyViewer({
|
|
|
14881
15412
|
}) {
|
|
14882
15413
|
const { totalIn, totalOut } = reactExports.useMemo(() => computeTokenSummary(logs), [logs]);
|
|
14883
15414
|
const { providers } = useProviders();
|
|
15415
|
+
const { uiScalePreference, resolvedUiScale, setUiScalePreference } = useUiScale();
|
|
14884
15416
|
const [exporting, setExporting] = reactExports.useState(null);
|
|
14885
15417
|
const [exportError, setExportError] = reactExports.useState(null);
|
|
14886
15418
|
const [importing, setImporting] = reactExports.useState(false);
|
|
@@ -15122,7 +15654,7 @@ function ProxyViewer({
|
|
|
15122
15654
|
onClick: toggleDetailsPanelCollapsed,
|
|
15123
15655
|
className: cn(
|
|
15124
15656
|
"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-[
|
|
15657
|
+
detailsPanelCollapsed ? "right-3" : "lg:right-[calc(21.25rem-0.875rem)] xl:right-[calc(22.5rem-0.875rem)]"
|
|
15126
15658
|
),
|
|
15127
15659
|
"aria-label": detailsPanelCollapsed ? "Show details panel" : "Hide details panel",
|
|
15128
15660
|
title: detailsPanelCollapsed ? "Show details panel" : "Hide details panel",
|
|
@@ -15132,13 +15664,13 @@ function ProxyViewer({
|
|
|
15132
15664
|
]
|
|
15133
15665
|
}
|
|
15134
15666
|
),
|
|
15135
|
-
detailsPanelCollapsed && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
15667
|
+
detailsPanelCollapsed && /* @__PURE__ */ jsxRuntimeExports.jsx(InspectorPet, { logs }),
|
|
15136
15668
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
15137
15669
|
"div",
|
|
15138
15670
|
{
|
|
15139
15671
|
className: cn(
|
|
15140
15672
|
"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)
|
|
15673
|
+
detailsPanelCollapsed ? "lg:grid-cols-[minmax(0,1fr)]" : "lg:grid-cols-[minmax(0,1fr)_21.25rem] xl:grid-cols-[minmax(0,1fr)_22.5rem]"
|
|
15142
15674
|
),
|
|
15143
15675
|
children: [
|
|
15144
15676
|
!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 +15680,10 @@ function ProxyViewer({
|
|
|
15148
15680
|
compact: true,
|
|
15149
15681
|
crabEntrancePhase,
|
|
15150
15682
|
currentSessionId: labSessionId,
|
|
15151
|
-
logCount: logs.length
|
|
15683
|
+
logCount: logs.length,
|
|
15684
|
+
uiScalePreference,
|
|
15685
|
+
resolvedUiScale,
|
|
15686
|
+
onUiScaleChange: setUiScalePreference
|
|
15152
15687
|
}
|
|
15153
15688
|
),
|
|
15154
15689
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(SidebarPanel, { label: "Session", children: [
|
|
@@ -15489,6 +16024,32 @@ function ProxyViewer({
|
|
|
15489
16024
|
) })
|
|
15490
16025
|
] });
|
|
15491
16026
|
}
|
|
16027
|
+
function filterLogs(logs, selectedSession, selectedModel) {
|
|
16028
|
+
if (selectedSession === "__all__" && selectedModel === "__all__") return logs;
|
|
16029
|
+
return logs.filter((l) => {
|
|
16030
|
+
if (selectedSession !== "__all__" && l.sessionId !== selectedSession) return false;
|
|
16031
|
+
if (selectedModel !== "__all__" && l.model !== selectedModel) return false;
|
|
16032
|
+
return true;
|
|
16033
|
+
});
|
|
16034
|
+
}
|
|
16035
|
+
function mergeLogsById(previousLogs, incomingLogs) {
|
|
16036
|
+
if (previousLogs.length === 0) return [...incomingLogs];
|
|
16037
|
+
if (incomingLogs.length === 0) return [...previousLogs];
|
|
16038
|
+
const byId = /* @__PURE__ */ new Map();
|
|
16039
|
+
for (const log of previousLogs) byId.set(log.id, log);
|
|
16040
|
+
for (const log of incomingLogs) byId.set(log.id, log);
|
|
16041
|
+
return [...byId.values()].toSorted((left, right) => left.id - right.id);
|
|
16042
|
+
}
|
|
16043
|
+
function mergeSessionIds(previousSessions, incomingSessions) {
|
|
16044
|
+
const merged = /* @__PURE__ */ new Set();
|
|
16045
|
+
for (const session of previousSessions) {
|
|
16046
|
+
if (session !== "") merged.add(session);
|
|
16047
|
+
}
|
|
16048
|
+
for (const session of incomingSessions) {
|
|
16049
|
+
if (session !== "") merged.add(session);
|
|
16050
|
+
}
|
|
16051
|
+
return [...merged].sort();
|
|
16052
|
+
}
|
|
15492
16053
|
const SSEUpdateSchema = union([
|
|
15493
16054
|
object({
|
|
15494
16055
|
type: literal("init"),
|
|
@@ -15549,14 +16110,6 @@ function extractModels(logs) {
|
|
|
15549
16110
|
}
|
|
15550
16111
|
return [...set];
|
|
15551
16112
|
}
|
|
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
16113
|
const DEBOUNCE_MS = 100;
|
|
15561
16114
|
const HASH_SCROLL_ATTEMPTS = 12;
|
|
15562
16115
|
const HASH_HIGHLIGHT_MS = 1800;
|
|
@@ -15641,27 +16194,6 @@ async function deleteAllGroupsForFullHistoryDelete() {
|
|
|
15641
16194
|
return { deleted: 0, ok: false };
|
|
15642
16195
|
}
|
|
15643
16196
|
}
|
|
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
16197
|
function ProxyViewerContainer({
|
|
15666
16198
|
initialSessionId
|
|
15667
16199
|
} = {}) {
|