@tonyclaw/agent-inspector 3.0.29 → 3.0.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.output/cli.js +791 -191
- package/.output/nitro.json +1 -1
- package/.output/public/assets/CompareDrawer-DB2KggLE.js +1 -0
- package/.output/public/assets/InspectorPet-CfwDw6kD.js +4108 -0
- package/.output/public/assets/ProxyViewerContainer-PcrO96_F.js +126 -0
- package/.output/public/assets/{ReplayDialog-CctnITbt.js → ReplayDialog-3Pl7EKjp.js} +1 -1
- package/.output/public/assets/{RequestAnatomy-BrN0RBbL.js → RequestAnatomy-BcPjcHLX.js} +1 -1
- package/.output/public/assets/ResponseView-DOx51wV3.js +2 -0
- package/.output/public/assets/StreamingChunkSequence-LkYJWM1A.js +1 -0
- package/.output/public/assets/_sessionId-BSg32vC6.js +1 -0
- package/.output/public/assets/{_sessionId-DKM91udC.js → _sessionId-C0CA68QV.js} +1 -1
- package/.output/public/assets/{index-Bq-nqolG.js → index-BpBUqdAB.js} +1 -1
- package/.output/public/assets/index-D93dCgAQ.js +1 -0
- package/.output/public/assets/{index-DPiESBo2.js → index-FV5sxqx3.js} +6 -6
- package/.output/public/assets/index-VUsF4nhf.js +76 -0
- package/.output/public/assets/index-hyQHZeQI.css +1 -0
- package/.output/public/assets/{json-viewer-CfaDJwx8.js → json-viewer-WctIbAh_.js} +1 -1
- package/.output/public/assets/jszip.min-DnSIoTix.js +2 -0
- package/.output/public/assets/qwen-mMn3f5ul.webp +0 -0
- package/.output/server/_libs/jszip.mjs +35 -9
- package/.output/server/_libs/lucide-react.mjs +80 -80
- package/.output/server/_libs/radix-ui__react-dialog.mjs +3 -3
- package/.output/server/_libs/tanstack__react-router.mjs +1 -1
- package/.output/server/{_sessionId-CwGXPD4C.mjs → _sessionId-BHBK3VbF.mjs} +15 -15
- package/.output/server/_sessionId-CyuJ6Kfl.mjs +81 -0
- package/.output/server/_ssr/{CompareDrawer-R_P1-VNr.mjs → CompareDrawer-27amlv_a.mjs} +138 -103
- package/.output/server/_ssr/InspectorPet-CQnGXfLs.mjs +925 -0
- package/.output/server/_ssr/{ProxyViewerContainer-DUgxRNbj.mjs → ProxyViewerContainer-DlAl0uF-.mjs} +1569 -1646
- package/.output/server/_ssr/{ReplayDialog-De9wKKzS.mjs → ReplayDialog-5m2jtlLa.mjs} +18 -18
- package/.output/server/_ssr/{RequestAnatomy-Db4MxUYo.mjs → RequestAnatomy--1WtQNY9.mjs} +58 -58
- package/.output/server/_ssr/{ResponseView-8rDXOiNB.mjs → ResponseView-CgbqS8sr.mjs} +60 -71
- package/.output/server/_ssr/{StreamingChunkSequence-N9teZHkA.mjs → StreamingChunkSequence-BwpnopWx.mjs} +16 -16
- package/.output/server/_ssr/{index-D4DvByuW.mjs → index-CNVi1TzT.mjs} +15 -15
- package/.output/server/_ssr/index-DMCjH_4V.mjs +81 -0
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{json-viewer-BjoHRbjS.mjs → json-viewer-DNGN2uoe.mjs} +58 -58
- package/.output/server/_ssr/{router-BYlePDj8.mjs → router-CgsqLnk5.mjs} +16007 -12632
- package/.output/server/_tanstack-start-manifest_v-BH5f_kWV.mjs +4 -0
- package/.output/server/index.mjs +99 -71
- package/.output/workers/logFinalizer.worker.js +16908 -0
- package/.output/workers/sessionWorkerEntry.js +16904 -0
- package/README.md +21 -5
- package/package.json +6 -2
- package/src/assets/logos/qwen.webp +0 -0
- package/src/cli.ts +85 -10
- package/src/components/OnboardingBanner.tsx +41 -21
- package/src/components/ProxyViewer.tsx +198 -269
- package/src/components/ProxyViewerContainer.tsx +128 -17
- package/src/components/ecosystem/AgentLabDialog.tsx +166 -19
- package/src/components/errors/SafeErrorBoundary.tsx +201 -0
- package/src/components/pi-agent/PiAgentPanel.tsx +209 -35
- package/src/components/pi-agent/piAgentChatLogic.ts +263 -0
- package/src/components/providers/ImportWizardDialog.tsx +18 -42
- package/src/components/providers/ProviderLogo.tsx +1 -1
- package/src/components/providers/ProvidersPanel.tsx +8 -5
- package/src/components/providers/SettingsDialog.tsx +34 -11
- package/src/components/proxy-viewer/ApplicationBar.tsx +63 -0
- package/src/components/proxy-viewer/CompareDrawer.tsx +92 -49
- package/src/components/proxy-viewer/LiveConnectionStatus.tsx +186 -0
- package/src/components/proxy-viewer/LogEntry.tsx +283 -275
- package/src/components/proxy-viewer/RawExportWarning.tsx +77 -0
- package/src/components/proxy-viewer/SessionLoadProgressBar.tsx +61 -0
- package/src/components/proxy-viewer/ThreadConnector.tsx +16 -1
- package/src/components/proxy-viewer/TurnGroup.tsx +13 -2
- package/src/components/proxy-viewer/accessibility.ts +8 -0
- package/src/components/proxy-viewer/lazy.ts +4 -0
- package/src/components/proxy-viewer/liveConnectionState.ts +158 -0
- package/src/components/proxy-viewer/proxyViewerLogic.ts +10 -0
- package/src/components/proxy-viewer/viewerState.ts +2 -6
- package/src/components/ui/select.tsx +1 -1
- package/src/components/ui/tabs.tsx +3 -3
- package/src/components/ui/transient-toast.tsx +7 -6
- package/src/lib/apiClient.ts +17 -2
- package/src/lib/ecosystemContract.ts +34 -0
- package/src/lib/export-logs.ts +1 -1
- package/src/lib/piAgentContract.ts +80 -0
- package/src/lib/providerContract.ts +70 -4
- package/src/lib/providerImportContract.ts +27 -0
- package/src/lib/providerModelMetadata.ts +16 -7
- package/src/lib/resourceLimits.ts +152 -0
- package/src/lib/safeDiagnostic.ts +38 -0
- package/src/lib/useProviders.ts +4 -4
- package/src/mcp/server.ts +39 -6
- package/src/mcp/toolHandlers.ts +131 -4
- package/src/proxy/chunkStorage.ts +20 -6
- package/src/proxy/config.ts +20 -6
- package/src/proxy/dataDir.ts +3 -0
- package/src/proxy/ecosystemExecutionConfirmation.ts +114 -0
- package/src/proxy/ecosystemExecutionRoute.ts +116 -0
- package/src/proxy/ecosystemTasks.ts +48 -0
- package/src/proxy/evidenceExporter.ts +23 -9
- package/src/proxy/groupEvidenceExporter.ts +26 -5
- package/src/proxy/groupStore.ts +13 -3
- package/src/proxy/handler.ts +103 -20
- package/src/proxy/identityProxy.ts +333 -14
- package/src/proxy/logFinalizer.ts +73 -6
- package/src/proxy/logImportUpload.ts +128 -0
- package/src/proxy/logImporter.ts +321 -70
- package/src/proxy/logIndex.ts +16 -6
- package/src/proxy/logger.ts +294 -41
- package/src/proxy/privateDataPath.ts +183 -0
- package/src/proxy/providerScanStore.ts +87 -0
- package/src/proxy/providerSecretStore.ts +58 -19
- package/src/proxy/providers.ts +175 -58
- package/src/proxy/rawStreamCapture.ts +66 -5
- package/src/proxy/runStore.ts +13 -3
- package/src/proxy/runtimeAdmission.ts +52 -0
- package/src/proxy/runtimeHealth.ts +206 -0
- package/src/proxy/runtimeShutdown.ts +75 -0
- package/src/proxy/sessionArchive.ts +15 -2
- package/src/proxy/sessionProcess.ts +19 -0
- package/src/proxy/sessionRuntime.ts +7 -0
- package/src/proxy/shutdownCoordinator.ts +90 -0
- package/src/proxy/sqliteLogIndex.ts +18 -2
- package/src/proxy/store.ts +18 -2
- package/src/routes/__root.tsx +18 -1
- package/src/routes/api/alerts.summary.ts +12 -8
- package/src/routes/api/alerts.ts +27 -9
- package/src/routes/api/ecosystem.packages.$packageId.help.ts +3 -8
- package/src/routes/api/ecosystem.packages.$packageId.install.ts +3 -8
- package/src/routes/api/ecosystem.packages.$packageId.runner-presets.ts +3 -11
- package/src/routes/api/ecosystem.packages.$packageId.upgrade.ts +3 -8
- package/src/routes/api/ecosystem.recipes.$recipeId.run.ts +3 -8
- package/src/routes/api/health.ts +9 -2
- package/src/routes/api/knowledge.project-context.ts +11 -0
- package/src/routes/api/knowledge.search.ts +33 -2
- package/src/routes/api/logs.$id.body.ts +16 -2
- package/src/routes/api/logs.import.ts +7 -18
- package/src/routes/api/logs.stream.ts +147 -69
- package/src/routes/api/logs.ts +55 -14
- package/src/routes/api/providers.$providerId.model-metadata.ts +22 -4
- package/src/routes/api/providers.$providerId.ts +37 -6
- package/src/routes/api/providers.export.ts +34 -16
- package/src/routes/api/providers.import.ts +42 -8
- package/src/routes/api/providers.scan.ts +13 -8
- package/src/routes/api/providers.ts +36 -5
- package/src/routes/api/runs.ts +12 -12
- package/src/routes/api/sessions.ts +15 -8
- package/src/routes/index.tsx +6 -0
- package/src/routes/livez.ts +13 -0
- package/src/routes/readyz.ts +18 -0
- package/src/routes/session/$sessionId.tsx +6 -0
- package/src/services/piAgent.ts +131 -102
- package/src/services/piAgentRetrieval.ts +1180 -0
- package/styles/globals.css +19 -3
- package/.output/public/assets/CompareDrawer-Cb5ccPeX.js +0 -1
- package/.output/public/assets/ProxyViewerContainer-COBe5GTT.js +0 -4234
- package/.output/public/assets/ResponseView-Cqq87lX_.js +0 -3
- package/.output/public/assets/StreamingChunkSequence-CnTa9mCr.js +0 -1
- package/.output/public/assets/index-DTLNVcgc.js +0 -76
- package/.output/public/assets/index-DliqmwUw.css +0 -1
- package/.output/public/assets/qwen-CONDcHqt.png +0 -0
- package/.output/server/_tanstack-start-manifest_v-DMCA8KK3.mjs +0 -4
- package/src/assets/logos/mcp.png +0 -0
- package/src/assets/logos/qwen.png +0 -0
- package/src/components/ui/mcp-logo.tsx +0 -20
package/.output/server/_ssr/{ProxyViewerContainer-DUgxRNbj.mjs → ProxyViewerContainer-DlAl0uF-.mjs}
RENAMED
|
@@ -1,26 +1,31 @@
|
|
|
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, M 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, m as cn, F as LazyFeatureBoundary, x as formatTokens, B as Button, d as RuntimeConfigSchema, g as readStoredUiScalePreference, h as persistUiScalePreference, j as applyUiScalePreference, ac as CrabLogo, p as packageJson, k as normalizeUiScalePreference, N as GroupEvidenceExportResultSchema, P as DeleteInspectorGroupResponseSchema, y as copyTextToClipboard, l as RedactedProviderDtoSchema, U as UI_SCALE_STORAGE_KEY, v as apiFormatForPath, i as isRecord, a2 as createPendingProviderTestResults, a3 as ProviderTestResultsSchema, a4 as createFailedProviderTestResults, a5 as MAX_SLOW_RESPONSE_THRESHOLD_SECONDS, a6 as MAX_PROVIDER_TEST_TIMEOUT_SECONDS, a7 as TimeDisplayFormatSchema, G as AlertSummarySchema, H as AlertListResponseSchema, r as readStoredThemeMode, e as applyThemeMode, f as persistThemeMode, af as formatUiScale, J as InspectorGroupsListResponseSchema, I as GroupEvidenceReadResponseSchema, a8 as EcosystemPackagesResponseSchema, a9 as EcosystemTaskResponseSchema, aa as EcosystemTasksResponseSchema, Y as PATH_V1_MESSAGES, Z as PATH_V1_CHAT_COMPLETIONS, _ as PATH_V1_RESPONSES, V as providerHasContextMetadata, Q as ProviderScanResponseSchema, T as THEME_MODE_STORAGE_KEY, n as normalizeThemeMode, ab as EcosystemExecutionConfirmationResponseSchema, s as safeGetOwnProperty, $ as formatContextWindowInput, W as findProviderModelMetadata, X as formatContextWindowTokens, w as getSessionPath, q as parseOpenAIResponse, t as parseOpenAIResponsesResponse, O as OpenAIRequestSchema, u as OpenAIResponsesRequestSchema, A as AnthropicResponseSchema$1, o as AnthropicRequestSchema, ad as resolveProviderContextWindow, a0 as parseContextWindowTokensInput, a1 as previewUpstreamUrl, K as KnowledgeCandidateSchema, ae as isPlainRecord, E as stripClaudeCodeBillingHeader, L as LogBodyChunkSchema, z as getStatusCategory } from "./router-CgsqLnk5.mjs";
|
|
3
3
|
import { u as useSWR, a as useSWRConfig } from "../_libs/swr.mjs";
|
|
4
|
-
import { J as JSZip } from "../_libs/jszip.mjs";
|
|
5
|
-
import { c as clsx } from "../_libs/clsx.mjs";
|
|
6
|
-
import { t as twMerge } from "../_libs/tailwind-merge.mjs";
|
|
7
|
-
import { c as cva } from "../_libs/class-variance-authority.mjs";
|
|
8
4
|
import { u as useWindowVirtualizer, a as useVirtualizer } from "../_libs/tanstack__react-virtual.mjs";
|
|
5
|
+
import { c as cva } from "../_libs/class-variance-authority.mjs";
|
|
9
6
|
import { d as diffJson, a as diffLines } from "../_libs/diff.mjs";
|
|
10
|
-
import { r as
|
|
11
|
-
import {
|
|
12
|
-
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 CodeXml, a0 as Cpu, a1 as FolderOpen, a2 as Bell, a3 as Clock3, a4 as ShieldAlert, a5 as EyeOff, a6 as ExternalLink, a7 as Clock, a8 as RotateCw, a9 as CircleCheckBig, aa as Pencil, ab as MessageSquare, ac as Zap, ad as Wrench, ae as Brain, af as Minus, ag as CircleX, ah as ShieldCheck, ai as Save, aj as FileSearch, ak as CloudUpload, al as CircleQuestionMark, am as Server, an as Lock, ao as Wifi, ap as WifiOff, aq as OctagonAlert, ar as Radio, as as Globe, at as FileTerminal, au as ChevronsUp, av as ChevronsDown, aw as FileDiff, ax as RotateCcw, ay as GitCompareArrows, az as ArrowUp, aA as ArrowDown, aB as Ellipsis, aC as Blocks, aD as MousePointerClick, aE as FileText, aF as Rows3, aG as Columns2 } from "../_libs/lucide-react.mjs";
|
|
13
|
-
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";
|
|
7
|
+
import { T as TriangleAlert, C as CircleCheck, X, P as PanelRightOpen, a as PanelRightClose, S as Search, U as Upload, D as Download, F as FileBraces, R as RefreshCw, b as Trash2, I as Info, c as ChevronDown, d as Check, e as Settings, f as Siren, L as LoaderCircle, g as Sun, E as Eye, M as Moon, A as ALargeSmall, h as Layers, i as FlaskConical, j as Sparkles, k as Activity, B as Beaker, N as Network, l as Copy, m as Terminal, n as BrainCircuit, o as RotateCcw, p as Send, q as ArrowLeft, r as ChevronUp, s as ChevronsLeft, t as ChevronLeft, u as ChevronRight, v as ChevronsRight, w as CircleStop, x as Clapperboard, y as Flag, z as Timer, G as Gauge, H as Scan, J as Plus, K as CircleAlert, O as Rocket, Q as PackageCheck, V as History, W as Monitor, Y as EyeOff, Z as ExternalLink, _ as Clock, $ as RotateCw, a0 as CircleCheckBig, a1 as Pencil, a2 as Bell, a3 as Clock3, a4 as ShieldAlert, a5 as ArrowUpRight, a6 as ArrowDownRight, a7 as CodeXml, a8 as Cpu, a9 as FolderOpen, aa as MessageSquare, ab as Zap, ac as Wrench, ad as Brain, ae as Minus, af as CircleQuestionMark, ag as Server, ah as Lock, ai as Wifi, aj as WifiOff, ak as CircleX, al as ShieldCheck, am as Save, an as FileSearch, ao as CloudUpload, ap as OctagonAlert, aq as Radio, ar as Globe, as as FileTerminal, at as ChevronsUp, au as ChevronsDown, av as FileDiff, aw as GitCompareArrows, ax as ArrowUp, ay as ArrowDown, az as Ellipsis, aA as Blocks, aB as MousePointerClick, aC as FileText, aD as Rows3, aE as Columns2 } from "../_libs/lucide-react.mjs";
|
|
8
|
+
import { u as union, o as object, e as array, l as literal, n as number, d as boolean, b as string } from "../_libs/zod.mjs";
|
|
14
9
|
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";
|
|
15
|
-
import { D as Dialog$1, a as DialogContent$1, b as DialogClose, c as DialogTitle$1, d as DialogDescription$1, e as
|
|
10
|
+
import { D as Dialog$1, a as DialogContent$1, b as DialogClose, c as DialogTitle$1, d as DialogDescription$1, e as DialogTrigger$1, f as DialogPortal$1, g as DialogOverlay$1 } from "../_libs/radix-ui__react-dialog.mjs";
|
|
11
|
+
import { R as Root2, C as Content, L as List, T as Trigger } from "../_libs/radix-ui__react-tabs.mjs";
|
|
16
12
|
import { S as Slot } from "../_libs/radix-ui__react-slot.mjs";
|
|
17
|
-
import { R as Root2, L as List, T as Trigger, C as Content } from "../_libs/radix-ui__react-tabs.mjs";
|
|
18
13
|
import { P as Provider, R as Root3, T as Trigger$1, a as Portal, C as Content2, A as Arrow2 } from "../_libs/radix-ui__react-tooltip.mjs";
|
|
19
14
|
import { R as Root, C as CollapsibleContent$1, a as CollapsibleTrigger$1 } from "../_libs/radix-ui__react-collapsible.mjs";
|
|
20
15
|
import { R as Root$1, V as Viewport, C as Corner, S as ScrollAreaScrollbar, a as ScrollAreaThumb } from "../_libs/radix-ui__react-scroll-area.mjs";
|
|
21
16
|
const ApiErrorSchema = object({
|
|
22
17
|
error: string()
|
|
23
18
|
});
|
|
19
|
+
const MUTATION_METHODS = /* @__PURE__ */ new Set(["POST", "PUT", "PATCH", "DELETE"]);
|
|
20
|
+
function withBrowserMutationProof(init) {
|
|
21
|
+
const method = init?.method?.toUpperCase();
|
|
22
|
+
if (method === void 0 || !MUTATION_METHODS.has(method)) return init;
|
|
23
|
+
const headers = new Headers(init?.headers);
|
|
24
|
+
if (!headers.has("x-agent-inspector-csrf")) {
|
|
25
|
+
headers.set("x-agent-inspector-csrf", "1");
|
|
26
|
+
}
|
|
27
|
+
return { ...init, headers };
|
|
28
|
+
}
|
|
24
29
|
async function parseJsonResponse$1(response, schema) {
|
|
25
30
|
const data = await response.json();
|
|
26
31
|
return schema.parse(data);
|
|
@@ -35,7 +40,7 @@ async function readApiError(response, fallback) {
|
|
|
35
40
|
}
|
|
36
41
|
}
|
|
37
42
|
async function fetchJson(input, schema, init, errorFallback) {
|
|
38
|
-
const response = await fetch(input, init);
|
|
43
|
+
const response = await fetch(input, withBrowserMutationProof(init));
|
|
39
44
|
if (!response.ok) {
|
|
40
45
|
const fallback = errorFallback?.(response) ?? `Request failed with status ${response.status}`;
|
|
41
46
|
throw new Error(await readApiError(response, fallback));
|
|
@@ -69,7 +74,10 @@ async function fetchWithTimeout(input, timeoutMs, init) {
|
|
|
69
74
|
}
|
|
70
75
|
}
|
|
71
76
|
try {
|
|
72
|
-
return await fetch(input, {
|
|
77
|
+
return await fetch(input, {
|
|
78
|
+
...withBrowserMutationProof(init),
|
|
79
|
+
signal: controller.signal
|
|
80
|
+
});
|
|
73
81
|
} catch (error) {
|
|
74
82
|
if (timedOut && error instanceof DOMException && error.name === "AbortError") {
|
|
75
83
|
throw new ApiTimeoutError(timeoutMs);
|
|
@@ -248,22 +256,23 @@ function useOnboarding() {
|
|
|
248
256
|
markSeen
|
|
249
257
|
};
|
|
250
258
|
}
|
|
251
|
-
function
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
259
|
+
function OnboardingTip({
|
|
260
|
+
expanded,
|
|
261
|
+
onToggle,
|
|
262
|
+
onDismiss
|
|
263
|
+
}) {
|
|
255
264
|
const detailClass = expanded ? "grid" : "hidden sm:grid";
|
|
256
265
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
257
266
|
"div",
|
|
258
267
|
{
|
|
259
268
|
role: "note",
|
|
260
269
|
"aria-label": "Onboarding tip",
|
|
261
|
-
className: "mx-
|
|
270
|
+
className: "mx-3 mt-2 mb-1 rounded-md border border-warning/30 bg-warning/10 px-3 py-2 text-sm shadow-sm sm:mx-4",
|
|
262
271
|
children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-3", children: [
|
|
263
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(Info, { className: "mt-0.5 size-4 shrink-0 text-
|
|
272
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Info, { className: "mt-0.5 size-4 shrink-0 text-warning", "aria-hidden": "true" }),
|
|
264
273
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
265
274
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: [
|
|
266
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium text-
|
|
275
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium text-foreground", children: "Inspector ready" }),
|
|
267
276
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "hidden truncate text-xs text-muted-foreground sm:inline", children: "Request, response, tool, timing, token, replay, and memory signals are active." })
|
|
268
277
|
] }),
|
|
269
278
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1 text-xs leading-relaxed text-muted-foreground sm:hidden", children: "Core capture is active." }),
|
|
@@ -290,8 +299,8 @@ function OnboardingBanner() {
|
|
|
290
299
|
"button",
|
|
291
300
|
{
|
|
292
301
|
type: "button",
|
|
293
|
-
onClick:
|
|
294
|
-
className: "inline-flex h-8 shrink-0 items-center gap-1 rounded-md border border-
|
|
302
|
+
onClick: onToggle,
|
|
303
|
+
className: "inline-flex h-8 shrink-0 items-center gap-1 rounded-md border border-warning/35 px-2 text-xs font-medium text-foreground transition-colors hover:bg-warning/15 focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none sm:hidden",
|
|
295
304
|
"aria-expanded": expanded,
|
|
296
305
|
"aria-label": expanded ? "Hide onboarding details" : "Show onboarding details",
|
|
297
306
|
children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -306,10 +315,8 @@ function OnboardingBanner() {
|
|
|
306
315
|
"button",
|
|
307
316
|
{
|
|
308
317
|
type: "button",
|
|
309
|
-
onClick:
|
|
310
|
-
|
|
311
|
-
},
|
|
312
|
-
className: "hidden h-8 shrink-0 items-center gap-1.5 rounded-md border border-amber-500/40 px-3 text-xs text-amber-200 transition-colors hover:bg-amber-500/10 sm:inline-flex",
|
|
318
|
+
onClick: onDismiss,
|
|
319
|
+
className: "hidden h-8 shrink-0 items-center gap-1.5 rounded-md border border-warning/40 px-3 text-xs font-medium text-foreground transition-colors hover:bg-warning/15 focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none sm:inline-flex",
|
|
313
320
|
"aria-label": "Dismiss onboarding tip",
|
|
314
321
|
children: [
|
|
315
322
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-3.5" }),
|
|
@@ -321,10 +328,8 @@ function OnboardingBanner() {
|
|
|
321
328
|
"button",
|
|
322
329
|
{
|
|
323
330
|
type: "button",
|
|
324
|
-
onClick:
|
|
325
|
-
|
|
326
|
-
},
|
|
327
|
-
className: "-m-1 shrink-0 p-1 text-muted-foreground transition-colors hover:text-foreground",
|
|
331
|
+
onClick: onDismiss,
|
|
332
|
+
className: "-m-1 shrink-0 rounded-sm p-1 text-muted-foreground transition-colors hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none",
|
|
328
333
|
"aria-label": "Dismiss",
|
|
329
334
|
children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "size-3.5" })
|
|
330
335
|
}
|
|
@@ -333,6 +338,21 @@ function OnboardingBanner() {
|
|
|
333
338
|
}
|
|
334
339
|
);
|
|
335
340
|
}
|
|
341
|
+
function OnboardingBanner() {
|
|
342
|
+
const { hasSeenOnboarding, isLoading, markSeen } = useOnboarding();
|
|
343
|
+
const [expanded, setExpanded] = reactExports.useState(false);
|
|
344
|
+
if (isLoading || hasSeenOnboarding) return null;
|
|
345
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
346
|
+
OnboardingTip,
|
|
347
|
+
{
|
|
348
|
+
expanded,
|
|
349
|
+
onToggle: () => setExpanded((value) => !value),
|
|
350
|
+
onDismiss: () => {
|
|
351
|
+
void markSeen();
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
);
|
|
355
|
+
}
|
|
336
356
|
const REDACTED = "[REDACTED]";
|
|
337
357
|
const SECRET_KEY_PATTERN = /(^|[-_])(api[-_]?key|authorization|cookie|token|secret|password|access[-_]?token|refresh[-_]?token)([-_]|$)/i;
|
|
338
358
|
const SECRET_TEXT_PATTERNS = [
|
|
@@ -446,6 +466,9 @@ async function exportLogsAsZip(logs, mode = "redacted", options = {}) {
|
|
|
446
466
|
if (initialCancel !== null) return initialCancel;
|
|
447
467
|
const limitMessage = exportLimitMessage(logs);
|
|
448
468
|
if (limitMessage !== null) return { ok: false, message: limitMessage };
|
|
469
|
+
const { default: JSZip } = await import("../_libs/jszip.mjs").then(function(n) {
|
|
470
|
+
return n.i;
|
|
471
|
+
});
|
|
449
472
|
const zip = new JSZip();
|
|
450
473
|
const suffix = mode === "redacted" ? "redacted" : "raw";
|
|
451
474
|
const streamingLogs = logs.filter((log) => log.streaming).slice(0, MAX_STREAMING_CHUNK_EXPORTS);
|
|
@@ -492,61 +515,6 @@ async function exportLogsAsZip(logs, mode = "redacted", options = {}) {
|
|
|
492
515
|
URL.revokeObjectURL(url);
|
|
493
516
|
return { ok: true };
|
|
494
517
|
}
|
|
495
|
-
function restoreSelection(selection, ranges) {
|
|
496
|
-
if (selection === null) return;
|
|
497
|
-
selection.removeAllRanges();
|
|
498
|
-
for (const range of ranges) {
|
|
499
|
-
selection.addRange(range);
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
function readSelectionRanges(selection) {
|
|
503
|
-
if (selection === null) return [];
|
|
504
|
-
const ranges = [];
|
|
505
|
-
for (let index = 0; index < selection.rangeCount; index++) {
|
|
506
|
-
ranges.push(selection.getRangeAt(index));
|
|
507
|
-
}
|
|
508
|
-
return ranges;
|
|
509
|
-
}
|
|
510
|
-
function copyWithTextareaFallback(text) {
|
|
511
|
-
if (typeof document === "undefined") return false;
|
|
512
|
-
const activeElement = document.activeElement;
|
|
513
|
-
const selection = document.getSelection();
|
|
514
|
-
const ranges = readSelectionRanges(selection);
|
|
515
|
-
const textarea = document.createElement("textarea");
|
|
516
|
-
textarea.value = text;
|
|
517
|
-
textarea.setAttribute("readonly", "");
|
|
518
|
-
textarea.style.position = "fixed";
|
|
519
|
-
textarea.style.top = "0";
|
|
520
|
-
textarea.style.left = "-9999px";
|
|
521
|
-
textarea.style.opacity = "0";
|
|
522
|
-
document.body.appendChild(textarea);
|
|
523
|
-
textarea.focus();
|
|
524
|
-
textarea.select();
|
|
525
|
-
textarea.setSelectionRange(0, text.length);
|
|
526
|
-
let copied = false;
|
|
527
|
-
try {
|
|
528
|
-
copied = document.execCommand("copy");
|
|
529
|
-
} catch {
|
|
530
|
-
} finally {
|
|
531
|
-
document.body.removeChild(textarea);
|
|
532
|
-
restoreSelection(selection, ranges);
|
|
533
|
-
if (typeof HTMLElement !== "undefined" && activeElement instanceof HTMLElement) {
|
|
534
|
-
activeElement.focus({ preventScroll: true });
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
return copied;
|
|
538
|
-
}
|
|
539
|
-
async function copyTextToClipboard(text) {
|
|
540
|
-
const clipboard = globalThis.navigator?.clipboard;
|
|
541
|
-
if (clipboard !== void 0) {
|
|
542
|
-
try {
|
|
543
|
-
await clipboard.writeText(text);
|
|
544
|
-
return true;
|
|
545
|
-
} catch {
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
return copyWithTextareaFallback(text);
|
|
549
|
-
}
|
|
550
518
|
function formatTimestamp$2(iso, format) {
|
|
551
519
|
switch (format) {
|
|
552
520
|
case "full":
|
|
@@ -562,72 +530,6 @@ function formatTimestamp$2(iso, format) {
|
|
|
562
530
|
function formatTimestampRange(startedAt, endedAt, format) {
|
|
563
531
|
return `${formatTimestamp$2(startedAt, format)} - ${formatTimestamp$2(endedAt, format)}`;
|
|
564
532
|
}
|
|
565
|
-
function cn(...inputs) {
|
|
566
|
-
return twMerge(clsx(inputs));
|
|
567
|
-
}
|
|
568
|
-
function formatTokens(count) {
|
|
569
|
-
const absoluteCount = Math.abs(count);
|
|
570
|
-
if (absoluteCount < 1e3) return String(count);
|
|
571
|
-
if (absoluteCount >= 1e6) {
|
|
572
|
-
return (count / 1e6).toFixed(1).replace(/\.0$/, "") + "M";
|
|
573
|
-
}
|
|
574
|
-
return (count / 1e3).toFixed(1).replace(/\.0$/, "") + "K";
|
|
575
|
-
}
|
|
576
|
-
function formatContextWindowTokens(count) {
|
|
577
|
-
if (count >= 1024 * 1024) {
|
|
578
|
-
return (count / (1024 * 1024)).toFixed(1).replace(/\.0$/, "") + "M";
|
|
579
|
-
}
|
|
580
|
-
return (count / 1024).toFixed(1).replace(/\.0$/, "") + "K";
|
|
581
|
-
}
|
|
582
|
-
function formatExactContextUnit(count, multiplier, unit) {
|
|
583
|
-
const tenths = count * 10;
|
|
584
|
-
if (!Number.isSafeInteger(tenths) || tenths % multiplier !== 0) return null;
|
|
585
|
-
return (tenths / multiplier / 10).toFixed(1).replace(/\.0$/, "") + unit;
|
|
586
|
-
}
|
|
587
|
-
function formatContextWindowInput(count) {
|
|
588
|
-
if (!Number.isSafeInteger(count) || count <= 0) return count.toString();
|
|
589
|
-
if (count >= 1024 * 1024) {
|
|
590
|
-
const megaValue = formatExactContextUnit(count, 1024 * 1024, "M");
|
|
591
|
-
if (megaValue !== null) return megaValue;
|
|
592
|
-
}
|
|
593
|
-
const kiloValue = formatExactContextUnit(count, 1024, "K");
|
|
594
|
-
if (kiloValue !== null) return kiloValue;
|
|
595
|
-
return count.toString();
|
|
596
|
-
}
|
|
597
|
-
function contextWindowUnitMultiplier(unit) {
|
|
598
|
-
if (unit === void 0 || unit === "") return 1;
|
|
599
|
-
switch (unit.toLowerCase()) {
|
|
600
|
-
case "k":
|
|
601
|
-
return 1024;
|
|
602
|
-
case "m":
|
|
603
|
-
return 1024 * 1024;
|
|
604
|
-
default:
|
|
605
|
-
return null;
|
|
606
|
-
}
|
|
607
|
-
}
|
|
608
|
-
function parseContextWindowTokensInput(value) {
|
|
609
|
-
const trimmed = value.trim().replaceAll(",", "");
|
|
610
|
-
if (trimmed === "") return null;
|
|
611
|
-
const match = /^(\d+(?:\.\d+)?)\s*([kKmM])?$/.exec(trimmed);
|
|
612
|
-
if (match === null) return null;
|
|
613
|
-
const amountText = match[1];
|
|
614
|
-
if (amountText === void 0) return null;
|
|
615
|
-
const amount = Number(amountText);
|
|
616
|
-
const unit = match[2];
|
|
617
|
-
const multiplier = contextWindowUnitMultiplier(unit);
|
|
618
|
-
if (!Number.isFinite(amount) || amount <= 0 || multiplier === null) return null;
|
|
619
|
-
if ((unit === void 0 || unit === "") && !Number.isInteger(amount)) return null;
|
|
620
|
-
const tokens = Math.round(amount * multiplier);
|
|
621
|
-
if (!Number.isSafeInteger(tokens) || tokens <= 0) return null;
|
|
622
|
-
return tokens;
|
|
623
|
-
}
|
|
624
|
-
function getStatusCategory(status) {
|
|
625
|
-
if (status === null) return "pending";
|
|
626
|
-
if (status >= 200 && status < 300) return "success";
|
|
627
|
-
if (status >= 400 && status < 500) return "client_error";
|
|
628
|
-
if (status >= 500) return "server_error";
|
|
629
|
-
return "pending";
|
|
630
|
-
}
|
|
631
533
|
function useThemeMode() {
|
|
632
534
|
const [themeMode, setThemeModeState] = reactExports.useState(readStoredThemeMode);
|
|
633
535
|
const setThemeMode = reactExports.useCallback((nextThemeMode) => {
|
|
@@ -684,7 +586,7 @@ function useUiScale() {
|
|
|
684
586
|
async function fetcher(url) {
|
|
685
587
|
return fetchJson(
|
|
686
588
|
url,
|
|
687
|
-
|
|
589
|
+
RedactedProviderDtoSchema.array(),
|
|
688
590
|
void 0,
|
|
689
591
|
(response) => `Failed to fetch ${url}: ${response.status}`
|
|
690
592
|
);
|
|
@@ -799,46 +701,6 @@ function DialogDescription({
|
|
|
799
701
|
}
|
|
800
702
|
);
|
|
801
703
|
}
|
|
802
|
-
const buttonVariants = cva(
|
|
803
|
-
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
804
|
-
{
|
|
805
|
-
variants: {
|
|
806
|
-
variant: {
|
|
807
|
-
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
808
|
-
destructive: "bg-destructive text-white hover:bg-destructive/90",
|
|
809
|
-
outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
|
|
810
|
-
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
811
|
-
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
812
|
-
link: "text-primary underline-offset-4 hover:underline"
|
|
813
|
-
},
|
|
814
|
-
size: {
|
|
815
|
-
default: "h-9 px-4 py-2",
|
|
816
|
-
sm: "h-8 rounded-md px-3 text-xs",
|
|
817
|
-
lg: "h-10 rounded-md px-8",
|
|
818
|
-
icon: "size-9"
|
|
819
|
-
}
|
|
820
|
-
},
|
|
821
|
-
defaultVariants: {
|
|
822
|
-
variant: "default",
|
|
823
|
-
size: "default"
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
);
|
|
827
|
-
function Button({
|
|
828
|
-
className,
|
|
829
|
-
variant,
|
|
830
|
-
size,
|
|
831
|
-
...props
|
|
832
|
-
}) {
|
|
833
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
834
|
-
"button",
|
|
835
|
-
{
|
|
836
|
-
"data-slot": "button",
|
|
837
|
-
className: cn(buttonVariants({ variant, size, className })),
|
|
838
|
-
...props
|
|
839
|
-
}
|
|
840
|
-
);
|
|
841
|
-
}
|
|
842
704
|
function ConfirmDialog({
|
|
843
705
|
open,
|
|
844
706
|
onOpenChange,
|
|
@@ -1009,7 +871,7 @@ const OpenAILogoSvg = "data:image/svg+xml,%3csvg%20height='2500'%20viewBox='-1%2
|
|
|
1009
871
|
const DeepSeekLogoSvg = "data:image/svg+xml,%3csvg%20fill='none'%20height='1320'%20viewBox='3.771%206.973%2023.993%2017.652'%20width='2500'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='m27.501%208.469c-.252-.123-.36.111-.508.23-.05.04-.093.09-.135.135-.368.395-.797.652-1.358.621-.821-.045-1.521.213-2.14.842-.132-.776-.57-1.238-1.235-1.535-.349-.155-.701-.309-.944-.645-.171-.238-.217-.504-.303-.765-.054-.159-.108-.32-.29-.348-.197-.031-.274.135-.352.273-.31.567-.43%201.192-.419%201.825.028%201.421.628%202.554%201.82%203.36.136.093.17.186.128.321-.081.278-.178.547-.264.824-.054.178-.135.217-.324.14a5.448%205.448%200%200%201%20-1.719-1.169c-.848-.82-1.614-1.726-2.57-2.435-.225-.166-.449-.32-.681-.467-.976-.95.128-1.729.383-1.82.267-.096.093-.428-.77-.424s-1.653.293-2.659.677a2.782%202.782%200%200%201%20-.46.135%209.554%209.554%200%200%200%20-2.853-.1c-1.866.21-3.356%201.092-4.452%202.6-1.315%201.81-1.625%203.87-1.246%206.018.399%202.261%201.552%204.136%203.326%205.601%201.837%201.518%203.955%202.262%206.37%202.12%201.466-.085%203.1-.282%204.942-1.842.465.23.952.322%201.762.392.623.059%201.223-.031%201.687-.127.728-.154.677-.828.414-.953-2.132-.994-1.665-.59-2.09-.916%201.084-1.285%202.717-2.619%203.356-6.94.05-.343.007-.558%200-.837-.004-.168.034-.235.228-.254a4.084%204.084%200%200%200%201.529-.47c1.382-.757%201.938-1.997%202.07-3.485.02-.227-.004-.463-.243-.582zm-12.041%2013.391c-2.067-1.627-3.07-2.162-3.483-2.138-.387.021-.318.465-.233.754.089.285.205.482.368.732.113.166.19.414-.112.598-.666.414-1.823-.139-1.878-.166-1.347-.793-2.473-1.842-3.267-3.276-.765-1.38-1.21-2.861-1.284-4.441-.02-.383.093-.518.472-.586a4.692%204.692%200%200%201%201.514-.04c2.109.31%203.905%201.255%205.41%202.749.86.853%201.51%201.871%202.18%202.865.711%201.057%201.478%202.063%202.454%202.887.343.289.619.51.881.672-.792.088-2.117.107-3.022-.61zm.99-6.38a.304.304%200%201%201%20.609%200c0%20.17-.136.304-.306.304a.3.3%200%200%201%20-.303-.305zm3.077%201.581c-.197.08-.394.15-.584.159a1.246%201.246%200%200%201%20-.79-.252c-.27-.227-.463-.354-.546-.752a1.752%201.752%200%200%201%20.016-.582c.07-.324-.008-.531-.235-.72-.187-.155-.422-.196-.682-.196a.551.551%200%200%201%20-.252-.078c-.108-.055-.197-.19-.112-.356.027-.053.159-.183.19-.207.352-.201.758-.135%201.134.016.349.142.611.404.99.773.388.448.457.573.678.906.174.264.333.534.441.842.066.192-.02.35-.248.448z'%20fill='%234d6bfe'/%3e%3c/svg%3e";
|
|
1010
872
|
const MiniMaxLogoSvg = "/assets/minimax-BPMzvuL-.jpeg";
|
|
1011
873
|
const AlibabaLogoSvg = "/assets/alibaba-TTwafVwX.svg";
|
|
1012
|
-
const QwenLogoSvg = "/assets/qwen-
|
|
874
|
+
const QwenLogoSvg = "/assets/qwen-mMn3f5ul.webp";
|
|
1013
875
|
const ZhipuAILogoSvg = "/assets/zhipuai-BPNAnxo-.svg";
|
|
1014
876
|
const PROVIDER_MAP = {
|
|
1015
877
|
"claude-": "anthropic",
|
|
@@ -2024,6 +1886,79 @@ function readLogFocusRequest(event) {
|
|
|
2024
1886
|
return null;
|
|
2025
1887
|
}
|
|
2026
1888
|
}
|
|
1889
|
+
function normalizeAnthropicStopReason(value) {
|
|
1890
|
+
switch (value) {
|
|
1891
|
+
case "end_turn":
|
|
1892
|
+
case "tool_use":
|
|
1893
|
+
return value;
|
|
1894
|
+
case "max_tokens":
|
|
1895
|
+
return "length";
|
|
1896
|
+
default:
|
|
1897
|
+
return null;
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1900
|
+
function normalizeOpenAIFinishReason(value) {
|
|
1901
|
+
switch (value) {
|
|
1902
|
+
case "stop":
|
|
1903
|
+
case "length":
|
|
1904
|
+
return value;
|
|
1905
|
+
case "max_tokens":
|
|
1906
|
+
return "length";
|
|
1907
|
+
default:
|
|
1908
|
+
return null;
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
function isResponsesLengthLimitReason(value) {
|
|
1912
|
+
switch (value) {
|
|
1913
|
+
case "max_output_tokens":
|
|
1914
|
+
case "max_tokens":
|
|
1915
|
+
return true;
|
|
1916
|
+
default:
|
|
1917
|
+
return false;
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
function extractStopReason(log) {
|
|
1921
|
+
if (log.responseText === null) return null;
|
|
1922
|
+
try {
|
|
1923
|
+
let json = JSON.parse(log.responseText);
|
|
1924
|
+
if (typeof json === "string") {
|
|
1925
|
+
json = JSON.parse(json);
|
|
1926
|
+
}
|
|
1927
|
+
if (!isRecord(json)) return null;
|
|
1928
|
+
if (typeof json.stop_reason === "string") {
|
|
1929
|
+
return normalizeAnthropicStopReason(json.stop_reason);
|
|
1930
|
+
}
|
|
1931
|
+
if (Array.isArray(json.choices)) {
|
|
1932
|
+
for (const choice of json.choices) {
|
|
1933
|
+
if (!isRecord(choice) || typeof choice.finish_reason !== "string") continue;
|
|
1934
|
+
const reason = normalizeOpenAIFinishReason(choice.finish_reason);
|
|
1935
|
+
if (reason !== null) return reason;
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
if (Array.isArray(json.output)) {
|
|
1939
|
+
for (const item of json.output) {
|
|
1940
|
+
if (isRecord(item) && item.type === "function_call") {
|
|
1941
|
+
return "tool_use";
|
|
1942
|
+
}
|
|
1943
|
+
}
|
|
1944
|
+
if (json.status === "completed") {
|
|
1945
|
+
return "stop";
|
|
1946
|
+
}
|
|
1947
|
+
}
|
|
1948
|
+
if (json.status === "incomplete" && isRecord(json.incomplete_details)) {
|
|
1949
|
+
const reason = json.incomplete_details.reason;
|
|
1950
|
+
if (typeof reason === "string" && isResponsesLengthLimitReason(reason)) {
|
|
1951
|
+
return "length";
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
return null;
|
|
1955
|
+
} catch {
|
|
1956
|
+
return null;
|
|
1957
|
+
}
|
|
1958
|
+
}
|
|
1959
|
+
function isTurnBoundary(stopReason) {
|
|
1960
|
+
return stopReason === "end_turn" || stopReason === "stop" || stopReason === "length";
|
|
1961
|
+
}
|
|
2027
1962
|
function SvgShell({
|
|
2028
1963
|
className,
|
|
2029
1964
|
style,
|
|
@@ -2521,9 +2456,9 @@ function TabsTrigger({
|
|
|
2521
2456
|
{
|
|
2522
2457
|
"data-slot": "tabs-trigger",
|
|
2523
2458
|
className: cn(
|
|
2524
|
-
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring text-
|
|
2525
|
-
"group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-[state=active]:
|
|
2526
|
-
"data-[state=active]:
|
|
2459
|
+
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring text-muted-foreground hover:text-foreground relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 group-data-[variant=default]/tabs-list:data-[state=active]:shadow-sm group-data-[variant=line]/tabs-list:data-[state=active]:shadow-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
2460
|
+
"group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-[state=active]:border-transparent group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent",
|
|
2461
|
+
"data-[state=active]:border-border data-[state=active]:bg-background data-[state=active]:text-foreground",
|
|
2527
2462
|
"after:bg-foreground after:absolute after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-[state=active]:after:opacity-100",
|
|
2528
2463
|
className
|
|
2529
2464
|
),
|
|
@@ -2569,27 +2504,30 @@ function useCopyFeedback(text) {
|
|
|
2569
2504
|
return { copied, copy };
|
|
2570
2505
|
}
|
|
2571
2506
|
const LazyCompareDrawer = reactExports.lazy(
|
|
2572
|
-
() => import("./CompareDrawer-
|
|
2507
|
+
() => import("./CompareDrawer-27amlv_a.mjs").then((m) => ({ default: m.CompareDrawer }))
|
|
2508
|
+
);
|
|
2509
|
+
const LazyInspectorPet = reactExports.lazy(
|
|
2510
|
+
() => import("./InspectorPet-CQnGXfLs.mjs").then((m) => ({ default: m.InspectorPet }))
|
|
2573
2511
|
);
|
|
2574
2512
|
const LazyReplayDialog = reactExports.lazy(
|
|
2575
|
-
() => import("./ReplayDialog-
|
|
2513
|
+
() => import("./ReplayDialog-5m2jtlLa.mjs").then((m) => ({ default: m.ReplayDialog }))
|
|
2576
2514
|
);
|
|
2577
2515
|
const LazyRequestAnatomy = reactExports.lazy(
|
|
2578
|
-
() => import("./RequestAnatomy
|
|
2516
|
+
() => import("./RequestAnatomy--1WtQNY9.mjs").then((m) => ({ default: m.RequestAnatomy }))
|
|
2579
2517
|
);
|
|
2580
2518
|
const LazyResponseView = reactExports.lazy(
|
|
2581
|
-
() => import("./ResponseView-
|
|
2519
|
+
() => import("./ResponseView-CgbqS8sr.mjs").then((m) => ({ default: m.ResponseView }))
|
|
2582
2520
|
);
|
|
2583
2521
|
const LazyStreamingChunkSequence = reactExports.lazy(
|
|
2584
|
-
() => import("./StreamingChunkSequence-
|
|
2522
|
+
() => import("./StreamingChunkSequence-BwpnopWx.mjs").then((m) => ({
|
|
2585
2523
|
default: m.StreamingChunkSequence
|
|
2586
2524
|
}))
|
|
2587
2525
|
);
|
|
2588
2526
|
const LazyJsonViewer = reactExports.lazy(
|
|
2589
|
-
() => import("./json-viewer-
|
|
2527
|
+
() => import("./json-viewer-DNGN2uoe.mjs").then((m) => ({ default: m.JsonViewer }))
|
|
2590
2528
|
);
|
|
2591
2529
|
const LazyJsonViewerFromString = reactExports.lazy(
|
|
2592
|
-
() => import("./json-viewer-
|
|
2530
|
+
() => import("./json-viewer-DNGN2uoe.mjs").then((m) => ({ default: m.JsonViewerFromString }))
|
|
2593
2531
|
);
|
|
2594
2532
|
const HIGHLIGHT_DURATION_MS = 1200;
|
|
2595
2533
|
const MAX_HIGHLIGHT_ATTEMPTS = 12;
|
|
@@ -4397,7 +4335,7 @@ const LogEntry = reactExports.memo(function({
|
|
|
4397
4335
|
"aria-hidden": "true"
|
|
4398
4336
|
}
|
|
4399
4337
|
),
|
|
4400
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(Tabs, { value: activeTab, onValueChange: setActiveTab, className: "gap-2", children: [
|
|
4338
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(LazyFeatureBoundary, { feature: "Log details", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tabs, { value: activeTab, onValueChange: setActiveTab, className: "gap-2", children: [
|
|
4401
4339
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
4402
4340
|
TabsList,
|
|
4403
4341
|
{
|
|
@@ -4533,7 +4471,13 @@ const LogEntry = reactExports.memo(function({
|
|
|
4533
4471
|
headers: displayLog.headers,
|
|
4534
4472
|
emptyLabel: "No transformation applied; raw and processed headers are identical."
|
|
4535
4473
|
}
|
|
4536
|
-
) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4474
|
+
) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4475
|
+
HeaderRows,
|
|
4476
|
+
{
|
|
4477
|
+
headers: displayLog.headers,
|
|
4478
|
+
emptyLabel: "No headers captured"
|
|
4479
|
+
}
|
|
4480
|
+
)
|
|
4537
4481
|
] }) }),
|
|
4538
4482
|
shouldShowRawHeadersTab(
|
|
4539
4483
|
viewMode,
|
|
@@ -4618,14 +4562,14 @@ const LogEntry = reactExports.memo(function({
|
|
|
4618
4562
|
}
|
|
4619
4563
|
) })
|
|
4620
4564
|
] }) })
|
|
4621
|
-
] })
|
|
4565
|
+
] }) })
|
|
4622
4566
|
]
|
|
4623
4567
|
}
|
|
4624
4568
|
)
|
|
4625
4569
|
]
|
|
4626
4570
|
}
|
|
4627
4571
|
),
|
|
4628
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4572
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(LazyFeatureBoundary, { feature: "Replay", children: /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4629
4573
|
LazyReplayDialog,
|
|
4630
4574
|
{
|
|
4631
4575
|
log: displayLog,
|
|
@@ -4633,7 +4577,7 @@ const LogEntry = reactExports.memo(function({
|
|
|
4633
4577
|
open: replayOpen,
|
|
4634
4578
|
onOpenChange: setReplayOpen
|
|
4635
4579
|
}
|
|
4636
|
-
) })
|
|
4580
|
+
) }) })
|
|
4637
4581
|
] });
|
|
4638
4582
|
});
|
|
4639
4583
|
function boundaryTitle(stopReason) {
|
|
@@ -4658,6 +4602,7 @@ function ThreadConnector({
|
|
|
4658
4602
|
isFirst,
|
|
4659
4603
|
isTurnStart,
|
|
4660
4604
|
isOnlyEntry = false,
|
|
4605
|
+
isOpenTurnTail = false,
|
|
4661
4606
|
crabIndex = 0,
|
|
4662
4607
|
collapsible = false,
|
|
4663
4608
|
onToggle
|
|
@@ -4741,8 +4686,23 @@ function ThreadConnector({
|
|
|
4741
4686
|
}
|
|
4742
4687
|
)
|
|
4743
4688
|
}
|
|
4689
|
+
) : isOpenTurnTail ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4690
|
+
"span",
|
|
4691
|
+
{
|
|
4692
|
+
title: isPending ? "Current end of open turn (processing)" : "Current end of open turn",
|
|
4693
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4694
|
+
Crab,
|
|
4695
|
+
{
|
|
4696
|
+
className: cn(
|
|
4697
|
+
"size-3.5 text-cyan-300/85",
|
|
4698
|
+
isRunning ? "animate-crab-crawl" : "animate-crab-appear",
|
|
4699
|
+
"drop-shadow-[0_0_4px_rgba(103,232,249,0.4)]"
|
|
4700
|
+
)
|
|
4701
|
+
}
|
|
4702
|
+
)
|
|
4703
|
+
}
|
|
4744
4704
|
) : isRunning ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { title: "Processing", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Crab, { className: cn("size-3.5 text-amber-300/80", "animate-crab-crawl") }) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { title: "Request in turn", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Crab, { className: "size-3.5 text-muted-foreground/40" }) }),
|
|
4745
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 flex justify-center min-h-0", children: !isBoundary && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4705
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 flex justify-center min-h-0", children: !isBoundary && !isOpenTurnTail && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4746
4706
|
"div",
|
|
4747
4707
|
{
|
|
4748
4708
|
className: cn(
|
|
@@ -4767,8 +4727,8 @@ function responseMayContainToolTrace(log, format) {
|
|
|
4767
4727
|
return false;
|
|
4768
4728
|
}
|
|
4769
4729
|
}
|
|
4770
|
-
function isTurnCollapsible(entryCount
|
|
4771
|
-
return entryCount > 1
|
|
4730
|
+
function isTurnCollapsible(entryCount) {
|
|
4731
|
+
return entryCount > 1;
|
|
4772
4732
|
}
|
|
4773
4733
|
function buildTurnGroups(logs) {
|
|
4774
4734
|
const groups = [];
|
|
@@ -5019,7 +4979,7 @@ const TurnGroup = reactExports.memo(function TurnGroup2({
|
|
|
5019
4979
|
const isComplete = lastStop !== null ? isTurnBoundary(lastStop) : false;
|
|
5020
4980
|
const isPending = entries[lastIdx]?.log.responseStatus === null;
|
|
5021
4981
|
const isSingleLog = entries.length === 1;
|
|
5022
|
-
const collapsible = isTurnCollapsible(entries.length
|
|
4982
|
+
const collapsible = isTurnCollapsible(entries.length);
|
|
5023
4983
|
const [collapsed, setCollapsed] = reactExports.useState(false);
|
|
5024
4984
|
const prevCompleteRef = reactExports.useRef(false);
|
|
5025
4985
|
reactExports.useEffect(() => {
|
|
@@ -5162,7 +5122,7 @@ const TurnGroup = reactExports.memo(function TurnGroup2({
|
|
|
5162
5122
|
}
|
|
5163
5123
|
),
|
|
5164
5124
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 flex justify-center min-h-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-px bg-muted-foreground/14 h-full" }) }),
|
|
5165
|
-
isComplete
|
|
5125
|
+
isComplete ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5166
5126
|
CollapsedCrab,
|
|
5167
5127
|
{
|
|
5168
5128
|
className: cn(
|
|
@@ -5170,7 +5130,16 @@ const TurnGroup = reactExports.memo(function TurnGroup2({
|
|
|
5170
5130
|
"drop-shadow-[0_0_4px_rgba(251,191,36,0.45)]"
|
|
5171
5131
|
)
|
|
5172
5132
|
}
|
|
5173
|
-
)
|
|
5133
|
+
) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { title: "Current end of open turn", "aria-label": "Current end of open turn", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5134
|
+
CollapsedCrab,
|
|
5135
|
+
{
|
|
5136
|
+
className: cn(
|
|
5137
|
+
"size-3.5 text-cyan-300/85",
|
|
5138
|
+
isPending ? "animate-crab-crawl" : "animate-crab-appear",
|
|
5139
|
+
"drop-shadow-[0_0_4px_rgba(103,232,249,0.4)]"
|
|
5140
|
+
)
|
|
5141
|
+
}
|
|
5142
|
+
) })
|
|
5174
5143
|
] }),
|
|
5175
5144
|
entries.length > 1 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
5176
5145
|
"div",
|
|
@@ -5263,6 +5232,7 @@ const TurnGroup = reactExports.memo(function TurnGroup2({
|
|
|
5263
5232
|
isFirst: visibleIdx === 0,
|
|
5264
5233
|
isTurnStart,
|
|
5265
5234
|
isOnlyEntry: isSingleLog,
|
|
5235
|
+
isOpenTurnTail: visibleIdx === lastIdx && !isComplete,
|
|
5266
5236
|
crabIndex: log.id % 12,
|
|
5267
5237
|
collapsible: collapsible && isTurnStart,
|
|
5268
5238
|
onToggle: toggleCollapse
|
|
@@ -6266,9 +6236,14 @@ const ConversationGroup = reactExports.memo(function({
|
|
|
6266
6236
|
] })
|
|
6267
6237
|
] });
|
|
6268
6238
|
});
|
|
6239
|
+
const COPYABLE_COMMAND_CONTAINER_CLASS_NAME = "flex w-full min-w-0 items-center gap-2 rounded-md border border-border/70 bg-muted/35 px-3 py-2 sm:w-auto sm:max-w-full";
|
|
6240
|
+
const COPYABLE_COMMAND_TEXT_CLASS_NAME = "m-0 min-w-0 flex-1 overflow-x-auto font-mono text-xs text-foreground sm:text-sm";
|
|
6269
6241
|
function shouldShowRawExport(captureMode) {
|
|
6270
6242
|
return captureMode === "full";
|
|
6271
6243
|
}
|
|
6244
|
+
function exportRequiresConfirmation(mode) {
|
|
6245
|
+
return mode === "raw";
|
|
6246
|
+
}
|
|
6272
6247
|
function getExportActionVisibility(captureMode, logCount) {
|
|
6273
6248
|
const hasLogs = logCount > 0;
|
|
6274
6249
|
return {
|
|
@@ -6565,46 +6540,6 @@ function formatPaginationStatus({
|
|
|
6565
6540
|
}
|
|
6566
6541
|
return `Showing ${logs.length} of ${pagination.total} logs (${range})`;
|
|
6567
6542
|
}
|
|
6568
|
-
function CrabLogo({ className }) {
|
|
6569
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
6570
|
-
"svg",
|
|
6571
|
-
{
|
|
6572
|
-
viewBox: "0 0 24 24",
|
|
6573
|
-
fill: "none",
|
|
6574
|
-
stroke: "currentColor",
|
|
6575
|
-
strokeWidth: "1.5",
|
|
6576
|
-
strokeLinecap: "round",
|
|
6577
|
-
strokeLinejoin: "round",
|
|
6578
|
-
"aria-hidden": "true",
|
|
6579
|
-
className: cn("inline-block size-5", className),
|
|
6580
|
-
children: [
|
|
6581
|
-
/* @__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" }),
|
|
6582
|
-
/* @__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" }),
|
|
6583
|
-
/* @__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" }),
|
|
6584
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10", y1: "7", x2: "9.5", y2: "5" }),
|
|
6585
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14", y1: "7", x2: "14.5", y2: "5" }),
|
|
6586
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "9.5", cy: "4.5", r: "0.9", fill: "currentColor", stroke: "none" }),
|
|
6587
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "14.5", cy: "4.5", r: "0.9", fill: "currentColor", stroke: "none" }),
|
|
6588
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "6.5", y1: "16", x2: "4.5", y2: "19.5" }),
|
|
6589
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "9", y1: "17.5", x2: "8", y2: "20.5" }),
|
|
6590
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "15", y1: "17.5", x2: "16", y2: "20.5" }),
|
|
6591
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "17.5", y1: "16", x2: "19.5", y2: "19.5" })
|
|
6592
|
-
]
|
|
6593
|
-
}
|
|
6594
|
-
);
|
|
6595
|
-
}
|
|
6596
|
-
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=";
|
|
6597
|
-
function McpLogo({ className }) {
|
|
6598
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
6599
|
-
"img",
|
|
6600
|
-
{
|
|
6601
|
-
src: McpLogoPng,
|
|
6602
|
-
alt: "Model Context Protocol",
|
|
6603
|
-
"aria-hidden": "true",
|
|
6604
|
-
className: cn("inline-block size-8 object-contain invert", className)
|
|
6605
|
-
}
|
|
6606
|
-
);
|
|
6607
|
-
}
|
|
6608
6543
|
function Select({
|
|
6609
6544
|
...props
|
|
6610
6545
|
}) {
|
|
@@ -6650,7 +6585,7 @@ function SelectContent({
|
|
|
6650
6585
|
{
|
|
6651
6586
|
"data-slot": "select-content",
|
|
6652
6587
|
className: cn(
|
|
6653
|
-
"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",
|
|
6588
|
+
"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 motion-reduce:data-[state=open]:animate-none motion-reduce:data-[state=closed]:animate-none 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",
|
|
6654
6589
|
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",
|
|
6655
6590
|
className
|
|
6656
6591
|
),
|
|
@@ -7345,14 +7280,17 @@ function TransientToast({
|
|
|
7345
7280
|
"div",
|
|
7346
7281
|
{
|
|
7347
7282
|
className: cn(
|
|
7348
|
-
"pointer-events-auto flex items-start gap-2 rounded-md border px-3 py-2 text-sm shadow-[
|
|
7349
|
-
isError ? "border-
|
|
7283
|
+
"pointer-events-auto flex items-start gap-2 rounded-md border bg-popover/95 px-3 py-2 text-sm text-popover-foreground shadow-[0_18px_50px_color-mix(in_oklch,var(--foreground)_16%,transparent)] backdrop-blur",
|
|
7284
|
+
isError ? "border-status-danger/35" : "border-status-success/35"
|
|
7350
7285
|
),
|
|
7351
7286
|
children: [
|
|
7352
7287
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
7353
7288
|
Icon,
|
|
7354
7289
|
{
|
|
7355
|
-
className: cn(
|
|
7290
|
+
className: cn(
|
|
7291
|
+
"mt-0.5 size-4 shrink-0",
|
|
7292
|
+
isError ? "text-status-danger" : "text-status-success"
|
|
7293
|
+
)
|
|
7356
7294
|
}
|
|
7357
7295
|
),
|
|
7358
7296
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "min-w-0 flex-1 break-words leading-5", children: notice.message }),
|
|
@@ -7360,7 +7298,7 @@ function TransientToast({
|
|
|
7360
7298
|
"button",
|
|
7361
7299
|
{
|
|
7362
7300
|
type: "button",
|
|
7363
|
-
className: "inline-flex size-6 shrink-0 items-center justify-center rounded-md text-current/70 transition-colors hover:bg-white/10 hover:text-current",
|
|
7301
|
+
className: "inline-flex size-6 shrink-0 items-center justify-center rounded-md text-current/70 transition-colors hover:bg-white/10 hover:text-current focus-visible:ring-1 focus-visible:ring-current focus-visible:outline-none",
|
|
7364
7302
|
"aria-label": "Dismiss notification",
|
|
7365
7303
|
onClick: onDismiss,
|
|
7366
7304
|
children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "size-3.5" })
|
|
@@ -8357,21 +8295,6 @@ function MemberMetadata({ entries }) {
|
|
|
8357
8295
|
}) })
|
|
8358
8296
|
] });
|
|
8359
8297
|
}
|
|
8360
|
-
const ExternalProviderSchema = object({
|
|
8361
|
-
name: string(),
|
|
8362
|
-
apiKey: string(),
|
|
8363
|
-
format: _enum(["anthropic", "openai"]),
|
|
8364
|
-
anthropicBaseUrl: string(),
|
|
8365
|
-
openaiBaseUrl: string(),
|
|
8366
|
-
openaiResponsesBaseUrl: string().optional().default(""),
|
|
8367
|
-
models: array(string()),
|
|
8368
|
-
sourceTool: _enum(["claude-code", "opencode", "mimo-code"]),
|
|
8369
|
-
alreadyExists: boolean()
|
|
8370
|
-
});
|
|
8371
|
-
const ScanResponseSchema = object({
|
|
8372
|
-
providers: array(ExternalProviderSchema),
|
|
8373
|
-
warnings: array(string()).optional()
|
|
8374
|
-
});
|
|
8375
8298
|
const ImportResponseSchema$1 = object({
|
|
8376
8299
|
success: boolean().optional(),
|
|
8377
8300
|
imported: number().optional(),
|
|
@@ -8386,6 +8309,7 @@ function ImportWizardDialog({
|
|
|
8386
8309
|
}) {
|
|
8387
8310
|
const [scanning, setScanning] = reactExports.useState(false);
|
|
8388
8311
|
const [scanError, setScanError] = reactExports.useState(null);
|
|
8312
|
+
const [scanId, setScanId] = reactExports.useState(null);
|
|
8389
8313
|
const [providers, setProviders] = reactExports.useState([]);
|
|
8390
8314
|
const [warnings, setWarnings] = reactExports.useState([]);
|
|
8391
8315
|
const [selected, setSelected] = reactExports.useState(/* @__PURE__ */ new Set());
|
|
@@ -8400,18 +8324,20 @@ function ImportWizardDialog({
|
|
|
8400
8324
|
setScanning(true);
|
|
8401
8325
|
setScanError(null);
|
|
8402
8326
|
setWarnings([]);
|
|
8327
|
+
setScanId(null);
|
|
8403
8328
|
setProviders([]);
|
|
8404
8329
|
setSelected(/* @__PURE__ */ new Set());
|
|
8405
8330
|
setImportResult(null);
|
|
8406
8331
|
setImportError(null);
|
|
8407
8332
|
void fetchJsonWithTimeout(
|
|
8408
8333
|
"/api/providers/scan",
|
|
8409
|
-
|
|
8334
|
+
ProviderScanResponseSchema,
|
|
8410
8335
|
PROVIDER_IMPORT_TIMEOUT_MS$1,
|
|
8411
|
-
|
|
8336
|
+
{ method: "POST" },
|
|
8412
8337
|
(response) => `Scan failed (${String(response.status)})`
|
|
8413
8338
|
).then((data) => {
|
|
8414
8339
|
if (scanRequestIdRef.current !== requestId) return;
|
|
8340
|
+
setScanId(data.scanId);
|
|
8415
8341
|
setProviders(data.providers);
|
|
8416
8342
|
setWarnings(data.warnings ?? []);
|
|
8417
8343
|
const indices = /* @__PURE__ */ new Set();
|
|
@@ -8452,25 +8378,12 @@ function ImportWizardDialog({
|
|
|
8452
8378
|
}, []);
|
|
8453
8379
|
const importSelected = reactExports.useCallback(() => {
|
|
8454
8380
|
const toImport = providers.filter((_, i) => selected.has(i));
|
|
8455
|
-
if (toImport.length === 0) return;
|
|
8381
|
+
if (toImport.length === 0 || scanId === null) return;
|
|
8456
8382
|
const requestId = importRequestIdRef.current + 1;
|
|
8457
8383
|
importRequestIdRef.current = requestId;
|
|
8458
8384
|
setImporting(true);
|
|
8459
8385
|
setImportError(null);
|
|
8460
8386
|
setImportResult(null);
|
|
8461
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
8462
|
-
const providersPayload = toImport.map((p) => ({
|
|
8463
|
-
id: window.crypto.randomUUID(),
|
|
8464
|
-
name: p.name,
|
|
8465
|
-
apiKey: p.apiKey,
|
|
8466
|
-
format: p.format,
|
|
8467
|
-
anthropicBaseUrl: p.anthropicBaseUrl,
|
|
8468
|
-
openaiBaseUrl: p.openaiBaseUrl,
|
|
8469
|
-
openaiResponsesBaseUrl: p.openaiResponsesBaseUrl,
|
|
8470
|
-
models: p.models,
|
|
8471
|
-
createdAt: now,
|
|
8472
|
-
updatedAt: now
|
|
8473
|
-
}));
|
|
8474
8387
|
void fetchJsonWithTimeout(
|
|
8475
8388
|
"/api/providers/import",
|
|
8476
8389
|
ImportResponseSchema$1,
|
|
@@ -8478,7 +8391,10 @@ function ImportWizardDialog({
|
|
|
8478
8391
|
{
|
|
8479
8392
|
method: "POST",
|
|
8480
8393
|
headers: { "Content-Type": "application/json" },
|
|
8481
|
-
body: JSON.stringify({
|
|
8394
|
+
body: JSON.stringify({
|
|
8395
|
+
scanId,
|
|
8396
|
+
selectionIds: toImport.map((provider) => provider.selectionId)
|
|
8397
|
+
})
|
|
8482
8398
|
},
|
|
8483
8399
|
(response) => `Import failed (${String(response.status)})`
|
|
8484
8400
|
).then((result) => {
|
|
@@ -8500,7 +8416,7 @@ function ImportWizardDialog({
|
|
|
8500
8416
|
if (importRequestIdRef.current !== requestId) return;
|
|
8501
8417
|
setImporting(false);
|
|
8502
8418
|
});
|
|
8503
|
-
}, [providers, selected, onImportComplete]);
|
|
8419
|
+
}, [providers, scanId, selected, onImportComplete]);
|
|
8504
8420
|
const hasSelectable = providers.some((p) => !p.alreadyExists);
|
|
8505
8421
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogContent, { className: "max-w-xl max-h-[80vh] overflow-hidden flex flex-col", children: [
|
|
8506
8422
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(DialogHeader, { children: [
|
|
@@ -8546,11 +8462,11 @@ function ImportWizardDialog({
|
|
|
8546
8462
|
p.models.length > 4 ? ` +${p.models.length - 4} more` : ""
|
|
8547
8463
|
] }),
|
|
8548
8464
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-muted-foreground mt-0.5 truncate", children: p.format === "anthropic" ? p.anthropicBaseUrl : p.openaiResponsesBaseUrl !== "" ? p.openaiResponsesBaseUrl : p.openaiBaseUrl }),
|
|
8549
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-muted-foreground mt-0.5 font-mono", children: p.
|
|
8465
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-muted-foreground mt-0.5 font-mono", children: p.apiKeyHint })
|
|
8550
8466
|
] })
|
|
8551
8467
|
]
|
|
8552
8468
|
},
|
|
8553
|
-
|
|
8469
|
+
p.selectionId
|
|
8554
8470
|
)),
|
|
8555
8471
|
warnings.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-muted-foreground space-y-1 border-t pt-2", children: warnings.map((w, i) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
8556
8472
|
/* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "size-3" }),
|
|
@@ -10327,7 +10243,7 @@ const ImportResponseSchema = object({
|
|
|
10327
10243
|
errors: array(string()).optional()
|
|
10328
10244
|
});
|
|
10329
10245
|
const ModelMetadataRefreshResponseSchema = object({
|
|
10330
|
-
provider:
|
|
10246
|
+
provider: RedactedProviderDtoSchema,
|
|
10331
10247
|
imported: number(),
|
|
10332
10248
|
matchedModels: array(string()),
|
|
10333
10249
|
missingModels: array(string()),
|
|
@@ -10606,7 +10522,7 @@ function ProvidersPanel({
|
|
|
10606
10522
|
try {
|
|
10607
10523
|
const newProvider = await fetchJsonWithTimeout(
|
|
10608
10524
|
"/api/providers",
|
|
10609
|
-
|
|
10525
|
+
RedactedProviderDtoSchema,
|
|
10610
10526
|
PROVIDER_WRITE_TIMEOUT_MS,
|
|
10611
10527
|
{
|
|
10612
10528
|
method: "POST",
|
|
@@ -10633,7 +10549,7 @@ function ProvidersPanel({
|
|
|
10633
10549
|
try {
|
|
10634
10550
|
const updated = await fetchJsonWithTimeout(
|
|
10635
10551
|
`/api/providers/${editingProvider.id}`,
|
|
10636
|
-
|
|
10552
|
+
RedactedProviderDtoSchema,
|
|
10637
10553
|
PROVIDER_WRITE_TIMEOUT_MS,
|
|
10638
10554
|
{
|
|
10639
10555
|
method: "PUT",
|
|
@@ -10754,61 +10670,68 @@ function ProvidersPanel({
|
|
|
10754
10670
|
] });
|
|
10755
10671
|
}
|
|
10756
10672
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
|
|
10757
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
10758
|
-
|
|
10759
|
-
|
|
10760
|
-
|
|
10761
|
-
|
|
10762
|
-
|
|
10763
|
-
|
|
10764
|
-
|
|
10765
|
-
|
|
10766
|
-
|
|
10767
|
-
|
|
10768
|
-
|
|
10769
|
-
|
|
10770
|
-
|
|
10771
|
-
|
|
10772
|
-
|
|
10773
|
-
|
|
10774
|
-
|
|
10775
|
-
|
|
10776
|
-
|
|
10777
|
-
|
|
10778
|
-
|
|
10779
|
-
|
|
10780
|
-
|
|
10781
|
-
|
|
10782
|
-
|
|
10783
|
-
|
|
10784
|
-
|
|
10785
|
-
|
|
10786
|
-
|
|
10787
|
-
|
|
10788
|
-
|
|
10789
|
-
|
|
10790
|
-
|
|
10791
|
-
|
|
10792
|
-
|
|
10793
|
-
|
|
10794
|
-
|
|
10795
|
-
|
|
10796
|
-
|
|
10797
|
-
|
|
10798
|
-
|
|
10799
|
-
|
|
10800
|
-
|
|
10801
|
-
|
|
10802
|
-
|
|
10803
|
-
|
|
10804
|
-
|
|
10805
|
-
|
|
10806
|
-
|
|
10807
|
-
|
|
10808
|
-
|
|
10809
|
-
|
|
10810
|
-
|
|
10811
|
-
|
|
10673
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
10674
|
+
"div",
|
|
10675
|
+
{
|
|
10676
|
+
"data-provider-toolbar": "true",
|
|
10677
|
+
className: "sticky top-0 z-10 flex min-w-0 flex-wrap items-center justify-start gap-2 rounded-[8px] bg-background/95 px-1 py-1 backdrop-blur sm:justify-end",
|
|
10678
|
+
children: [
|
|
10679
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
10680
|
+
Button,
|
|
10681
|
+
{
|
|
10682
|
+
variant: "outline",
|
|
10683
|
+
size: "sm",
|
|
10684
|
+
onClick: () => handleExport(),
|
|
10685
|
+
className: "gap-1 hover:bg-muted",
|
|
10686
|
+
children: [
|
|
10687
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Download, { className: "size-3" }),
|
|
10688
|
+
"Export"
|
|
10689
|
+
]
|
|
10690
|
+
}
|
|
10691
|
+
),
|
|
10692
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
10693
|
+
Button,
|
|
10694
|
+
{
|
|
10695
|
+
variant: "outline",
|
|
10696
|
+
size: "sm",
|
|
10697
|
+
onClick: handleImportClick,
|
|
10698
|
+
className: "gap-1 hover:bg-muted",
|
|
10699
|
+
children: [
|
|
10700
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Upload, { className: "size-3" }),
|
|
10701
|
+
"Import"
|
|
10702
|
+
]
|
|
10703
|
+
}
|
|
10704
|
+
),
|
|
10705
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10706
|
+
"input",
|
|
10707
|
+
{
|
|
10708
|
+
type: "file",
|
|
10709
|
+
ref: fileInputRef,
|
|
10710
|
+
accept: ".json",
|
|
10711
|
+
onChange: handleFileChange,
|
|
10712
|
+
style: { display: "none" }
|
|
10713
|
+
}
|
|
10714
|
+
),
|
|
10715
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
10716
|
+
Button,
|
|
10717
|
+
{
|
|
10718
|
+
variant: "outline",
|
|
10719
|
+
size: "sm",
|
|
10720
|
+
onClick: () => setShowImportWizard(true),
|
|
10721
|
+
className: "gap-1",
|
|
10722
|
+
children: [
|
|
10723
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Scan, { className: "size-3" }),
|
|
10724
|
+
"Scan"
|
|
10725
|
+
]
|
|
10726
|
+
}
|
|
10727
|
+
),
|
|
10728
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(Button, { onClick: () => setShowForm(true), size: "sm", className: "gap-1", children: [
|
|
10729
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "size-4" }),
|
|
10730
|
+
"Add Provider"
|
|
10731
|
+
] })
|
|
10732
|
+
]
|
|
10733
|
+
}
|
|
10734
|
+
),
|
|
10812
10735
|
configPath !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 rounded-[8px] bg-muted/15 px-3 py-2 text-xs text-muted-foreground", children: [
|
|
10813
10736
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono truncate", title: configPath, children: configPath }),
|
|
10814
10737
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -10896,6 +10819,23 @@ function ProvidersPanel({
|
|
|
10896
10819
|
)
|
|
10897
10820
|
] });
|
|
10898
10821
|
}
|
|
10822
|
+
const SETTINGS_SECTIONS = [
|
|
10823
|
+
{ value: "providers", label: "Providers" },
|
|
10824
|
+
{ value: "proxy", label: "Proxy" },
|
|
10825
|
+
{ value: "storage", label: "Storage" },
|
|
10826
|
+
{ value: "mcp", label: "MCP" },
|
|
10827
|
+
{ value: "onboarding", label: "Onboarding" }
|
|
10828
|
+
];
|
|
10829
|
+
function ResponsiveSettingsTabs() {
|
|
10830
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10831
|
+
TabsList,
|
|
10832
|
+
{
|
|
10833
|
+
"aria-label": "Settings sections",
|
|
10834
|
+
className: "grid w-full grid-cols-3 justify-stretch gap-1 bg-muted/35 p-1 group-data-[orientation=horizontal]/tabs:h-auto sm:grid-cols-5",
|
|
10835
|
+
children: SETTINGS_SECTIONS.map((section) => /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: section.value, className: "min-w-0 w-full", children: section.label }, section.value))
|
|
10836
|
+
}
|
|
10837
|
+
);
|
|
10838
|
+
}
|
|
10899
10839
|
function SettingsDialog() {
|
|
10900
10840
|
const [open, setOpen] = reactExports.useState(false);
|
|
10901
10841
|
const [activeTab, setActiveTab] = reactExports.useState("providers");
|
|
@@ -10948,39 +10888,41 @@ function SettingsDialog() {
|
|
|
10948
10888
|
]
|
|
10949
10889
|
}
|
|
10950
10890
|
) }),
|
|
10951
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(DialogContent, { className: "flex max-h-[
|
|
10891
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(DialogContent, { className: "flex max-h-[calc(100vh-1rem)] w-[calc(100%-1rem)] max-w-2xl flex-col overflow-hidden p-4 sm:max-h-[80vh] sm:p-6", children: [
|
|
10952
10892
|
/* @__PURE__ */ jsxRuntimeExports.jsx(DialogHeader, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(DialogTitle, { children: "Settings" }) }),
|
|
10953
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
10954
|
-
|
|
10955
|
-
|
|
10956
|
-
|
|
10957
|
-
|
|
10958
|
-
|
|
10959
|
-
|
|
10960
|
-
|
|
10961
|
-
|
|
10962
|
-
|
|
10963
|
-
|
|
10964
|
-
|
|
10965
|
-
|
|
10966
|
-
|
|
10967
|
-
|
|
10968
|
-
|
|
10969
|
-
|
|
10970
|
-
|
|
10971
|
-
|
|
10972
|
-
|
|
10973
|
-
|
|
10974
|
-
|
|
10975
|
-
|
|
10976
|
-
|
|
10977
|
-
|
|
10978
|
-
|
|
10979
|
-
|
|
10980
|
-
|
|
10981
|
-
|
|
10982
|
-
|
|
10983
|
-
|
|
10893
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
10894
|
+
Tabs,
|
|
10895
|
+
{
|
|
10896
|
+
value: activeTab,
|
|
10897
|
+
onValueChange: setActiveTab,
|
|
10898
|
+
className: "min-h-0 min-w-0 flex-1 overflow-hidden",
|
|
10899
|
+
children: [
|
|
10900
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ResponsiveSettingsTabs, {}),
|
|
10901
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-4 min-w-0 flex-1 overflow-x-hidden overflow-y-auto pr-1 sm:pr-2", children: [
|
|
10902
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "providers", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10903
|
+
ProvidersPanel,
|
|
10904
|
+
{
|
|
10905
|
+
externalProviders: providers,
|
|
10906
|
+
isLoading,
|
|
10907
|
+
externalTestResults: testResults,
|
|
10908
|
+
externalTestingProviders: testingProviders,
|
|
10909
|
+
externalTestingTimeLeft: testingTimeLeft,
|
|
10910
|
+
onProvidersMutate: () => {
|
|
10911
|
+
return mutate();
|
|
10912
|
+
},
|
|
10913
|
+
onTestResultsChange: handleTestResultsChange,
|
|
10914
|
+
onTestingProvidersChange: handleTestingProvidersChange,
|
|
10915
|
+
onTestingTimeLeftChange: handleTestingTimeLeftChange
|
|
10916
|
+
}
|
|
10917
|
+
) }),
|
|
10918
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "proxy", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ProxySettingsTab, {}) }),
|
|
10919
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "storage", children: /* @__PURE__ */ jsxRuntimeExports.jsx(StorageSettingsTab, {}) }),
|
|
10920
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "mcp", children: /* @__PURE__ */ jsxRuntimeExports.jsx(McpSettingsTab, {}) }),
|
|
10921
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "onboarding", children: /* @__PURE__ */ jsxRuntimeExports.jsx(OnboardingSettingsTab, {}) })
|
|
10922
|
+
] })
|
|
10923
|
+
]
|
|
10924
|
+
}
|
|
10925
|
+
)
|
|
10984
10926
|
] })
|
|
10985
10927
|
] });
|
|
10986
10928
|
}
|
|
@@ -11122,7 +11064,7 @@ function CopyableSetupValue({
|
|
|
11122
11064
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 rounded-md border border-border/45 bg-muted/15 px-3 py-2 transition-colors hover:bg-muted/25", children: [
|
|
11123
11065
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-1 text-xs font-medium text-muted-foreground", children: label }),
|
|
11124
11066
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
11125
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "min-w-0 flex-1 truncate font-mono text-xs text-foreground", children: value }),
|
|
11067
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "min-w-0 flex-1 truncate font-mono text-xs text-foreground", title: value, children: value }),
|
|
11126
11068
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
11127
11069
|
Button,
|
|
11128
11070
|
{
|
|
@@ -11593,83 +11535,6 @@ function ProxySettingsTab() {
|
|
|
11593
11535
|
] })
|
|
11594
11536
|
] });
|
|
11595
11537
|
}
|
|
11596
|
-
const EcosystemPackageStateSchema = _enum([
|
|
11597
|
-
"installed",
|
|
11598
|
-
"update-available",
|
|
11599
|
-
"available",
|
|
11600
|
-
"planned",
|
|
11601
|
-
"unknown"
|
|
11602
|
-
]);
|
|
11603
|
-
const EcosystemPackageSchema = object({
|
|
11604
|
-
id: string(),
|
|
11605
|
-
name: string(),
|
|
11606
|
-
npmName: string(),
|
|
11607
|
-
capability: string(),
|
|
11608
|
-
description: string(),
|
|
11609
|
-
workflow: string(),
|
|
11610
|
-
installCommand: string(),
|
|
11611
|
-
state: EcosystemPackageStateSchema,
|
|
11612
|
-
installedVersion: string().nullable(),
|
|
11613
|
-
latestVersion: string().nullable(),
|
|
11614
|
-
primary: boolean()
|
|
11615
|
-
});
|
|
11616
|
-
const EcosystemRunnerPresetSchema = object({
|
|
11617
|
-
id: string(),
|
|
11618
|
-
name: string(),
|
|
11619
|
-
validatedVersion: string(),
|
|
11620
|
-
binary: string(),
|
|
11621
|
-
modelFlag: string(),
|
|
11622
|
-
variantFlag: string().nullable(),
|
|
11623
|
-
tools: array(string()),
|
|
11624
|
-
logDir: string(),
|
|
11625
|
-
skillsDir: string(),
|
|
11626
|
-
agentsDir: string()
|
|
11627
|
-
});
|
|
11628
|
-
const EcosystemRecipeSchema = object({
|
|
11629
|
-
id: string(),
|
|
11630
|
-
title: string(),
|
|
11631
|
-
stage: string(),
|
|
11632
|
-
packageId: string(),
|
|
11633
|
-
description: string(),
|
|
11634
|
-
command: string(),
|
|
11635
|
-
requiresSession: boolean(),
|
|
11636
|
-
runnable: boolean()
|
|
11637
|
-
});
|
|
11638
|
-
const EcosystemPackagesResponseSchema = object({
|
|
11639
|
-
checkedAt: string(),
|
|
11640
|
-
packages: array(EcosystemPackageSchema),
|
|
11641
|
-
runnerPresets: array(EcosystemRunnerPresetSchema),
|
|
11642
|
-
recipes: array(EcosystemRecipeSchema)
|
|
11643
|
-
});
|
|
11644
|
-
const EcosystemTaskActionSchema = _enum([
|
|
11645
|
-
"install",
|
|
11646
|
-
"upgrade",
|
|
11647
|
-
"help",
|
|
11648
|
-
"runner-presets",
|
|
11649
|
-
"recipe"
|
|
11650
|
-
]);
|
|
11651
|
-
const EcosystemTaskStatusSchema = _enum(["queued", "running", "succeeded", "failed"]);
|
|
11652
|
-
const EcosystemTaskSchema = object({
|
|
11653
|
-
id: string(),
|
|
11654
|
-
packageId: string(),
|
|
11655
|
-
npmName: string(),
|
|
11656
|
-
recipeId: string().nullable().default(null),
|
|
11657
|
-
action: EcosystemTaskActionSchema,
|
|
11658
|
-
status: EcosystemTaskStatusSchema,
|
|
11659
|
-
command: string(),
|
|
11660
|
-
output: string(),
|
|
11661
|
-
createdAt: string(),
|
|
11662
|
-
startedAt: string().nullable(),
|
|
11663
|
-
finishedAt: string().nullable(),
|
|
11664
|
-
exitCode: number().nullable(),
|
|
11665
|
-
error: string().nullable()
|
|
11666
|
-
});
|
|
11667
|
-
const EcosystemTaskResponseSchema = object({
|
|
11668
|
-
task: EcosystemTaskSchema
|
|
11669
|
-
});
|
|
11670
|
-
const EcosystemTasksResponseSchema = object({
|
|
11671
|
-
tasks: array(EcosystemTaskSchema)
|
|
11672
|
-
});
|
|
11673
11538
|
const WORKFLOWS = [
|
|
11674
11539
|
{
|
|
11675
11540
|
id: "observe",
|
|
@@ -11728,21 +11593,48 @@ async function fetchEcosystemTasks(url) {
|
|
|
11728
11593
|
(response) => `Failed to load ecosystem tasks: ${String(response.status)}`
|
|
11729
11594
|
);
|
|
11730
11595
|
}
|
|
11731
|
-
async function
|
|
11596
|
+
async function prepareEcosystemTask(packageId, action) {
|
|
11597
|
+
const endpoint = `/api/ecosystem/packages/${encodeURIComponent(packageId)}/${action}`;
|
|
11732
11598
|
const response = await fetchJson(
|
|
11733
|
-
|
|
11734
|
-
|
|
11735
|
-
{
|
|
11736
|
-
|
|
11599
|
+
endpoint,
|
|
11600
|
+
EcosystemExecutionConfirmationResponseSchema,
|
|
11601
|
+
{
|
|
11602
|
+
method: "POST",
|
|
11603
|
+
headers: { "content-type": "application/json" },
|
|
11604
|
+
body: JSON.stringify({ intent: "prepare" })
|
|
11605
|
+
},
|
|
11606
|
+
(result) => `Failed to prepare ecosystem task: ${String(result.status)}`
|
|
11737
11607
|
);
|
|
11738
|
-
return response.
|
|
11608
|
+
return { endpoint, confirmation: response.confirmation };
|
|
11609
|
+
}
|
|
11610
|
+
async function prepareEcosystemRecipe(recipeId) {
|
|
11611
|
+
const endpoint = `/api/ecosystem/recipes/${encodeURIComponent(recipeId)}/run`;
|
|
11612
|
+
const response = await fetchJson(
|
|
11613
|
+
endpoint,
|
|
11614
|
+
EcosystemExecutionConfirmationResponseSchema,
|
|
11615
|
+
{
|
|
11616
|
+
method: "POST",
|
|
11617
|
+
headers: { "content-type": "application/json" },
|
|
11618
|
+
body: JSON.stringify({ intent: "prepare" })
|
|
11619
|
+
},
|
|
11620
|
+
(result) => `Failed to prepare ecosystem recipe: ${String(result.status)}`
|
|
11621
|
+
);
|
|
11622
|
+
return { endpoint, confirmation: response.confirmation };
|
|
11739
11623
|
}
|
|
11740
|
-
async function
|
|
11624
|
+
async function confirmEcosystemExecution(pending) {
|
|
11741
11625
|
const response = await fetchJson(
|
|
11742
|
-
|
|
11626
|
+
pending.endpoint,
|
|
11743
11627
|
EcosystemTaskResponseSchema,
|
|
11744
|
-
{
|
|
11745
|
-
|
|
11628
|
+
{
|
|
11629
|
+
method: "POST",
|
|
11630
|
+
headers: { "content-type": "application/json" },
|
|
11631
|
+
body: JSON.stringify({
|
|
11632
|
+
intent: "confirm",
|
|
11633
|
+
nonce: pending.confirmation.nonce,
|
|
11634
|
+
confirmation: pending.confirmation.phrase
|
|
11635
|
+
})
|
|
11636
|
+
},
|
|
11637
|
+
(result) => `Failed to start ecosystem task: ${String(result.status)}`
|
|
11746
11638
|
);
|
|
11747
11639
|
return response.task;
|
|
11748
11640
|
}
|
|
@@ -12049,6 +11941,76 @@ function RecentTaskRow({
|
|
|
12049
11941
|
)
|
|
12050
11942
|
] });
|
|
12051
11943
|
}
|
|
11944
|
+
function ExecutionConfirmationDialog({
|
|
11945
|
+
pending,
|
|
11946
|
+
busy,
|
|
11947
|
+
onOpenChange,
|
|
11948
|
+
onConfirm
|
|
11949
|
+
}) {
|
|
11950
|
+
const plan = pending?.confirmation.plan ?? null;
|
|
11951
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Dialog, { open: pending !== null, onOpenChange, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogContent, { className: "max-w-xl", children: [
|
|
11952
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(DialogHeader, { children: [
|
|
11953
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(DialogTitle, { children: "Confirm local command" }),
|
|
11954
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(DialogDescription, { children: "Review the exact allowlisted action Agent Inspector will run on this machine." })
|
|
11955
|
+
] }),
|
|
11956
|
+
plan !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-3", children: [
|
|
11957
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid gap-2 text-xs sm:grid-cols-2", children: [
|
|
11958
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-md border bg-muted/30 p-3", children: [
|
|
11959
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-muted-foreground", children: "Source" }),
|
|
11960
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1 break-words font-medium", children: plan.source })
|
|
11961
|
+
] }),
|
|
11962
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-md border bg-muted/30 p-3", children: [
|
|
11963
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-muted-foreground", children: "Timeout" }),
|
|
11964
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-1 font-medium", children: [
|
|
11965
|
+
String(plan.timeoutMs / 1e3),
|
|
11966
|
+
" seconds"
|
|
11967
|
+
] })
|
|
11968
|
+
] }),
|
|
11969
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-md border bg-muted/30 p-3 sm:col-span-2", children: [
|
|
11970
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-muted-foreground", children: "Affected scope" }),
|
|
11971
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1 font-medium", children: plan.scope })
|
|
11972
|
+
] })
|
|
11973
|
+
] }),
|
|
11974
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
11975
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-1 text-xs font-medium", children: "Resolved command" }),
|
|
11976
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "max-h-32 overflow-auto whitespace-pre-wrap break-all rounded-md bg-black/80 p-3 font-mono text-xs leading-5 text-white/80", children: plan.command })
|
|
11977
|
+
] }),
|
|
11978
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-xs text-muted-foreground", children: [
|
|
11979
|
+
"Confirmation phrase: ",
|
|
11980
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: pending?.confirmation.phrase }),
|
|
11981
|
+
". The one-time confirmation expires at",
|
|
11982
|
+
" ",
|
|
11983
|
+
new Date(pending?.confirmation.expiresAt ?? "").toLocaleTimeString(),
|
|
11984
|
+
"."
|
|
11985
|
+
] })
|
|
11986
|
+
] }),
|
|
11987
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", children: [
|
|
11988
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
11989
|
+
Button,
|
|
11990
|
+
{
|
|
11991
|
+
type: "button",
|
|
11992
|
+
variant: "outline",
|
|
11993
|
+
disabled: busy,
|
|
11994
|
+
onClick: () => onOpenChange(false),
|
|
11995
|
+
children: "Cancel"
|
|
11996
|
+
}
|
|
11997
|
+
),
|
|
11998
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
11999
|
+
Button,
|
|
12000
|
+
{
|
|
12001
|
+
type: "button",
|
|
12002
|
+
variant: "secondary",
|
|
12003
|
+
disabled: busy || plan === null,
|
|
12004
|
+
onClick: onConfirm,
|
|
12005
|
+
children: [
|
|
12006
|
+
busy ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-3.5 animate-spin" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Terminal, { className: "size-3.5" }),
|
|
12007
|
+
busy ? "Starting" : "Confirm & Run"
|
|
12008
|
+
]
|
|
12009
|
+
}
|
|
12010
|
+
)
|
|
12011
|
+
] })
|
|
12012
|
+
] }) });
|
|
12013
|
+
}
|
|
12052
12014
|
function AgentLabDialog({ currentSessionId, logCount }) {
|
|
12053
12015
|
const [open, setOpen] = reactExports.useState(false);
|
|
12054
12016
|
const [copied, setCopied] = reactExports.useState(false);
|
|
@@ -12056,6 +12018,8 @@ function AgentLabDialog({ currentSessionId, logCount }) {
|
|
|
12056
12018
|
const [copiedRecipeId, setCopiedRecipeId] = reactExports.useState(null);
|
|
12057
12019
|
const [activeTaskId, setActiveTaskId] = reactExports.useState(null);
|
|
12058
12020
|
const [taskError, setTaskError] = reactExports.useState(null);
|
|
12021
|
+
const [pendingExecution, setPendingExecution] = reactExports.useState(null);
|
|
12022
|
+
const [confirmationBusy, setConfirmationBusy] = reactExports.useState(false);
|
|
12059
12023
|
const response = useSWR("/api/ecosystem/packages", fetchEcosystemPackages, {
|
|
12060
12024
|
revalidateOnFocus: false,
|
|
12061
12025
|
revalidateIfStale: false
|
|
@@ -12105,12 +12069,10 @@ function AgentLabDialog({ currentSessionId, logCount }) {
|
|
|
12105
12069
|
};
|
|
12106
12070
|
const runRecipe = (recipe) => {
|
|
12107
12071
|
setTaskError(null);
|
|
12108
|
-
void
|
|
12109
|
-
|
|
12110
|
-
void activeTaskResponse.mutate({ task }, { revalidate: true });
|
|
12111
|
-
void tasksResponse.mutate();
|
|
12072
|
+
void prepareEcosystemRecipe(recipe.id).then((pending) => {
|
|
12073
|
+
setPendingExecution(pending);
|
|
12112
12074
|
}).catch((error) => {
|
|
12113
|
-
setTaskError(error instanceof Error ? error.message : "Failed to
|
|
12075
|
+
setTaskError(error instanceof Error ? error.message : "Failed to prepare ecosystem recipe");
|
|
12114
12076
|
});
|
|
12115
12077
|
};
|
|
12116
12078
|
const activeTask = activeTaskResponse.data?.task ?? null;
|
|
@@ -12122,12 +12084,25 @@ function AgentLabDialog({ currentSessionId, logCount }) {
|
|
|
12122
12084
|
}, [activeTask, response, tasksResponse]);
|
|
12123
12085
|
const handleStartTask = (packageId, action) => {
|
|
12124
12086
|
setTaskError(null);
|
|
12125
|
-
void
|
|
12087
|
+
void prepareEcosystemTask(packageId, action).then((pending) => {
|
|
12088
|
+
setPendingExecution(pending);
|
|
12089
|
+
}).catch((error) => {
|
|
12090
|
+
setTaskError(error instanceof Error ? error.message : "Failed to prepare ecosystem task");
|
|
12091
|
+
});
|
|
12092
|
+
};
|
|
12093
|
+
const confirmPendingExecution = () => {
|
|
12094
|
+
if (pendingExecution === null) return;
|
|
12095
|
+
setTaskError(null);
|
|
12096
|
+
setConfirmationBusy(true);
|
|
12097
|
+
void confirmEcosystemExecution(pendingExecution).then((task) => {
|
|
12126
12098
|
setActiveTaskId(task.id);
|
|
12099
|
+
setPendingExecution(null);
|
|
12127
12100
|
void activeTaskResponse.mutate({ task }, { revalidate: true });
|
|
12128
12101
|
void tasksResponse.mutate();
|
|
12129
12102
|
}).catch((error) => {
|
|
12130
12103
|
setTaskError(error instanceof Error ? error.message : "Failed to start ecosystem task");
|
|
12104
|
+
}).finally(() => {
|
|
12105
|
+
setConfirmationBusy(false);
|
|
12131
12106
|
});
|
|
12132
12107
|
};
|
|
12133
12108
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(Dialog, { open, onOpenChange: setOpen, children: [
|
|
@@ -12288,877 +12263,277 @@ function AgentLabDialog({ currentSessionId, logCount }) {
|
|
|
12288
12263
|
] }),
|
|
12289
12264
|
/* @__PURE__ */ jsxRuntimeExports.jsx(TaskConsole, { task: activeTask })
|
|
12290
12265
|
] })
|
|
12291
|
-
] })
|
|
12266
|
+
] }),
|
|
12267
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
12268
|
+
ExecutionConfirmationDialog,
|
|
12269
|
+
{
|
|
12270
|
+
pending: pendingExecution,
|
|
12271
|
+
busy: confirmationBusy,
|
|
12272
|
+
onOpenChange: (confirmationOpen) => {
|
|
12273
|
+
if (!confirmationOpen && !confirmationBusy) setPendingExecution(null);
|
|
12274
|
+
},
|
|
12275
|
+
onConfirm: confirmPendingExecution
|
|
12276
|
+
}
|
|
12277
|
+
)
|
|
12292
12278
|
] });
|
|
12293
12279
|
}
|
|
12294
|
-
const
|
|
12295
|
-
|
|
12296
|
-
|
|
12297
|
-
|
|
12298
|
-
|
|
12299
|
-
|
|
12300
|
-
|
|
12301
|
-
|
|
12302
|
-
|
|
12303
|
-
|
|
12304
|
-
|
|
12305
|
-
|
|
12306
|
-
|
|
12307
|
-
|
|
12308
|
-
|
|
12309
|
-
|
|
12310
|
-
|
|
12311
|
-
|
|
12312
|
-
|
|
12313
|
-
|
|
12314
|
-
|
|
12315
|
-
|
|
12316
|
-
|
|
12317
|
-
|
|
12318
|
-
|
|
12319
|
-
|
|
12320
|
-
|
|
12321
|
-
|
|
12322
|
-
|
|
12323
|
-
|
|
12324
|
-
return {
|
|
12325
|
-
|
|
12326
|
-
|
|
12327
|
-
|
|
12328
|
-
|
|
12329
|
-
|
|
12330
|
-
|
|
12331
|
-
const edgeGap = scaledMetric(INSPECTOR_PET_EDGE_GAP, viewport);
|
|
12332
|
-
const distances = [
|
|
12333
|
-
{ edge: "left", distance: clamped.x - edgeGap },
|
|
12334
|
-
{ edge: "right", distance: maximumPetX(viewport) - clamped.x },
|
|
12335
|
-
{ edge: "top", distance: clamped.y - edgeGap },
|
|
12336
|
-
{ edge: "bottom", distance: maximumPetY(viewport) - clamped.y }
|
|
12337
|
-
];
|
|
12338
|
-
return distances.reduce((best, current) => current.distance < best.distance ? current : best).edge;
|
|
12339
|
-
}
|
|
12340
|
-
function snapInspectorPetToEdge(position, viewport) {
|
|
12341
|
-
const clamped = clampInspectorPetPosition(position, viewport);
|
|
12342
|
-
const edge = nearestInspectorPetEdge(clamped, viewport);
|
|
12343
|
-
const edgeGap = scaledMetric(INSPECTOR_PET_EDGE_GAP, viewport);
|
|
12344
|
-
switch (edge) {
|
|
12345
|
-
case "left":
|
|
12346
|
-
return { x: edgeGap, y: clamped.y };
|
|
12347
|
-
case "right":
|
|
12348
|
-
return { x: maximumPetX(viewport), y: clamped.y };
|
|
12349
|
-
case "top":
|
|
12350
|
-
return { x: clamped.x, y: edgeGap };
|
|
12351
|
-
case "bottom":
|
|
12352
|
-
return { x: clamped.x, y: maximumPetY(viewport) };
|
|
12353
|
-
}
|
|
12354
|
-
}
|
|
12355
|
-
function randomInspectorPetEdgePosition(viewport, positionSample) {
|
|
12356
|
-
const maxX = maximumPetX(viewport);
|
|
12357
|
-
const maxY = maximumPetY(viewport);
|
|
12358
|
-
const edgeGap = scaledMetric(INSPECTOR_PET_EDGE_GAP, viewport);
|
|
12359
|
-
return {
|
|
12360
|
-
x: edgeGap + clampUnit(positionSample) * (maxX - edgeGap),
|
|
12361
|
-
y: maxY
|
|
12362
|
-
};
|
|
12280
|
+
const PI_AGENT_STARTERS = [
|
|
12281
|
+
{
|
|
12282
|
+
id: "reliability",
|
|
12283
|
+
label: "Reliability",
|
|
12284
|
+
question: "Which requests failed, stalled, or look most likely to hang, and why?"
|
|
12285
|
+
},
|
|
12286
|
+
{
|
|
12287
|
+
id: "performance",
|
|
12288
|
+
label: "Performance",
|
|
12289
|
+
question: "Summarize latency and identify the slowest requests with supporting evidence."
|
|
12290
|
+
},
|
|
12291
|
+
{
|
|
12292
|
+
id: "tokens",
|
|
12293
|
+
label: "Token usage",
|
|
12294
|
+
question: "Where are tokens being spent, and which requests have unusually high usage?"
|
|
12295
|
+
},
|
|
12296
|
+
{
|
|
12297
|
+
id: "providers",
|
|
12298
|
+
label: "Providers",
|
|
12299
|
+
question: "Compare Provider and model reliability, latency, and token usage in this scope."
|
|
12300
|
+
},
|
|
12301
|
+
{
|
|
12302
|
+
id: "tools",
|
|
12303
|
+
label: "Tool activity",
|
|
12304
|
+
question: "Which tools were used most, and where did tool calls fail or produce warnings?"
|
|
12305
|
+
}
|
|
12306
|
+
];
|
|
12307
|
+
const MAX_HISTORY_CONTENT_CHARS = 4e3;
|
|
12308
|
+
const MAX_METRICS = 12;
|
|
12309
|
+
function createEmptyPiAgentConversation() {
|
|
12310
|
+
return { messages: [], question: "", error: null };
|
|
12311
|
+
}
|
|
12312
|
+
function buildPiAgentHistory(messages) {
|
|
12313
|
+
return messages.filter((message) => message.content.trim().length > 0).slice(-10).map((message) => ({
|
|
12314
|
+
role: message.role,
|
|
12315
|
+
content: message.content.trim().slice(0, MAX_HISTORY_CONTENT_CHARS)
|
|
12316
|
+
}));
|
|
12363
12317
|
}
|
|
12364
|
-
function
|
|
12365
|
-
const
|
|
12366
|
-
|
|
12367
|
-
|
|
12368
|
-
const edge = nearestInspectorPetEdge(clamped, viewport);
|
|
12369
|
-
const maxX = maximumPetX(viewport);
|
|
12370
|
-
const maxY = maximumPetY(viewport);
|
|
12371
|
-
const edgeGap = scaledMetric(INSPECTOR_PET_EDGE_GAP, viewport);
|
|
12372
|
-
const minimumSafeY = Math.min(scaledMetric(INSPECTOR_PET_VERTICAL_SAFE_MARGIN, viewport), maxY);
|
|
12373
|
-
switch (edge) {
|
|
12374
|
-
case "left":
|
|
12375
|
-
return {
|
|
12376
|
-
x: edgeGap,
|
|
12377
|
-
y: Math.min(Math.max(clamped.y + step * direction, minimumSafeY), maxY)
|
|
12378
|
-
};
|
|
12379
|
-
case "right":
|
|
12380
|
-
return {
|
|
12381
|
-
x: maxX,
|
|
12382
|
-
y: Math.min(Math.max(clamped.y + step * direction, minimumSafeY), maxY)
|
|
12383
|
-
};
|
|
12384
|
-
case "top":
|
|
12385
|
-
return {
|
|
12386
|
-
x: Math.min(Math.max(clamped.x + step * direction, edgeGap), maxX),
|
|
12387
|
-
y: edgeGap
|
|
12388
|
-
};
|
|
12389
|
-
case "bottom":
|
|
12390
|
-
return {
|
|
12391
|
-
x: Math.min(Math.max(clamped.x + step * direction, edgeGap), maxX),
|
|
12392
|
-
y: maxY
|
|
12393
|
-
};
|
|
12318
|
+
function readString(value, ...keys) {
|
|
12319
|
+
for (const key of keys) {
|
|
12320
|
+
const candidate = safeGetOwnProperty(value, key);
|
|
12321
|
+
if (typeof candidate === "string" && candidate.trim().length > 0) return candidate;
|
|
12394
12322
|
}
|
|
12323
|
+
return null;
|
|
12395
12324
|
}
|
|
12396
|
-
function
|
|
12397
|
-
const
|
|
12398
|
-
|
|
12399
|
-
|
|
12400
|
-
const panelHeight = scaledMetric(INSPECTOR_PET_PANEL_HEIGHT, viewport);
|
|
12401
|
-
const panelGap = scaledMetric(INSPECTOR_PET_PANEL_GAP, viewport);
|
|
12402
|
-
const margin = scaledMetric(INSPECTOR_PET_MARGIN, viewport);
|
|
12403
|
-
let x = position.x + petSize / 2 - panelWidth / 2;
|
|
12404
|
-
let y = position.y + petSize / 2 - panelHeight / 2;
|
|
12405
|
-
switch (edge) {
|
|
12406
|
-
case "left":
|
|
12407
|
-
x = position.x + petSize + panelGap;
|
|
12408
|
-
break;
|
|
12409
|
-
case "right":
|
|
12410
|
-
x = position.x - panelWidth - panelGap;
|
|
12411
|
-
break;
|
|
12412
|
-
case "top":
|
|
12413
|
-
y = position.y + petSize + panelGap;
|
|
12414
|
-
break;
|
|
12415
|
-
case "bottom":
|
|
12416
|
-
y = position.y - panelHeight - panelGap;
|
|
12417
|
-
break;
|
|
12325
|
+
function readNumber(value, ...keys) {
|
|
12326
|
+
for (const key of keys) {
|
|
12327
|
+
const candidate = safeGetOwnProperty(value, key);
|
|
12328
|
+
if (typeof candidate === "number" && Number.isFinite(candidate)) return candidate;
|
|
12418
12329
|
}
|
|
12330
|
+
return null;
|
|
12331
|
+
}
|
|
12332
|
+
function readStringArray(value, key) {
|
|
12333
|
+
const candidate = safeGetOwnProperty(value, key);
|
|
12334
|
+
if (!Array.isArray(candidate)) return [];
|
|
12335
|
+
return candidate.filter((item) => typeof item === "string").slice(0, 8);
|
|
12336
|
+
}
|
|
12337
|
+
function evidenceView(value) {
|
|
12338
|
+
const source = readString(value, "source") ?? "log";
|
|
12339
|
+
const id = readString(value, "id") ?? "";
|
|
12340
|
+
const logId = readNumber(value, "logId", "id");
|
|
12341
|
+
if (id === "" && logId === null) return null;
|
|
12342
|
+
if (logId !== null && (!Number.isInteger(logId) || logId < 0)) return null;
|
|
12343
|
+
const inputTokens = readNumber(value, "inputTokens");
|
|
12344
|
+
const outputTokens = readNumber(value, "outputTokens");
|
|
12345
|
+
const explicitTotal = readNumber(value, "totalTokens", "tokenCount");
|
|
12346
|
+
const statusNumber = readNumber(value, "responseStatus", "status");
|
|
12347
|
+
const statusString = readString(value, "responseStatus", "status");
|
|
12419
12348
|
return {
|
|
12420
|
-
|
|
12421
|
-
|
|
12349
|
+
source,
|
|
12350
|
+
id: id !== "" ? id : String(logId),
|
|
12351
|
+
logId,
|
|
12352
|
+
sessionId: readString(value, "sessionId"),
|
|
12353
|
+
timestamp: readString(value, "timestamp"),
|
|
12354
|
+
model: readString(value, "model"),
|
|
12355
|
+
providerName: readString(value, "providerName", "provider"),
|
|
12356
|
+
path: readString(value, "path"),
|
|
12357
|
+
status: statusNumber ?? statusString,
|
|
12358
|
+
elapsedMs: readNumber(value, "elapsedMs", "latencyMs"),
|
|
12359
|
+
inputTokens,
|
|
12360
|
+
outputTokens,
|
|
12361
|
+
totalTokens: explicitTotal ?? (inputTokens === null && outputTokens === null ? null : (inputTokens ?? 0) + (outputTokens ?? 0)),
|
|
12362
|
+
score: readNumber(value, "score", "relevanceScore"),
|
|
12363
|
+
matchedFields: readStringArray(value, "matchedFields"),
|
|
12364
|
+
excerpt: readString(value, "excerpt", "snippet") ?? "No excerpt available."
|
|
12422
12365
|
};
|
|
12423
12366
|
}
|
|
12424
|
-
function
|
|
12425
|
-
|
|
12426
|
-
|
|
12427
|
-
if (latest === null || log.id > latest.id) latest = log;
|
|
12428
|
-
}
|
|
12429
|
-
return latest;
|
|
12430
|
-
}
|
|
12431
|
-
function logNeedsAttention(log) {
|
|
12432
|
-
const hasHttpError = log.responseStatus !== null && log.responseStatus >= 400;
|
|
12433
|
-
const hasStreamError = log.error !== null && log.error !== void 0 && log.error !== "";
|
|
12434
|
-
return hasHttpError || hasStreamError;
|
|
12367
|
+
function humanizeMetricKey(key) {
|
|
12368
|
+
const spaced = key.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").trim();
|
|
12369
|
+
return spaced.length === 0 ? "Metric" : `${spaced[0]?.toUpperCase() ?? ""}${spaced.slice(1)}`;
|
|
12435
12370
|
}
|
|
12436
|
-
function
|
|
12437
|
-
|
|
12438
|
-
|
|
12439
|
-
if (
|
|
12440
|
-
|
|
12441
|
-
|
|
12442
|
-
|
|
12443
|
-
|
|
12444
|
-
|
|
12445
|
-
};
|
|
12446
|
-
}
|
|
12447
|
-
const latest = latestCapturedLog(logs);
|
|
12448
|
-
if (latest !== null && logNeedsAttention(latest)) {
|
|
12449
|
-
return {
|
|
12450
|
-
mood: "attention",
|
|
12451
|
-
label: "Latest request needs attention",
|
|
12452
|
-
pendingCount,
|
|
12453
|
-
capturedCount
|
|
12454
|
-
};
|
|
12455
|
-
}
|
|
12456
|
-
if (latest === null) {
|
|
12457
|
-
return {
|
|
12458
|
-
mood: "idle",
|
|
12459
|
-
label: "Waiting for traffic",
|
|
12460
|
-
pendingCount,
|
|
12461
|
-
capturedCount
|
|
12462
|
-
};
|
|
12371
|
+
function metricValue(value) {
|
|
12372
|
+
if (typeof value === "number" && Number.isFinite(value)) return value.toLocaleString();
|
|
12373
|
+
if (typeof value === "string" && value.trim().length > 0) return value;
|
|
12374
|
+
if (typeof value === "boolean") return value ? "Yes" : "No";
|
|
12375
|
+
if (Array.isArray(value)) {
|
|
12376
|
+
const items = value.filter(
|
|
12377
|
+
(item) => typeof item === "string" || typeof item === "number" && Number.isFinite(item)
|
|
12378
|
+
).slice(0, 6);
|
|
12379
|
+
return items.length > 0 ? items.join(", ") : null;
|
|
12463
12380
|
}
|
|
12464
|
-
|
|
12465
|
-
|
|
12466
|
-
|
|
12467
|
-
|
|
12468
|
-
|
|
12469
|
-
|
|
12470
|
-
|
|
12471
|
-
|
|
12381
|
+
return null;
|
|
12382
|
+
}
|
|
12383
|
+
function objectMetricEntries(value) {
|
|
12384
|
+
return Object.getOwnPropertyNames(value).map((key) => [key, safeGetOwnProperty(value, key)]);
|
|
12385
|
+
}
|
|
12386
|
+
function metricViews(value) {
|
|
12387
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return [];
|
|
12388
|
+
const entries = [];
|
|
12389
|
+
for (const [key, rawValue] of objectMetricEntries(value)) {
|
|
12390
|
+
const directValue = metricValue(rawValue);
|
|
12391
|
+
if (directValue !== null) {
|
|
12392
|
+
entries.push({ key, label: humanizeMetricKey(key), value: directValue });
|
|
12393
|
+
if (entries.length >= MAX_METRICS) break;
|
|
12394
|
+
continue;
|
|
12395
|
+
}
|
|
12396
|
+
if (rawValue === null || typeof rawValue !== "object" || Array.isArray(rawValue)) continue;
|
|
12397
|
+
for (const [nestedKey, nestedValue] of objectMetricEntries(rawValue)) {
|
|
12398
|
+
const formatted = metricValue(nestedValue);
|
|
12399
|
+
if (formatted === null) continue;
|
|
12400
|
+
const metricKey = `${key}.${nestedKey}`;
|
|
12401
|
+
entries.push({
|
|
12402
|
+
key: metricKey,
|
|
12403
|
+
label: `${humanizeMetricKey(key)} ${humanizeMetricKey(nestedKey).toLowerCase()}`,
|
|
12404
|
+
value: formatted
|
|
12405
|
+
});
|
|
12406
|
+
if (entries.length >= MAX_METRICS) break;
|
|
12407
|
+
}
|
|
12408
|
+
if (entries.length >= MAX_METRICS) break;
|
|
12409
|
+
}
|
|
12410
|
+
return entries;
|
|
12411
|
+
}
|
|
12412
|
+
function normalizePiAgentResponse(value) {
|
|
12413
|
+
const answer = readString(value, "answer");
|
|
12414
|
+
const providerId = readString(value, "providerId");
|
|
12415
|
+
const providerName = readString(value, "providerName");
|
|
12416
|
+
const model = readString(value, "model");
|
|
12417
|
+
const protocol = readString(value, "protocol");
|
|
12418
|
+
const logCount = readNumber(value, "logCount");
|
|
12419
|
+
if (answer === null || providerId === null || providerName === null || model === null || protocol === null || logCount === null) {
|
|
12420
|
+
return null;
|
|
12472
12421
|
}
|
|
12422
|
+
const rawEvidence = safeGetOwnProperty(value, "evidence");
|
|
12423
|
+
const evidence = Array.isArray(rawEvidence) ? rawEvidence.map(evidenceView).filter((item) => item !== null).slice(0, 12) : [];
|
|
12473
12424
|
return {
|
|
12474
|
-
|
|
12475
|
-
|
|
12476
|
-
|
|
12477
|
-
|
|
12425
|
+
answer,
|
|
12426
|
+
providerId,
|
|
12427
|
+
providerName,
|
|
12428
|
+
model,
|
|
12429
|
+
protocol,
|
|
12430
|
+
logCount,
|
|
12431
|
+
evidence,
|
|
12432
|
+
summaryMetrics: metricViews(safeGetOwnProperty(value, "summary")),
|
|
12433
|
+
queryMetrics: metricViews(safeGetOwnProperty(value, "queryStats"))
|
|
12478
12434
|
};
|
|
12479
12435
|
}
|
|
12480
|
-
|
|
12481
|
-
|
|
12482
|
-
|
|
12483
|
-
|
|
12484
|
-
|
|
12485
|
-
|
|
12486
|
-
|
|
12487
|
-
}
|
|
12488
|
-
function addClaw(root, side, shellMaterial, accentMaterial) {
|
|
12489
|
-
const clawScale = side < 0 ? 1.5 : 0.68;
|
|
12490
|
-
const clawGroup = new Group();
|
|
12491
|
-
const pincers = [];
|
|
12492
|
-
root.add(clawGroup);
|
|
12493
|
-
const shoulder = new Vector3(side * 1.2, 0.25, -0.05);
|
|
12494
|
-
const wrist = new Vector3(side * (1.65 + clawScale * 0.18), 0.5, 0);
|
|
12495
|
-
const arm = createRod(shoulder, wrist, 0.16 * clawScale, accentMaterial);
|
|
12496
|
-
clawGroup.add(arm);
|
|
12497
|
-
const palm = new Mesh(new SphereGeometry(0.55, 24, 16), shellMaterial);
|
|
12498
|
-
palm.position.set(side * (1.95 + clawScale * 0.16), 0.62, 0.05);
|
|
12499
|
-
palm.scale.set(1.05 * clawScale, 0.72 * clawScale, 0.55 * clawScale);
|
|
12500
|
-
clawGroup.add(palm);
|
|
12501
|
-
for (const pincerDirection of [-1, 1]) {
|
|
12502
|
-
const pincer = new Mesh(new SphereGeometry(0.36, 20, 14), accentMaterial);
|
|
12503
|
-
pincer.position.set(
|
|
12504
|
-
side * (2.22 + clawScale * 0.26),
|
|
12505
|
-
0.62 + pincerDirection * 0.24 * clawScale,
|
|
12506
|
-
0.08
|
|
12507
|
-
);
|
|
12508
|
-
pincer.scale.set(1.05 * clawScale, 0.34 * clawScale, 0.42 * clawScale);
|
|
12509
|
-
pincer.rotation.z = pincerDirection * side * 0.42;
|
|
12510
|
-
clawGroup.add(pincer);
|
|
12511
|
-
pincers.push({
|
|
12512
|
-
direction: pincerDirection,
|
|
12513
|
-
mesh: pincer,
|
|
12514
|
-
restRotationZ: pincer.rotation.z,
|
|
12515
|
-
restY: pincer.position.y
|
|
12516
|
-
});
|
|
12517
|
-
}
|
|
12518
|
-
return { group: clawGroup, pincers, scale: clawScale };
|
|
12519
|
-
}
|
|
12520
|
-
function pinchPulse(cycleTime, start, duration) {
|
|
12521
|
-
const progress = (cycleTime - start) / duration;
|
|
12522
|
-
if (progress <= 0 || progress >= 1) return 0;
|
|
12523
|
-
return Math.sin(progress * Math.PI);
|
|
12524
|
-
}
|
|
12525
|
-
function dominantClawGrip(elapsed) {
|
|
12526
|
-
const cycleTime = elapsed % 6.8;
|
|
12527
|
-
return Math.max(pinchPulse(cycleTime, 0.72, 0.82), pinchPulse(cycleTime, 1.72, 0.68));
|
|
12528
|
-
}
|
|
12529
|
-
function addEyes(root, shellMaterial, eyeMaterial) {
|
|
12530
|
-
const eyes = [];
|
|
12531
|
-
for (const side of [-1, 1]) {
|
|
12532
|
-
const stalkStart = new Vector3(side * 0.48, 0.68, 0.05);
|
|
12533
|
-
const stalkEnd = new Vector3(side * 0.1, 0.82, 0.07);
|
|
12534
|
-
const eyeGroup = new Group();
|
|
12535
|
-
eyeGroup.position.copy(stalkStart);
|
|
12536
|
-
eyeGroup.add(createRod(new Vector3(0, 0, 0), stalkEnd, 0.1, shellMaterial));
|
|
12537
|
-
const eye = new Mesh(new SphereGeometry(0.24, 20, 16), eyeMaterial);
|
|
12538
|
-
eye.position.copy(stalkEnd);
|
|
12539
|
-
eye.scale.set(1, 1, 0.85);
|
|
12540
|
-
eyeGroup.add(eye);
|
|
12541
|
-
const pupil = new Mesh(
|
|
12542
|
-
new SphereGeometry(0.105, 16, 12),
|
|
12543
|
-
new MeshPhysicalMaterial({ color: 1120295, roughness: 0.25 })
|
|
12544
|
-
);
|
|
12545
|
-
const pupilRest = new Vector3(stalkEnd.x, stalkEnd.y, stalkEnd.z + 0.2);
|
|
12546
|
-
pupil.position.copy(pupilRest);
|
|
12547
|
-
eyeGroup.add(pupil);
|
|
12548
|
-
root.add(eyeGroup);
|
|
12549
|
-
eyes.push({
|
|
12550
|
-
group: eyeGroup,
|
|
12551
|
-
phase: side < 0 ? 0 : Math.PI / 3,
|
|
12552
|
-
pupil,
|
|
12553
|
-
pupilRest
|
|
12554
|
-
});
|
|
12555
|
-
}
|
|
12556
|
-
return eyes;
|
|
12557
|
-
}
|
|
12558
|
-
function addLegs(root, legMaterial) {
|
|
12559
|
-
const legs = [];
|
|
12560
|
-
for (const side of [-1, 1]) {
|
|
12561
|
-
for (let index = 0; index < 4; index += 1) {
|
|
12562
|
-
const leg = new Group();
|
|
12563
|
-
const baseY = -0.3 - index * 0.22;
|
|
12564
|
-
leg.position.set(side * (0.8 + index * 0.12), baseY, -0.18);
|
|
12565
|
-
leg.add(
|
|
12566
|
-
createRod(
|
|
12567
|
-
new Vector3(0, 0, 0),
|
|
12568
|
-
new Vector3(side * (0.62 + index * 0.06), -0.34, 0),
|
|
12569
|
-
0.095,
|
|
12570
|
-
legMaterial
|
|
12571
|
-
)
|
|
12572
|
-
);
|
|
12573
|
-
leg.add(
|
|
12574
|
-
createRod(
|
|
12575
|
-
new Vector3(side * (0.58 + index * 0.06), -0.31, 0),
|
|
12576
|
-
new Vector3(side * (1.02 + index * 0.08), -0.88 + index * 0.07, 0.04),
|
|
12577
|
-
0.075,
|
|
12578
|
-
legMaterial
|
|
12579
|
-
)
|
|
12580
|
-
);
|
|
12581
|
-
root.add(leg);
|
|
12582
|
-
legs.push({ group: leg, phase: index * Math.PI + (side > 0 ? Math.PI / 2 : 0), side });
|
|
12436
|
+
const LazyReactMarkdown = reactExports.lazy(() => import("../_libs/react-markdown.mjs"));
|
|
12437
|
+
const ANSWER_MARKDOWN_CLASS = "prose prose-sm dark:prose-invert max-w-none text-[13px] leading-[1.65] [&_pre]:bg-muted [&_pre]:text-foreground [&_code]:text-[0.8em] [&_p]:my-1 [&_p]:leading-[1.65] [&_ul]:my-1 [&_ol]:my-1 [&_li]:my-0.5 [&_li]:leading-[1.6]";
|
|
12438
|
+
function AnswerMarkdown({ text }) {
|
|
12439
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: ANSWER_MARKDOWN_CLASS, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
12440
|
+
reactExports.Suspense,
|
|
12441
|
+
{
|
|
12442
|
+
fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-muted-foreground", children: "Loading Markdown..." }),
|
|
12443
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(LazyReactMarkdown, { children: text })
|
|
12583
12444
|
}
|
|
12445
|
+
) });
|
|
12446
|
+
}
|
|
12447
|
+
const DEFAULT_QUESTION = "Analyze the current Inspector session. What looks abnormal, slow, or likely to hang?";
|
|
12448
|
+
function providerSupportsPiAgent(provider) {
|
|
12449
|
+
return provider.openaiResponsesBaseUrl !== void 0 || provider.openaiBaseUrl !== void 0 || provider.anthropicBaseUrl !== void 0;
|
|
12450
|
+
}
|
|
12451
|
+
function providerProtocolLabel(provider) {
|
|
12452
|
+
if (provider.openaiResponsesBaseUrl !== void 0 && provider.openaiResponsesBaseUrl !== "") {
|
|
12453
|
+
return "Responses";
|
|
12584
12454
|
}
|
|
12585
|
-
|
|
12586
|
-
|
|
12587
|
-
|
|
12588
|
-
|
|
12589
|
-
|
|
12590
|
-
|
|
12591
|
-
|
|
12592
|
-
|
|
12593
|
-
|
|
12594
|
-
|
|
12595
|
-
|
|
12596
|
-
});
|
|
12597
|
-
const accentMaterial = new MeshPhysicalMaterial({
|
|
12598
|
-
color: 16486972,
|
|
12599
|
-
roughness: 0.42,
|
|
12600
|
-
metalness: 0.02,
|
|
12601
|
-
clearcoat: 0.52,
|
|
12602
|
-
clearcoatRoughness: 0.28
|
|
12603
|
-
});
|
|
12604
|
-
const legMaterial = new MeshPhysicalMaterial({
|
|
12605
|
-
color: 14251782,
|
|
12606
|
-
roughness: 0.48,
|
|
12607
|
-
clearcoat: 0.35,
|
|
12608
|
-
clearcoatRoughness: 0.35
|
|
12609
|
-
});
|
|
12610
|
-
const eyeMaterial = new MeshPhysicalMaterial({
|
|
12611
|
-
color: 16776171,
|
|
12612
|
-
roughness: 0.22,
|
|
12613
|
-
clearcoat: 0.8,
|
|
12614
|
-
clearcoatRoughness: 0.12
|
|
12615
|
-
});
|
|
12616
|
-
const root = new Group();
|
|
12617
|
-
root.rotation.x = -0.12;
|
|
12618
|
-
root.rotation.y = -0.08;
|
|
12619
|
-
root.scale.setScalar(1.08);
|
|
12620
|
-
scene.add(root);
|
|
12621
|
-
const shadow = new Mesh(
|
|
12622
|
-
new CircleGeometry(1.65, 40),
|
|
12623
|
-
new MeshBasicMaterial({ color: 1120295, transparent: true, opacity: 0.16, depthWrite: false })
|
|
12624
|
-
);
|
|
12625
|
-
shadow.position.set(0, -1.33, -0.65);
|
|
12626
|
-
shadow.scale.set(1.4, 0.34, 1);
|
|
12627
|
-
root.add(shadow);
|
|
12628
|
-
const body = new Mesh(new SphereGeometry(1, 36, 24), shellMaterial);
|
|
12629
|
-
body.position.set(0, 0.02, 0);
|
|
12630
|
-
body.scale.set(1.58, 0.92, 0.68);
|
|
12631
|
-
root.add(body);
|
|
12632
|
-
const lowerShell = new Mesh(new SphereGeometry(0.92, 28, 20), accentMaterial);
|
|
12633
|
-
lowerShell.position.set(0, -0.48, 0.22);
|
|
12634
|
-
lowerShell.scale.set(1.28, 0.42, 0.56);
|
|
12635
|
-
root.add(lowerShell);
|
|
12636
|
-
const dominantClaw = addClaw(root, -1, shellMaterial, accentMaterial);
|
|
12637
|
-
addClaw(root, 1, shellMaterial, accentMaterial);
|
|
12638
|
-
const eyes = addEyes(root, shellMaterial, eyeMaterial);
|
|
12639
|
-
const legs = addLegs(root, legMaterial);
|
|
12640
|
-
scene.add(new AmbientLight(16775149, 1.65));
|
|
12641
|
-
scene.add(new HemisphereLight(16775149, 1515571, 2.15));
|
|
12642
|
-
const keyLight = new DirectionalLight(16777215, 3.6);
|
|
12643
|
-
keyLight.position.set(3.5, 4.5, 6);
|
|
12644
|
-
scene.add(keyLight);
|
|
12645
|
-
const fillLight = new DirectionalLight(16498468, 1.35);
|
|
12646
|
-
fillLight.position.set(-4, 1.5, 4);
|
|
12647
|
-
scene.add(fillLight);
|
|
12648
|
-
const rimLight = new PointLight(16096779, 1.8, 12, 2);
|
|
12649
|
-
rimLight.position.set(0, 1.8, 4.5);
|
|
12650
|
-
scene.add(rimLight);
|
|
12651
|
-
return { bodyMaterial: shellMaterial, dominantClaw, eyes, legs, rimLight, root };
|
|
12652
|
-
}
|
|
12653
|
-
function moodColor(mood) {
|
|
12654
|
-
switch (mood) {
|
|
12655
|
-
case "active":
|
|
12656
|
-
return 2282478;
|
|
12657
|
-
case "attention":
|
|
12658
|
-
return 15680580;
|
|
12659
|
-
case "idle":
|
|
12660
|
-
return 16096779;
|
|
12661
|
-
case "sleeping":
|
|
12662
|
-
return 9741240;
|
|
12663
|
-
}
|
|
12664
|
-
}
|
|
12665
|
-
function isDisposableMesh(object2) {
|
|
12666
|
-
return object2 instanceof Mesh;
|
|
12667
|
-
}
|
|
12668
|
-
function disposeScene(scene) {
|
|
12669
|
-
const materials = /* @__PURE__ */ new Set();
|
|
12670
|
-
scene.traverse((object2) => {
|
|
12671
|
-
if (!isDisposableMesh(object2)) return;
|
|
12672
|
-
object2.geometry.dispose();
|
|
12673
|
-
const material = object2.material;
|
|
12674
|
-
if (Array.isArray(material)) {
|
|
12675
|
-
for (const item of material) materials.add(item);
|
|
12676
|
-
return;
|
|
12677
|
-
}
|
|
12678
|
-
materials.add(material);
|
|
12455
|
+
if (provider.openaiBaseUrl !== void 0 && provider.openaiBaseUrl !== "") {
|
|
12456
|
+
return "Chat";
|
|
12457
|
+
}
|
|
12458
|
+
return "Anthropic";
|
|
12459
|
+
}
|
|
12460
|
+
function sortProviderBySource(providers) {
|
|
12461
|
+
return providers.toSorted((left, right) => {
|
|
12462
|
+
const leftCompanyRank = left.source === "company" ? 0 : 1;
|
|
12463
|
+
const rightCompanyRank = right.source === "company" ? 0 : 1;
|
|
12464
|
+
if (leftCompanyRank !== rightCompanyRank) return leftCompanyRank - rightCompanyRank;
|
|
12465
|
+
return left.name.localeCompare(right.name);
|
|
12679
12466
|
});
|
|
12680
|
-
for (const material of materials) material.dispose();
|
|
12681
12467
|
}
|
|
12682
|
-
function
|
|
12683
|
-
|
|
12684
|
-
moving,
|
|
12685
|
-
reduceMotion
|
|
12686
|
-
}) {
|
|
12687
|
-
const canvasRef = reactExports.useRef(null);
|
|
12688
|
-
const moodRef = reactExports.useRef(mood);
|
|
12689
|
-
const movingRef = reactExports.useRef(moving);
|
|
12690
|
-
const reduceMotionRef = reactExports.useRef(reduceMotion);
|
|
12691
|
-
const [renderFailed, setRenderFailed] = reactExports.useState(false);
|
|
12692
|
-
reactExports.useEffect(() => {
|
|
12693
|
-
moodRef.current = mood;
|
|
12694
|
-
}, [mood]);
|
|
12695
|
-
reactExports.useEffect(() => {
|
|
12696
|
-
movingRef.current = moving;
|
|
12697
|
-
}, [moving]);
|
|
12698
|
-
reactExports.useEffect(() => {
|
|
12699
|
-
reduceMotionRef.current = reduceMotion;
|
|
12700
|
-
}, [reduceMotion]);
|
|
12701
|
-
reactExports.useEffect(() => {
|
|
12702
|
-
const canvas = canvasRef.current;
|
|
12703
|
-
if (canvas === null) return void 0;
|
|
12704
|
-
let renderer;
|
|
12705
|
-
try {
|
|
12706
|
-
renderer = new WebGLRenderer({
|
|
12707
|
-
alpha: true,
|
|
12708
|
-
antialias: true,
|
|
12709
|
-
canvas,
|
|
12710
|
-
powerPreference: "low-power",
|
|
12711
|
-
preserveDrawingBuffer: true
|
|
12712
|
-
});
|
|
12713
|
-
} catch {
|
|
12714
|
-
setRenderFailed(true);
|
|
12715
|
-
return void 0;
|
|
12716
|
-
}
|
|
12717
|
-
renderer.setClearColor(0, 0);
|
|
12718
|
-
renderer.outputColorSpace = SRGBColorSpace;
|
|
12719
|
-
renderer.toneMapping = ACESFilmicToneMapping;
|
|
12720
|
-
renderer.toneMappingExposure = 1.18;
|
|
12721
|
-
const scene = new Scene();
|
|
12722
|
-
const camera = new OrthographicCamera(-3.65, 3.65, 3.65, -3.65, 0.1, 20);
|
|
12723
|
-
camera.position.set(0, 0.05, 8);
|
|
12724
|
-
camera.lookAt(0, 0, 0);
|
|
12725
|
-
const parts = createCrabScene(scene);
|
|
12726
|
-
const startedAt = window.performance.now();
|
|
12727
|
-
let lastFrameAt = 0;
|
|
12728
|
-
const renderFrame = (timestamp) => {
|
|
12729
|
-
if (timestamp - lastFrameAt < 32) return;
|
|
12730
|
-
lastFrameAt = timestamp;
|
|
12731
|
-
const elapsed = (timestamp - startedAt) / 1e3;
|
|
12732
|
-
const motionAllowed = !reduceMotionRef.current;
|
|
12733
|
-
const gait = movingRef.current ? 1 : moodRef.current === "active" ? 0.42 : 0;
|
|
12734
|
-
const idleMotion = motionAllowed ? Math.sin(elapsed * 0.85) : 0;
|
|
12735
|
-
const stepMotion = motionAllowed ? Math.sin(elapsed * 3.4) : 0;
|
|
12736
|
-
const clawGrip = motionAllowed ? dominantClawGrip(elapsed) : 0;
|
|
12737
|
-
parts.root.position.y = idleMotion * 0.035 + Math.abs(stepMotion) * 0.055 * gait;
|
|
12738
|
-
parts.root.rotation.y = -0.08 + idleMotion * 0.055;
|
|
12739
|
-
parts.root.rotation.z = stepMotion * 0.028 * gait;
|
|
12740
|
-
parts.dominantClaw.group.rotation.z = -clawGrip * 0.035;
|
|
12741
|
-
for (const pincer of parts.dominantClaw.pincers) {
|
|
12742
|
-
pincer.mesh.position.y = pincer.restY - pincer.direction * parts.dominantClaw.scale * 0.16 * clawGrip;
|
|
12743
|
-
pincer.mesh.rotation.z = pincer.restRotationZ * (1 - clawGrip * 0.72);
|
|
12744
|
-
}
|
|
12745
|
-
for (const leg of parts.legs) {
|
|
12746
|
-
leg.group.rotation.z = motionAllowed && gait > 0 ? Math.sin(elapsed * 4.25 + leg.phase) * 0.2 * leg.side * gait : 0;
|
|
12747
|
-
leg.group.rotation.x = motionAllowed && gait > 0 ? stepMotion * 0.045 * gait : 0;
|
|
12748
|
-
}
|
|
12749
|
-
for (const eye of parts.eyes) {
|
|
12750
|
-
const gaze = motionAllowed ? Math.sin(elapsed * 0.72 + eye.phase) : 0;
|
|
12751
|
-
const lift = motionAllowed ? Math.cos(elapsed * 0.9 + eye.phase) : 0;
|
|
12752
|
-
eye.group.rotation.z = gaze * 0.075;
|
|
12753
|
-
eye.group.rotation.x = lift * 0.025;
|
|
12754
|
-
eye.pupil.position.set(
|
|
12755
|
-
eye.pupilRest.x + gaze * 0.055,
|
|
12756
|
-
eye.pupilRest.y + lift * 0.025,
|
|
12757
|
-
eye.pupilRest.z
|
|
12758
|
-
);
|
|
12759
|
-
}
|
|
12760
|
-
const color = moodColor(moodRef.current);
|
|
12761
|
-
parts.rimLight.color.setHex(color);
|
|
12762
|
-
parts.rimLight.intensity = moodRef.current === "attention" ? 3.2 : 1.8;
|
|
12763
|
-
parts.bodyMaterial.emissive.setHex(color);
|
|
12764
|
-
parts.bodyMaterial.emissiveIntensity = moodRef.current === "active" ? 0.12 : 0.035;
|
|
12765
|
-
renderer.render(scene, camera);
|
|
12766
|
-
};
|
|
12767
|
-
const resize = () => {
|
|
12768
|
-
const width = Math.max(canvas.clientWidth, 1);
|
|
12769
|
-
const height = Math.max(canvas.clientHeight, 1);
|
|
12770
|
-
renderer.setDrawingBufferSize(width, height, Math.min(window.devicePixelRatio, 2));
|
|
12771
|
-
renderer.render(scene, camera);
|
|
12772
|
-
};
|
|
12773
|
-
const resizeObserver = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(resize);
|
|
12774
|
-
if (resizeObserver === null) {
|
|
12775
|
-
window.addEventListener("resize", resize);
|
|
12776
|
-
} else {
|
|
12777
|
-
resizeObserver.observe(canvas);
|
|
12778
|
-
}
|
|
12779
|
-
resize();
|
|
12780
|
-
const handleContextLost = (event) => {
|
|
12781
|
-
event.preventDefault();
|
|
12782
|
-
setRenderFailed(true);
|
|
12783
|
-
};
|
|
12784
|
-
canvas.addEventListener("webglcontextlost", handleContextLost);
|
|
12785
|
-
renderer.setAnimationLoop(renderFrame);
|
|
12786
|
-
return () => {
|
|
12787
|
-
renderer.setAnimationLoop(null);
|
|
12788
|
-
if (resizeObserver === null) {
|
|
12789
|
-
window.removeEventListener("resize", resize);
|
|
12790
|
-
} else {
|
|
12791
|
-
resizeObserver.disconnect();
|
|
12792
|
-
}
|
|
12793
|
-
canvas.removeEventListener("webglcontextlost", handleContextLost);
|
|
12794
|
-
disposeScene(scene);
|
|
12795
|
-
renderer.dispose();
|
|
12796
|
-
};
|
|
12797
|
-
}, []);
|
|
12798
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "relative flex size-24 items-center justify-center", "aria-hidden": "true", children: [
|
|
12799
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
12800
|
-
"canvas",
|
|
12801
|
-
{
|
|
12802
|
-
ref: canvasRef,
|
|
12803
|
-
className: renderFailed ? "hidden" : "block size-full bg-transparent",
|
|
12804
|
-
"data-inspector-pet-canvas": "true"
|
|
12805
|
-
}
|
|
12806
|
-
),
|
|
12807
|
-
renderFailed && /* @__PURE__ */ jsxRuntimeExports.jsx(CrabLogo, { className: "size-22 text-amber-500 drop-shadow-[0_0_18px_rgba(245,158,11,0.28)]" })
|
|
12808
|
-
] });
|
|
12468
|
+
function nextMessageId(role) {
|
|
12469
|
+
return `${role}-${String(Date.now())}-${String(Math.random()).slice(2)}`;
|
|
12809
12470
|
}
|
|
12810
|
-
|
|
12811
|
-
|
|
12812
|
-
|
|
12813
|
-
|
|
12814
|
-
|
|
12815
|
-
|
|
12816
|
-
const INSPECTOR_PET_DRAG_THRESHOLD = 4;
|
|
12817
|
-
const INSPECTOR_PET_TOP_LAYER_Z_INDEX = 2147483647;
|
|
12818
|
-
function readViewport() {
|
|
12819
|
-
if (typeof window === "undefined") return { width: 1280, height: 720, scale: 1 };
|
|
12820
|
-
const rawScale = window.getComputedStyle(document.documentElement).getPropertyValue("--inspector-ui-scale");
|
|
12821
|
-
const parsedScale = Number.parseFloat(rawScale);
|
|
12822
|
-
const scale = Number.isFinite(parsedScale) && parsedScale > 0 ? parsedScale : 1;
|
|
12823
|
-
return {
|
|
12824
|
-
width: Math.max(window.innerWidth, INSPECTOR_PET_MARGIN * 2),
|
|
12825
|
-
height: Math.max(window.innerHeight, INSPECTOR_PET_MARGIN * 2),
|
|
12826
|
-
scale
|
|
12827
|
-
};
|
|
12471
|
+
function MetricStrip({ metrics }) {
|
|
12472
|
+
if (metrics.length === 0) return null;
|
|
12473
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 grid grid-cols-2 gap-1.5", children: metrics.slice(0, 8).map((metric) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-sm bg-black/20 px-2 py-1", children: [
|
|
12474
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "truncate text-[9px] uppercase text-muted-foreground", children: metric.label }),
|
|
12475
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "truncate font-mono text-[11px] text-cyan-50", children: metric.value })
|
|
12476
|
+
] }, metric.key)) });
|
|
12828
12477
|
}
|
|
12829
|
-
function
|
|
12830
|
-
|
|
12831
|
-
|
|
12832
|
-
|
|
12833
|
-
}
|
|
12834
|
-
|
|
12835
|
-
|
|
12478
|
+
function EvidenceCard({ evidence }) {
|
|
12479
|
+
const openLog = () => {
|
|
12480
|
+
if (evidence.logId === null) return;
|
|
12481
|
+
dispatchLogFocusRequest({ logId: evidence.logId, tab: "anatomy" });
|
|
12482
|
+
};
|
|
12483
|
+
const title = evidence.logId === null ? `${evidence.source}:${evidence.id}` : `${evidence.source}:log #${String(evidence.logId)}`;
|
|
12484
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
12485
|
+
"button",
|
|
12486
|
+
{
|
|
12487
|
+
type: "button",
|
|
12488
|
+
onClick: openLog,
|
|
12489
|
+
disabled: evidence.logId === null,
|
|
12490
|
+
className: "w-full rounded-sm bg-black/20 px-2 py-2 text-left shadow-[inset_0_0_0_1px_rgba(255,255,255,0.05)] transition-colors hover:bg-black/30 disabled:cursor-default disabled:hover:bg-black/20",
|
|
12491
|
+
children: [
|
|
12492
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center justify-between gap-2", children: [
|
|
12493
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate font-mono text-[10px] text-cyan-100", children: title }),
|
|
12494
|
+
evidence.score !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0 font-mono text-[9px] text-muted-foreground", children: evidence.score.toFixed(1) })
|
|
12495
|
+
] }),
|
|
12496
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-1 flex flex-wrap gap-x-2 gap-y-1 text-[10px] text-muted-foreground", children: [
|
|
12497
|
+
evidence.providerName !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: evidence.providerName }),
|
|
12498
|
+
evidence.model !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: evidence.model }),
|
|
12499
|
+
evidence.status !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
12500
|
+
"status ",
|
|
12501
|
+
String(evidence.status)
|
|
12502
|
+
] }),
|
|
12503
|
+
evidence.elapsedMs !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
12504
|
+
String(evidence.elapsedMs),
|
|
12505
|
+
" ms"
|
|
12506
|
+
] })
|
|
12507
|
+
] }),
|
|
12508
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-1 line-clamp-3 text-[11px] leading-4 text-foreground/85", children: evidence.excerpt })
|
|
12509
|
+
]
|
|
12510
|
+
}
|
|
12511
|
+
);
|
|
12836
12512
|
}
|
|
12837
|
-
function
|
|
12838
|
-
|
|
12839
|
-
|
|
12840
|
-
|
|
12841
|
-
|
|
12842
|
-
|
|
12843
|
-
|
|
12844
|
-
|
|
12845
|
-
|
|
12846
|
-
|
|
12847
|
-
|
|
12513
|
+
function AssistantMessage({ response }) {
|
|
12514
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-md bg-black/25 p-3 shadow-[inset_0_0_0_1px_rgba(255,255,255,0.05)]", children: [
|
|
12515
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(AnswerMarkdown, { text: response.answer }),
|
|
12516
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-2 break-words font-mono text-[10px] text-cyan-100/70", children: [
|
|
12517
|
+
response.providerName,
|
|
12518
|
+
" / ",
|
|
12519
|
+
response.model,
|
|
12520
|
+
" / ",
|
|
12521
|
+
response.protocol,
|
|
12522
|
+
" /",
|
|
12523
|
+
" ",
|
|
12524
|
+
String(response.logCount),
|
|
12525
|
+
" matched logs"
|
|
12526
|
+
] }),
|
|
12527
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(MetricStrip, { metrics: response.summaryMetrics }),
|
|
12528
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(MetricStrip, { metrics: response.queryMetrics }),
|
|
12529
|
+
response.evidence.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 space-y-1.5", children: response.evidence.slice(0, 6).map((evidence) => /* @__PURE__ */ jsxRuntimeExports.jsx(EvidenceCard, { evidence }, `${evidence.source}-${evidence.id}`)) })
|
|
12530
|
+
] });
|
|
12848
12531
|
}
|
|
12849
|
-
function
|
|
12850
|
-
|
|
12851
|
-
|
|
12852
|
-
return "inspector-pet-active";
|
|
12853
|
-
case "attention":
|
|
12854
|
-
return "inspector-pet-attention";
|
|
12855
|
-
case "idle":
|
|
12856
|
-
return "";
|
|
12857
|
-
case "sleeping":
|
|
12858
|
-
return "inspector-pet-sleeping";
|
|
12532
|
+
function ConversationMessage({ message }) {
|
|
12533
|
+
if (message.role === "assistant" && message.response !== null) {
|
|
12534
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(AssistantMessage, { response: message.response });
|
|
12859
12535
|
}
|
|
12860
|
-
}
|
|
12861
|
-
function InspectorPet({ logs }) {
|
|
12862
|
-
const [portalHost, setPortalHost] = reactExports.useState(null);
|
|
12863
|
-
const [viewport, setViewport] = reactExports.useState(readViewport);
|
|
12864
|
-
const [position, setPosition] = reactExports.useState({
|
|
12865
|
-
x: INSPECTOR_PET_MARGIN,
|
|
12866
|
-
y: INSPECTOR_PET_MARGIN
|
|
12867
|
-
});
|
|
12868
|
-
const [clockMs, setClockMs] = reactExports.useState(() => Date.now());
|
|
12869
|
-
const [scuttling, setScuttling] = reactExports.useState(false);
|
|
12870
|
-
const [panelTick, setPanelTick] = reactExports.useState(0);
|
|
12871
|
-
const [panelVisible, setPanelVisible] = reactExports.useState(false);
|
|
12872
|
-
const [reactionTick, setReactionTick] = reactExports.useState(0);
|
|
12873
|
-
const [reactionVisible, setReactionVisible] = reactExports.useState(false);
|
|
12874
|
-
const [dragging, setDragging] = reactExports.useState(false);
|
|
12875
|
-
const [roaming, setRoaming] = reactExports.useState(readStoredRoaming);
|
|
12876
|
-
const [reduceMotion, setReduceMotion] = reactExports.useState(false);
|
|
12877
|
-
const dragStateRef = reactExports.useRef(null);
|
|
12878
|
-
const dragOccurredRef = reactExports.useRef(false);
|
|
12879
|
-
const status = reactExports.useMemo(() => resolveInspectorPetStatus(logs, clockMs), [clockMs, logs]);
|
|
12880
|
-
const panelPosition = reactExports.useMemo(
|
|
12881
|
-
() => inspectorPetPanelPosition(position, viewport),
|
|
12882
|
-
[position, viewport]
|
|
12883
|
-
);
|
|
12884
|
-
reactExports.useEffect(() => setPortalHost(document.body), []);
|
|
12885
|
-
reactExports.useEffect(() => {
|
|
12886
|
-
const nextViewport = readViewport();
|
|
12887
|
-
setViewport(nextViewport);
|
|
12888
|
-
setPosition(randomInspectorPetEdgePosition(nextViewport, Math.random()));
|
|
12889
|
-
}, []);
|
|
12890
|
-
reactExports.useEffect(() => {
|
|
12891
|
-
const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
12892
|
-
const handleChange = (event) => setReduceMotion(event.matches);
|
|
12893
|
-
setReduceMotion(mediaQuery.matches);
|
|
12894
|
-
mediaQuery.addEventListener("change", handleChange);
|
|
12895
|
-
return () => mediaQuery.removeEventListener("change", handleChange);
|
|
12896
|
-
}, []);
|
|
12897
|
-
reactExports.useEffect(() => {
|
|
12898
|
-
const intervalId = window.setInterval(() => setClockMs(Date.now()), 15e3);
|
|
12899
|
-
return () => window.clearInterval(intervalId);
|
|
12900
|
-
}, []);
|
|
12901
|
-
reactExports.useEffect(() => {
|
|
12902
|
-
try {
|
|
12903
|
-
window.localStorage.setItem(INSPECTOR_PET_ROAMING_STORAGE_KEY, roaming ? "1" : "0");
|
|
12904
|
-
} catch {
|
|
12905
|
-
}
|
|
12906
|
-
}, [roaming]);
|
|
12907
|
-
reactExports.useEffect(() => {
|
|
12908
|
-
if (!roaming || dragging || reduceMotion) return void 0;
|
|
12909
|
-
let pauseTimeoutId = null;
|
|
12910
|
-
let scuttleTimeoutId = null;
|
|
12911
|
-
const scheduleScuttle = () => {
|
|
12912
|
-
const delay = INSPECTOR_PET_MIN_PAUSE_MS + Math.random() * INSPECTOR_PET_PAUSE_WINDOW_MS;
|
|
12913
|
-
pauseTimeoutId = window.setTimeout(() => {
|
|
12914
|
-
setScuttling(true);
|
|
12915
|
-
setPosition(
|
|
12916
|
-
(current) => nextInspectorPetWalkingPosition(current, viewport, Math.random(), Math.random())
|
|
12917
|
-
);
|
|
12918
|
-
scuttleTimeoutId = window.setTimeout(() => {
|
|
12919
|
-
setScuttling(false);
|
|
12920
|
-
scheduleScuttle();
|
|
12921
|
-
}, INSPECTOR_PET_SCUTTLE_MS);
|
|
12922
|
-
}, delay);
|
|
12923
|
-
};
|
|
12924
|
-
scheduleScuttle();
|
|
12925
|
-
return () => {
|
|
12926
|
-
if (pauseTimeoutId !== null) window.clearTimeout(pauseTimeoutId);
|
|
12927
|
-
if (scuttleTimeoutId !== null) window.clearTimeout(scuttleTimeoutId);
|
|
12928
|
-
};
|
|
12929
|
-
}, [dragging, reduceMotion, roaming, viewport]);
|
|
12930
|
-
reactExports.useEffect(() => {
|
|
12931
|
-
const handleResize = () => {
|
|
12932
|
-
const nextViewport = readViewport();
|
|
12933
|
-
setScuttling(false);
|
|
12934
|
-
setViewport(nextViewport);
|
|
12935
|
-
setPosition((current) => snapInspectorPetToEdge(current, nextViewport));
|
|
12936
|
-
};
|
|
12937
|
-
window.addEventListener("resize", handleResize);
|
|
12938
|
-
return () => window.removeEventListener("resize", handleResize);
|
|
12939
|
-
}, []);
|
|
12940
|
-
reactExports.useEffect(() => {
|
|
12941
|
-
if (!panelVisible) return void 0;
|
|
12942
|
-
const timeoutId = window.setTimeout(
|
|
12943
|
-
() => setPanelVisible(false),
|
|
12944
|
-
INSPECTOR_PET_PANEL_DISMISS_MS
|
|
12945
|
-
);
|
|
12946
|
-
return () => window.clearTimeout(timeoutId);
|
|
12947
|
-
}, [panelTick, panelVisible]);
|
|
12948
|
-
reactExports.useEffect(() => {
|
|
12949
|
-
if (!reactionVisible) return void 0;
|
|
12950
|
-
const timeoutId = window.setTimeout(() => setReactionVisible(false), INSPECTOR_PET_REACTION_MS);
|
|
12951
|
-
return () => window.clearTimeout(timeoutId);
|
|
12952
|
-
}, [reactionTick, reactionVisible]);
|
|
12953
|
-
const handlePet = reactExports.useCallback(() => {
|
|
12954
|
-
if (dragOccurredRef.current) {
|
|
12955
|
-
dragOccurredRef.current = false;
|
|
12956
|
-
return;
|
|
12957
|
-
}
|
|
12958
|
-
setClockMs(Date.now());
|
|
12959
|
-
setPanelTick((current) => current + 1);
|
|
12960
|
-
setPanelVisible(true);
|
|
12961
|
-
setReactionTick((current) => current + 1);
|
|
12962
|
-
setReactionVisible(true);
|
|
12963
|
-
}, []);
|
|
12964
|
-
const handlePointerDown = reactExports.useCallback((event) => {
|
|
12965
|
-
const rect = event.currentTarget.getBoundingClientRect();
|
|
12966
|
-
dragOccurredRef.current = false;
|
|
12967
|
-
dragStateRef.current = {
|
|
12968
|
-
pointerId: event.pointerId,
|
|
12969
|
-
offsetX: event.clientX - rect.left,
|
|
12970
|
-
offsetY: event.clientY - rect.top,
|
|
12971
|
-
startX: event.clientX,
|
|
12972
|
-
startY: event.clientY,
|
|
12973
|
-
moved: false
|
|
12974
|
-
};
|
|
12975
|
-
event.currentTarget.setPointerCapture(event.pointerId);
|
|
12976
|
-
setScuttling(false);
|
|
12977
|
-
setPanelVisible(false);
|
|
12978
|
-
setDragging(true);
|
|
12979
|
-
}, []);
|
|
12980
|
-
const handlePointerMove = reactExports.useCallback(
|
|
12981
|
-
(event) => {
|
|
12982
|
-
const dragState = dragStateRef.current;
|
|
12983
|
-
if (dragState === null || dragState.pointerId !== event.pointerId) return;
|
|
12984
|
-
const moved = dragState.moved || Math.abs(event.clientX - dragState.startX) >= INSPECTOR_PET_DRAG_THRESHOLD || Math.abs(event.clientY - dragState.startY) >= INSPECTOR_PET_DRAG_THRESHOLD;
|
|
12985
|
-
dragState.moved = moved;
|
|
12986
|
-
dragOccurredRef.current = moved;
|
|
12987
|
-
setPosition(
|
|
12988
|
-
clampInspectorPetPosition(
|
|
12989
|
-
{
|
|
12990
|
-
x: event.clientX - dragState.offsetX,
|
|
12991
|
-
y: event.clientY - dragState.offsetY
|
|
12992
|
-
},
|
|
12993
|
-
viewport
|
|
12994
|
-
)
|
|
12995
|
-
);
|
|
12996
|
-
},
|
|
12997
|
-
[viewport]
|
|
12998
|
-
);
|
|
12999
|
-
const handlePointerUp = reactExports.useCallback(
|
|
13000
|
-
(event) => {
|
|
13001
|
-
const dragState = dragStateRef.current;
|
|
13002
|
-
if (dragState === null || dragState.pointerId !== event.pointerId) return;
|
|
13003
|
-
if (event.currentTarget.hasPointerCapture(event.pointerId)) {
|
|
13004
|
-
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
13005
|
-
}
|
|
13006
|
-
dragOccurredRef.current = dragState.moved;
|
|
13007
|
-
dragStateRef.current = null;
|
|
13008
|
-
setDragging(false);
|
|
13009
|
-
setPosition((current) => snapInspectorPetToEdge(current, viewport));
|
|
13010
|
-
},
|
|
13011
|
-
[viewport]
|
|
13012
|
-
);
|
|
13013
|
-
const handlePointerCancel = reactExports.useCallback((event) => {
|
|
13014
|
-
if (event.currentTarget.hasPointerCapture(event.pointerId)) {
|
|
13015
|
-
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
13016
|
-
}
|
|
13017
|
-
dragStateRef.current = null;
|
|
13018
|
-
dragOccurredRef.current = false;
|
|
13019
|
-
setDragging(false);
|
|
13020
|
-
}, []);
|
|
13021
|
-
const handleToggleRoaming = reactExports.useCallback(() => {
|
|
13022
|
-
setScuttling(false);
|
|
13023
|
-
setRoaming((current) => !current);
|
|
13024
|
-
}, []);
|
|
13025
|
-
const petStyle = reactExports.useMemo(
|
|
13026
|
-
() => ({
|
|
13027
|
-
transform: `translate3d(${String(position.x)}px, ${String(position.y)}px, 0) scale(${dragging ? "1.04" : "1"})`,
|
|
13028
|
-
transition: dragging ? "none" : scuttling ? `transform ${String(INSPECTOR_PET_SCUTTLE_MS)}ms cubic-bezier(0.22, 0.72, 0.32, 1)` : "transform 900ms cubic-bezier(0.22, 0.72, 0.32, 1)",
|
|
13029
|
-
touchAction: "none"
|
|
13030
|
-
}),
|
|
13031
|
-
[dragging, position.x, position.y, scuttling]
|
|
13032
|
-
);
|
|
13033
|
-
const panelStyle = reactExports.useMemo(
|
|
13034
|
-
() => ({ left: panelPosition.x, top: panelPosition.y }),
|
|
13035
|
-
[panelPosition.x, panelPosition.y]
|
|
13036
|
-
);
|
|
13037
|
-
const roamingLabel = roaming ? "Pause pet roaming" : "Resume pet roaming";
|
|
13038
|
-
if (portalHost === null) return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, {});
|
|
13039
|
-
return reactDomExports.createPortal(
|
|
13040
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
13041
|
-
"div",
|
|
13042
|
-
{
|
|
13043
|
-
className: "pointer-events-none fixed inset-0 isolate",
|
|
13044
|
-
style: { zIndex: INSPECTOR_PET_TOP_LAYER_Z_INDEX },
|
|
13045
|
-
"data-inspector-pet-layer": "true",
|
|
13046
|
-
children: [
|
|
13047
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
13048
|
-
"button",
|
|
13049
|
-
{
|
|
13050
|
-
type: "button",
|
|
13051
|
-
className: cn(
|
|
13052
|
-
"pointer-events-auto fixed left-0 top-0 z-10 flex size-28 items-center justify-center bg-transparent text-foreground outline-none transition-[filter,opacity] duration-200 hover:opacity-95 hover:drop-shadow-[0_0_28px_rgba(245,158,11,0.32)] focus-visible:drop-shadow-[0_0_14px_rgba(251,191,36,0.72)]",
|
|
13053
|
-
dragging ? "cursor-grabbing" : "cursor-grab"
|
|
13054
|
-
),
|
|
13055
|
-
style: petStyle,
|
|
13056
|
-
"data-pet-mood": status.mood,
|
|
13057
|
-
"data-pet-moving": scuttling ? "true" : "false",
|
|
13058
|
-
onClick: handlePet,
|
|
13059
|
-
onPointerDown: handlePointerDown,
|
|
13060
|
-
onPointerMove: handlePointerMove,
|
|
13061
|
-
onPointerUp: handlePointerUp,
|
|
13062
|
-
onPointerCancel: handlePointerCancel,
|
|
13063
|
-
"aria-label": `Inspector pet: ${status.label}`,
|
|
13064
|
-
title: status.label,
|
|
13065
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
13066
|
-
"span",
|
|
13067
|
-
{
|
|
13068
|
-
className: cn(
|
|
13069
|
-
"relative z-10 flex size-24 items-center justify-center",
|
|
13070
|
-
reactionVisible && "inspector-pet-patted"
|
|
13071
|
-
),
|
|
13072
|
-
"aria-hidden": "true",
|
|
13073
|
-
children: [
|
|
13074
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
13075
|
-
"span",
|
|
13076
|
-
{
|
|
13077
|
-
className: cn(
|
|
13078
|
-
"relative flex size-24 items-center justify-center",
|
|
13079
|
-
moodMotionClass(status.mood)
|
|
13080
|
-
),
|
|
13081
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "relative flex size-24 items-center justify-center", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
13082
|
-
InspectorPetCrab3D,
|
|
13083
|
-
{
|
|
13084
|
-
mood: status.mood,
|
|
13085
|
-
moving: scuttling && !dragging,
|
|
13086
|
-
reduceMotion
|
|
13087
|
-
}
|
|
13088
|
-
) })
|
|
13089
|
-
}
|
|
13090
|
-
),
|
|
13091
|
-
reactionVisible && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
13092
|
-
Heart,
|
|
13093
|
-
{
|
|
13094
|
-
className: "inspector-pet-heart absolute -right-2 -top-3 size-5 fill-amber-400 text-amber-400"
|
|
13095
|
-
},
|
|
13096
|
-
reactionTick
|
|
13097
|
-
)
|
|
13098
|
-
]
|
|
13099
|
-
}
|
|
13100
|
-
)
|
|
13101
|
-
}
|
|
13102
|
-
),
|
|
13103
|
-
panelVisible && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
13104
|
-
"div",
|
|
13105
|
-
{
|
|
13106
|
-
className: "pointer-events-auto fixed z-20 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",
|
|
13107
|
-
style: panelStyle,
|
|
13108
|
-
role: "status",
|
|
13109
|
-
"aria-live": "polite",
|
|
13110
|
-
children: [
|
|
13111
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
13112
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn("size-2 shrink-0 rounded-full", moodDotClass(status.mood)) }),
|
|
13113
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0 flex-1 truncate text-xs font-medium", children: status.label }),
|
|
13114
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
13115
|
-
"button",
|
|
13116
|
-
{
|
|
13117
|
-
type: "button",
|
|
13118
|
-
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",
|
|
13119
|
-
onClick: handleToggleRoaming,
|
|
13120
|
-
"aria-label": roamingLabel,
|
|
13121
|
-
title: roamingLabel,
|
|
13122
|
-
children: roaming ? /* @__PURE__ */ jsxRuntimeExports.jsx(Pause, { className: "size-3.5" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Play, { className: "size-3.5" })
|
|
13123
|
-
}
|
|
13124
|
-
)
|
|
13125
|
-
] }),
|
|
13126
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-1 flex items-center justify-between gap-3 font-mono text-[10px] text-muted-foreground", children: [
|
|
13127
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
13128
|
-
String(status.capturedCount),
|
|
13129
|
-
" captured"
|
|
13130
|
-
] }),
|
|
13131
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: status.pendingCount > 0 ? `${String(status.pendingCount)} active` : scuttling ? "Scuttling" : roaming ? "Resting" : "Paused" })
|
|
13132
|
-
] })
|
|
13133
|
-
]
|
|
13134
|
-
}
|
|
13135
|
-
)
|
|
13136
|
-
]
|
|
13137
|
-
}
|
|
13138
|
-
),
|
|
13139
|
-
portalHost
|
|
13140
|
-
);
|
|
13141
|
-
}
|
|
13142
|
-
const DEFAULT_QUESTION = "Analyze the current Inspector session. What looks abnormal, slow, or likely to hang?";
|
|
13143
|
-
function providerSupportsPiAgent(provider) {
|
|
13144
|
-
return provider.openaiResponsesBaseUrl !== void 0 || provider.openaiBaseUrl !== void 0 || provider.anthropicBaseUrl !== void 0;
|
|
13145
|
-
}
|
|
13146
|
-
function providerProtocolLabel(provider) {
|
|
13147
|
-
if (provider.openaiResponsesBaseUrl !== void 0 && provider.openaiResponsesBaseUrl !== "") {
|
|
13148
|
-
return "Responses";
|
|
13149
|
-
}
|
|
13150
|
-
if (provider.openaiBaseUrl !== void 0 && provider.openaiBaseUrl !== "") {
|
|
13151
|
-
return "Chat";
|
|
13152
|
-
}
|
|
13153
|
-
return "Anthropic";
|
|
13154
|
-
}
|
|
13155
|
-
function sortProviderBySource(providers) {
|
|
13156
|
-
return providers.toSorted((left, right) => {
|
|
13157
|
-
const leftCompanyRank = left.source === "company" ? 0 : 1;
|
|
13158
|
-
const rightCompanyRank = right.source === "company" ? 0 : 1;
|
|
13159
|
-
if (leftCompanyRank !== rightCompanyRank) return leftCompanyRank - rightCompanyRank;
|
|
13160
|
-
return left.name.localeCompare(right.name);
|
|
13161
|
-
});
|
|
12536
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "rounded-md bg-cyan-400/10 px-3 py-2 text-xs leading-5 text-cyan-50", children: message.content });
|
|
13162
12537
|
}
|
|
13163
12538
|
function PiAgentPanel({ currentSessionId, logCount }) {
|
|
13164
12539
|
const { providers } = useProviders();
|
|
@@ -13166,60 +12541,97 @@ function PiAgentPanel({ currentSessionId, logCount }) {
|
|
|
13166
12541
|
() => sortProviderBySource(providers.filter(providerSupportsPiAgent)),
|
|
13167
12542
|
[providers]
|
|
13168
12543
|
);
|
|
13169
|
-
const [
|
|
12544
|
+
const [conversation, setConversation] = reactExports.useState(() => ({
|
|
12545
|
+
...createEmptyPiAgentConversation(),
|
|
12546
|
+
question: DEFAULT_QUESTION
|
|
12547
|
+
}));
|
|
13170
12548
|
const [providerId, setProviderId] = reactExports.useState("__auto__");
|
|
13171
12549
|
const [model, setModel] = reactExports.useState("__auto__");
|
|
13172
|
-
const [answer, setAnswer] = reactExports.useState("");
|
|
13173
|
-
const [status, setStatus] = reactExports.useState("");
|
|
13174
12550
|
const [loading, setLoading] = reactExports.useState(false);
|
|
13175
12551
|
const selectedProvider = piProviders.find((provider) => provider.id === providerId);
|
|
13176
12552
|
const modelOptions = selectedProvider?.models ?? [];
|
|
12553
|
+
const question = conversation.question;
|
|
13177
12554
|
const canAsk = question.trim() !== "" && piProviders.length > 0 && !loading;
|
|
13178
12555
|
const handleQuestionChange = (event) => {
|
|
13179
|
-
|
|
12556
|
+
setConversation((current) => ({ ...current, question: event.currentTarget.value }));
|
|
13180
12557
|
};
|
|
13181
12558
|
const handleProviderChange = (value) => {
|
|
13182
12559
|
setProviderId(value);
|
|
13183
12560
|
setModel("__auto__");
|
|
13184
12561
|
};
|
|
12562
|
+
const resetConversation = () => {
|
|
12563
|
+
setConversation({ ...createEmptyPiAgentConversation(), question: DEFAULT_QUESTION });
|
|
12564
|
+
};
|
|
12565
|
+
const setStarter = (questionText) => {
|
|
12566
|
+
setConversation((current) => ({ ...current, question: questionText, error: null }));
|
|
12567
|
+
};
|
|
13185
12568
|
const askPiAgent = () => {
|
|
13186
12569
|
if (!canAsk) return;
|
|
12570
|
+
const trimmedQuestion = question.trim();
|
|
12571
|
+
const history = buildPiAgentHistory(conversation.messages);
|
|
12572
|
+
const userMessage = {
|
|
12573
|
+
id: nextMessageId("user"),
|
|
12574
|
+
role: "user",
|
|
12575
|
+
content: trimmedQuestion,
|
|
12576
|
+
response: null
|
|
12577
|
+
};
|
|
13187
12578
|
setLoading(true);
|
|
13188
|
-
|
|
13189
|
-
|
|
12579
|
+
setConversation((current) => ({
|
|
12580
|
+
...current,
|
|
12581
|
+
messages: [...current.messages, userMessage],
|
|
12582
|
+
question: "",
|
|
12583
|
+
error: null
|
|
12584
|
+
}));
|
|
13190
12585
|
const body = {
|
|
13191
|
-
question:
|
|
12586
|
+
question: trimmedQuestion,
|
|
12587
|
+
history,
|
|
13192
12588
|
...currentSessionId !== null ? { sessionId: currentSessionId } : {},
|
|
13193
12589
|
...providerId !== "__auto__" ? { providerId } : {},
|
|
13194
12590
|
...model !== "__auto__" ? { model } : {},
|
|
13195
|
-
logLimit:
|
|
12591
|
+
logLimit: 16
|
|
13196
12592
|
};
|
|
13197
12593
|
void fetch("/api/pi-agent", {
|
|
13198
12594
|
method: "POST",
|
|
13199
|
-
headers: {
|
|
12595
|
+
headers: {
|
|
12596
|
+
"content-type": "application/json",
|
|
12597
|
+
"x-agent-inspector-csrf": "1"
|
|
12598
|
+
},
|
|
13200
12599
|
body: JSON.stringify(body)
|
|
13201
12600
|
}).then(async (response) => {
|
|
13202
12601
|
const raw = await response.text();
|
|
13203
12602
|
if (!response.ok) {
|
|
13204
|
-
|
|
13205
|
-
|
|
12603
|
+
setConversation((current) => ({
|
|
12604
|
+
...current,
|
|
12605
|
+
error: `Pi Agent failed: HTTP ${String(response.status)} ${raw}`
|
|
12606
|
+
}));
|
|
13206
12607
|
return;
|
|
13207
12608
|
}
|
|
13208
12609
|
const parsedJson = JSON.parse(raw);
|
|
13209
|
-
const
|
|
13210
|
-
if (
|
|
13211
|
-
|
|
13212
|
-
|
|
12610
|
+
const normalized = normalizePiAgentResponse(parsedJson);
|
|
12611
|
+
if (normalized === null) {
|
|
12612
|
+
setConversation((current) => ({
|
|
12613
|
+
...current,
|
|
12614
|
+
error: "Pi Agent returned an unexpected response."
|
|
12615
|
+
}));
|
|
13213
12616
|
return;
|
|
13214
12617
|
}
|
|
13215
|
-
|
|
13216
|
-
|
|
13217
|
-
|
|
13218
|
-
|
|
13219
|
-
|
|
13220
|
-
|
|
12618
|
+
setConversation((current) => ({
|
|
12619
|
+
...current,
|
|
12620
|
+
messages: [
|
|
12621
|
+
...current.messages,
|
|
12622
|
+
{
|
|
12623
|
+
id: nextMessageId("assistant"),
|
|
12624
|
+
role: "assistant",
|
|
12625
|
+
content: normalized.answer,
|
|
12626
|
+
response: normalized
|
|
12627
|
+
}
|
|
12628
|
+
]
|
|
12629
|
+
}));
|
|
13221
12630
|
}).catch((err) => {
|
|
13222
|
-
|
|
12631
|
+
setConversation((current) => ({
|
|
12632
|
+
...current,
|
|
12633
|
+
error: err instanceof Error ? err.message : "Pi Agent request failed."
|
|
12634
|
+
}));
|
|
13223
12635
|
}).finally(() => {
|
|
13224
12636
|
setLoading(false);
|
|
13225
12637
|
});
|
|
@@ -13229,8 +12641,18 @@ function PiAgentPanel({ currentSessionId, logCount }) {
|
|
|
13229
12641
|
/* @__PURE__ */ jsxRuntimeExports.jsx(BrainCircuit, { className: "size-4 text-cyan-200" }),
|
|
13230
12642
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
13231
12643
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs font-semibold text-foreground", children: "Pi Agent" }),
|
|
13232
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[11px] text-muted-foreground", children: currentSessionId === null ? "Inspector-wide
|
|
13233
|
-
] })
|
|
12644
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[11px] text-muted-foreground", children: currentSessionId === null ? "Inspector-wide ChatBI" : "Session ChatBI" })
|
|
12645
|
+
] }),
|
|
12646
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
12647
|
+
"button",
|
|
12648
|
+
{
|
|
12649
|
+
type: "button",
|
|
12650
|
+
onClick: resetConversation,
|
|
12651
|
+
className: "inline-flex size-7 items-center justify-center rounded-md bg-black/25 text-muted-foreground transition-colors hover:text-foreground",
|
|
12652
|
+
title: "Reset conversation",
|
|
12653
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(RotateCcw, { className: "size-3.5" })
|
|
12654
|
+
}
|
|
12655
|
+
)
|
|
13234
12656
|
] }),
|
|
13235
12657
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-3 grid grid-cols-2 gap-2", children: [
|
|
13236
12658
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(Select, { value: providerId, onValueChange: handleProviderChange, children: [
|
|
@@ -13252,56 +12674,454 @@ function PiAgentPanel({ currentSessionId, logCount }) {
|
|
|
13252
12674
|
] })
|
|
13253
12675
|
] })
|
|
13254
12676
|
] }),
|
|
12677
|
+
conversation.messages.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-3 flex flex-wrap gap-1.5", children: PI_AGENT_STARTERS.map((starter) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
12678
|
+
"button",
|
|
12679
|
+
{
|
|
12680
|
+
type: "button",
|
|
12681
|
+
onClick: () => {
|
|
12682
|
+
setStarter(starter.question);
|
|
12683
|
+
},
|
|
12684
|
+
className: "inline-flex h-7 items-center gap-1.5 rounded-sm bg-black/25 px-2 text-[11px] text-cyan-50 transition-colors hover:bg-cyan-400/12",
|
|
12685
|
+
children: [
|
|
12686
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Sparkles, { className: "size-3" }),
|
|
12687
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: starter.label })
|
|
12688
|
+
]
|
|
12689
|
+
},
|
|
12690
|
+
starter.id
|
|
12691
|
+
)) }),
|
|
12692
|
+
conversation.messages.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-3 max-h-96 space-y-2 overflow-y-auto pr-1", children: [
|
|
12693
|
+
conversation.messages.map((message) => /* @__PURE__ */ jsxRuntimeExports.jsx(ConversationMessage, { message }, message.id)),
|
|
12694
|
+
loading && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "inline-flex items-center gap-2 rounded-md bg-black/25 px-3 py-2 text-xs text-muted-foreground", children: [
|
|
12695
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-3.5 animate-spin" }),
|
|
12696
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Searching Inspector..." })
|
|
12697
|
+
] })
|
|
12698
|
+
] }),
|
|
12699
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
12700
|
+
"textarea",
|
|
12701
|
+
{
|
|
12702
|
+
value: question,
|
|
12703
|
+
onChange: handleQuestionChange,
|
|
12704
|
+
className: "mt-3 min-h-20 w-full resize-y rounded-md bg-black/25 px-3 py-2 text-xs leading-5 text-foreground outline-none shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors placeholder:text-muted-foreground focus-visible:ring-1 focus-visible:ring-ring",
|
|
12705
|
+
placeholder: "Ask Pi Agent across saved Inspector data..."
|
|
12706
|
+
}
|
|
12707
|
+
),
|
|
12708
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
12709
|
+
"button",
|
|
12710
|
+
{
|
|
12711
|
+
type: "button",
|
|
12712
|
+
onClick: askPiAgent,
|
|
12713
|
+
disabled: !canAsk,
|
|
12714
|
+
className: "mt-2 inline-flex h-8 w-full items-center justify-center gap-2 rounded-md bg-cyan-400/12 px-3 text-xs font-medium text-cyan-100 shadow-[inset_0_0_0_1px_rgba(103,232,249,0.18)] transition-colors hover:bg-cyan-400/18 disabled:cursor-not-allowed disabled:opacity-50",
|
|
12715
|
+
children: [
|
|
12716
|
+
loading ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-3.5 animate-spin" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Send, { className: "size-3.5" }),
|
|
12717
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: loading ? "Thinking..." : "Ask Pi" })
|
|
12718
|
+
]
|
|
12719
|
+
}
|
|
12720
|
+
),
|
|
12721
|
+
conversation.error !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-2 break-words text-[11px] leading-5 text-red-200", children: conversation.error }),
|
|
12722
|
+
piProviders.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-2 text-[11px] leading-5 text-muted-foreground", children: "Configure a Provider with Responses, Chat, or Anthropic URL to enable Pi Agent." }),
|
|
12723
|
+
logCount === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-2 text-[11px] leading-5 text-muted-foreground", children: "No logs are visible in this scope yet; Pi Agent can still answer Provider setup questions." })
|
|
12724
|
+
] });
|
|
12725
|
+
}
|
|
12726
|
+
function computeCacheTrends(groups) {
|
|
12727
|
+
const result = /* @__PURE__ */ new Map();
|
|
12728
|
+
for (const group of groups) {
|
|
12729
|
+
const logs = group.logs;
|
|
12730
|
+
for (let i = 1; i < logs.length; i++) {
|
|
12731
|
+
const prev = logs[i - 1];
|
|
12732
|
+
const curr = logs[i];
|
|
12733
|
+
if (prev === void 0 || curr === void 0) continue;
|
|
12734
|
+
result.set(curr.id, {
|
|
12735
|
+
creation: compareField(prev.cacheCreationInputTokens, curr.cacheCreationInputTokens),
|
|
12736
|
+
read: compareField(prev.cacheReadInputTokens, curr.cacheReadInputTokens)
|
|
12737
|
+
});
|
|
12738
|
+
}
|
|
12739
|
+
}
|
|
12740
|
+
return result;
|
|
12741
|
+
}
|
|
12742
|
+
function compareField(previous, current) {
|
|
12743
|
+
if (current === null) return null;
|
|
12744
|
+
if (previous === null) return null;
|
|
12745
|
+
if (current > previous) return { direction: "up", delta: current - previous };
|
|
12746
|
+
if (current < previous) return { direction: "down", delta: previous - current };
|
|
12747
|
+
return null;
|
|
12748
|
+
}
|
|
12749
|
+
function formatLastSuccess(lastSuccessAt) {
|
|
12750
|
+
if (lastSuccessAt === null) return null;
|
|
12751
|
+
return new Date(lastSuccessAt).toLocaleTimeString([], {
|
|
12752
|
+
hour: "2-digit",
|
|
12753
|
+
minute: "2-digit",
|
|
12754
|
+
second: "2-digit"
|
|
12755
|
+
});
|
|
12756
|
+
}
|
|
12757
|
+
function buildDescription(state, message, hasLogs) {
|
|
12758
|
+
const lastSuccess = formatLastSuccess(state.lastSuccessAt);
|
|
12759
|
+
const retry = state.retryCount > 0 ? ` Retry ${state.retryCount.toString()}.` : "";
|
|
12760
|
+
const retained = hasLogs ? " Captured logs remain visible." : "";
|
|
12761
|
+
const lastUpdate = lastSuccess === null ? "" : ` Last update ${lastSuccess}.`;
|
|
12762
|
+
return `${message}${lastUpdate}${retry}${retained}`;
|
|
12763
|
+
}
|
|
12764
|
+
function presentationForStatus(status, state, hasLogs) {
|
|
12765
|
+
switch (status) {
|
|
12766
|
+
case "connecting":
|
|
12767
|
+
return {
|
|
12768
|
+
label: "Connecting",
|
|
12769
|
+
description: buildDescription(state, "Waiting for the first live update.", hasLogs),
|
|
12770
|
+
toneClass: "border-cyan-400/20 bg-cyan-500/8 text-cyan-100",
|
|
12771
|
+
dotClass: "bg-cyan-300 animate-pulse motion-reduce:animate-none",
|
|
12772
|
+
canRetry: false,
|
|
12773
|
+
canStop: false
|
|
12774
|
+
};
|
|
12775
|
+
case "live":
|
|
12776
|
+
return {
|
|
12777
|
+
label: "Live",
|
|
12778
|
+
description: buildDescription(state, "Live updates are current.", hasLogs),
|
|
12779
|
+
toneClass: "border-emerald-400/20 bg-emerald-500/8 text-emerald-100",
|
|
12780
|
+
dotClass: "bg-emerald-300",
|
|
12781
|
+
canRetry: false,
|
|
12782
|
+
canStop: false
|
|
12783
|
+
};
|
|
12784
|
+
case "reconnecting":
|
|
12785
|
+
return {
|
|
12786
|
+
label: "Reconnecting",
|
|
12787
|
+
description: buildDescription(state, "Live updates were interrupted.", hasLogs),
|
|
12788
|
+
toneClass: "border-amber-400/20 bg-amber-500/8 text-amber-100",
|
|
12789
|
+
dotClass: "bg-amber-300 animate-pulse motion-reduce:animate-none",
|
|
12790
|
+
canRetry: true,
|
|
12791
|
+
canStop: true
|
|
12792
|
+
};
|
|
12793
|
+
case "stale":
|
|
12794
|
+
return {
|
|
12795
|
+
label: "Stale data",
|
|
12796
|
+
description: buildDescription(state, "Live updates have not resumed.", hasLogs),
|
|
12797
|
+
toneClass: "border-orange-400/25 bg-orange-500/10 text-orange-100",
|
|
12798
|
+
dotClass: "bg-orange-300",
|
|
12799
|
+
canRetry: true,
|
|
12800
|
+
canStop: true
|
|
12801
|
+
};
|
|
12802
|
+
case "offline":
|
|
12803
|
+
return {
|
|
12804
|
+
label: "Offline",
|
|
12805
|
+
description: buildDescription(
|
|
12806
|
+
state,
|
|
12807
|
+
state.errorMessage ?? "Live updates are paused.",
|
|
12808
|
+
hasLogs
|
|
12809
|
+
),
|
|
12810
|
+
toneClass: "border-slate-400/20 bg-slate-500/10 text-slate-200",
|
|
12811
|
+
dotClass: "bg-slate-400",
|
|
12812
|
+
canRetry: true,
|
|
12813
|
+
canStop: false
|
|
12814
|
+
};
|
|
12815
|
+
case "error":
|
|
12816
|
+
return {
|
|
12817
|
+
label: "Connection error",
|
|
12818
|
+
description: buildDescription(
|
|
12819
|
+
state,
|
|
12820
|
+
state.errorMessage ?? "The live stream reported a recoverable error.",
|
|
12821
|
+
hasLogs
|
|
12822
|
+
),
|
|
12823
|
+
toneClass: "border-red-400/25 bg-red-500/10 text-red-100",
|
|
12824
|
+
dotClass: "bg-red-300",
|
|
12825
|
+
canRetry: true,
|
|
12826
|
+
canStop: true
|
|
12827
|
+
};
|
|
12828
|
+
}
|
|
12829
|
+
}
|
|
12830
|
+
function LiveConnectionBadge({ state }) {
|
|
12831
|
+
const presentation = presentationForStatus(state.status, state, false);
|
|
12832
|
+
const lastSuccess = formatLastSuccess(state.lastSuccessAt);
|
|
12833
|
+
const retryLabel = state.retryCount > 0 ? `Retry ${state.retryCount.toString()}` : null;
|
|
12834
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
12835
|
+
"span",
|
|
12836
|
+
{
|
|
12837
|
+
role: "status",
|
|
12838
|
+
"aria-label": presentation.description,
|
|
12839
|
+
"data-connection-state": state.status,
|
|
12840
|
+
className: cn(
|
|
12841
|
+
"inline-flex h-7 max-w-full items-center gap-1.5 rounded-full border px-2.5 text-xs font-medium",
|
|
12842
|
+
presentation.toneClass
|
|
12843
|
+
),
|
|
12844
|
+
children: [
|
|
12845
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn("size-1.5 shrink-0 rounded-full", presentation.dotClass) }),
|
|
12846
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0", children: presentation.label }),
|
|
12847
|
+
retryLabel !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "hidden truncate text-current/70 sm:inline", children: retryLabel }),
|
|
12848
|
+
lastSuccess !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "hidden truncate font-mono text-[10px] text-current/65 md:inline", children: [
|
|
12849
|
+
"Last ",
|
|
12850
|
+
lastSuccess
|
|
12851
|
+
] })
|
|
12852
|
+
]
|
|
12853
|
+
}
|
|
12854
|
+
);
|
|
12855
|
+
}
|
|
12856
|
+
function LiveConnectionStatus({
|
|
12857
|
+
state,
|
|
12858
|
+
hasLogs,
|
|
12859
|
+
onRetry,
|
|
12860
|
+
onStop
|
|
12861
|
+
}) {
|
|
12862
|
+
const presentation = presentationForStatus(state.status, state, hasLogs);
|
|
12863
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
12864
|
+
"div",
|
|
12865
|
+
{
|
|
12866
|
+
role: "status",
|
|
12867
|
+
"aria-live": "polite",
|
|
12868
|
+
"data-connection-state": state.status,
|
|
12869
|
+
className: cn(
|
|
12870
|
+
"mt-2 flex flex-wrap items-center gap-x-3 gap-y-2 rounded-md border px-3 py-2 text-xs",
|
|
12871
|
+
presentation.toneClass
|
|
12872
|
+
),
|
|
12873
|
+
children: [
|
|
12874
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
|
|
12875
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn("size-2 shrink-0 rounded-full", presentation.dotClass) }),
|
|
12876
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0 font-semibold", children: presentation.label }),
|
|
12877
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0 text-current/75", children: presentation.description })
|
|
12878
|
+
] }),
|
|
12879
|
+
(presentation.canRetry || presentation.canStop) && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex shrink-0 items-center gap-1.5", children: [
|
|
12880
|
+
presentation.canRetry && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
12881
|
+
"button",
|
|
12882
|
+
{
|
|
12883
|
+
type: "button",
|
|
12884
|
+
onClick: onRetry,
|
|
12885
|
+
className: "inline-flex h-7 items-center gap-1 rounded-md bg-black/15 px-2 font-medium transition-colors hover:bg-black/25 focus-visible:ring-1 focus-visible:ring-current focus-visible:outline-none",
|
|
12886
|
+
children: [
|
|
12887
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: "size-3" }),
|
|
12888
|
+
"Retry now"
|
|
12889
|
+
]
|
|
12890
|
+
}
|
|
12891
|
+
),
|
|
12892
|
+
presentation.canStop && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
12893
|
+
"button",
|
|
12894
|
+
{
|
|
12895
|
+
type: "button",
|
|
12896
|
+
onClick: onStop,
|
|
12897
|
+
className: "inline-flex h-7 items-center gap-1 rounded-md px-2 text-current/70 transition-colors hover:bg-black/15 hover:text-current focus-visible:ring-1 focus-visible:ring-current focus-visible:outline-none",
|
|
12898
|
+
children: [
|
|
12899
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(CircleStop, { className: "size-3" }),
|
|
12900
|
+
"Stop retrying"
|
|
12901
|
+
]
|
|
12902
|
+
}
|
|
12903
|
+
)
|
|
12904
|
+
] })
|
|
12905
|
+
]
|
|
12906
|
+
}
|
|
12907
|
+
);
|
|
12908
|
+
}
|
|
12909
|
+
function ApplicationBar({
|
|
12910
|
+
liveConnection,
|
|
12911
|
+
alertsAction,
|
|
12912
|
+
settingsAction
|
|
12913
|
+
}) {
|
|
12914
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
12915
|
+
"header",
|
|
12916
|
+
{
|
|
12917
|
+
"data-application-bar": "true",
|
|
12918
|
+
className: "border-border/70 bg-background/95 sticky top-0 z-50 shrink-0 border-b px-3 py-2 shadow-[0_10px_30px_rgba(0,0,0,0.14)] backdrop-blur lg:px-4",
|
|
12919
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid min-w-0 grid-cols-[minmax(0,1fr)_auto] items-center gap-x-3 gap-y-2 sm:grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)]", children: [
|
|
12920
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
12921
|
+
"a",
|
|
12922
|
+
{
|
|
12923
|
+
href: "/",
|
|
12924
|
+
"aria-label": "Agent Inspector home",
|
|
12925
|
+
className: "flex min-w-0 items-center gap-2 rounded-md focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none",
|
|
12926
|
+
children: [
|
|
12927
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(CrabLogo, { className: "size-7 shrink-0 text-amber-500" }),
|
|
12928
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "min-w-0", children: [
|
|
12929
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "block truncate text-sm font-bold leading-4", children: "Agent Inspector" }),
|
|
12930
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "hidden truncate text-[10px] font-medium text-muted-foreground md:block", children: "Local First. Evidence First." })
|
|
12931
|
+
] }),
|
|
12932
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "hidden shrink-0 font-mono text-[10px] text-muted-foreground lg:inline", children: [
|
|
12933
|
+
"v",
|
|
12934
|
+
packageJson.version
|
|
12935
|
+
] })
|
|
12936
|
+
]
|
|
12937
|
+
}
|
|
12938
|
+
),
|
|
12939
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "order-3 col-span-2 flex min-w-0 justify-start sm:order-2 sm:col-span-1 sm:justify-center", children: liveConnection === void 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
12940
|
+
"span",
|
|
12941
|
+
{
|
|
12942
|
+
"data-connection-state": "stored",
|
|
12943
|
+
className: "border-border/70 bg-muted/50 inline-flex h-7 max-w-full items-center gap-1.5 rounded-full border px-2.5 text-xs font-medium text-muted-foreground",
|
|
12944
|
+
children: [
|
|
12945
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "size-1.5 shrink-0 rounded-full bg-slate-400" }),
|
|
12946
|
+
"Stored session"
|
|
12947
|
+
]
|
|
12948
|
+
}
|
|
12949
|
+
) : /* @__PURE__ */ jsxRuntimeExports.jsx(LiveConnectionBadge, { state: liveConnection }) }),
|
|
12950
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
12951
|
+
"nav",
|
|
12952
|
+
{
|
|
12953
|
+
"aria-label": "Application actions",
|
|
12954
|
+
className: "order-2 flex shrink-0 items-center justify-end gap-1 sm:order-3",
|
|
12955
|
+
children: [
|
|
12956
|
+
alertsAction,
|
|
12957
|
+
settingsAction
|
|
12958
|
+
]
|
|
12959
|
+
}
|
|
12960
|
+
)
|
|
12961
|
+
] })
|
|
12962
|
+
}
|
|
12963
|
+
);
|
|
12964
|
+
}
|
|
12965
|
+
function formatDurationSeconds(ms) {
|
|
12966
|
+
return `${Math.max(0, Math.ceil(ms / 1e3)).toString()}s`;
|
|
12967
|
+
}
|
|
12968
|
+
function SessionLoadProgressBar({
|
|
12969
|
+
progress
|
|
12970
|
+
}) {
|
|
12971
|
+
const elapsedRatio = Math.min(1, progress.elapsedMs / progress.timeoutMs);
|
|
12972
|
+
const percent = Math.max(4, Math.round(elapsedRatio * 100));
|
|
12973
|
+
const remainingMs = Math.max(0, progress.timeoutMs - progress.elapsedMs);
|
|
12974
|
+
const nearTimeout = elapsedRatio >= 0.75;
|
|
12975
|
+
const details = [
|
|
12976
|
+
progress.loadedLogs > 0 ? `${progress.loadedLogs.toString()} logs` : null,
|
|
12977
|
+
progress.loadedPages > 0 ? `${progress.loadedPages.toString()} page${progress.loadedPages === 1 ? "" : "s"}` : null,
|
|
12978
|
+
`${formatDurationSeconds(remainingMs)} before timeout`
|
|
12979
|
+
].filter((item) => item !== null);
|
|
12980
|
+
const valueText = `${progress.label}: ${details.join(", ")}`;
|
|
12981
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 space-y-1 px-1 pb-1", children: [
|
|
12982
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center justify-between gap-3 font-mono text-[10px] text-muted-foreground", children: [
|
|
12983
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0 truncate", children: progress.label }),
|
|
12984
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn("shrink-0 tabular-nums", nearTimeout && "text-amber-300"), children: details.join(" / ") })
|
|
12985
|
+
] }),
|
|
13255
12986
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
13256
|
-
"
|
|
13257
|
-
{
|
|
13258
|
-
value: question,
|
|
13259
|
-
onChange: handleQuestionChange,
|
|
13260
|
-
className: "mt-2 min-h-24 w-full resize-y rounded-md bg-black/25 px-3 py-2 text-xs leading-5 text-foreground outline-none shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors placeholder:text-muted-foreground focus-visible:ring-1 focus-visible:ring-ring",
|
|
13261
|
-
placeholder: "Ask Pi Agent about this session..."
|
|
13262
|
-
}
|
|
13263
|
-
),
|
|
13264
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
13265
|
-
"button",
|
|
12987
|
+
"div",
|
|
13266
12988
|
{
|
|
13267
|
-
|
|
13268
|
-
|
|
13269
|
-
|
|
13270
|
-
|
|
13271
|
-
|
|
13272
|
-
|
|
13273
|
-
|
|
13274
|
-
|
|
12989
|
+
role: "progressbar",
|
|
12990
|
+
"aria-label": progress.label,
|
|
12991
|
+
"aria-valuemin": 0,
|
|
12992
|
+
"aria-valuemax": progress.timeoutMs,
|
|
12993
|
+
"aria-valuenow": Math.min(progress.elapsedMs, progress.timeoutMs),
|
|
12994
|
+
"aria-valuetext": valueText,
|
|
12995
|
+
className: "h-1.5 overflow-hidden rounded-full bg-white/[0.06]",
|
|
12996
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
12997
|
+
"div",
|
|
12998
|
+
{
|
|
12999
|
+
className: cn(
|
|
13000
|
+
"h-full rounded-full transition-all duration-300 motion-reduce:transition-none",
|
|
13001
|
+
nearTimeout ? "bg-amber-300/80" : "bg-cyan-300/70"
|
|
13002
|
+
),
|
|
13003
|
+
style: { width: `${percent.toString()}%` }
|
|
13004
|
+
}
|
|
13005
|
+
)
|
|
13275
13006
|
}
|
|
13276
|
-
)
|
|
13277
|
-
piProviders.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-2 text-[11px] leading-5 text-muted-foreground", children: "Configure a Provider with Responses, Chat, or Anthropic URL to enable Pi Agent." }),
|
|
13278
|
-
status !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-2 break-words font-mono text-[10px] text-cyan-100/70", children: status }),
|
|
13279
|
-
answer !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-3 max-h-64 overflow-y-auto whitespace-pre-wrap rounded-md bg-black/25 p-3 text-xs leading-5 text-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.05)]", children: answer }),
|
|
13280
|
-
logCount === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-2 text-[11px] leading-5 text-muted-foreground", children: "No logs are visible in this scope yet; Pi Agent can still answer Provider setup questions." })
|
|
13007
|
+
)
|
|
13281
13008
|
] });
|
|
13282
13009
|
}
|
|
13283
|
-
function
|
|
13284
|
-
|
|
13285
|
-
|
|
13286
|
-
|
|
13287
|
-
|
|
13288
|
-
|
|
13289
|
-
|
|
13290
|
-
|
|
13291
|
-
|
|
13292
|
-
|
|
13293
|
-
|
|
13294
|
-
|
|
13010
|
+
function preferredScrollBehavior(reducedMotion) {
|
|
13011
|
+
return reducedMotion ? "auto" : "smooth";
|
|
13012
|
+
}
|
|
13013
|
+
function browserPrefersReducedMotion() {
|
|
13014
|
+
if (typeof window === "undefined") return false;
|
|
13015
|
+
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
13016
|
+
}
|
|
13017
|
+
function createInitialLiveConnectionState() {
|
|
13018
|
+
return {
|
|
13019
|
+
status: "connecting",
|
|
13020
|
+
lastSuccessAt: null,
|
|
13021
|
+
retryCount: 0,
|
|
13022
|
+
errorMessage: null
|
|
13023
|
+
};
|
|
13024
|
+
}
|
|
13025
|
+
function reduceLiveConnectionState(state, event) {
|
|
13026
|
+
switch (event.type) {
|
|
13027
|
+
case "connect-requested":
|
|
13028
|
+
return {
|
|
13029
|
+
...state,
|
|
13030
|
+
status: state.lastSuccessAt === null ? "connecting" : state.status === "stale" ? "stale" : "reconnecting",
|
|
13031
|
+
errorMessage: null
|
|
13032
|
+
};
|
|
13033
|
+
case "message-received":
|
|
13034
|
+
return {
|
|
13035
|
+
status: "live",
|
|
13036
|
+
lastSuccessAt: event.at,
|
|
13037
|
+
retryCount: 0,
|
|
13038
|
+
errorMessage: null
|
|
13039
|
+
};
|
|
13040
|
+
case "connection-lost": {
|
|
13041
|
+
const retryCount = state.retryCount + 1;
|
|
13042
|
+
if (!event.online) {
|
|
13043
|
+
return {
|
|
13044
|
+
...state,
|
|
13045
|
+
status: "offline",
|
|
13046
|
+
retryCount,
|
|
13047
|
+
errorMessage: "Browser is offline."
|
|
13048
|
+
};
|
|
13049
|
+
}
|
|
13050
|
+
return {
|
|
13051
|
+
...state,
|
|
13052
|
+
status: state.lastSuccessAt === null ? "error" : "reconnecting",
|
|
13053
|
+
retryCount,
|
|
13054
|
+
errorMessage: event.message
|
|
13055
|
+
};
|
|
13295
13056
|
}
|
|
13057
|
+
case "stale-timeout":
|
|
13058
|
+
if (state.lastSuccessAt === null || state.status === "live" || state.status === "offline") {
|
|
13059
|
+
return state;
|
|
13060
|
+
}
|
|
13061
|
+
return { ...state, status: "stale" };
|
|
13062
|
+
case "browser-offline":
|
|
13063
|
+
return {
|
|
13064
|
+
...state,
|
|
13065
|
+
status: "offline",
|
|
13066
|
+
errorMessage: "Browser is offline."
|
|
13067
|
+
};
|
|
13068
|
+
case "stop-retrying":
|
|
13069
|
+
return {
|
|
13070
|
+
...state,
|
|
13071
|
+
status: "offline",
|
|
13072
|
+
errorMessage: "Automatic live updates are paused."
|
|
13073
|
+
};
|
|
13074
|
+
case "recoverable-error":
|
|
13075
|
+
return {
|
|
13076
|
+
...state,
|
|
13077
|
+
status: "error",
|
|
13078
|
+
errorMessage: event.message
|
|
13079
|
+
};
|
|
13296
13080
|
}
|
|
13297
|
-
return result;
|
|
13298
13081
|
}
|
|
13299
|
-
function
|
|
13300
|
-
if (
|
|
13301
|
-
|
|
13302
|
-
|
|
13303
|
-
|
|
13304
|
-
|
|
13082
|
+
function resolveLiveEmptyState(state) {
|
|
13083
|
+
if (state === void 0 || state.status === "live") return "empty";
|
|
13084
|
+
return state.status;
|
|
13085
|
+
}
|
|
13086
|
+
function getLiveEmptyStateCopy(state) {
|
|
13087
|
+
switch (state) {
|
|
13088
|
+
case "connecting":
|
|
13089
|
+
return {
|
|
13090
|
+
title: "Connecting to the live stream...",
|
|
13091
|
+
description: "Waiting for the first successful initialization before checking for logs.",
|
|
13092
|
+
showConnectionCommands: false
|
|
13093
|
+
};
|
|
13094
|
+
case "empty":
|
|
13095
|
+
return {
|
|
13096
|
+
title: "No logs captured yet.",
|
|
13097
|
+
description: "Connect an AI coding tool to capture its first request.",
|
|
13098
|
+
showConnectionCommands: true
|
|
13099
|
+
};
|
|
13100
|
+
case "reconnecting":
|
|
13101
|
+
return {
|
|
13102
|
+
title: "Reconnecting to live updates...",
|
|
13103
|
+
description: "The stream was interrupted. Agent Inspector is retrying automatically.",
|
|
13104
|
+
showConnectionCommands: false
|
|
13105
|
+
};
|
|
13106
|
+
case "stale":
|
|
13107
|
+
return {
|
|
13108
|
+
title: "Live data is stale.",
|
|
13109
|
+
description: "No logs are hidden; retry the connection to resume live updates.",
|
|
13110
|
+
showConnectionCommands: false
|
|
13111
|
+
};
|
|
13112
|
+
case "offline":
|
|
13113
|
+
return {
|
|
13114
|
+
title: "Live updates are offline.",
|
|
13115
|
+
description: "Check the browser and Inspector connection, then retry.",
|
|
13116
|
+
showConnectionCommands: false
|
|
13117
|
+
};
|
|
13118
|
+
case "error":
|
|
13119
|
+
return {
|
|
13120
|
+
title: "Live updates could not initialize.",
|
|
13121
|
+
description: "The error is recoverable. Retry without reloading the page.",
|
|
13122
|
+
showConnectionCommands: false
|
|
13123
|
+
};
|
|
13124
|
+
}
|
|
13305
13125
|
}
|
|
13306
13126
|
const COLLAPSED_CLIENTS_STORAGE_KEY = "agent-inspector.hierarchy.collapsedClients";
|
|
13307
13127
|
const COLLAPSED_PROCESSES_STORAGE_KEY = "agent-inspector.hierarchy.collapsedProcesses";
|
|
@@ -13782,6 +13602,61 @@ function ProcessGroupSection({
|
|
|
13782
13602
|
)) })
|
|
13783
13603
|
] });
|
|
13784
13604
|
}
|
|
13605
|
+
const RAW_EXPORT_DIALOG_CLASS_NAME = "w-[calc(100%-1rem)] border-warning/30 bg-popover text-popover-foreground sm:max-w-lg";
|
|
13606
|
+
const RAW_EXPORT_RISK_ITEMS = [
|
|
13607
|
+
{
|
|
13608
|
+
label: "Headers",
|
|
13609
|
+
detail: "request and response headers, including authorization or cookie values"
|
|
13610
|
+
},
|
|
13611
|
+
{
|
|
13612
|
+
label: "Prompts",
|
|
13613
|
+
detail: "system instructions, user prompts, model responses, and conversation history"
|
|
13614
|
+
},
|
|
13615
|
+
{
|
|
13616
|
+
label: "Source content",
|
|
13617
|
+
detail: "source code, file contents, tool inputs, and tool output"
|
|
13618
|
+
},
|
|
13619
|
+
{
|
|
13620
|
+
label: "Secrets",
|
|
13621
|
+
detail: "API keys, access tokens, credentials, and other sensitive values"
|
|
13622
|
+
}
|
|
13623
|
+
];
|
|
13624
|
+
function RawExportWarning({
|
|
13625
|
+
onCancel,
|
|
13626
|
+
onExportRedacted,
|
|
13627
|
+
onConfirmRaw
|
|
13628
|
+
}) {
|
|
13629
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
13630
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(DialogHeader, { children: [
|
|
13631
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(DialogTitle, { children: "Export unredacted logs?" }),
|
|
13632
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(DialogDescription, { children: "Raw exports bypass Agent Inspector redaction and may expose sensitive captured data." })
|
|
13633
|
+
] }),
|
|
13634
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
13635
|
+
"div",
|
|
13636
|
+
{
|
|
13637
|
+
role: "alert",
|
|
13638
|
+
className: "rounded-md border border-warning/35 bg-warning/10 px-3 py-3 text-sm text-foreground",
|
|
13639
|
+
children: [
|
|
13640
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "font-medium", children: "The raw archive may include:" }),
|
|
13641
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("ul", { className: "mt-2 list-disc space-y-1 pl-5 text-xs leading-relaxed text-muted-foreground", children: RAW_EXPORT_RISK_ITEMS.map((item) => /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { children: [
|
|
13642
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-semibold text-foreground", children: [
|
|
13643
|
+
item.label,
|
|
13644
|
+
":"
|
|
13645
|
+
] }),
|
|
13646
|
+
" ",
|
|
13647
|
+
item.detail
|
|
13648
|
+
] }, item.label)) }),
|
|
13649
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-3 text-xs leading-relaxed text-muted-foreground", children: "Only continue if you trust where this file will be stored and everyone it may be shared with." })
|
|
13650
|
+
]
|
|
13651
|
+
}
|
|
13652
|
+
),
|
|
13653
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", children: [
|
|
13654
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: onCancel, children: "Cancel" }),
|
|
13655
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: onExportRedacted, children: "Export redacted instead" }),
|
|
13656
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Button, { type: "button", variant: "destructive", size: "sm", onClick: onConfirmRaw, children: "Export raw data" })
|
|
13657
|
+
] })
|
|
13658
|
+
] });
|
|
13659
|
+
}
|
|
13785
13660
|
const NAV_ATTR = "data-nav-id";
|
|
13786
13661
|
const NAV_ACTION_ATTR = "data-nav-action";
|
|
13787
13662
|
function findNavItems(container) {
|
|
@@ -15209,7 +15084,7 @@ function LogPaginationButton({
|
|
|
15209
15084
|
type: "button",
|
|
15210
15085
|
onClick,
|
|
15211
15086
|
disabled,
|
|
15212
|
-
className: "border border-input bg-background hover:bg-accent hover:text-accent-foreground inline-flex h-8 items-center gap-1.5 rounded-md px-2.5 text-xs text-muted-foreground transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-45",
|
|
15087
|
+
className: "border border-input bg-background hover:bg-accent hover:text-accent-foreground inline-flex h-8 items-center gap-1.5 rounded-md px-2.5 text-xs text-muted-foreground transition-colors hover:text-foreground focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-45",
|
|
15213
15088
|
title,
|
|
15214
15089
|
children: [
|
|
15215
15090
|
icon,
|
|
@@ -15218,36 +15093,6 @@ function LogPaginationButton({
|
|
|
15218
15093
|
}
|
|
15219
15094
|
);
|
|
15220
15095
|
}
|
|
15221
|
-
function formatDurationSeconds(ms) {
|
|
15222
|
-
return `${Math.max(0, Math.ceil(ms / 1e3)).toString()}s`;
|
|
15223
|
-
}
|
|
15224
|
-
function SessionLoadProgressBar({ progress }) {
|
|
15225
|
-
const elapsedRatio = Math.min(1, progress.elapsedMs / progress.timeoutMs);
|
|
15226
|
-
const percent = Math.max(4, Math.round(elapsedRatio * 100));
|
|
15227
|
-
const remainingMs = Math.max(0, progress.timeoutMs - progress.elapsedMs);
|
|
15228
|
-
const nearTimeout = elapsedRatio >= 0.75;
|
|
15229
|
-
const details = [
|
|
15230
|
-
progress.loadedLogs > 0 ? `${progress.loadedLogs.toString()} logs` : null,
|
|
15231
|
-
progress.loadedPages > 0 ? `${progress.loadedPages.toString()} page${progress.loadedPages === 1 ? "" : "s"}` : null,
|
|
15232
|
-
`${formatDurationSeconds(remainingMs)} before timeout`
|
|
15233
|
-
].filter((item) => item !== null);
|
|
15234
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 space-y-1 px-1 pb-1", children: [
|
|
15235
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center justify-between gap-3 font-mono text-[10px] text-muted-foreground", children: [
|
|
15236
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0 truncate", children: progress.label }),
|
|
15237
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn("shrink-0 tabular-nums", nearTimeout && "text-amber-300"), children: details.join(" / ") })
|
|
15238
|
-
] }),
|
|
15239
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-1.5 overflow-hidden rounded-full bg-white/[0.06]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
15240
|
-
"div",
|
|
15241
|
-
{
|
|
15242
|
-
className: cn(
|
|
15243
|
-
"h-full rounded-full transition-all duration-300",
|
|
15244
|
-
nearTimeout ? "bg-amber-300/80" : "bg-cyan-300/70"
|
|
15245
|
-
),
|
|
15246
|
-
style: { width: `${percent.toString()}%` }
|
|
15247
|
-
}
|
|
15248
|
-
) })
|
|
15249
|
-
] });
|
|
15250
|
-
}
|
|
15251
15096
|
function LogPaginationBar({
|
|
15252
15097
|
logs,
|
|
15253
15098
|
pagination,
|
|
@@ -15256,16 +15101,19 @@ function LogPaginationBar({
|
|
|
15256
15101
|
if (pagination === void 0) return null;
|
|
15257
15102
|
const disabled = pagination.isLoading;
|
|
15258
15103
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
15259
|
-
"
|
|
15104
|
+
"nav",
|
|
15260
15105
|
{
|
|
15106
|
+
"aria-label": "Session log pagination",
|
|
15261
15107
|
className: cn(
|
|
15262
15108
|
"flex min-h-9 flex-col gap-2 px-1 py-1 sm:flex-row sm:items-center",
|
|
15263
15109
|
embedded ? "border-t border-white/10 pt-2" : "border border-border bg-card shadow-sm mb-3 rounded-[8px] px-2"
|
|
15264
15110
|
),
|
|
15265
15111
|
children: [
|
|
15266
15112
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full min-w-0 px-1 font-mono text-[11px] text-muted-foreground sm:flex-1", children: [
|
|
15267
|
-
|
|
15268
|
-
|
|
15113
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { role: "status", "aria-live": "polite", "aria-atomic": "true", children: [
|
|
15114
|
+
formatPaginationStatus({ logs, pagination }),
|
|
15115
|
+
pagination.isLoading && logs.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ml-2", children: "Loading..." })
|
|
15116
|
+
] }),
|
|
15269
15117
|
pagination.loadProgress !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(SessionLoadProgressBar, { progress: pagination.loadProgress })
|
|
15270
15118
|
] }),
|
|
15271
15119
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex w-full items-center gap-1 overflow-x-auto sm:w-auto", children: [
|
|
@@ -15363,7 +15211,10 @@ function highlightLogTarget(target) {
|
|
|
15363
15211
|
function focusLogTarget(logId) {
|
|
15364
15212
|
const target = document.getElementById(`log-${String(logId)}`);
|
|
15365
15213
|
if (!(target instanceof HTMLElement)) return false;
|
|
15366
|
-
target.scrollIntoView({
|
|
15214
|
+
target.scrollIntoView({
|
|
15215
|
+
block: "center",
|
|
15216
|
+
behavior: preferredScrollBehavior(browserPrefersReducedMotion())
|
|
15217
|
+
});
|
|
15367
15218
|
target.focus({ preventScroll: true });
|
|
15368
15219
|
highlightLogTarget(target);
|
|
15369
15220
|
return true;
|
|
@@ -15390,14 +15241,14 @@ function CopyableCommand({ command }) {
|
|
|
15390
15241
|
setTimeout(() => setCopied(false), 2e3);
|
|
15391
15242
|
});
|
|
15392
15243
|
}, [command]);
|
|
15393
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", {
|
|
15394
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className:
|
|
15244
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { "data-command-example": "true", className: COPYABLE_COMMAND_CONTAINER_CLASS_NAME, children: [
|
|
15245
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: COPYABLE_COMMAND_TEXT_CLASS_NAME, children: command }),
|
|
15395
15246
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
15396
15247
|
"button",
|
|
15397
15248
|
{
|
|
15398
15249
|
type: "button",
|
|
15399
15250
|
onClick: handleCopy,
|
|
15400
|
-
className: "shrink-0 cursor-pointer text-muted-foreground transition-colors hover:text-foreground",
|
|
15251
|
+
className: "shrink-0 cursor-pointer rounded-sm text-muted-foreground transition-colors hover:text-foreground focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none",
|
|
15401
15252
|
"aria-label": "Copy command",
|
|
15402
15253
|
children: copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-4" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-4" })
|
|
15403
15254
|
}
|
|
@@ -15429,46 +15280,6 @@ function SidebarMetric({ label, value }) {
|
|
|
15429
15280
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-0.5 truncate font-mono text-[10px] uppercase tracking-[0.12em] text-white/35", children: label })
|
|
15430
15281
|
] });
|
|
15431
15282
|
}
|
|
15432
|
-
const CRAB_VARIANT_COLORS = [
|
|
15433
|
-
"text-amber-500",
|
|
15434
|
-
"text-rose-500",
|
|
15435
|
-
"text-sky-500",
|
|
15436
|
-
"text-emerald-500",
|
|
15437
|
-
"text-violet-500",
|
|
15438
|
-
"text-orange-500",
|
|
15439
|
-
"text-cyan-500",
|
|
15440
|
-
"text-pink-500",
|
|
15441
|
-
"text-lime-500",
|
|
15442
|
-
"text-blue-500",
|
|
15443
|
-
"text-yellow-500",
|
|
15444
|
-
"text-fuchsia-500"
|
|
15445
|
-
];
|
|
15446
|
-
function CrabFamily({
|
|
15447
|
-
compact,
|
|
15448
|
-
entrancePhase
|
|
15449
|
-
}) {
|
|
15450
|
-
if (compact) {
|
|
15451
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(CrabLogo, { className: "size-14 text-amber-500" });
|
|
15452
|
-
}
|
|
15453
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex shrink-0 items-end gap-1 group cursor-default", "aria-hidden": "true", children: [
|
|
15454
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(CrabLogo, { className: "size-10 text-amber-500 transition-all duration-300 group-hover:scale-125 group-hover:-translate-y-1.5" }),
|
|
15455
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "hidden items-end gap-0.5 sm:flex", children: crabVariants.map((Crab, i) => {
|
|
15456
|
-
const color = CRAB_VARIANT_COLORS[i] ?? "text-amber-500";
|
|
15457
|
-
const entranceClass = entrancePhase === "hidden" ? "opacity-0 scale-0" : entrancePhase === "playing" ? "animate-crab-piano-pop" : "";
|
|
15458
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
15459
|
-
Crab,
|
|
15460
|
-
{
|
|
15461
|
-
className: `size-5 ${color} transition-all duration-300 ease-out group-hover:scale-125 group-hover:-translate-y-1 ${entranceClass}`,
|
|
15462
|
-
style: {
|
|
15463
|
-
transitionDelay: `${i * 50}ms`,
|
|
15464
|
-
...entrancePhase === "playing" ? { animationDelay: `${i * 400}ms` } : {}
|
|
15465
|
-
}
|
|
15466
|
-
},
|
|
15467
|
-
i
|
|
15468
|
-
);
|
|
15469
|
-
}) })
|
|
15470
|
-
] });
|
|
15471
|
-
}
|
|
15472
15283
|
function ThemeModeToggle() {
|
|
15473
15284
|
const { themeMode, setThemeMode } = useThemeMode();
|
|
15474
15285
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
@@ -15484,7 +15295,7 @@ function ThemeModeToggle() {
|
|
|
15484
15295
|
type: "button",
|
|
15485
15296
|
onClick: () => setThemeMode("light"),
|
|
15486
15297
|
className: cn(
|
|
15487
|
-
"inline-flex size-7 items-center justify-center rounded-[6px] text-muted-foreground transition-colors hover:text-foreground",
|
|
15298
|
+
"inline-flex size-7 items-center justify-center rounded-[6px] text-muted-foreground transition-colors hover:text-foreground focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none",
|
|
15488
15299
|
themeMode === "light" && "bg-background text-foreground shadow-sm"
|
|
15489
15300
|
),
|
|
15490
15301
|
"aria-label": "Use light mode",
|
|
@@ -15499,7 +15310,7 @@ function ThemeModeToggle() {
|
|
|
15499
15310
|
type: "button",
|
|
15500
15311
|
onClick: () => setThemeMode("eye-care"),
|
|
15501
15312
|
className: cn(
|
|
15502
|
-
"inline-flex size-7 items-center justify-center rounded-[6px] text-muted-foreground transition-colors hover:text-foreground",
|
|
15313
|
+
"inline-flex size-7 items-center justify-center rounded-[6px] text-muted-foreground transition-colors hover:text-foreground focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none",
|
|
15503
15314
|
themeMode === "eye-care" && "bg-background text-foreground shadow-sm"
|
|
15504
15315
|
),
|
|
15505
15316
|
"aria-label": "Use eye care mode",
|
|
@@ -15514,7 +15325,7 @@ function ThemeModeToggle() {
|
|
|
15514
15325
|
type: "button",
|
|
15515
15326
|
onClick: () => setThemeMode("dark"),
|
|
15516
15327
|
className: cn(
|
|
15517
|
-
"inline-flex size-7 items-center justify-center rounded-[6px] text-muted-foreground transition-colors hover:text-foreground",
|
|
15328
|
+
"inline-flex size-7 items-center justify-center rounded-[6px] text-muted-foreground transition-colors hover:text-foreground focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none",
|
|
15518
15329
|
themeMode === "dark" && "bg-background text-foreground shadow-sm"
|
|
15519
15330
|
),
|
|
15520
15331
|
"aria-label": "Use dark mode",
|
|
@@ -15583,81 +15394,6 @@ function UiScaleControl({
|
|
|
15583
15394
|
}
|
|
15584
15395
|
);
|
|
15585
15396
|
}
|
|
15586
|
-
function BrandHeader({
|
|
15587
|
-
compact,
|
|
15588
|
-
crabEntrancePhase,
|
|
15589
|
-
currentSessionId,
|
|
15590
|
-
logCount,
|
|
15591
|
-
uiScalePreference,
|
|
15592
|
-
resolvedUiScale,
|
|
15593
|
-
onUiScaleChange
|
|
15594
|
-
}) {
|
|
15595
|
-
if (compact) {
|
|
15596
|
-
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: [
|
|
15597
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-fit items-start gap-3", children: [
|
|
15598
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(CrabFamily, { compact: true, entrancePhase: crabEntrancePhase }),
|
|
15599
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-fit", children: [
|
|
15600
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-fit flex-wrap items-baseline gap-x-2 gap-y-0.5", children: [
|
|
15601
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "whitespace-nowrap text-base font-bold", children: "Agent Inspector" }),
|
|
15602
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "hidden shrink-0 font-mono text-[11px] font-semibold text-muted-foreground sm:inline", children: [
|
|
15603
|
-
"v",
|
|
15604
|
-
packageJson.version
|
|
15605
|
-
] })
|
|
15606
|
-
] }),
|
|
15607
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "hidden text-[11px] font-semibold text-muted-foreground sm:block", children: "Local First. Evidence First." })
|
|
15608
|
-
] })
|
|
15609
|
-
] }),
|
|
15610
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [
|
|
15611
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(ThemeModeToggle, {}),
|
|
15612
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
15613
|
-
UiScaleControl,
|
|
15614
|
-
{
|
|
15615
|
-
preference: uiScalePreference,
|
|
15616
|
-
resolvedScale: resolvedUiScale,
|
|
15617
|
-
onChange: onUiScaleChange
|
|
15618
|
-
}
|
|
15619
|
-
),
|
|
15620
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(AlertsDialog, {}),
|
|
15621
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(GroupsDialog, {}),
|
|
15622
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(AgentLabDialog, { currentSessionId, logCount }),
|
|
15623
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(SettingsDialog, {})
|
|
15624
|
-
] })
|
|
15625
|
-
] }) });
|
|
15626
|
-
}
|
|
15627
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-start justify-between gap-x-4 gap-y-3 pb-6", children: [
|
|
15628
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "min-w-10 flex-1", "aria-hidden": "true" }),
|
|
15629
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("h1", { className: "flex min-w-fit flex-col items-center gap-2 text-center", children: [
|
|
15630
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex max-w-full flex-wrap items-end justify-center gap-x-2 gap-y-1", children: [
|
|
15631
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(CrabFamily, { compact: false, entrancePhase: crabEntrancePhase }),
|
|
15632
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-fit flex-wrap items-baseline justify-center gap-x-2 gap-y-0.5 pl-1", children: [
|
|
15633
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "whitespace-nowrap text-lg font-bold", children: "Agent Inspector" }),
|
|
15634
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "shrink-0 font-mono text-xs font-semibold text-muted-foreground", children: [
|
|
15635
|
-
"v",
|
|
15636
|
-
packageJson.version
|
|
15637
|
-
] })
|
|
15638
|
-
] }),
|
|
15639
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "size-4 shrink-0 text-muted-foreground/70", "aria-hidden": "true" }),
|
|
15640
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(McpLogo, { className: "size-10 shrink-0" })
|
|
15641
|
-
] }),
|
|
15642
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "max-w-full text-sm font-semibold text-muted-foreground", children: "Local First. Evidence First." })
|
|
15643
|
-
] }),
|
|
15644
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-1 justify-end gap-1", children: [
|
|
15645
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(ThemeModeToggle, {}),
|
|
15646
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
15647
|
-
UiScaleControl,
|
|
15648
|
-
{
|
|
15649
|
-
preference: uiScalePreference,
|
|
15650
|
-
resolvedScale: resolvedUiScale,
|
|
15651
|
-
onChange: onUiScaleChange
|
|
15652
|
-
}
|
|
15653
|
-
),
|
|
15654
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(AlertsDialog, {}),
|
|
15655
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(GroupsDialog, {}),
|
|
15656
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(AgentLabDialog, { currentSessionId, logCount }),
|
|
15657
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(SettingsDialog, {})
|
|
15658
|
-
] })
|
|
15659
|
-
] });
|
|
15660
|
-
}
|
|
15661
15397
|
const DETAILS_PANEL_COLLAPSED_STORAGE_KEY = "agent-inspector.detailsPanelCollapsed";
|
|
15662
15398
|
const INSPECTOR_PET_VISIBLE_STORAGE_KEY = "agent-inspector.pet.visible";
|
|
15663
15399
|
function readStoredDetailsPanelCollapsed() {
|
|
@@ -15981,8 +15717,12 @@ function ProxyViewer({
|
|
|
15981
15717
|
slowResponseThresholdSeconds,
|
|
15982
15718
|
timeDisplayFormat,
|
|
15983
15719
|
isLoading = false,
|
|
15720
|
+
liveConnection,
|
|
15721
|
+
onRetryLiveConnection,
|
|
15722
|
+
onStopLiveConnection,
|
|
15984
15723
|
pagination,
|
|
15985
15724
|
sessionLoadProgress,
|
|
15725
|
+
sessionLoadError,
|
|
15986
15726
|
sessionMemberships = [],
|
|
15987
15727
|
hideSessionFilter = false,
|
|
15988
15728
|
pinnedSessionId
|
|
@@ -15992,6 +15732,7 @@ function ProxyViewer({
|
|
|
15992
15732
|
const { uiScalePreference, resolvedUiScale, setUiScalePreference } = useUiScale();
|
|
15993
15733
|
const [exporting, setExporting] = reactExports.useState(null);
|
|
15994
15734
|
const [exportError, setExportError] = reactExports.useState(null);
|
|
15735
|
+
const [rawExportDialogOpen, setRawExportDialogOpen] = reactExports.useState(false);
|
|
15995
15736
|
const [importing, setImporting] = reactExports.useState(false);
|
|
15996
15737
|
const [importStatus, setImportStatus] = reactExports.useState(null);
|
|
15997
15738
|
const [importError, setImportError] = reactExports.useState(null);
|
|
@@ -16002,9 +15743,6 @@ function ProxyViewer({
|
|
|
16002
15743
|
const [petVisible, setPetVisible] = reactExports.useState(true);
|
|
16003
15744
|
const [petVisibilityStorageLoaded, setPetVisibilityStorageLoaded] = reactExports.useState(false);
|
|
16004
15745
|
const [comparePair, setComparePair] = reactExports.useState(null);
|
|
16005
|
-
const [crabEntrancePhase, setCrabEntrancePhase] = reactExports.useState(
|
|
16006
|
-
"hidden"
|
|
16007
|
-
);
|
|
16008
15746
|
const logListRef = reactExports.useRef(null);
|
|
16009
15747
|
const logListWrapperRef = reactExports.useRef(null);
|
|
16010
15748
|
const importInputRef = reactExports.useRef(null);
|
|
@@ -16026,17 +15764,6 @@ function ProxyViewer({
|
|
|
16026
15764
|
},
|
|
16027
15765
|
[]
|
|
16028
15766
|
);
|
|
16029
|
-
reactExports.useEffect(() => {
|
|
16030
|
-
const perCrabDuration = 400;
|
|
16031
|
-
const startDelay = 50;
|
|
16032
|
-
const playingDone = startDelay + crabVariants.length * perCrabDuration;
|
|
16033
|
-
const t1 = setTimeout(() => setCrabEntrancePhase("playing"), startDelay);
|
|
16034
|
-
const t2 = setTimeout(() => setCrabEntrancePhase("done"), playingDone);
|
|
16035
|
-
return () => {
|
|
16036
|
-
clearTimeout(t1);
|
|
16037
|
-
clearTimeout(t2);
|
|
16038
|
-
};
|
|
16039
|
-
}, []);
|
|
16040
15767
|
reactExports.useEffect(() => {
|
|
16041
15768
|
setDetailsPanelCollapsed(readStoredDetailsPanelCollapsed());
|
|
16042
15769
|
setDetailsPanelStorageLoaded(true);
|
|
@@ -16096,6 +15823,24 @@ function ProxyViewer({
|
|
|
16096
15823
|
},
|
|
16097
15824
|
[logs, onNotify]
|
|
16098
15825
|
);
|
|
15826
|
+
const handleExportRequest = reactExports.useCallback(
|
|
15827
|
+
(mode) => {
|
|
15828
|
+
if (exportRequiresConfirmation(mode)) {
|
|
15829
|
+
setRawExportDialogOpen(true);
|
|
15830
|
+
return;
|
|
15831
|
+
}
|
|
15832
|
+
void handleExport(mode);
|
|
15833
|
+
},
|
|
15834
|
+
[handleExport]
|
|
15835
|
+
);
|
|
15836
|
+
const handleExportRedactedInstead = reactExports.useCallback(() => {
|
|
15837
|
+
setRawExportDialogOpen(false);
|
|
15838
|
+
void handleExport("redacted");
|
|
15839
|
+
}, [handleExport]);
|
|
15840
|
+
const handleConfirmRawExport = reactExports.useCallback(() => {
|
|
15841
|
+
setRawExportDialogOpen(false);
|
|
15842
|
+
void handleExport("raw");
|
|
15843
|
+
}, [handleExport]);
|
|
16099
15844
|
const handleImportClick = reactExports.useCallback(() => {
|
|
16100
15845
|
importInputRef.current?.click();
|
|
16101
15846
|
}, []);
|
|
@@ -16207,6 +15952,8 @@ function ProxyViewer({
|
|
|
16207
15952
|
const sessionInputValue = selectedSession === "__all__" ? "" : selectedSession;
|
|
16208
15953
|
const sessionSelectValue = selectedSession === "__all__" || sessions.includes(selectedSession) ? selectedSession : "__typed__";
|
|
16209
15954
|
const activeScopeLabel = hasSessionContext && sessionContextScope !== null ? truncateSessionId(sessionContextScope.label) : selectedSession === "__all__" ? "All sessions" : truncateSessionId(selectedSession);
|
|
15955
|
+
const liveEmptyState = resolveLiveEmptyState(liveConnection);
|
|
15956
|
+
const liveEmptyStateCopy = getLiveEmptyStateCopy(liveEmptyState);
|
|
16210
15957
|
const slateStats = reactExports.useMemo(
|
|
16211
15958
|
() => buildSessionSlateStats({
|
|
16212
15959
|
logs,
|
|
@@ -16239,14 +15986,22 @@ function ProxyViewer({
|
|
|
16239
15986
|
[onSessionChange]
|
|
16240
15987
|
);
|
|
16241
15988
|
const labSessionId = pinnedSessionId !== void 0 ? pinnedSessionId : selectedSession === "__all__" ? null : selectedSession;
|
|
16242
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-background min-h-screen w-full text-foreground lg:h-screen lg:flex lg:flex-col lg:overflow-hidden", children: [
|
|
15989
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-background min-h-screen w-full overflow-x-clip text-foreground lg:h-screen lg:flex lg:flex-col lg:overflow-hidden", children: [
|
|
15990
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
15991
|
+
ApplicationBar,
|
|
15992
|
+
{
|
|
15993
|
+
liveConnection,
|
|
15994
|
+
alertsAction: /* @__PURE__ */ jsxRuntimeExports.jsx(AlertsDialog, {}),
|
|
15995
|
+
settingsAction: /* @__PURE__ */ jsxRuntimeExports.jsx(SettingsDialog, {})
|
|
15996
|
+
}
|
|
15997
|
+
),
|
|
16243
15998
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
16244
15999
|
"button",
|
|
16245
16000
|
{
|
|
16246
16001
|
type: "button",
|
|
16247
16002
|
onClick: toggleDetailsPanelCollapsed,
|
|
16248
16003
|
className: cn(
|
|
16249
|
-
"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",
|
|
16004
|
+
"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 motion-reduce:transition-none 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",
|
|
16250
16005
|
detailsPanelCollapsed ? "right-3" : "lg:right-[calc(21.25rem-0.875rem)] xl:right-[calc(22.5rem-0.875rem)]"
|
|
16251
16006
|
),
|
|
16252
16007
|
"aria-label": detailsPanelCollapsed ? "Show details panel" : "Hide details panel",
|
|
@@ -16257,7 +16012,7 @@ function ProxyViewer({
|
|
|
16257
16012
|
]
|
|
16258
16013
|
}
|
|
16259
16014
|
),
|
|
16260
|
-
petVisibilityStorageLoaded && petVisible && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
16015
|
+
petVisibilityStorageLoaded && petVisible && /* @__PURE__ */ jsxRuntimeExports.jsx(LazyFeatureBoundary, { feature: "Inspector Pet", children: /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntimeExports.jsx(LazyInspectorPet, { logs }) }) }),
|
|
16261
16016
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
16262
16017
|
"div",
|
|
16263
16018
|
{
|
|
@@ -16267,18 +16022,19 @@ function ProxyViewer({
|
|
|
16267
16022
|
),
|
|
16268
16023
|
children: [
|
|
16269
16024
|
!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: [
|
|
16270
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
16271
|
-
|
|
16272
|
-
|
|
16273
|
-
|
|
16274
|
-
|
|
16275
|
-
|
|
16276
|
-
|
|
16277
|
-
|
|
16278
|
-
|
|
16279
|
-
|
|
16280
|
-
}
|
|
16281
|
-
|
|
16025
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SidebarPanel, { label: "Tools", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [
|
|
16026
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ThemeModeToggle, {}),
|
|
16027
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
16028
|
+
UiScaleControl,
|
|
16029
|
+
{
|
|
16030
|
+
preference: uiScalePreference,
|
|
16031
|
+
resolvedScale: resolvedUiScale,
|
|
16032
|
+
onChange: setUiScalePreference
|
|
16033
|
+
}
|
|
16034
|
+
),
|
|
16035
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(GroupsDialog, {}),
|
|
16036
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(AgentLabDialog, { currentSessionId: labSessionId, logCount: logs.length })
|
|
16037
|
+
] }) }),
|
|
16282
16038
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(SidebarPanel, { label: "Session", children: [
|
|
16283
16039
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
16284
16040
|
/* @__PURE__ */ jsxRuntimeExports.jsx(SidebarMetric, { label: "Requests", value: logs.length }),
|
|
@@ -16346,7 +16102,7 @@ function ProxyViewer({
|
|
|
16346
16102
|
{
|
|
16347
16103
|
type: "button",
|
|
16348
16104
|
onClick: () => onSessionChange("__all__"),
|
|
16349
|
-
className: "absolute right-1.5 top-1/2 inline-flex size-6 -translate-y-1/2 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-white/[0.06] hover:text-foreground",
|
|
16105
|
+
className: "absolute right-1.5 top-1/2 inline-flex size-6 -translate-y-1/2 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-white/[0.06] hover:text-foreground focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none",
|
|
16350
16106
|
"aria-label": "Clear session filter",
|
|
16351
16107
|
title: "Clear session filter",
|
|
16352
16108
|
children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "size-3.5" })
|
|
@@ -16354,7 +16110,14 @@ function ProxyViewer({
|
|
|
16354
16110
|
)
|
|
16355
16111
|
] }),
|
|
16356
16112
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(Select, { value: sessionSelectValue, onValueChange: handleSessionSelectChange, children: [
|
|
16357
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
16113
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
16114
|
+
SelectTrigger,
|
|
16115
|
+
{
|
|
16116
|
+
"aria-label": "Select a session",
|
|
16117
|
+
className: "bg-black/25 hover:bg-white/[0.045] h-9 w-full border-0 text-xs text-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)]",
|
|
16118
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue, { placeholder: "All sessions" })
|
|
16119
|
+
}
|
|
16120
|
+
),
|
|
16358
16121
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(SelectContent, { children: [
|
|
16359
16122
|
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: "__all__", children: "All sessions" }),
|
|
16360
16123
|
sessionSelectValue === "__typed__" && /* @__PURE__ */ jsxRuntimeExports.jsxs(SelectItem, { value: "__typed__", children: [
|
|
@@ -16366,7 +16129,14 @@ function ProxyViewer({
|
|
|
16366
16129
|
] })
|
|
16367
16130
|
] }),
|
|
16368
16131
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(Select, { value: selectedModel, onValueChange: onModelChange, children: [
|
|
16369
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
16132
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
16133
|
+
SelectTrigger,
|
|
16134
|
+
{
|
|
16135
|
+
"aria-label": "Select a model",
|
|
16136
|
+
className: "bg-black/25 hover:bg-white/[0.045] h-9 w-full border-0 text-xs text-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)]",
|
|
16137
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue, { placeholder: "All models" })
|
|
16138
|
+
}
|
|
16139
|
+
),
|
|
16370
16140
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(SelectContent, { children: [
|
|
16371
16141
|
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: "__all__", children: "All models" }),
|
|
16372
16142
|
models.map((m) => /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: m, children: m }, m))
|
|
@@ -16399,7 +16169,7 @@ function ProxyViewer({
|
|
|
16399
16169
|
type: "button",
|
|
16400
16170
|
onClick: handleImportClick,
|
|
16401
16171
|
disabled: importing,
|
|
16402
|
-
className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
|
16172
|
+
className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
|
|
16403
16173
|
title: "Import Agent Inspector export",
|
|
16404
16174
|
children: importing ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Importing..." }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
16405
16175
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Upload, { className: "size-3.5" }),
|
|
@@ -16413,10 +16183,10 @@ function ProxyViewer({
|
|
|
16413
16183
|
{
|
|
16414
16184
|
type: "button",
|
|
16415
16185
|
onClick: () => {
|
|
16416
|
-
|
|
16186
|
+
handleExportRequest("redacted");
|
|
16417
16187
|
},
|
|
16418
16188
|
disabled: exporting !== null,
|
|
16419
|
-
className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
|
16189
|
+
className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
|
|
16420
16190
|
title: "Export redacted logs as JSON ZIP",
|
|
16421
16191
|
children: exporting === "redacted" ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Exporting..." }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
16422
16192
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Download, { className: "size-3.5" }),
|
|
@@ -16429,10 +16199,10 @@ function ProxyViewer({
|
|
|
16429
16199
|
{
|
|
16430
16200
|
type: "button",
|
|
16431
16201
|
onClick: () => {
|
|
16432
|
-
|
|
16202
|
+
handleExportRequest("raw");
|
|
16433
16203
|
},
|
|
16434
16204
|
disabled: exporting !== null,
|
|
16435
|
-
className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-2.5 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
|
16205
|
+
className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-2.5 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
|
|
16436
16206
|
title: "Export raw logs without redaction",
|
|
16437
16207
|
children: exporting === "raw" ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Exporting..." }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
16438
16208
|
/* @__PURE__ */ jsxRuntimeExports.jsx(FileBraces, { className: "size-3.5" }),
|
|
@@ -16446,10 +16216,18 @@ function ProxyViewer({
|
|
|
16446
16216
|
type: "button",
|
|
16447
16217
|
onClick: handleReloadCurrentSession,
|
|
16448
16218
|
disabled: isLoading,
|
|
16449
|
-
className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
|
16219
|
+
className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
|
|
16450
16220
|
title: "Reload this session from stored logs",
|
|
16451
16221
|
children: [
|
|
16452
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
16222
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
16223
|
+
RefreshCw,
|
|
16224
|
+
{
|
|
16225
|
+
className: cn(
|
|
16226
|
+
"size-3.5",
|
|
16227
|
+
isLoading && "animate-spin motion-reduce:animate-none"
|
|
16228
|
+
)
|
|
16229
|
+
}
|
|
16230
|
+
),
|
|
16453
16231
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: reloadSessionLabel })
|
|
16454
16232
|
]
|
|
16455
16233
|
}
|
|
@@ -16460,7 +16238,7 @@ function ProxyViewer({
|
|
|
16460
16238
|
type: "button",
|
|
16461
16239
|
onClick: handleClearCurrentView,
|
|
16462
16240
|
disabled: !canClearCurrentView,
|
|
16463
|
-
className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
|
16241
|
+
className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
|
|
16464
16242
|
title: "Clear the current view. Stored logs remain reloadable.",
|
|
16465
16243
|
children: [
|
|
16466
16244
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" }),
|
|
@@ -16474,7 +16252,7 @@ function ProxyViewer({
|
|
|
16474
16252
|
type: "button",
|
|
16475
16253
|
onClick: handleRequestDeleteCurrentView,
|
|
16476
16254
|
disabled: !canDeleteCurrentView || deletingCurrentView,
|
|
16477
|
-
className: "bg-red-500/[0.07] hover:bg-red-500/[0.12] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-red-200 shadow-[inset_0_0_0_1px_rgba(248,113,113,0.14)] transition-colors hover:text-red-100 disabled:cursor-not-allowed disabled:opacity-50",
|
|
16255
|
+
className: "bg-red-500/[0.07] hover:bg-red-500/[0.12] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-red-200 shadow-[inset_0_0_0_1px_rgba(248,113,113,0.14)] transition-colors hover:text-red-100 focus-visible:ring-1 focus-visible:ring-red-300 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
|
|
16478
16256
|
title: "Delete persisted history for the selected session.",
|
|
16479
16257
|
children: [
|
|
16480
16258
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" }),
|
|
@@ -16484,15 +16262,50 @@ function ProxyViewer({
|
|
|
16484
16262
|
)
|
|
16485
16263
|
] }),
|
|
16486
16264
|
pagination === void 0 && sessionLoadProgress !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 rounded-md bg-black/20 px-2 py-2 shadow-[inset_0_0_0_1px_rgba(255,255,255,0.045)]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SessionLoadProgressBar, { progress: sessionLoadProgress }) }),
|
|
16265
|
+
sessionLoadError !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
16266
|
+
"div",
|
|
16267
|
+
{
|
|
16268
|
+
role: "alert",
|
|
16269
|
+
className: "mt-2 flex flex-wrap items-center gap-2 rounded-md border border-red-400/25 bg-red-500/10 px-3 py-2 text-xs text-red-100",
|
|
16270
|
+
children: [
|
|
16271
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "min-w-0 flex-1", children: [
|
|
16272
|
+
"Session logs could not be loaded. ",
|
|
16273
|
+
sessionLoadError,
|
|
16274
|
+
" Existing logs remain visible."
|
|
16275
|
+
] }),
|
|
16276
|
+
onReloadSession !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
16277
|
+
"button",
|
|
16278
|
+
{
|
|
16279
|
+
type: "button",
|
|
16280
|
+
onClick: handleReloadCurrentSession,
|
|
16281
|
+
className: "inline-flex h-7 items-center gap-1 rounded-md bg-black/15 px-2 font-medium transition-colors hover:bg-black/25 focus-visible:ring-1 focus-visible:ring-current focus-visible:outline-none",
|
|
16282
|
+
children: [
|
|
16283
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: "size-3" }),
|
|
16284
|
+
"Retry"
|
|
16285
|
+
]
|
|
16286
|
+
}
|
|
16287
|
+
)
|
|
16288
|
+
]
|
|
16289
|
+
}
|
|
16290
|
+
),
|
|
16487
16291
|
/* @__PURE__ */ jsxRuntimeExports.jsx(LogPaginationBar, { logs, pagination, embedded: true }),
|
|
16488
16292
|
onNotify === void 0 && exportError !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-xs text-destructive", children: exportError }),
|
|
16489
16293
|
onNotify === void 0 && importError !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-xs text-destructive", children: importError }),
|
|
16490
|
-
onNotify === void 0 && importStatus !== null && importError === null && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 rounded-md border border-cyan-400/25 bg-cyan-500/10 px-3 py-2 text-xs text-cyan-100", children: importStatus })
|
|
16294
|
+
onNotify === void 0 && importStatus !== null && importError === null && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 rounded-md border border-cyan-400/25 bg-cyan-500/10 px-3 py-2 text-xs text-cyan-100", children: importStatus }),
|
|
16295
|
+
liveConnection !== void 0 && liveConnection.status !== "live" && onRetryLiveConnection !== void 0 && onStopLiveConnection !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
16296
|
+
LiveConnectionStatus,
|
|
16297
|
+
{
|
|
16298
|
+
state: liveConnection,
|
|
16299
|
+
hasLogs: logs.length > 0,
|
|
16300
|
+
onRetry: onRetryLiveConnection,
|
|
16301
|
+
onStop: onStopLiveConnection
|
|
16302
|
+
}
|
|
16303
|
+
)
|
|
16491
16304
|
] }),
|
|
16492
16305
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-4 lg:px-5", children: [
|
|
16493
16306
|
/* @__PURE__ */ jsxRuntimeExports.jsx(SessionOpeningSlate, { stats: slateStats }),
|
|
16494
16307
|
logs.length === 0 ? selectedSession !== "__all__" ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "py-16 text-center text-muted-foreground", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-white/[0.035] shadow-[inset_0_1px_0_rgba(255,255,255,0.045),0_18px_52px_rgba(0,0,0,0.18)] mx-auto max-w-xl space-y-4 rounded-[8px] px-4 py-8", children: [
|
|
16495
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-medium", children: isLoading ? "Loading session data..." : "No logs loaded for this session" }),
|
|
16308
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-medium", children: isLoading ? "Loading session data..." : sessionLoadError === void 0 ? "No logs loaded for this session" : "Session logs could not be loaded" }),
|
|
16496
16309
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "inline-block max-w-full rounded bg-muted px-3 py-1 font-mono text-xs break-all", children: truncateSessionId(selectedSession) }),
|
|
16497
16310
|
sessionLoadProgress !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mx-auto max-w-md rounded-md bg-black/20 px-2 py-2 text-left shadow-[inset_0_0_0_1px_rgba(255,255,255,0.045)]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SessionLoadProgressBar, { progress: sessionLoadProgress }) }),
|
|
16498
16311
|
sessionMemberships.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-left", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SessionMembershipPanel, { memberships: sessionMemberships }) }),
|
|
@@ -16504,7 +16317,7 @@ function ProxyViewer({
|
|
|
16504
16317
|
{
|
|
16505
16318
|
type: "button",
|
|
16506
16319
|
onClick: handleReloadCurrentSession,
|
|
16507
|
-
className: "bg-white/[0.045] hover:bg-white/[0.075] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground",
|
|
16320
|
+
className: "bg-white/[0.045] hover:bg-white/[0.075] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none",
|
|
16508
16321
|
children: [
|
|
16509
16322
|
/* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: "size-3.5" }),
|
|
16510
16323
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Load session" })
|
|
@@ -16515,7 +16328,7 @@ function ProxyViewer({
|
|
|
16515
16328
|
"a",
|
|
16516
16329
|
{
|
|
16517
16330
|
href: "/",
|
|
16518
|
-
className: "inline-flex h-8 items-center rounded-md px-3 text-xs text-muted-foreground underline transition-colors hover:text-foreground",
|
|
16331
|
+
className: "inline-flex h-8 items-center rounded-md px-3 text-xs text-muted-foreground underline transition-colors hover:text-foreground focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none",
|
|
16519
16332
|
children: "Back to all sessions"
|
|
16520
16333
|
}
|
|
16521
16334
|
) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -16523,26 +16336,30 @@ function ProxyViewer({
|
|
|
16523
16336
|
{
|
|
16524
16337
|
type: "button",
|
|
16525
16338
|
onClick: () => onSessionChange("__all__"),
|
|
16526
|
-
className: "inline-flex h-8 items-center rounded-md px-3 text-xs text-muted-foreground underline transition-colors hover:text-foreground",
|
|
16339
|
+
className: "inline-flex h-8 items-center rounded-md px-3 text-xs text-muted-foreground underline transition-colors hover:text-foreground focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none",
|
|
16527
16340
|
children: "Show all sessions"
|
|
16528
16341
|
}
|
|
16529
16342
|
)
|
|
16530
16343
|
] })
|
|
16531
16344
|
] })
|
|
16532
16345
|
] }) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "py-16 text-center text-muted-foreground", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-white/[0.035] shadow-[inset_0_1px_0_rgba(255,255,255,0.045),0_18px_52px_rgba(0,0,0,0.18)] mx-auto max-w-2xl space-y-4 rounded-[8px] px-4 py-8", children: [
|
|
16533
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm", children:
|
|
16534
|
-
|
|
16535
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
16536
|
-
|
|
16537
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
16538
|
-
|
|
16539
|
-
|
|
16346
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-medium", children: liveEmptyStateCopy.title }),
|
|
16347
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mx-auto max-w-xl text-xs leading-relaxed text-muted-foreground", children: liveEmptyStateCopy.description }),
|
|
16348
|
+
liveEmptyState === "empty" && sessions.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mx-auto max-w-xl text-xs leading-relaxed text-muted-foreground", children: "Pick a session from the filter panel to load stored logs on demand." }),
|
|
16349
|
+
liveEmptyStateCopy.showConnectionCommands && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
16350
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center gap-2", children: [
|
|
16351
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(CopyableCommand, { command: "ANTHROPIC_BASE_URL=http://localhost:9527/proxy <your-tool>" }),
|
|
16352
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(CopyableCommand, { command: "OPENAI_BASE_URL=http://localhost:9527/proxy <your-tool>" })
|
|
16353
|
+
] }),
|
|
16354
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mx-auto max-w-xl text-xs leading-relaxed text-muted-foreground", children: "Container note: if your AI tool runs in a different container or host than Agent Inspector, replace localhost with an address reachable from that tool and verify the network/firewall path." })
|
|
16355
|
+
] })
|
|
16540
16356
|
] }) }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
16541
16357
|
"div",
|
|
16542
16358
|
{
|
|
16543
16359
|
ref: logListWrapperRef,
|
|
16544
16360
|
tabIndex: 0,
|
|
16545
|
-
|
|
16361
|
+
"aria-label": "Captured logs",
|
|
16362
|
+
className: "flex flex-col gap-2 rounded-md focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:outline-none",
|
|
16546
16363
|
children: [
|
|
16547
16364
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: logListRef, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
16548
16365
|
ConversationGroupList,
|
|
@@ -16568,6 +16385,14 @@ function ProxyViewer({
|
|
|
16568
16385
|
]
|
|
16569
16386
|
}
|
|
16570
16387
|
),
|
|
16388
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Dialog, { open: rawExportDialogOpen, onOpenChange: setRawExportDialogOpen, children: /* @__PURE__ */ jsxRuntimeExports.jsx(DialogContent, { className: RAW_EXPORT_DIALOG_CLASS_NAME, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
16389
|
+
RawExportWarning,
|
|
16390
|
+
{
|
|
16391
|
+
onCancel: () => setRawExportDialogOpen(false),
|
|
16392
|
+
onExportRedacted: handleExportRedactedInstead,
|
|
16393
|
+
onConfirmRaw: handleConfirmRawExport
|
|
16394
|
+
}
|
|
16395
|
+
) }) }),
|
|
16571
16396
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Dialog, { open: deleteDialogOpen, onOpenChange: setDeleteDialogOpen, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogContent, { className: "border-red-500/20 bg-zinc-950 text-zinc-100 sm:max-w-md", children: [
|
|
16572
16397
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(DialogHeader, { children: [
|
|
16573
16398
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(DialogTitle, { children: [
|
|
@@ -16606,7 +16431,7 @@ function ProxyViewer({
|
|
|
16606
16431
|
)
|
|
16607
16432
|
] })
|
|
16608
16433
|
] }) }),
|
|
16609
|
-
comparePair !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
16434
|
+
comparePair !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(LazyFeatureBoundary, { feature: "Compare", children: /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
16610
16435
|
LazyCompareDrawer,
|
|
16611
16436
|
{
|
|
16612
16437
|
left: comparePair[0],
|
|
@@ -16615,7 +16440,7 @@ function ProxyViewer({
|
|
|
16615
16440
|
rightDisplayNumber: displayNumberForLog(comparePair[1], displayNumberByLogId),
|
|
16616
16441
|
onClose: closeCompare
|
|
16617
16442
|
}
|
|
16618
|
-
) })
|
|
16443
|
+
) }) })
|
|
16619
16444
|
] });
|
|
16620
16445
|
}
|
|
16621
16446
|
function filterLogs(logs, selectedSession, selectedModel) {
|
|
@@ -16712,11 +16537,12 @@ const SESSION_RELOAD_PAGE_LIMIT = 500;
|
|
|
16712
16537
|
const MAX_SESSION_RELOAD_PAGES = 200;
|
|
16713
16538
|
const SESSION_LOGS_FETCH_TIMEOUT_MS = 2e4;
|
|
16714
16539
|
const SESSION_MEMBERSHIP_FETCH_TIMEOUT_MS = 1e4;
|
|
16540
|
+
const SSE_RECONNECT_DELAY_MS = 3e3;
|
|
16541
|
+
const SSE_STALE_AFTER_MS = 1e4;
|
|
16715
16542
|
function buildLogsStreamUrl(sessionId) {
|
|
16716
|
-
const params = new URLSearchParams();
|
|
16543
|
+
const params = new URLSearchParams({ compact: "1" });
|
|
16717
16544
|
if (sessionId !== void 0) {
|
|
16718
16545
|
params.set("sessionId", sessionId);
|
|
16719
|
-
params.set("compact", "1");
|
|
16720
16546
|
}
|
|
16721
16547
|
const query = params.toString();
|
|
16722
16548
|
return query.length > 0 ? `/api/logs/stream?${query}` : "/api/logs/stream";
|
|
@@ -16796,9 +16622,10 @@ function ProxyViewerContainer({
|
|
|
16796
16622
|
const [selectedModel, setSelectedModel] = reactExports.useState("__all__");
|
|
16797
16623
|
const [knownSessions, setKnownSessions] = reactExports.useState([]);
|
|
16798
16624
|
const { notice, showToast, dismissToast } = useTransientToast();
|
|
16799
|
-
const [
|
|
16625
|
+
const [liveConnection, setLiveConnection] = reactExports.useState(createInitialLiveConnectionState);
|
|
16800
16626
|
const [logPage, setLogPage] = reactExports.useState(null);
|
|
16801
16627
|
const [sessionPageLoading, setSessionPageLoading] = reactExports.useState(initialSessionId !== void 0);
|
|
16628
|
+
const [sessionLoadError, setSessionLoadError] = reactExports.useState(null);
|
|
16802
16629
|
const [sessionLoadProgress, setSessionLoadProgress] = reactExports.useState(
|
|
16803
16630
|
void 0
|
|
16804
16631
|
);
|
|
@@ -16806,6 +16633,8 @@ function ProxyViewerContainer({
|
|
|
16806
16633
|
const [, startLogTransition] = reactExports.useTransition();
|
|
16807
16634
|
const eventSourceRef = reactExports.useRef(null);
|
|
16808
16635
|
const reconnectTimeoutRef = reactExports.useRef(null);
|
|
16636
|
+
const staleTimeoutRef = reactExports.useRef(null);
|
|
16637
|
+
const automaticRetryEnabledRef = reactExports.useRef(true);
|
|
16809
16638
|
const handledHashRef = reactExports.useRef(null);
|
|
16810
16639
|
const sessionPageRequestIdRef = reactExports.useRef(0);
|
|
16811
16640
|
const sessionLoadStartedAtRef = reactExports.useRef(null);
|
|
@@ -16904,7 +16733,11 @@ function ProxyViewerContainer({
|
|
|
16904
16733
|
if (eventSourceRef.current) {
|
|
16905
16734
|
eventSourceRef.current.close();
|
|
16906
16735
|
}
|
|
16907
|
-
|
|
16736
|
+
if (reconnectTimeoutRef.current !== null) {
|
|
16737
|
+
clearTimeout(reconnectTimeoutRef.current);
|
|
16738
|
+
reconnectTimeoutRef.current = null;
|
|
16739
|
+
}
|
|
16740
|
+
setLiveConnection((state) => reduceLiveConnectionState(state, { type: "connect-requested" }));
|
|
16908
16741
|
const es = new EventSource(buildLogsStreamUrl(initialSessionId));
|
|
16909
16742
|
eventSourceRef.current = es;
|
|
16910
16743
|
es.onmessage = (event) => {
|
|
@@ -16913,6 +16746,12 @@ function ProxyViewerContainer({
|
|
|
16913
16746
|
const parsed = JSON.parse(rawData);
|
|
16914
16747
|
const updateResult = SSEUpdateSchema.safeParse(parsed);
|
|
16915
16748
|
if (!updateResult.success) {
|
|
16749
|
+
setLiveConnection(
|
|
16750
|
+
(state) => reduceLiveConnectionState(state, {
|
|
16751
|
+
type: "recoverable-error",
|
|
16752
|
+
message: "The live stream returned invalid data."
|
|
16753
|
+
})
|
|
16754
|
+
);
|
|
16916
16755
|
showErrorToast("Failed to parse SSE data");
|
|
16917
16756
|
return;
|
|
16918
16757
|
}
|
|
@@ -16929,7 +16768,13 @@ function ProxyViewerContainer({
|
|
|
16929
16768
|
return nextLogs;
|
|
16930
16769
|
});
|
|
16931
16770
|
setKnownSessions((prev) => mergeSessionIds(prev, extractSessions(update.logs)));
|
|
16932
|
-
|
|
16771
|
+
if (staleTimeoutRef.current !== null) {
|
|
16772
|
+
clearTimeout(staleTimeoutRef.current);
|
|
16773
|
+
staleTimeoutRef.current = null;
|
|
16774
|
+
}
|
|
16775
|
+
setLiveConnection(
|
|
16776
|
+
(state) => reduceLiveConnectionState(state, { type: "message-received", at: Date.now() })
|
|
16777
|
+
);
|
|
16933
16778
|
dismissToast();
|
|
16934
16779
|
} else if (update.type === "update") {
|
|
16935
16780
|
setKnownSessions((prev) => {
|
|
@@ -16937,27 +16782,73 @@ function ProxyViewerContainer({
|
|
|
16937
16782
|
return mergeSessionIds(prev, [update.log.sessionId]);
|
|
16938
16783
|
});
|
|
16939
16784
|
scheduleUpdate(update.log);
|
|
16785
|
+
if (staleTimeoutRef.current !== null) {
|
|
16786
|
+
clearTimeout(staleTimeoutRef.current);
|
|
16787
|
+
staleTimeoutRef.current = null;
|
|
16788
|
+
}
|
|
16789
|
+
setLiveConnection(
|
|
16790
|
+
(state) => reduceLiveConnectionState(state, { type: "message-received", at: Date.now() })
|
|
16791
|
+
);
|
|
16940
16792
|
}
|
|
16941
16793
|
} catch {
|
|
16794
|
+
setLiveConnection(
|
|
16795
|
+
(state) => reduceLiveConnectionState(state, {
|
|
16796
|
+
type: "recoverable-error",
|
|
16797
|
+
message: "The live stream returned malformed JSON."
|
|
16798
|
+
})
|
|
16799
|
+
);
|
|
16942
16800
|
showErrorToast("Failed to parse SSE data");
|
|
16943
16801
|
}
|
|
16944
16802
|
};
|
|
16945
16803
|
es.onerror = () => {
|
|
16946
|
-
|
|
16947
|
-
|
|
16804
|
+
const online = navigator.onLine;
|
|
16805
|
+
setLiveConnection(
|
|
16806
|
+
(state) => reduceLiveConnectionState(state, {
|
|
16807
|
+
type: "connection-lost",
|
|
16808
|
+
online,
|
|
16809
|
+
message: "The live stream disconnected."
|
|
16810
|
+
})
|
|
16811
|
+
);
|
|
16948
16812
|
es.close();
|
|
16949
|
-
if (
|
|
16950
|
-
|
|
16813
|
+
if (!online || !automaticRetryEnabledRef.current) return;
|
|
16814
|
+
if (staleTimeoutRef.current === null) {
|
|
16815
|
+
staleTimeoutRef.current = setTimeout(() => {
|
|
16816
|
+
staleTimeoutRef.current = null;
|
|
16817
|
+
setLiveConnection((state) => reduceLiveConnectionState(state, { type: "stale-timeout" }));
|
|
16818
|
+
}, SSE_STALE_AFTER_MS);
|
|
16951
16819
|
}
|
|
16952
|
-
reconnectTimeoutRef.current = setTimeout(connectSSE,
|
|
16820
|
+
reconnectTimeoutRef.current = setTimeout(connectSSE, SSE_RECONNECT_DELAY_MS);
|
|
16953
16821
|
};
|
|
16954
16822
|
}, [dismissToast, initialSessionId, scheduleUpdate, showErrorToast]);
|
|
16823
|
+
const retryLiveConnection = reactExports.useCallback(() => {
|
|
16824
|
+
automaticRetryEnabledRef.current = true;
|
|
16825
|
+
if (reconnectTimeoutRef.current !== null) {
|
|
16826
|
+
clearTimeout(reconnectTimeoutRef.current);
|
|
16827
|
+
reconnectTimeoutRef.current = null;
|
|
16828
|
+
}
|
|
16829
|
+
connectSSE();
|
|
16830
|
+
}, [connectSSE]);
|
|
16831
|
+
const stopLiveConnection = reactExports.useCallback(() => {
|
|
16832
|
+
automaticRetryEnabledRef.current = false;
|
|
16833
|
+
eventSourceRef.current?.close();
|
|
16834
|
+
eventSourceRef.current = null;
|
|
16835
|
+
if (reconnectTimeoutRef.current !== null) {
|
|
16836
|
+
clearTimeout(reconnectTimeoutRef.current);
|
|
16837
|
+
reconnectTimeoutRef.current = null;
|
|
16838
|
+
}
|
|
16839
|
+
if (staleTimeoutRef.current !== null) {
|
|
16840
|
+
clearTimeout(staleTimeoutRef.current);
|
|
16841
|
+
staleTimeoutRef.current = null;
|
|
16842
|
+
}
|
|
16843
|
+
setLiveConnection((state) => reduceLiveConnectionState(state, { type: "stop-retrying" }));
|
|
16844
|
+
}, []);
|
|
16955
16845
|
const loadSessionPage = reactExports.useCallback(
|
|
16956
16846
|
(request) => {
|
|
16957
16847
|
if (initialSessionId === void 0) return;
|
|
16958
16848
|
const requestId = sessionPageRequestIdRef.current + 1;
|
|
16959
16849
|
sessionPageRequestIdRef.current = requestId;
|
|
16960
16850
|
setSessionPageLoading(true);
|
|
16851
|
+
setSessionLoadError(null);
|
|
16961
16852
|
startSessionLoadProgress("Loading session logs", requestId);
|
|
16962
16853
|
dismissToast();
|
|
16963
16854
|
void fetchSessionLogsPage(initialSessionId, request).then((page) => {
|
|
@@ -16968,15 +16859,16 @@ function ProxyViewerContainer({
|
|
|
16968
16859
|
setLogPage(page);
|
|
16969
16860
|
setSelectedSession(initialSessionId);
|
|
16970
16861
|
setSessionPageLoading(false);
|
|
16862
|
+
setSessionLoadError(null);
|
|
16971
16863
|
stopSessionLoadProgress();
|
|
16972
16864
|
dismissToast();
|
|
16973
16865
|
}).catch((err) => {
|
|
16974
16866
|
if (sessionPageRequestIdRef.current !== requestId) return;
|
|
16975
|
-
setAllLogs([]);
|
|
16976
|
-
setLogPage(null);
|
|
16977
16867
|
setSessionPageLoading(false);
|
|
16978
16868
|
stopSessionLoadProgress();
|
|
16979
|
-
|
|
16869
|
+
const message = err instanceof Error ? err.message : "Failed to load session logs";
|
|
16870
|
+
setSessionLoadError(message);
|
|
16871
|
+
showErrorToast(message);
|
|
16980
16872
|
});
|
|
16981
16873
|
},
|
|
16982
16874
|
[
|
|
@@ -16992,6 +16884,7 @@ function ProxyViewerContainer({
|
|
|
16992
16884
|
const requestId = sessionPageRequestIdRef.current + 1;
|
|
16993
16885
|
sessionPageRequestIdRef.current = requestId;
|
|
16994
16886
|
setSessionPageLoading(true);
|
|
16887
|
+
setSessionLoadError(null);
|
|
16995
16888
|
startSessionLoadProgress("Reloading full session", requestId);
|
|
16996
16889
|
dismissToast();
|
|
16997
16890
|
void (async () => {
|
|
@@ -17027,6 +16920,7 @@ function ProxyViewerContainer({
|
|
|
17027
16920
|
});
|
|
17028
16921
|
setKnownSessions((prev) => mergeSessionIds(prev, [sessionId]));
|
|
17029
16922
|
setSessionPageLoading(false);
|
|
16923
|
+
setSessionLoadError(null);
|
|
17030
16924
|
stopSessionLoadProgress();
|
|
17031
16925
|
if (page.hasNewer) {
|
|
17032
16926
|
showToast({
|
|
@@ -17040,7 +16934,9 @@ function ProxyViewerContainer({
|
|
|
17040
16934
|
if (sessionPageRequestIdRef.current !== requestId) return;
|
|
17041
16935
|
setSessionPageLoading(false);
|
|
17042
16936
|
stopSessionLoadProgress();
|
|
17043
|
-
|
|
16937
|
+
const message = err instanceof Error ? err.message : "Failed to reload session logs";
|
|
16938
|
+
setSessionLoadError(message);
|
|
16939
|
+
showErrorToast(message);
|
|
17044
16940
|
});
|
|
17045
16941
|
},
|
|
17046
16942
|
[
|
|
@@ -17092,7 +16988,28 @@ function ProxyViewerContainer({
|
|
|
17092
16988
|
reactExports.useEffect(() => {
|
|
17093
16989
|
if (initialSessionId !== void 0) return void 0;
|
|
17094
16990
|
connectSSE();
|
|
16991
|
+
const handleOffline = () => {
|
|
16992
|
+
eventSourceRef.current?.close();
|
|
16993
|
+
eventSourceRef.current = null;
|
|
16994
|
+
if (reconnectTimeoutRef.current !== null) {
|
|
16995
|
+
clearTimeout(reconnectTimeoutRef.current);
|
|
16996
|
+
reconnectTimeoutRef.current = null;
|
|
16997
|
+
}
|
|
16998
|
+
if (staleTimeoutRef.current !== null) {
|
|
16999
|
+
clearTimeout(staleTimeoutRef.current);
|
|
17000
|
+
staleTimeoutRef.current = null;
|
|
17001
|
+
}
|
|
17002
|
+
setLiveConnection((state) => reduceLiveConnectionState(state, { type: "browser-offline" }));
|
|
17003
|
+
};
|
|
17004
|
+
const handleOnline = () => {
|
|
17005
|
+
if (!automaticRetryEnabledRef.current) return;
|
|
17006
|
+
connectSSE();
|
|
17007
|
+
};
|
|
17008
|
+
window.addEventListener("offline", handleOffline);
|
|
17009
|
+
window.addEventListener("online", handleOnline);
|
|
17095
17010
|
return () => {
|
|
17011
|
+
window.removeEventListener("offline", handleOffline);
|
|
17012
|
+
window.removeEventListener("online", handleOnline);
|
|
17096
17013
|
if (eventSourceRef.current) {
|
|
17097
17014
|
eventSourceRef.current.close();
|
|
17098
17015
|
eventSourceRef.current = null;
|
|
@@ -17101,6 +17018,10 @@ function ProxyViewerContainer({
|
|
|
17101
17018
|
clearTimeout(reconnectTimeoutRef.current);
|
|
17102
17019
|
reconnectTimeoutRef.current = null;
|
|
17103
17020
|
}
|
|
17021
|
+
if (staleTimeoutRef.current !== null) {
|
|
17022
|
+
clearTimeout(staleTimeoutRef.current);
|
|
17023
|
+
staleTimeoutRef.current = null;
|
|
17024
|
+
}
|
|
17104
17025
|
if (flushTimerRef.current !== null) {
|
|
17105
17026
|
clearTimeout(flushTimerRef.current);
|
|
17106
17027
|
flushTimerRef.current = null;
|
|
@@ -17125,7 +17046,10 @@ function ProxyViewerContainer({
|
|
|
17125
17046
|
const target = document.getElementById(targetId);
|
|
17126
17047
|
if (target !== null) {
|
|
17127
17048
|
handledHashRef.current = hash;
|
|
17128
|
-
target.scrollIntoView({
|
|
17049
|
+
target.scrollIntoView({
|
|
17050
|
+
block: "center",
|
|
17051
|
+
behavior: preferredScrollBehavior(browserPrefersReducedMotion())
|
|
17052
|
+
});
|
|
17129
17053
|
if (target instanceof HTMLElement) {
|
|
17130
17054
|
highlightedTarget = target;
|
|
17131
17055
|
target.setAttribute("data-deep-link-highlight", "true");
|
|
@@ -17385,9 +17309,13 @@ function ProxyViewerContainer({
|
|
|
17385
17309
|
onClearGroup: handleClearGroup,
|
|
17386
17310
|
onNotify: showToast,
|
|
17387
17311
|
onImportLogs: initialSessionId === void 0 ? handleImportLogs : void 0,
|
|
17388
|
-
isLoading: initialSessionId === void 0 ?
|
|
17312
|
+
isLoading: initialSessionId === void 0 ? liveConnection.status === "connecting" && liveConnection.lastSuccessAt === null || sessionPageLoading : sessionPageLoading,
|
|
17313
|
+
liveConnection: initialSessionId === void 0 ? liveConnection : void 0,
|
|
17314
|
+
onRetryLiveConnection: retryLiveConnection,
|
|
17315
|
+
onStopLiveConnection: stopLiveConnection,
|
|
17389
17316
|
pagination,
|
|
17390
17317
|
sessionLoadProgress,
|
|
17318
|
+
sessionLoadError: sessionLoadError ?? void 0,
|
|
17391
17319
|
sessionMemberships,
|
|
17392
17320
|
viewMode,
|
|
17393
17321
|
captureMode,
|
|
@@ -17405,40 +17333,35 @@ export {
|
|
|
17405
17333
|
Badge as B,
|
|
17406
17334
|
CONTEXT_USAGE_THRESHOLDS as C,
|
|
17407
17335
|
Dialog as D,
|
|
17408
|
-
CollapsibleContent as E,
|
|
17409
|
-
ScrollArea as F,
|
|
17410
|
-
LazyJsonViewer as G,
|
|
17411
|
-
safeJsonValue as H,
|
|
17412
|
-
parseJsonText as I,
|
|
17413
17336
|
LazyJsonViewerFromString as L,
|
|
17414
17337
|
ProxyViewerContainer as P,
|
|
17415
17338
|
ROLE_COLOR_CLASSES as R,
|
|
17416
17339
|
SegmentBar as S,
|
|
17417
17340
|
Tabs as T,
|
|
17418
17341
|
getConversationId as a,
|
|
17419
|
-
|
|
17420
|
-
|
|
17421
|
-
|
|
17422
|
-
|
|
17423
|
-
|
|
17342
|
+
DialogContent as b,
|
|
17343
|
+
DialogHeader as c,
|
|
17344
|
+
DialogTitle as d,
|
|
17345
|
+
TabsList as e,
|
|
17346
|
+
fetchJsonWithTimeout as f,
|
|
17424
17347
|
getLogFormatAdapter as g,
|
|
17425
|
-
|
|
17426
|
-
|
|
17427
|
-
|
|
17428
|
-
|
|
17429
|
-
|
|
17430
|
-
|
|
17431
|
-
|
|
17432
|
-
|
|
17433
|
-
|
|
17434
|
-
|
|
17348
|
+
TabsTrigger as h,
|
|
17349
|
+
TabsContent as i,
|
|
17350
|
+
TooltipProvider as j,
|
|
17351
|
+
Tooltip as k,
|
|
17352
|
+
TooltipTrigger as l,
|
|
17353
|
+
TooltipContent as m,
|
|
17354
|
+
dispatchLogFocusRequest as n,
|
|
17355
|
+
analyzeContextIntelligence as o,
|
|
17356
|
+
ANATOMY_ROLE_LABELS as p,
|
|
17357
|
+
AnswerMarkdown as q,
|
|
17435
17358
|
resolveLogFormat as r,
|
|
17436
|
-
|
|
17437
|
-
|
|
17359
|
+
Collapsible as s,
|
|
17360
|
+
CollapsibleTrigger as t,
|
|
17438
17361
|
useProviders as u,
|
|
17439
|
-
|
|
17440
|
-
|
|
17441
|
-
|
|
17442
|
-
|
|
17443
|
-
|
|
17362
|
+
CollapsibleContent as v,
|
|
17363
|
+
ScrollArea as w,
|
|
17364
|
+
LazyJsonViewer as x,
|
|
17365
|
+
safeJsonValue as y,
|
|
17366
|
+
parseJsonText as z
|
|
17444
17367
|
};
|