@tonyclaw/agent-inspector 3.0.28 → 3.0.30
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-B6cXJohL.js +1 -0
- package/.output/public/assets/InspectorPet-mAzeGmEE.js +4108 -0
- package/.output/public/assets/ProxyViewerContainer-CkFWv_Nm.js +126 -0
- package/.output/public/assets/{ReplayDialog-CZMApaF4.js → ReplayDialog-DodiTL6E.js} +1 -1
- package/.output/public/assets/{RequestAnatomy-DNWccR7O.js → RequestAnatomy-B3IauToI.js} +1 -1
- package/.output/public/assets/ResponseView-Hn-5ordK.js +3 -0
- package/.output/public/assets/StreamingChunkSequence-vLDOVQM_.js +1 -0
- package/.output/public/assets/_sessionId-BFH4TOaI.js +1 -0
- package/.output/public/assets/{_sessionId-DRfvuE2k.js → _sessionId-Cj_HIFZx.js} +1 -1
- package/.output/public/assets/{index-D4HkS7Ct.js → index-Bmj2lcWE.js} +1 -1
- package/.output/public/assets/index-CgJj-HBC.css +1 -0
- package/.output/public/assets/index-Ch7uqnCT.js +1 -0
- package/.output/public/assets/index-DkDdKvLl.js +76 -0
- package/.output/public/assets/{index-B3aAuqWq.js → index-ZlhqCrSg.js} +6 -6
- package/.output/public/assets/{json-viewer-wuJSKaed.js → json-viewer-BdrnVQu-.js} +1 -1
- package/.output/public/assets/jszip.min-CS_nt_o1.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 +86 -86
- 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-BJTNiP_O.mjs → _sessionId-C5S3pGZd.mjs} +15 -15
- package/.output/server/_sessionId-g6D69lKq.mjs +81 -0
- package/.output/server/_ssr/{CompareDrawer-BMRH3N97.mjs → CompareDrawer-CqUmGHal.mjs} +138 -103
- package/.output/server/_ssr/InspectorPet-DI0UJd01.mjs +925 -0
- package/.output/server/_ssr/{ProxyViewerContainer-AFwcHAIR.mjs → ProxyViewerContainer-CvsUmbJ3.mjs} +1216 -1659
- package/.output/server/_ssr/{ReplayDialog-CbWvRHiN.mjs → ReplayDialog-DS48dpFG.mjs} +18 -18
- package/.output/server/_ssr/{RequestAnatomy-C4kcPyqN.mjs → RequestAnatomy-DxYVQU1C.mjs} +58 -58
- package/.output/server/_ssr/{ResponseView-D8VYt-gZ.mjs → ResponseView-BLXW73eq.mjs} +60 -60
- package/.output/server/_ssr/{StreamingChunkSequence-BUUo6vU0.mjs → StreamingChunkSequence-DD0iFuy0.mjs} +16 -16
- package/.output/server/_ssr/{index-DTwMEEXO.mjs → index-B10LIaK0.mjs} +15 -15
- package/.output/server/_ssr/index-RHVJnU2p.mjs +81 -0
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{json-viewer-BqF1pSQD.mjs → json-viewer-LDu2XBaK.mjs} +58 -58
- package/.output/server/_ssr/{router-C8BOns7y.mjs → router-GKvrwifJ.mjs} +9005 -6488
- package/.output/server/_tanstack-start-manifest_v-Df2n4mbT.mjs +4 -0
- package/.output/server/index.mjs +105 -77
- 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/clients/ClientLogo.tsx +9 -6
- package/src/components/ecosystem/AgentLabDialog.tsx +166 -19
- package/src/components/errors/SafeErrorBoundary.tsx +201 -0
- package/src/components/pi-agent/PiAgentPanel.tsx +4 -1
- 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/ConversationGroupList.tsx +49 -34
- package/src/components/proxy-viewer/ConversationHeader.tsx +22 -18
- 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 +1 -1
- 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/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/lib/utils.ts +5 -1
- 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/styles/globals.css +19 -3
- package/.output/public/assets/CompareDrawer-TghZr5t1.js +0 -1
- package/.output/public/assets/ProxyViewerContainer-fShBAZjj.js +0 -4234
- package/.output/public/assets/ResponseView-d25MdFhY.js +0 -3
- package/.output/public/assets/StreamingChunkSequence-DIFZEnWe.js +0 -1
- package/.output/public/assets/index-BsxAGqMA.css +0 -1
- package/.output/public/assets/index-DzARL2Fi.js +0 -76
- package/.output/public/assets/qwen-CONDcHqt.png +0 -0
- package/.output/server/_tanstack-start-manifest_v-BBf2nRhb.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-AFwcHAIR.mjs → ProxyViewerContainer-CvsUmbJ3.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, P 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, H as extractStopReason, af as CrabLogo, p as packageJson, k as normalizeUiScalePreference, Q as GroupEvidenceExportResultSchema, V as DeleteInspectorGroupResponseSchema, y as copyTextToClipboard, l as RedactedProviderDtoSchema, U as UI_SCALE_STORAGE_KEY, v as apiFormatForPath, a4 as createPendingProviderTestResults, a5 as ProviderTestResultsSchema, a6 as createFailedProviderTestResults, a7 as MAX_SLOW_RESPONSE_THRESHOLD_SECONDS, a8 as MAX_PROVIDER_TEST_TIMEOUT_SECONDS, a9 as TimeDisplayFormatSchema, I as AlertSummarySchema, J as AlertListResponseSchema, r as readStoredThemeMode, e as applyThemeMode, f as persistThemeMode, ai as formatUiScale, N as InspectorGroupsListResponseSchema, M as GroupEvidenceReadResponseSchema, aa as EcosystemPackagesResponseSchema, ab as EcosystemTaskResponseSchema, ac as EcosystemTasksResponseSchema, ae as PiAgentResponseSchema, G as isTurnBoundary, _ as PATH_V1_MESSAGES, $ as PATH_V1_CHAT_COMPLETIONS, a0 as PATH_V1_RESPONSES, X as providerHasContextMetadata, W as ProviderScanResponseSchema, T as THEME_MODE_STORAGE_KEY, n as normalizeThemeMode, ad as EcosystemExecutionConfirmationResponseSchema, i as isRecord, a1 as formatContextWindowInput, Y as findProviderModelMetadata, Z as formatContextWindowTokens, w as getSessionPath, q as parseOpenAIResponse, t as parseOpenAIResponsesResponse, O as OpenAIRequestSchema, u as OpenAIResponsesRequestSchema, A as AnthropicResponseSchema$1, o as AnthropicRequestSchema, s as safeGetOwnProperty, ag as resolveProviderContextWindow, a2 as parseContextWindowTokensInput, a3 as previewUpstreamUrl, K as KnowledgeCandidateSchema, ah as isPlainRecord, E as stripClaudeCodeBillingHeader, L as LogBodyChunkSchema, z as getStatusCategory } from "./router-GKvrwifJ.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 Send, p as ArrowLeft, q as ChevronUp, r as ChevronsLeft, s as ChevronLeft, t as ChevronRight, u as ChevronsRight, v as CircleStop, w as Clapperboard, x as Flag, y as Timer, G as Gauge, z as Scan, H as Plus, J as CircleAlert, K as Rocket, O as PackageCheck, Q as History, V as Monitor, W as EyeOff, Y as ExternalLink, Z as Clock, _ as RotateCw, $ as CircleCheckBig, a0 as Pencil, a1 as Bell, a2 as Clock3, a3 as ShieldAlert, a4 as ArrowUpRight, a5 as ArrowDownRight, a6 as CodeXml, a7 as Cpu, a8 as FolderOpen, a9 as MessageSquare, aa as Zap, ab as Wrench, ac as Brain, ad as Minus, ae as CircleQuestionMark, af as Server, ag as Lock, ah as Wifi, ai as WifiOff, aj as CircleX, ak as ShieldCheck, al as Save, am as FileSearch, an as CloudUpload, ao as OctagonAlert, ap as Radio, aq as Globe, ar as FileTerminal, as as ChevronsUp, at as ChevronsDown, au as FileDiff, av as RotateCcw, 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,68 +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
|
-
if (count >= 1e6) return (count / 1e6).toFixed(1).replace(/\.0$/, "") + "M";
|
|
570
|
-
return (count / 1e3).toFixed(1).replace(/\.0$/, "") + "K";
|
|
571
|
-
}
|
|
572
|
-
function formatContextWindowTokens(count) {
|
|
573
|
-
if (count >= 1024 * 1024) {
|
|
574
|
-
return (count / (1024 * 1024)).toFixed(1).replace(/\.0$/, "") + "M";
|
|
575
|
-
}
|
|
576
|
-
return (count / 1024).toFixed(1).replace(/\.0$/, "") + "K";
|
|
577
|
-
}
|
|
578
|
-
function formatExactContextUnit(count, multiplier, unit) {
|
|
579
|
-
const tenths = count * 10;
|
|
580
|
-
if (!Number.isSafeInteger(tenths) || tenths % multiplier !== 0) return null;
|
|
581
|
-
return (tenths / multiplier / 10).toFixed(1).replace(/\.0$/, "") + unit;
|
|
582
|
-
}
|
|
583
|
-
function formatContextWindowInput(count) {
|
|
584
|
-
if (!Number.isSafeInteger(count) || count <= 0) return count.toString();
|
|
585
|
-
if (count >= 1024 * 1024) {
|
|
586
|
-
const megaValue = formatExactContextUnit(count, 1024 * 1024, "M");
|
|
587
|
-
if (megaValue !== null) return megaValue;
|
|
588
|
-
}
|
|
589
|
-
const kiloValue = formatExactContextUnit(count, 1024, "K");
|
|
590
|
-
if (kiloValue !== null) return kiloValue;
|
|
591
|
-
return count.toString();
|
|
592
|
-
}
|
|
593
|
-
function contextWindowUnitMultiplier(unit) {
|
|
594
|
-
if (unit === void 0 || unit === "") return 1;
|
|
595
|
-
switch (unit.toLowerCase()) {
|
|
596
|
-
case "k":
|
|
597
|
-
return 1024;
|
|
598
|
-
case "m":
|
|
599
|
-
return 1024 * 1024;
|
|
600
|
-
default:
|
|
601
|
-
return null;
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
function parseContextWindowTokensInput(value) {
|
|
605
|
-
const trimmed = value.trim().replaceAll(",", "");
|
|
606
|
-
if (trimmed === "") return null;
|
|
607
|
-
const match = /^(\d+(?:\.\d+)?)\s*([kKmM])?$/.exec(trimmed);
|
|
608
|
-
if (match === null) return null;
|
|
609
|
-
const amountText = match[1];
|
|
610
|
-
if (amountText === void 0) return null;
|
|
611
|
-
const amount = Number(amountText);
|
|
612
|
-
const unit = match[2];
|
|
613
|
-
const multiplier = contextWindowUnitMultiplier(unit);
|
|
614
|
-
if (!Number.isFinite(amount) || amount <= 0 || multiplier === null) return null;
|
|
615
|
-
if ((unit === void 0 || unit === "") && !Number.isInteger(amount)) return null;
|
|
616
|
-
const tokens = Math.round(amount * multiplier);
|
|
617
|
-
if (!Number.isSafeInteger(tokens) || tokens <= 0) return null;
|
|
618
|
-
return tokens;
|
|
619
|
-
}
|
|
620
|
-
function getStatusCategory(status) {
|
|
621
|
-
if (status === null) return "pending";
|
|
622
|
-
if (status >= 200 && status < 300) return "success";
|
|
623
|
-
if (status >= 400 && status < 500) return "client_error";
|
|
624
|
-
if (status >= 500) return "server_error";
|
|
625
|
-
return "pending";
|
|
626
|
-
}
|
|
627
533
|
function useThemeMode() {
|
|
628
534
|
const [themeMode, setThemeModeState] = reactExports.useState(readStoredThemeMode);
|
|
629
535
|
const setThemeMode = reactExports.useCallback((nextThemeMode) => {
|
|
@@ -680,7 +586,7 @@ function useUiScale() {
|
|
|
680
586
|
async function fetcher(url) {
|
|
681
587
|
return fetchJson(
|
|
682
588
|
url,
|
|
683
|
-
|
|
589
|
+
RedactedProviderDtoSchema.array(),
|
|
684
590
|
void 0,
|
|
685
591
|
(response) => `Failed to fetch ${url}: ${response.status}`
|
|
686
592
|
);
|
|
@@ -795,46 +701,6 @@ function DialogDescription({
|
|
|
795
701
|
}
|
|
796
702
|
);
|
|
797
703
|
}
|
|
798
|
-
const buttonVariants = cva(
|
|
799
|
-
"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",
|
|
800
|
-
{
|
|
801
|
-
variants: {
|
|
802
|
-
variant: {
|
|
803
|
-
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
804
|
-
destructive: "bg-destructive text-white hover:bg-destructive/90",
|
|
805
|
-
outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
|
|
806
|
-
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
807
|
-
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
808
|
-
link: "text-primary underline-offset-4 hover:underline"
|
|
809
|
-
},
|
|
810
|
-
size: {
|
|
811
|
-
default: "h-9 px-4 py-2",
|
|
812
|
-
sm: "h-8 rounded-md px-3 text-xs",
|
|
813
|
-
lg: "h-10 rounded-md px-8",
|
|
814
|
-
icon: "size-9"
|
|
815
|
-
}
|
|
816
|
-
},
|
|
817
|
-
defaultVariants: {
|
|
818
|
-
variant: "default",
|
|
819
|
-
size: "default"
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
);
|
|
823
|
-
function Button({
|
|
824
|
-
className,
|
|
825
|
-
variant,
|
|
826
|
-
size,
|
|
827
|
-
...props
|
|
828
|
-
}) {
|
|
829
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
830
|
-
"button",
|
|
831
|
-
{
|
|
832
|
-
"data-slot": "button",
|
|
833
|
-
className: cn(buttonVariants({ variant, size, className })),
|
|
834
|
-
...props
|
|
835
|
-
}
|
|
836
|
-
);
|
|
837
|
-
}
|
|
838
704
|
function ConfirmDialog({
|
|
839
705
|
open,
|
|
840
706
|
onOpenChange,
|
|
@@ -940,11 +806,11 @@ const CLIENT_LOGOS = {
|
|
|
940
806
|
"claude-code": ClaudeCodeLogoSvg
|
|
941
807
|
};
|
|
942
808
|
const CLIENT_LOGO_FRAMES = {
|
|
943
|
-
"agent-inspector": "border-orange-200/25 bg-orange-300/[0.12]",
|
|
944
|
-
codex: "border-cyan-200/20 bg-cyan-300/[0.08]",
|
|
945
|
-
opencode: "border-sky-200/25 bg-sky-300/[0.12]",
|
|
946
|
-
"mimo-code": "border-orange-200/25 bg-orange-400/[0.12]",
|
|
947
|
-
"claude-code": "border-amber-100/20 bg-amber-300/[0.09]"
|
|
809
|
+
"agent-inspector": "border-orange-700/15 bg-orange-500/[0.08] dark:border-orange-200/25 dark:bg-orange-300/[0.12]",
|
|
810
|
+
codex: "border-cyan-700/15 bg-cyan-500/[0.08] dark:border-cyan-200/20 dark:bg-cyan-300/[0.08]",
|
|
811
|
+
opencode: "border-sky-700/15 bg-sky-500/[0.09] dark:border-sky-200/25 dark:bg-sky-300/[0.12]",
|
|
812
|
+
"mimo-code": "border-orange-700/15 bg-orange-500/[0.09] dark:border-orange-200/25 dark:bg-orange-400/[0.12]",
|
|
813
|
+
"claude-code": "border-amber-700/15 bg-amber-500/[0.08] dark:border-amber-100/20 dark:bg-amber-300/[0.09]"
|
|
948
814
|
};
|
|
949
815
|
const CLIENT_LOGO_IMAGES = {
|
|
950
816
|
"agent-inspector": "p-0.5 drop-shadow-[0_0_8px_rgba(251,146,60,0.35)]",
|
|
@@ -966,7 +832,7 @@ function ClientLogo({
|
|
|
966
832
|
"span",
|
|
967
833
|
{
|
|
968
834
|
className: cn(
|
|
969
|
-
"inline-flex size-6 shrink-0 items-center justify-center rounded-md border border-cyan-
|
|
835
|
+
"inline-flex size-6 shrink-0 items-center justify-center rounded-md border border-cyan-700/15 bg-cyan-500/[0.08] text-[var(--inspector-status-cool)] shadow-sm dark:border-cyan-200/20 dark:bg-cyan-300/[0.08]",
|
|
970
836
|
className
|
|
971
837
|
),
|
|
972
838
|
"aria-label": decorative ? void 0 : label,
|
|
@@ -1005,7 +871,7 @@ const OpenAILogoSvg = "data:image/svg+xml,%3csvg%20height='2500'%20viewBox='-1%2
|
|
|
1005
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";
|
|
1006
872
|
const MiniMaxLogoSvg = "/assets/minimax-BPMzvuL-.jpeg";
|
|
1007
873
|
const AlibabaLogoSvg = "/assets/alibaba-TTwafVwX.svg";
|
|
1008
|
-
const QwenLogoSvg = "/assets/qwen-
|
|
874
|
+
const QwenLogoSvg = "/assets/qwen-mMn3f5ul.webp";
|
|
1009
875
|
const ZhipuAILogoSvg = "/assets/zhipuai-BPNAnxo-.svg";
|
|
1010
876
|
const PROVIDER_MAP = {
|
|
1011
877
|
"claude-": "anthropic",
|
|
@@ -1702,12 +1568,12 @@ function resolveLogFormat(log) {
|
|
|
1702
1568
|
const pathFormat = apiFormatForPath(log.path);
|
|
1703
1569
|
return pathFormat === "unknown" ? log.apiFormat : pathFormat;
|
|
1704
1570
|
}
|
|
1705
|
-
const HEADER_ACTION_BUTTON_CLASS$1 = "
|
|
1571
|
+
const HEADER_ACTION_BUTTON_CLASS$1 = "inline-flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-md bg-[var(--inspector-surface-low)] text-muted-foreground transition-colors hover:bg-[var(--inspector-surface-medium)] hover:text-foreground";
|
|
1706
1572
|
function isSyntheticSessionId(conversationId) {
|
|
1707
1573
|
return conversationId.startsWith("PID:") || conversationId.startsWith("process:") || conversationId.startsWith("connection:") || conversationId.includes("|");
|
|
1708
1574
|
}
|
|
1709
1575
|
function compactSessionLabel(conversationId) {
|
|
1710
|
-
if (isSyntheticSessionId(conversationId)) return "
|
|
1576
|
+
if (isSyntheticSessionId(conversationId)) return "No session ID";
|
|
1711
1577
|
return conversationId.length > 24 ? `${conversationId.slice(0, 12)}...${conversationId.slice(-12)}` : conversationId;
|
|
1712
1578
|
}
|
|
1713
1579
|
function HeaderMetric({
|
|
@@ -1720,7 +1586,7 @@ function HeaderMetric({
|
|
|
1720
1586
|
"span",
|
|
1721
1587
|
{
|
|
1722
1588
|
className: cn(
|
|
1723
|
-
"
|
|
1589
|
+
"inline-flex h-7 min-w-0 items-center gap-1.5 rounded-md bg-[var(--inspector-surface-low)] px-2 text-xs text-muted-foreground",
|
|
1724
1590
|
className
|
|
1725
1591
|
),
|
|
1726
1592
|
title,
|
|
@@ -1735,7 +1601,7 @@ function PendingTurnBadge() {
|
|
|
1735
1601
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
1736
1602
|
"span",
|
|
1737
1603
|
{
|
|
1738
|
-
className: "inline-flex h-6 shrink-0 items-center gap-1.5 rounded-md bg-
|
|
1604
|
+
className: "inline-flex h-6 shrink-0 items-center gap-1.5 rounded-md bg-[var(--inspector-surface-medium)] px-1.5 font-mono text-[10px] uppercase text-[var(--inspector-status-watch)] ring-1 ring-border/50",
|
|
1739
1605
|
title: "This session has a turn that has not finished yet",
|
|
1740
1606
|
children: [
|
|
1741
1607
|
/* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-3 animate-spin" }),
|
|
@@ -1797,11 +1663,11 @@ function ConversationHeader({
|
|
|
1797
1663
|
"data-nav-id": `conv-${conversationId}`,
|
|
1798
1664
|
"data-nav-action": expanded ? "collapse" : "expand",
|
|
1799
1665
|
className: cn(
|
|
1800
|
-
"
|
|
1801
|
-
"hover:bg-
|
|
1666
|
+
"relative flex cursor-pointer items-start gap-2.5 overflow-hidden rounded-md bg-[var(--inspector-surface-low)] px-3 py-2.5 transition-colors",
|
|
1667
|
+
"hover:bg-[var(--inspector-surface-medium)]",
|
|
1802
1668
|
"select-none",
|
|
1803
1669
|
"sticky top-0 z-10 mb-2",
|
|
1804
|
-
"focus-visible:ring-1 focus-visible:ring-
|
|
1670
|
+
"focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none"
|
|
1805
1671
|
),
|
|
1806
1672
|
onClick: onToggle,
|
|
1807
1673
|
onKeyDown: (e) => {
|
|
@@ -1822,11 +1688,11 @@ function ConversationHeader({
|
|
|
1822
1688
|
),
|
|
1823
1689
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "min-w-0 flex-1", children: [
|
|
1824
1690
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: [
|
|
1825
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0 rounded bg-
|
|
1691
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0 rounded bg-[var(--inspector-surface-medium)] px-1.5 py-0.5 font-mono text-[9px] uppercase text-muted-foreground", children: "Session" }),
|
|
1826
1692
|
isFallbackConversation && showProcessMetadata ? clientPid !== null && clientPid !== void 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
1827
1693
|
"span",
|
|
1828
1694
|
{
|
|
1829
|
-
className: "min-w-0 max-w-full truncate font-mono text-xs font-semibold text-
|
|
1695
|
+
className: "min-w-0 max-w-full truncate font-mono text-xs font-semibold text-foreground",
|
|
1830
1696
|
title: `PID ${clientPid}`,
|
|
1831
1697
|
children: [
|
|
1832
1698
|
"PID ",
|
|
@@ -1836,14 +1702,14 @@ function ConversationHeader({
|
|
|
1836
1702
|
) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
1837
1703
|
"span",
|
|
1838
1704
|
{
|
|
1839
|
-
className: "min-w-0 max-w-full truncate font-mono text-xs font-semibold text-
|
|
1705
|
+
className: "min-w-0 max-w-full truncate font-mono text-xs font-semibold text-foreground",
|
|
1840
1706
|
title: conversationId,
|
|
1841
1707
|
children: conversationId
|
|
1842
1708
|
}
|
|
1843
1709
|
) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
1844
1710
|
"span",
|
|
1845
1711
|
{
|
|
1846
|
-
className: "min-w-0 max-w-full truncate font-mono text-xs font-semibold text-
|
|
1712
|
+
className: "min-w-0 max-w-full truncate font-mono text-xs font-semibold text-foreground",
|
|
1847
1713
|
title: conversationId,
|
|
1848
1714
|
children: sessionLabel
|
|
1849
1715
|
}
|
|
@@ -1851,7 +1717,7 @@ function ConversationHeader({
|
|
|
1851
1717
|
!isFallbackConversation && showProcessMetadata && clientPid !== null && clientPid !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
1852
1718
|
"span",
|
|
1853
1719
|
{
|
|
1854
|
-
className: "
|
|
1720
|
+
className: "shrink-0 rounded bg-[var(--inspector-surface-medium)] px-1.5 py-0.5 font-mono text-xs tabular-nums text-muted-foreground",
|
|
1855
1721
|
title: `Client process ID ${clientPid}`,
|
|
1856
1722
|
children: [
|
|
1857
1723
|
"PID ",
|
|
@@ -1870,7 +1736,7 @@ function ConversationHeader({
|
|
|
1870
1736
|
showClientIdentity && clientDisplayLabel !== null && clientDisplayLabel !== "" && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
1871
1737
|
"span",
|
|
1872
1738
|
{
|
|
1873
|
-
className: "
|
|
1739
|
+
className: "inline-flex min-h-6 shrink-0 flex-wrap items-center gap-1 rounded-md bg-[var(--inspector-surface-medium)] px-1.5 py-0.5 text-xs text-muted-foreground",
|
|
1874
1740
|
title: clientTooltip ?? clientDisplayLabel,
|
|
1875
1741
|
children: [
|
|
1876
1742
|
/* @__PURE__ */ jsxRuntimeExports.jsx(ClientLogo, { client: clientApp, className: "size-4 shrink-0", decorative: true }),
|
|
@@ -1884,9 +1750,9 @@ function ConversationHeader({
|
|
|
1884
1750
|
/* @__PURE__ */ jsxRuntimeExports.jsx(HeaderMetric, { icon: /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "size-3 shrink-0" }), title: timeLabel, children: timeLabel }),
|
|
1885
1751
|
/* @__PURE__ */ jsxRuntimeExports.jsx(HeaderMetric, { icon: /* @__PURE__ */ jsxRuntimeExports.jsx(MessageSquare, { className: "size-3 shrink-0" }), children: callsLabel }),
|
|
1886
1752
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(HeaderMetric, { icon: /* @__PURE__ */ jsxRuntimeExports.jsx(Zap, { className: "size-3 shrink-0" }), className: "max-w-full", children: [
|
|
1887
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-
|
|
1753
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[var(--inspector-status-info)]", children: formatTokens(totalInputTokens) }),
|
|
1888
1754
|
" / ",
|
|
1889
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-
|
|
1755
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[var(--inspector-status-watch)]", children: formatTokens(totalOutputTokens) })
|
|
1890
1756
|
] })
|
|
1891
1757
|
] })
|
|
1892
1758
|
] }),
|
|
@@ -1921,7 +1787,7 @@ function ConversationHeader({
|
|
|
1921
1787
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
1922
1788
|
"span",
|
|
1923
1789
|
{
|
|
1924
|
-
className: "
|
|
1790
|
+
className: "inline-flex size-8 shrink-0 items-center justify-center rounded-md bg-[var(--inspector-surface-low)] text-muted-foreground transition-colors hover:bg-[var(--inspector-surface-medium)] hover:text-foreground",
|
|
1925
1791
|
"aria-hidden": "true",
|
|
1926
1792
|
children: expanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-4 shrink-0" }) : isLoading ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-4 shrink-0 animate-spin" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-4 shrink-0" })
|
|
1927
1793
|
}
|
|
@@ -1930,9 +1796,9 @@ function ConversationHeader({
|
|
|
1930
1796
|
isLoading && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
1931
1797
|
"span",
|
|
1932
1798
|
{
|
|
1933
|
-
className: "pointer-events-none absolute inset-x-3 bottom-0 h-px overflow-hidden rounded-full bg-
|
|
1799
|
+
className: "pointer-events-none absolute inset-x-3 bottom-0 h-px overflow-hidden rounded-full bg-[var(--inspector-surface-medium)]",
|
|
1934
1800
|
"aria-hidden": "true",
|
|
1935
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "absolute inset-y-0 left-0 w-1/3 animate-pulse rounded-full bg-
|
|
1801
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "absolute inset-y-0 left-0 w-1/3 animate-pulse rounded-full bg-[var(--inspector-status-watch)] opacity-70" })
|
|
1936
1802
|
}
|
|
1937
1803
|
),
|
|
1938
1804
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -2517,9 +2383,9 @@ function TabsTrigger({
|
|
|
2517
2383
|
{
|
|
2518
2384
|
"data-slot": "tabs-trigger",
|
|
2519
2385
|
className: cn(
|
|
2520
|
-
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring text-
|
|
2521
|
-
"group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-[state=active]:
|
|
2522
|
-
"data-[state=active]:
|
|
2386
|
+
"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",
|
|
2387
|
+
"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",
|
|
2388
|
+
"data-[state=active]:border-border data-[state=active]:bg-background data-[state=active]:text-foreground",
|
|
2523
2389
|
"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",
|
|
2524
2390
|
className
|
|
2525
2391
|
),
|
|
@@ -2565,27 +2431,30 @@ function useCopyFeedback(text) {
|
|
|
2565
2431
|
return { copied, copy };
|
|
2566
2432
|
}
|
|
2567
2433
|
const LazyCompareDrawer = reactExports.lazy(
|
|
2568
|
-
() => import("./CompareDrawer-
|
|
2434
|
+
() => import("./CompareDrawer-CqUmGHal.mjs").then((m) => ({ default: m.CompareDrawer }))
|
|
2435
|
+
);
|
|
2436
|
+
const LazyInspectorPet = reactExports.lazy(
|
|
2437
|
+
() => import("./InspectorPet-DI0UJd01.mjs").then((m) => ({ default: m.InspectorPet }))
|
|
2569
2438
|
);
|
|
2570
2439
|
const LazyReplayDialog = reactExports.lazy(
|
|
2571
|
-
() => import("./ReplayDialog-
|
|
2440
|
+
() => import("./ReplayDialog-DS48dpFG.mjs").then((m) => ({ default: m.ReplayDialog }))
|
|
2572
2441
|
);
|
|
2573
2442
|
const LazyRequestAnatomy = reactExports.lazy(
|
|
2574
|
-
() => import("./RequestAnatomy-
|
|
2443
|
+
() => import("./RequestAnatomy-DxYVQU1C.mjs").then((m) => ({ default: m.RequestAnatomy }))
|
|
2575
2444
|
);
|
|
2576
2445
|
const LazyResponseView = reactExports.lazy(
|
|
2577
|
-
() => import("./ResponseView-
|
|
2446
|
+
() => import("./ResponseView-BLXW73eq.mjs").then((m) => ({ default: m.ResponseView }))
|
|
2578
2447
|
);
|
|
2579
2448
|
const LazyStreamingChunkSequence = reactExports.lazy(
|
|
2580
|
-
() => import("./StreamingChunkSequence-
|
|
2449
|
+
() => import("./StreamingChunkSequence-DD0iFuy0.mjs").then((m) => ({
|
|
2581
2450
|
default: m.StreamingChunkSequence
|
|
2582
2451
|
}))
|
|
2583
2452
|
);
|
|
2584
2453
|
const LazyJsonViewer = reactExports.lazy(
|
|
2585
|
-
() => import("./json-viewer-
|
|
2454
|
+
() => import("./json-viewer-LDu2XBaK.mjs").then((m) => ({ default: m.JsonViewer }))
|
|
2586
2455
|
);
|
|
2587
2456
|
const LazyJsonViewerFromString = reactExports.lazy(
|
|
2588
|
-
() => import("./json-viewer-
|
|
2457
|
+
() => import("./json-viewer-LDu2XBaK.mjs").then((m) => ({ default: m.JsonViewerFromString }))
|
|
2589
2458
|
);
|
|
2590
2459
|
const HIGHLIGHT_DURATION_MS = 1200;
|
|
2591
2460
|
const MAX_HIGHLIGHT_ATTEMPTS = 12;
|
|
@@ -4393,7 +4262,7 @@ const LogEntry = reactExports.memo(function({
|
|
|
4393
4262
|
"aria-hidden": "true"
|
|
4394
4263
|
}
|
|
4395
4264
|
),
|
|
4396
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(Tabs, { value: activeTab, onValueChange: setActiveTab, className: "gap-2", children: [
|
|
4265
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(LazyFeatureBoundary, { feature: "Log details", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tabs, { value: activeTab, onValueChange: setActiveTab, className: "gap-2", children: [
|
|
4397
4266
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
4398
4267
|
TabsList,
|
|
4399
4268
|
{
|
|
@@ -4529,7 +4398,13 @@ const LogEntry = reactExports.memo(function({
|
|
|
4529
4398
|
headers: displayLog.headers,
|
|
4530
4399
|
emptyLabel: "No transformation applied; raw and processed headers are identical."
|
|
4531
4400
|
}
|
|
4532
|
-
) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4401
|
+
) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4402
|
+
HeaderRows,
|
|
4403
|
+
{
|
|
4404
|
+
headers: displayLog.headers,
|
|
4405
|
+
emptyLabel: "No headers captured"
|
|
4406
|
+
}
|
|
4407
|
+
)
|
|
4533
4408
|
] }) }),
|
|
4534
4409
|
shouldShowRawHeadersTab(
|
|
4535
4410
|
viewMode,
|
|
@@ -4614,14 +4489,14 @@ const LogEntry = reactExports.memo(function({
|
|
|
4614
4489
|
}
|
|
4615
4490
|
) })
|
|
4616
4491
|
] }) })
|
|
4617
|
-
] })
|
|
4492
|
+
] }) })
|
|
4618
4493
|
]
|
|
4619
4494
|
}
|
|
4620
4495
|
)
|
|
4621
4496
|
]
|
|
4622
4497
|
}
|
|
4623
4498
|
),
|
|
4624
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4499
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(LazyFeatureBoundary, { feature: "Replay", children: /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4625
4500
|
LazyReplayDialog,
|
|
4626
4501
|
{
|
|
4627
4502
|
log: displayLog,
|
|
@@ -4629,7 +4504,7 @@ const LogEntry = reactExports.memo(function({
|
|
|
4629
4504
|
open: replayOpen,
|
|
4630
4505
|
onOpenChange: setReplayOpen
|
|
4631
4506
|
}
|
|
4632
|
-
) })
|
|
4507
|
+
) }) })
|
|
4633
4508
|
] });
|
|
4634
4509
|
});
|
|
4635
4510
|
function boundaryTitle(stopReason) {
|
|
@@ -4654,6 +4529,7 @@ function ThreadConnector({
|
|
|
4654
4529
|
isFirst,
|
|
4655
4530
|
isTurnStart,
|
|
4656
4531
|
isOnlyEntry = false,
|
|
4532
|
+
isOpenTurnTail = false,
|
|
4657
4533
|
crabIndex = 0,
|
|
4658
4534
|
collapsible = false,
|
|
4659
4535
|
onToggle
|
|
@@ -4737,8 +4613,23 @@ function ThreadConnector({
|
|
|
4737
4613
|
}
|
|
4738
4614
|
)
|
|
4739
4615
|
}
|
|
4616
|
+
) : isOpenTurnTail ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4617
|
+
"span",
|
|
4618
|
+
{
|
|
4619
|
+
title: isPending ? "Current end of open turn (processing)" : "Current end of open turn",
|
|
4620
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4621
|
+
Crab,
|
|
4622
|
+
{
|
|
4623
|
+
className: cn(
|
|
4624
|
+
"size-3.5 text-cyan-300/85",
|
|
4625
|
+
isRunning ? "animate-crab-crawl" : "animate-crab-appear",
|
|
4626
|
+
"drop-shadow-[0_0_4px_rgba(103,232,249,0.4)]"
|
|
4627
|
+
)
|
|
4628
|
+
}
|
|
4629
|
+
)
|
|
4630
|
+
}
|
|
4740
4631
|
) : 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" }) }),
|
|
4741
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 flex justify-center min-h-0", children: !isBoundary && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4632
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 flex justify-center min-h-0", children: !isBoundary && !isOpenTurnTail && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4742
4633
|
"div",
|
|
4743
4634
|
{
|
|
4744
4635
|
className: cn(
|
|
@@ -4763,8 +4654,8 @@ function responseMayContainToolTrace(log, format) {
|
|
|
4763
4654
|
return false;
|
|
4764
4655
|
}
|
|
4765
4656
|
}
|
|
4766
|
-
function isTurnCollapsible(entryCount
|
|
4767
|
-
return entryCount > 1
|
|
4657
|
+
function isTurnCollapsible(entryCount) {
|
|
4658
|
+
return entryCount > 1;
|
|
4768
4659
|
}
|
|
4769
4660
|
function buildTurnGroups(logs) {
|
|
4770
4661
|
const groups = [];
|
|
@@ -5015,7 +4906,7 @@ const TurnGroup = reactExports.memo(function TurnGroup2({
|
|
|
5015
4906
|
const isComplete = lastStop !== null ? isTurnBoundary(lastStop) : false;
|
|
5016
4907
|
const isPending = entries[lastIdx]?.log.responseStatus === null;
|
|
5017
4908
|
const isSingleLog = entries.length === 1;
|
|
5018
|
-
const collapsible = isTurnCollapsible(entries.length
|
|
4909
|
+
const collapsible = isTurnCollapsible(entries.length);
|
|
5019
4910
|
const [collapsed, setCollapsed] = reactExports.useState(false);
|
|
5020
4911
|
const prevCompleteRef = reactExports.useRef(false);
|
|
5021
4912
|
reactExports.useEffect(() => {
|
|
@@ -5158,7 +5049,7 @@ const TurnGroup = reactExports.memo(function TurnGroup2({
|
|
|
5158
5049
|
}
|
|
5159
5050
|
),
|
|
5160
5051
|
/* @__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" }) }),
|
|
5161
|
-
isComplete
|
|
5052
|
+
isComplete ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5162
5053
|
CollapsedCrab,
|
|
5163
5054
|
{
|
|
5164
5055
|
className: cn(
|
|
@@ -5166,7 +5057,16 @@ const TurnGroup = reactExports.memo(function TurnGroup2({
|
|
|
5166
5057
|
"drop-shadow-[0_0_4px_rgba(251,191,36,0.45)]"
|
|
5167
5058
|
)
|
|
5168
5059
|
}
|
|
5169
|
-
)
|
|
5060
|
+
) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { title: "Current end of open turn", "aria-label": "Current end of open turn", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5061
|
+
CollapsedCrab,
|
|
5062
|
+
{
|
|
5063
|
+
className: cn(
|
|
5064
|
+
"size-3.5 text-cyan-300/85",
|
|
5065
|
+
isPending ? "animate-crab-crawl" : "animate-crab-appear",
|
|
5066
|
+
"drop-shadow-[0_0_4px_rgba(103,232,249,0.4)]"
|
|
5067
|
+
)
|
|
5068
|
+
}
|
|
5069
|
+
) })
|
|
5170
5070
|
] }),
|
|
5171
5071
|
entries.length > 1 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
5172
5072
|
"div",
|
|
@@ -5259,6 +5159,7 @@ const TurnGroup = reactExports.memo(function TurnGroup2({
|
|
|
5259
5159
|
isFirst: visibleIdx === 0,
|
|
5260
5160
|
isTurnStart,
|
|
5261
5161
|
isOnlyEntry: isSingleLog,
|
|
5162
|
+
isOpenTurnTail: visibleIdx === lastIdx && !isComplete,
|
|
5262
5163
|
crabIndex: log.id % 12,
|
|
5263
5164
|
collapsible: collapsible && isTurnStart,
|
|
5264
5165
|
onToggle: toggleCollapse
|
|
@@ -6262,9 +6163,14 @@ const ConversationGroup = reactExports.memo(function({
|
|
|
6262
6163
|
] })
|
|
6263
6164
|
] });
|
|
6264
6165
|
});
|
|
6166
|
+
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";
|
|
6167
|
+
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";
|
|
6265
6168
|
function shouldShowRawExport(captureMode) {
|
|
6266
6169
|
return captureMode === "full";
|
|
6267
6170
|
}
|
|
6171
|
+
function exportRequiresConfirmation(mode) {
|
|
6172
|
+
return mode === "raw";
|
|
6173
|
+
}
|
|
6268
6174
|
function getExportActionVisibility(captureMode, logCount) {
|
|
6269
6175
|
const hasLogs = logCount > 0;
|
|
6270
6176
|
return {
|
|
@@ -6561,46 +6467,6 @@ function formatPaginationStatus({
|
|
|
6561
6467
|
}
|
|
6562
6468
|
return `Showing ${logs.length} of ${pagination.total} logs (${range})`;
|
|
6563
6469
|
}
|
|
6564
|
-
function CrabLogo({ className }) {
|
|
6565
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
6566
|
-
"svg",
|
|
6567
|
-
{
|
|
6568
|
-
viewBox: "0 0 24 24",
|
|
6569
|
-
fill: "none",
|
|
6570
|
-
stroke: "currentColor",
|
|
6571
|
-
strokeWidth: "1.5",
|
|
6572
|
-
strokeLinecap: "round",
|
|
6573
|
-
strokeLinejoin: "round",
|
|
6574
|
-
"aria-hidden": "true",
|
|
6575
|
-
className: cn("inline-block size-5", className),
|
|
6576
|
-
children: [
|
|
6577
|
-
/* @__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" }),
|
|
6578
|
-
/* @__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" }),
|
|
6579
|
-
/* @__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" }),
|
|
6580
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10", y1: "7", x2: "9.5", y2: "5" }),
|
|
6581
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14", y1: "7", x2: "14.5", y2: "5" }),
|
|
6582
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "9.5", cy: "4.5", r: "0.9", fill: "currentColor", stroke: "none" }),
|
|
6583
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "14.5", cy: "4.5", r: "0.9", fill: "currentColor", stroke: "none" }),
|
|
6584
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "6.5", y1: "16", x2: "4.5", y2: "19.5" }),
|
|
6585
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "9", y1: "17.5", x2: "8", y2: "20.5" }),
|
|
6586
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "15", y1: "17.5", x2: "16", y2: "20.5" }),
|
|
6587
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "17.5", y1: "16", x2: "19.5", y2: "19.5" })
|
|
6588
|
-
]
|
|
6589
|
-
}
|
|
6590
|
-
);
|
|
6591
|
-
}
|
|
6592
|
-
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=";
|
|
6593
|
-
function McpLogo({ className }) {
|
|
6594
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
6595
|
-
"img",
|
|
6596
|
-
{
|
|
6597
|
-
src: McpLogoPng,
|
|
6598
|
-
alt: "Model Context Protocol",
|
|
6599
|
-
"aria-hidden": "true",
|
|
6600
|
-
className: cn("inline-block size-8 object-contain invert", className)
|
|
6601
|
-
}
|
|
6602
|
-
);
|
|
6603
|
-
}
|
|
6604
6470
|
function Select({
|
|
6605
6471
|
...props
|
|
6606
6472
|
}) {
|
|
@@ -6646,7 +6512,7 @@ function SelectContent({
|
|
|
6646
6512
|
{
|
|
6647
6513
|
"data-slot": "select-content",
|
|
6648
6514
|
className: cn(
|
|
6649
|
-
"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",
|
|
6515
|
+
"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",
|
|
6650
6516
|
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",
|
|
6651
6517
|
className
|
|
6652
6518
|
),
|
|
@@ -7356,7 +7222,7 @@ function TransientToast({
|
|
|
7356
7222
|
"button",
|
|
7357
7223
|
{
|
|
7358
7224
|
type: "button",
|
|
7359
|
-
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",
|
|
7225
|
+
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",
|
|
7360
7226
|
"aria-label": "Dismiss notification",
|
|
7361
7227
|
onClick: onDismiss,
|
|
7362
7228
|
children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "size-3.5" })
|
|
@@ -8353,21 +8219,6 @@ function MemberMetadata({ entries }) {
|
|
|
8353
8219
|
}) })
|
|
8354
8220
|
] });
|
|
8355
8221
|
}
|
|
8356
|
-
const ExternalProviderSchema = object({
|
|
8357
|
-
name: string(),
|
|
8358
|
-
apiKey: string(),
|
|
8359
|
-
format: _enum(["anthropic", "openai"]),
|
|
8360
|
-
anthropicBaseUrl: string(),
|
|
8361
|
-
openaiBaseUrl: string(),
|
|
8362
|
-
openaiResponsesBaseUrl: string().optional().default(""),
|
|
8363
|
-
models: array(string()),
|
|
8364
|
-
sourceTool: _enum(["claude-code", "opencode", "mimo-code"]),
|
|
8365
|
-
alreadyExists: boolean()
|
|
8366
|
-
});
|
|
8367
|
-
const ScanResponseSchema = object({
|
|
8368
|
-
providers: array(ExternalProviderSchema),
|
|
8369
|
-
warnings: array(string()).optional()
|
|
8370
|
-
});
|
|
8371
8222
|
const ImportResponseSchema$1 = object({
|
|
8372
8223
|
success: boolean().optional(),
|
|
8373
8224
|
imported: number().optional(),
|
|
@@ -8382,6 +8233,7 @@ function ImportWizardDialog({
|
|
|
8382
8233
|
}) {
|
|
8383
8234
|
const [scanning, setScanning] = reactExports.useState(false);
|
|
8384
8235
|
const [scanError, setScanError] = reactExports.useState(null);
|
|
8236
|
+
const [scanId, setScanId] = reactExports.useState(null);
|
|
8385
8237
|
const [providers, setProviders] = reactExports.useState([]);
|
|
8386
8238
|
const [warnings, setWarnings] = reactExports.useState([]);
|
|
8387
8239
|
const [selected, setSelected] = reactExports.useState(/* @__PURE__ */ new Set());
|
|
@@ -8396,18 +8248,20 @@ function ImportWizardDialog({
|
|
|
8396
8248
|
setScanning(true);
|
|
8397
8249
|
setScanError(null);
|
|
8398
8250
|
setWarnings([]);
|
|
8251
|
+
setScanId(null);
|
|
8399
8252
|
setProviders([]);
|
|
8400
8253
|
setSelected(/* @__PURE__ */ new Set());
|
|
8401
8254
|
setImportResult(null);
|
|
8402
8255
|
setImportError(null);
|
|
8403
8256
|
void fetchJsonWithTimeout(
|
|
8404
8257
|
"/api/providers/scan",
|
|
8405
|
-
|
|
8258
|
+
ProviderScanResponseSchema,
|
|
8406
8259
|
PROVIDER_IMPORT_TIMEOUT_MS$1,
|
|
8407
|
-
|
|
8260
|
+
{ method: "POST" },
|
|
8408
8261
|
(response) => `Scan failed (${String(response.status)})`
|
|
8409
8262
|
).then((data) => {
|
|
8410
8263
|
if (scanRequestIdRef.current !== requestId) return;
|
|
8264
|
+
setScanId(data.scanId);
|
|
8411
8265
|
setProviders(data.providers);
|
|
8412
8266
|
setWarnings(data.warnings ?? []);
|
|
8413
8267
|
const indices = /* @__PURE__ */ new Set();
|
|
@@ -8448,25 +8302,12 @@ function ImportWizardDialog({
|
|
|
8448
8302
|
}, []);
|
|
8449
8303
|
const importSelected = reactExports.useCallback(() => {
|
|
8450
8304
|
const toImport = providers.filter((_, i) => selected.has(i));
|
|
8451
|
-
if (toImport.length === 0) return;
|
|
8305
|
+
if (toImport.length === 0 || scanId === null) return;
|
|
8452
8306
|
const requestId = importRequestIdRef.current + 1;
|
|
8453
8307
|
importRequestIdRef.current = requestId;
|
|
8454
8308
|
setImporting(true);
|
|
8455
8309
|
setImportError(null);
|
|
8456
8310
|
setImportResult(null);
|
|
8457
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
8458
|
-
const providersPayload = toImport.map((p) => ({
|
|
8459
|
-
id: window.crypto.randomUUID(),
|
|
8460
|
-
name: p.name,
|
|
8461
|
-
apiKey: p.apiKey,
|
|
8462
|
-
format: p.format,
|
|
8463
|
-
anthropicBaseUrl: p.anthropicBaseUrl,
|
|
8464
|
-
openaiBaseUrl: p.openaiBaseUrl,
|
|
8465
|
-
openaiResponsesBaseUrl: p.openaiResponsesBaseUrl,
|
|
8466
|
-
models: p.models,
|
|
8467
|
-
createdAt: now,
|
|
8468
|
-
updatedAt: now
|
|
8469
|
-
}));
|
|
8470
8311
|
void fetchJsonWithTimeout(
|
|
8471
8312
|
"/api/providers/import",
|
|
8472
8313
|
ImportResponseSchema$1,
|
|
@@ -8474,7 +8315,10 @@ function ImportWizardDialog({
|
|
|
8474
8315
|
{
|
|
8475
8316
|
method: "POST",
|
|
8476
8317
|
headers: { "Content-Type": "application/json" },
|
|
8477
|
-
body: JSON.stringify({
|
|
8318
|
+
body: JSON.stringify({
|
|
8319
|
+
scanId,
|
|
8320
|
+
selectionIds: toImport.map((provider) => provider.selectionId)
|
|
8321
|
+
})
|
|
8478
8322
|
},
|
|
8479
8323
|
(response) => `Import failed (${String(response.status)})`
|
|
8480
8324
|
).then((result) => {
|
|
@@ -8496,7 +8340,7 @@ function ImportWizardDialog({
|
|
|
8496
8340
|
if (importRequestIdRef.current !== requestId) return;
|
|
8497
8341
|
setImporting(false);
|
|
8498
8342
|
});
|
|
8499
|
-
}, [providers, selected, onImportComplete]);
|
|
8343
|
+
}, [providers, scanId, selected, onImportComplete]);
|
|
8500
8344
|
const hasSelectable = providers.some((p) => !p.alreadyExists);
|
|
8501
8345
|
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: [
|
|
8502
8346
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(DialogHeader, { children: [
|
|
@@ -8542,11 +8386,11 @@ function ImportWizardDialog({
|
|
|
8542
8386
|
p.models.length > 4 ? ` +${p.models.length - 4} more` : ""
|
|
8543
8387
|
] }),
|
|
8544
8388
|
/* @__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 }),
|
|
8545
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-muted-foreground mt-0.5 font-mono", children: p.
|
|
8389
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-muted-foreground mt-0.5 font-mono", children: p.apiKeyHint })
|
|
8546
8390
|
] })
|
|
8547
8391
|
]
|
|
8548
8392
|
},
|
|
8549
|
-
|
|
8393
|
+
p.selectionId
|
|
8550
8394
|
)),
|
|
8551
8395
|
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: [
|
|
8552
8396
|
/* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "size-3" }),
|
|
@@ -10323,7 +10167,7 @@ const ImportResponseSchema = object({
|
|
|
10323
10167
|
errors: array(string()).optional()
|
|
10324
10168
|
});
|
|
10325
10169
|
const ModelMetadataRefreshResponseSchema = object({
|
|
10326
|
-
provider:
|
|
10170
|
+
provider: RedactedProviderDtoSchema,
|
|
10327
10171
|
imported: number(),
|
|
10328
10172
|
matchedModels: array(string()),
|
|
10329
10173
|
missingModels: array(string()),
|
|
@@ -10602,7 +10446,7 @@ function ProvidersPanel({
|
|
|
10602
10446
|
try {
|
|
10603
10447
|
const newProvider = await fetchJsonWithTimeout(
|
|
10604
10448
|
"/api/providers",
|
|
10605
|
-
|
|
10449
|
+
RedactedProviderDtoSchema,
|
|
10606
10450
|
PROVIDER_WRITE_TIMEOUT_MS,
|
|
10607
10451
|
{
|
|
10608
10452
|
method: "POST",
|
|
@@ -10629,7 +10473,7 @@ function ProvidersPanel({
|
|
|
10629
10473
|
try {
|
|
10630
10474
|
const updated = await fetchJsonWithTimeout(
|
|
10631
10475
|
`/api/providers/${editingProvider.id}`,
|
|
10632
|
-
|
|
10476
|
+
RedactedProviderDtoSchema,
|
|
10633
10477
|
PROVIDER_WRITE_TIMEOUT_MS,
|
|
10634
10478
|
{
|
|
10635
10479
|
method: "PUT",
|
|
@@ -10750,61 +10594,68 @@ function ProvidersPanel({
|
|
|
10750
10594
|
] });
|
|
10751
10595
|
}
|
|
10752
10596
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
|
|
10753
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
10754
|
-
|
|
10755
|
-
|
|
10756
|
-
|
|
10757
|
-
|
|
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
|
-
|
|
10597
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
10598
|
+
"div",
|
|
10599
|
+
{
|
|
10600
|
+
"data-provider-toolbar": "true",
|
|
10601
|
+
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",
|
|
10602
|
+
children: [
|
|
10603
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
10604
|
+
Button,
|
|
10605
|
+
{
|
|
10606
|
+
variant: "outline",
|
|
10607
|
+
size: "sm",
|
|
10608
|
+
onClick: () => handleExport(),
|
|
10609
|
+
className: "gap-1 hover:bg-muted",
|
|
10610
|
+
children: [
|
|
10611
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Download, { className: "size-3" }),
|
|
10612
|
+
"Export"
|
|
10613
|
+
]
|
|
10614
|
+
}
|
|
10615
|
+
),
|
|
10616
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
10617
|
+
Button,
|
|
10618
|
+
{
|
|
10619
|
+
variant: "outline",
|
|
10620
|
+
size: "sm",
|
|
10621
|
+
onClick: handleImportClick,
|
|
10622
|
+
className: "gap-1 hover:bg-muted",
|
|
10623
|
+
children: [
|
|
10624
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Upload, { className: "size-3" }),
|
|
10625
|
+
"Import"
|
|
10626
|
+
]
|
|
10627
|
+
}
|
|
10628
|
+
),
|
|
10629
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10630
|
+
"input",
|
|
10631
|
+
{
|
|
10632
|
+
type: "file",
|
|
10633
|
+
ref: fileInputRef,
|
|
10634
|
+
accept: ".json",
|
|
10635
|
+
onChange: handleFileChange,
|
|
10636
|
+
style: { display: "none" }
|
|
10637
|
+
}
|
|
10638
|
+
),
|
|
10639
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
10640
|
+
Button,
|
|
10641
|
+
{
|
|
10642
|
+
variant: "outline",
|
|
10643
|
+
size: "sm",
|
|
10644
|
+
onClick: () => setShowImportWizard(true),
|
|
10645
|
+
className: "gap-1",
|
|
10646
|
+
children: [
|
|
10647
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Scan, { className: "size-3" }),
|
|
10648
|
+
"Scan"
|
|
10649
|
+
]
|
|
10650
|
+
}
|
|
10651
|
+
),
|
|
10652
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(Button, { onClick: () => setShowForm(true), size: "sm", className: "gap-1", children: [
|
|
10653
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "size-4" }),
|
|
10654
|
+
"Add Provider"
|
|
10655
|
+
] })
|
|
10656
|
+
]
|
|
10657
|
+
}
|
|
10658
|
+
),
|
|
10808
10659
|
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: [
|
|
10809
10660
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono truncate", title: configPath, children: configPath }),
|
|
10810
10661
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -10892,6 +10743,23 @@ function ProvidersPanel({
|
|
|
10892
10743
|
)
|
|
10893
10744
|
] });
|
|
10894
10745
|
}
|
|
10746
|
+
const SETTINGS_SECTIONS = [
|
|
10747
|
+
{ value: "providers", label: "Providers" },
|
|
10748
|
+
{ value: "proxy", label: "Proxy" },
|
|
10749
|
+
{ value: "storage", label: "Storage" },
|
|
10750
|
+
{ value: "mcp", label: "MCP" },
|
|
10751
|
+
{ value: "onboarding", label: "Onboarding" }
|
|
10752
|
+
];
|
|
10753
|
+
function ResponsiveSettingsTabs() {
|
|
10754
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10755
|
+
TabsList,
|
|
10756
|
+
{
|
|
10757
|
+
"aria-label": "Settings sections",
|
|
10758
|
+
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",
|
|
10759
|
+
children: SETTINGS_SECTIONS.map((section) => /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: section.value, className: "min-w-0 w-full", children: section.label }, section.value))
|
|
10760
|
+
}
|
|
10761
|
+
);
|
|
10762
|
+
}
|
|
10895
10763
|
function SettingsDialog() {
|
|
10896
10764
|
const [open, setOpen] = reactExports.useState(false);
|
|
10897
10765
|
const [activeTab, setActiveTab] = reactExports.useState("providers");
|
|
@@ -10944,39 +10812,41 @@ function SettingsDialog() {
|
|
|
10944
10812
|
]
|
|
10945
10813
|
}
|
|
10946
10814
|
) }),
|
|
10947
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(DialogContent, { className: "flex max-h-[
|
|
10815
|
+
/* @__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: [
|
|
10948
10816
|
/* @__PURE__ */ jsxRuntimeExports.jsx(DialogHeader, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(DialogTitle, { children: "Settings" }) }),
|
|
10949
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
10950
|
-
|
|
10951
|
-
|
|
10952
|
-
|
|
10953
|
-
|
|
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
|
-
|
|
10817
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
10818
|
+
Tabs,
|
|
10819
|
+
{
|
|
10820
|
+
value: activeTab,
|
|
10821
|
+
onValueChange: setActiveTab,
|
|
10822
|
+
className: "min-h-0 min-w-0 flex-1 overflow-hidden",
|
|
10823
|
+
children: [
|
|
10824
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ResponsiveSettingsTabs, {}),
|
|
10825
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-4 min-w-0 flex-1 overflow-x-hidden overflow-y-auto pr-1 sm:pr-2", children: [
|
|
10826
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "providers", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10827
|
+
ProvidersPanel,
|
|
10828
|
+
{
|
|
10829
|
+
externalProviders: providers,
|
|
10830
|
+
isLoading,
|
|
10831
|
+
externalTestResults: testResults,
|
|
10832
|
+
externalTestingProviders: testingProviders,
|
|
10833
|
+
externalTestingTimeLeft: testingTimeLeft,
|
|
10834
|
+
onProvidersMutate: () => {
|
|
10835
|
+
return mutate();
|
|
10836
|
+
},
|
|
10837
|
+
onTestResultsChange: handleTestResultsChange,
|
|
10838
|
+
onTestingProvidersChange: handleTestingProvidersChange,
|
|
10839
|
+
onTestingTimeLeftChange: handleTestingTimeLeftChange
|
|
10840
|
+
}
|
|
10841
|
+
) }),
|
|
10842
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "proxy", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ProxySettingsTab, {}) }),
|
|
10843
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "storage", children: /* @__PURE__ */ jsxRuntimeExports.jsx(StorageSettingsTab, {}) }),
|
|
10844
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "mcp", children: /* @__PURE__ */ jsxRuntimeExports.jsx(McpSettingsTab, {}) }),
|
|
10845
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "onboarding", children: /* @__PURE__ */ jsxRuntimeExports.jsx(OnboardingSettingsTab, {}) })
|
|
10846
|
+
] })
|
|
10847
|
+
]
|
|
10848
|
+
}
|
|
10849
|
+
)
|
|
10980
10850
|
] })
|
|
10981
10851
|
] });
|
|
10982
10852
|
}
|
|
@@ -11118,7 +10988,7 @@ function CopyableSetupValue({
|
|
|
11118
10988
|
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: [
|
|
11119
10989
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-1 text-xs font-medium text-muted-foreground", children: label }),
|
|
11120
10990
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
11121
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "min-w-0 flex-1 truncate font-mono text-xs text-foreground", children: value }),
|
|
10991
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "min-w-0 flex-1 truncate font-mono text-xs text-foreground", title: value, children: value }),
|
|
11122
10992
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
11123
10993
|
Button,
|
|
11124
10994
|
{
|
|
@@ -11589,83 +11459,6 @@ function ProxySettingsTab() {
|
|
|
11589
11459
|
] })
|
|
11590
11460
|
] });
|
|
11591
11461
|
}
|
|
11592
|
-
const EcosystemPackageStateSchema = _enum([
|
|
11593
|
-
"installed",
|
|
11594
|
-
"update-available",
|
|
11595
|
-
"available",
|
|
11596
|
-
"planned",
|
|
11597
|
-
"unknown"
|
|
11598
|
-
]);
|
|
11599
|
-
const EcosystemPackageSchema = object({
|
|
11600
|
-
id: string(),
|
|
11601
|
-
name: string(),
|
|
11602
|
-
npmName: string(),
|
|
11603
|
-
capability: string(),
|
|
11604
|
-
description: string(),
|
|
11605
|
-
workflow: string(),
|
|
11606
|
-
installCommand: string(),
|
|
11607
|
-
state: EcosystemPackageStateSchema,
|
|
11608
|
-
installedVersion: string().nullable(),
|
|
11609
|
-
latestVersion: string().nullable(),
|
|
11610
|
-
primary: boolean()
|
|
11611
|
-
});
|
|
11612
|
-
const EcosystemRunnerPresetSchema = object({
|
|
11613
|
-
id: string(),
|
|
11614
|
-
name: string(),
|
|
11615
|
-
validatedVersion: string(),
|
|
11616
|
-
binary: string(),
|
|
11617
|
-
modelFlag: string(),
|
|
11618
|
-
variantFlag: string().nullable(),
|
|
11619
|
-
tools: array(string()),
|
|
11620
|
-
logDir: string(),
|
|
11621
|
-
skillsDir: string(),
|
|
11622
|
-
agentsDir: string()
|
|
11623
|
-
});
|
|
11624
|
-
const EcosystemRecipeSchema = object({
|
|
11625
|
-
id: string(),
|
|
11626
|
-
title: string(),
|
|
11627
|
-
stage: string(),
|
|
11628
|
-
packageId: string(),
|
|
11629
|
-
description: string(),
|
|
11630
|
-
command: string(),
|
|
11631
|
-
requiresSession: boolean(),
|
|
11632
|
-
runnable: boolean()
|
|
11633
|
-
});
|
|
11634
|
-
const EcosystemPackagesResponseSchema = object({
|
|
11635
|
-
checkedAt: string(),
|
|
11636
|
-
packages: array(EcosystemPackageSchema),
|
|
11637
|
-
runnerPresets: array(EcosystemRunnerPresetSchema),
|
|
11638
|
-
recipes: array(EcosystemRecipeSchema)
|
|
11639
|
-
});
|
|
11640
|
-
const EcosystemTaskActionSchema = _enum([
|
|
11641
|
-
"install",
|
|
11642
|
-
"upgrade",
|
|
11643
|
-
"help",
|
|
11644
|
-
"runner-presets",
|
|
11645
|
-
"recipe"
|
|
11646
|
-
]);
|
|
11647
|
-
const EcosystemTaskStatusSchema = _enum(["queued", "running", "succeeded", "failed"]);
|
|
11648
|
-
const EcosystemTaskSchema = object({
|
|
11649
|
-
id: string(),
|
|
11650
|
-
packageId: string(),
|
|
11651
|
-
npmName: string(),
|
|
11652
|
-
recipeId: string().nullable().default(null),
|
|
11653
|
-
action: EcosystemTaskActionSchema,
|
|
11654
|
-
status: EcosystemTaskStatusSchema,
|
|
11655
|
-
command: string(),
|
|
11656
|
-
output: string(),
|
|
11657
|
-
createdAt: string(),
|
|
11658
|
-
startedAt: string().nullable(),
|
|
11659
|
-
finishedAt: string().nullable(),
|
|
11660
|
-
exitCode: number().nullable(),
|
|
11661
|
-
error: string().nullable()
|
|
11662
|
-
});
|
|
11663
|
-
const EcosystemTaskResponseSchema = object({
|
|
11664
|
-
task: EcosystemTaskSchema
|
|
11665
|
-
});
|
|
11666
|
-
const EcosystemTasksResponseSchema = object({
|
|
11667
|
-
tasks: array(EcosystemTaskSchema)
|
|
11668
|
-
});
|
|
11669
11462
|
const WORKFLOWS = [
|
|
11670
11463
|
{
|
|
11671
11464
|
id: "observe",
|
|
@@ -11724,24 +11517,51 @@ async function fetchEcosystemTasks(url) {
|
|
|
11724
11517
|
(response) => `Failed to load ecosystem tasks: ${String(response.status)}`
|
|
11725
11518
|
);
|
|
11726
11519
|
}
|
|
11727
|
-
async function
|
|
11520
|
+
async function prepareEcosystemTask(packageId, action) {
|
|
11521
|
+
const endpoint = `/api/ecosystem/packages/${encodeURIComponent(packageId)}/${action}`;
|
|
11728
11522
|
const response = await fetchJson(
|
|
11729
|
-
|
|
11730
|
-
|
|
11731
|
-
{
|
|
11732
|
-
|
|
11523
|
+
endpoint,
|
|
11524
|
+
EcosystemExecutionConfirmationResponseSchema,
|
|
11525
|
+
{
|
|
11526
|
+
method: "POST",
|
|
11527
|
+
headers: { "content-type": "application/json" },
|
|
11528
|
+
body: JSON.stringify({ intent: "prepare" })
|
|
11529
|
+
},
|
|
11530
|
+
(result) => `Failed to prepare ecosystem task: ${String(result.status)}`
|
|
11733
11531
|
);
|
|
11734
|
-
return response.
|
|
11532
|
+
return { endpoint, confirmation: response.confirmation };
|
|
11735
11533
|
}
|
|
11736
|
-
async function
|
|
11534
|
+
async function prepareEcosystemRecipe(recipeId) {
|
|
11535
|
+
const endpoint = `/api/ecosystem/recipes/${encodeURIComponent(recipeId)}/run`;
|
|
11737
11536
|
const response = await fetchJson(
|
|
11738
|
-
|
|
11739
|
-
|
|
11740
|
-
{
|
|
11741
|
-
|
|
11742
|
-
|
|
11743
|
-
|
|
11744
|
-
}
|
|
11537
|
+
endpoint,
|
|
11538
|
+
EcosystemExecutionConfirmationResponseSchema,
|
|
11539
|
+
{
|
|
11540
|
+
method: "POST",
|
|
11541
|
+
headers: { "content-type": "application/json" },
|
|
11542
|
+
body: JSON.stringify({ intent: "prepare" })
|
|
11543
|
+
},
|
|
11544
|
+
(result) => `Failed to prepare ecosystem recipe: ${String(result.status)}`
|
|
11545
|
+
);
|
|
11546
|
+
return { endpoint, confirmation: response.confirmation };
|
|
11547
|
+
}
|
|
11548
|
+
async function confirmEcosystemExecution(pending) {
|
|
11549
|
+
const response = await fetchJson(
|
|
11550
|
+
pending.endpoint,
|
|
11551
|
+
EcosystemTaskResponseSchema,
|
|
11552
|
+
{
|
|
11553
|
+
method: "POST",
|
|
11554
|
+
headers: { "content-type": "application/json" },
|
|
11555
|
+
body: JSON.stringify({
|
|
11556
|
+
intent: "confirm",
|
|
11557
|
+
nonce: pending.confirmation.nonce,
|
|
11558
|
+
confirmation: pending.confirmation.phrase
|
|
11559
|
+
})
|
|
11560
|
+
},
|
|
11561
|
+
(result) => `Failed to start ecosystem task: ${String(result.status)}`
|
|
11562
|
+
);
|
|
11563
|
+
return response.task;
|
|
11564
|
+
}
|
|
11745
11565
|
function stateLabel(state) {
|
|
11746
11566
|
switch (state) {
|
|
11747
11567
|
case "installed":
|
|
@@ -12045,6 +11865,76 @@ function RecentTaskRow({
|
|
|
12045
11865
|
)
|
|
12046
11866
|
] });
|
|
12047
11867
|
}
|
|
11868
|
+
function ExecutionConfirmationDialog({
|
|
11869
|
+
pending,
|
|
11870
|
+
busy,
|
|
11871
|
+
onOpenChange,
|
|
11872
|
+
onConfirm
|
|
11873
|
+
}) {
|
|
11874
|
+
const plan = pending?.confirmation.plan ?? null;
|
|
11875
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Dialog, { open: pending !== null, onOpenChange, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogContent, { className: "max-w-xl", children: [
|
|
11876
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(DialogHeader, { children: [
|
|
11877
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(DialogTitle, { children: "Confirm local command" }),
|
|
11878
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(DialogDescription, { children: "Review the exact allowlisted action Agent Inspector will run on this machine." })
|
|
11879
|
+
] }),
|
|
11880
|
+
plan !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-3", children: [
|
|
11881
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid gap-2 text-xs sm:grid-cols-2", children: [
|
|
11882
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-md border bg-muted/30 p-3", children: [
|
|
11883
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-muted-foreground", children: "Source" }),
|
|
11884
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1 break-words font-medium", children: plan.source })
|
|
11885
|
+
] }),
|
|
11886
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-md border bg-muted/30 p-3", children: [
|
|
11887
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-muted-foreground", children: "Timeout" }),
|
|
11888
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-1 font-medium", children: [
|
|
11889
|
+
String(plan.timeoutMs / 1e3),
|
|
11890
|
+
" seconds"
|
|
11891
|
+
] })
|
|
11892
|
+
] }),
|
|
11893
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-md border bg-muted/30 p-3 sm:col-span-2", children: [
|
|
11894
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-muted-foreground", children: "Affected scope" }),
|
|
11895
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1 font-medium", children: plan.scope })
|
|
11896
|
+
] })
|
|
11897
|
+
] }),
|
|
11898
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
11899
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-1 text-xs font-medium", children: "Resolved command" }),
|
|
11900
|
+
/* @__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 })
|
|
11901
|
+
] }),
|
|
11902
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-xs text-muted-foreground", children: [
|
|
11903
|
+
"Confirmation phrase: ",
|
|
11904
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: pending?.confirmation.phrase }),
|
|
11905
|
+
". The one-time confirmation expires at",
|
|
11906
|
+
" ",
|
|
11907
|
+
new Date(pending?.confirmation.expiresAt ?? "").toLocaleTimeString(),
|
|
11908
|
+
"."
|
|
11909
|
+
] })
|
|
11910
|
+
] }),
|
|
11911
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", children: [
|
|
11912
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
11913
|
+
Button,
|
|
11914
|
+
{
|
|
11915
|
+
type: "button",
|
|
11916
|
+
variant: "outline",
|
|
11917
|
+
disabled: busy,
|
|
11918
|
+
onClick: () => onOpenChange(false),
|
|
11919
|
+
children: "Cancel"
|
|
11920
|
+
}
|
|
11921
|
+
),
|
|
11922
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
11923
|
+
Button,
|
|
11924
|
+
{
|
|
11925
|
+
type: "button",
|
|
11926
|
+
variant: "secondary",
|
|
11927
|
+
disabled: busy || plan === null,
|
|
11928
|
+
onClick: onConfirm,
|
|
11929
|
+
children: [
|
|
11930
|
+
busy ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-3.5 animate-spin" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Terminal, { className: "size-3.5" }),
|
|
11931
|
+
busy ? "Starting" : "Confirm & Run"
|
|
11932
|
+
]
|
|
11933
|
+
}
|
|
11934
|
+
)
|
|
11935
|
+
] })
|
|
11936
|
+
] }) });
|
|
11937
|
+
}
|
|
12048
11938
|
function AgentLabDialog({ currentSessionId, logCount }) {
|
|
12049
11939
|
const [open, setOpen] = reactExports.useState(false);
|
|
12050
11940
|
const [copied, setCopied] = reactExports.useState(false);
|
|
@@ -12052,6 +11942,8 @@ function AgentLabDialog({ currentSessionId, logCount }) {
|
|
|
12052
11942
|
const [copiedRecipeId, setCopiedRecipeId] = reactExports.useState(null);
|
|
12053
11943
|
const [activeTaskId, setActiveTaskId] = reactExports.useState(null);
|
|
12054
11944
|
const [taskError, setTaskError] = reactExports.useState(null);
|
|
11945
|
+
const [pendingExecution, setPendingExecution] = reactExports.useState(null);
|
|
11946
|
+
const [confirmationBusy, setConfirmationBusy] = reactExports.useState(false);
|
|
12055
11947
|
const response = useSWR("/api/ecosystem/packages", fetchEcosystemPackages, {
|
|
12056
11948
|
revalidateOnFocus: false,
|
|
12057
11949
|
revalidateIfStale: false
|
|
@@ -12101,12 +11993,10 @@ function AgentLabDialog({ currentSessionId, logCount }) {
|
|
|
12101
11993
|
};
|
|
12102
11994
|
const runRecipe = (recipe) => {
|
|
12103
11995
|
setTaskError(null);
|
|
12104
|
-
void
|
|
12105
|
-
|
|
12106
|
-
void activeTaskResponse.mutate({ task }, { revalidate: true });
|
|
12107
|
-
void tasksResponse.mutate();
|
|
11996
|
+
void prepareEcosystemRecipe(recipe.id).then((pending) => {
|
|
11997
|
+
setPendingExecution(pending);
|
|
12108
11998
|
}).catch((error) => {
|
|
12109
|
-
setTaskError(error instanceof Error ? error.message : "Failed to
|
|
11999
|
+
setTaskError(error instanceof Error ? error.message : "Failed to prepare ecosystem recipe");
|
|
12110
12000
|
});
|
|
12111
12001
|
};
|
|
12112
12002
|
const activeTask = activeTaskResponse.data?.task ?? null;
|
|
@@ -12118,12 +12008,25 @@ function AgentLabDialog({ currentSessionId, logCount }) {
|
|
|
12118
12008
|
}, [activeTask, response, tasksResponse]);
|
|
12119
12009
|
const handleStartTask = (packageId, action) => {
|
|
12120
12010
|
setTaskError(null);
|
|
12121
|
-
void
|
|
12011
|
+
void prepareEcosystemTask(packageId, action).then((pending) => {
|
|
12012
|
+
setPendingExecution(pending);
|
|
12013
|
+
}).catch((error) => {
|
|
12014
|
+
setTaskError(error instanceof Error ? error.message : "Failed to prepare ecosystem task");
|
|
12015
|
+
});
|
|
12016
|
+
};
|
|
12017
|
+
const confirmPendingExecution = () => {
|
|
12018
|
+
if (pendingExecution === null) return;
|
|
12019
|
+
setTaskError(null);
|
|
12020
|
+
setConfirmationBusy(true);
|
|
12021
|
+
void confirmEcosystemExecution(pendingExecution).then((task) => {
|
|
12122
12022
|
setActiveTaskId(task.id);
|
|
12023
|
+
setPendingExecution(null);
|
|
12123
12024
|
void activeTaskResponse.mutate({ task }, { revalidate: true });
|
|
12124
12025
|
void tasksResponse.mutate();
|
|
12125
12026
|
}).catch((error) => {
|
|
12126
12027
|
setTaskError(error instanceof Error ? error.message : "Failed to start ecosystem task");
|
|
12028
|
+
}).finally(() => {
|
|
12029
|
+
setConfirmationBusy(false);
|
|
12127
12030
|
});
|
|
12128
12031
|
};
|
|
12129
12032
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(Dialog, { open, onOpenChange: setOpen, children: [
|
|
@@ -12284,857 +12187,20 @@ function AgentLabDialog({ currentSessionId, logCount }) {
|
|
|
12284
12187
|
] }),
|
|
12285
12188
|
/* @__PURE__ */ jsxRuntimeExports.jsx(TaskConsole, { task: activeTask })
|
|
12286
12189
|
] })
|
|
12287
|
-
] })
|
|
12288
|
-
] });
|
|
12289
|
-
}
|
|
12290
|
-
const INSPECTOR_PET_SIZE = 112;
|
|
12291
|
-
const INSPECTOR_PET_MARGIN = 14;
|
|
12292
|
-
const INSPECTOR_PET_EDGE_GAP = 20;
|
|
12293
|
-
const INSPECTOR_PET_MIN_STEP = 36;
|
|
12294
|
-
const INSPECTOR_PET_MAX_STEP = 92;
|
|
12295
|
-
const INSPECTOR_PET_SLEEP_AFTER_MS = 45e3;
|
|
12296
|
-
const INSPECTOR_PET_PANEL_WIDTH = 192;
|
|
12297
|
-
const INSPECTOR_PET_PANEL_HEIGHT = 68;
|
|
12298
|
-
const INSPECTOR_PET_PANEL_GAP = 10;
|
|
12299
|
-
const INSPECTOR_PET_VERTICAL_SAFE_MARGIN = 78;
|
|
12300
|
-
function viewportScale(viewport) {
|
|
12301
|
-
const scale = viewport.scale ?? 1;
|
|
12302
|
-
return Number.isFinite(scale) && scale > 0 ? scale : 1;
|
|
12303
|
-
}
|
|
12304
|
-
function scaledMetric(value, viewport) {
|
|
12305
|
-
return value * viewportScale(viewport);
|
|
12306
|
-
}
|
|
12307
|
-
function clampUnit(value) {
|
|
12308
|
-
return Math.min(Math.max(value, 0), 1);
|
|
12309
|
-
}
|
|
12310
|
-
function maximumPetX(viewport) {
|
|
12311
|
-
const edgeGap = scaledMetric(INSPECTOR_PET_EDGE_GAP, viewport);
|
|
12312
|
-
return Math.max(edgeGap, viewport.width - scaledMetric(INSPECTOR_PET_SIZE, viewport) - edgeGap);
|
|
12313
|
-
}
|
|
12314
|
-
function maximumPetY(viewport) {
|
|
12315
|
-
const edgeGap = scaledMetric(INSPECTOR_PET_EDGE_GAP, viewport);
|
|
12316
|
-
return Math.max(edgeGap, viewport.height - scaledMetric(INSPECTOR_PET_SIZE, viewport) - edgeGap);
|
|
12317
|
-
}
|
|
12318
|
-
function clampInspectorPetPosition(position, viewport) {
|
|
12319
|
-
const edgeGap = scaledMetric(INSPECTOR_PET_EDGE_GAP, viewport);
|
|
12320
|
-
return {
|
|
12321
|
-
x: Math.min(Math.max(position.x, edgeGap), maximumPetX(viewport)),
|
|
12322
|
-
y: Math.min(Math.max(position.y, edgeGap), maximumPetY(viewport))
|
|
12323
|
-
};
|
|
12324
|
-
}
|
|
12325
|
-
function nearestInspectorPetEdge(position, viewport) {
|
|
12326
|
-
const clamped = clampInspectorPetPosition(position, viewport);
|
|
12327
|
-
const edgeGap = scaledMetric(INSPECTOR_PET_EDGE_GAP, viewport);
|
|
12328
|
-
const distances = [
|
|
12329
|
-
{ edge: "left", distance: clamped.x - edgeGap },
|
|
12330
|
-
{ edge: "right", distance: maximumPetX(viewport) - clamped.x },
|
|
12331
|
-
{ edge: "top", distance: clamped.y - edgeGap },
|
|
12332
|
-
{ edge: "bottom", distance: maximumPetY(viewport) - clamped.y }
|
|
12333
|
-
];
|
|
12334
|
-
return distances.reduce((best, current) => current.distance < best.distance ? current : best).edge;
|
|
12335
|
-
}
|
|
12336
|
-
function snapInspectorPetToEdge(position, viewport) {
|
|
12337
|
-
const clamped = clampInspectorPetPosition(position, viewport);
|
|
12338
|
-
const edge = nearestInspectorPetEdge(clamped, viewport);
|
|
12339
|
-
const edgeGap = scaledMetric(INSPECTOR_PET_EDGE_GAP, viewport);
|
|
12340
|
-
switch (edge) {
|
|
12341
|
-
case "left":
|
|
12342
|
-
return { x: edgeGap, y: clamped.y };
|
|
12343
|
-
case "right":
|
|
12344
|
-
return { x: maximumPetX(viewport), y: clamped.y };
|
|
12345
|
-
case "top":
|
|
12346
|
-
return { x: clamped.x, y: edgeGap };
|
|
12347
|
-
case "bottom":
|
|
12348
|
-
return { x: clamped.x, y: maximumPetY(viewport) };
|
|
12349
|
-
}
|
|
12350
|
-
}
|
|
12351
|
-
function randomInspectorPetEdgePosition(viewport, positionSample) {
|
|
12352
|
-
const maxX = maximumPetX(viewport);
|
|
12353
|
-
const maxY = maximumPetY(viewport);
|
|
12354
|
-
const edgeGap = scaledMetric(INSPECTOR_PET_EDGE_GAP, viewport);
|
|
12355
|
-
return {
|
|
12356
|
-
x: edgeGap + clampUnit(positionSample) * (maxX - edgeGap),
|
|
12357
|
-
y: maxY
|
|
12358
|
-
};
|
|
12359
|
-
}
|
|
12360
|
-
function nextInspectorPetWalkingPosition(position, viewport, stepSample, directionSample) {
|
|
12361
|
-
const clamped = snapInspectorPetToEdge(position, viewport);
|
|
12362
|
-
const step = scaledMetric(INSPECTOR_PET_MIN_STEP, viewport) + clampUnit(stepSample) * scaledMetric(INSPECTOR_PET_MAX_STEP - INSPECTOR_PET_MIN_STEP, viewport);
|
|
12363
|
-
const direction = directionSample >= 0.5 ? 1 : -1;
|
|
12364
|
-
const edge = nearestInspectorPetEdge(clamped, viewport);
|
|
12365
|
-
const maxX = maximumPetX(viewport);
|
|
12366
|
-
const maxY = maximumPetY(viewport);
|
|
12367
|
-
const edgeGap = scaledMetric(INSPECTOR_PET_EDGE_GAP, viewport);
|
|
12368
|
-
const minimumSafeY = Math.min(scaledMetric(INSPECTOR_PET_VERTICAL_SAFE_MARGIN, viewport), maxY);
|
|
12369
|
-
switch (edge) {
|
|
12370
|
-
case "left":
|
|
12371
|
-
return {
|
|
12372
|
-
x: edgeGap,
|
|
12373
|
-
y: Math.min(Math.max(clamped.y + step * direction, minimumSafeY), maxY)
|
|
12374
|
-
};
|
|
12375
|
-
case "right":
|
|
12376
|
-
return {
|
|
12377
|
-
x: maxX,
|
|
12378
|
-
y: Math.min(Math.max(clamped.y + step * direction, minimumSafeY), maxY)
|
|
12379
|
-
};
|
|
12380
|
-
case "top":
|
|
12381
|
-
return {
|
|
12382
|
-
x: Math.min(Math.max(clamped.x + step * direction, edgeGap), maxX),
|
|
12383
|
-
y: edgeGap
|
|
12384
|
-
};
|
|
12385
|
-
case "bottom":
|
|
12386
|
-
return {
|
|
12387
|
-
x: Math.min(Math.max(clamped.x + step * direction, edgeGap), maxX),
|
|
12388
|
-
y: maxY
|
|
12389
|
-
};
|
|
12390
|
-
}
|
|
12391
|
-
}
|
|
12392
|
-
function inspectorPetPanelPosition(position, viewport) {
|
|
12393
|
-
const edge = nearestInspectorPetEdge(position, viewport);
|
|
12394
|
-
const petSize = scaledMetric(INSPECTOR_PET_SIZE, viewport);
|
|
12395
|
-
const panelWidth = scaledMetric(INSPECTOR_PET_PANEL_WIDTH, viewport);
|
|
12396
|
-
const panelHeight = scaledMetric(INSPECTOR_PET_PANEL_HEIGHT, viewport);
|
|
12397
|
-
const panelGap = scaledMetric(INSPECTOR_PET_PANEL_GAP, viewport);
|
|
12398
|
-
const margin = scaledMetric(INSPECTOR_PET_MARGIN, viewport);
|
|
12399
|
-
let x = position.x + petSize / 2 - panelWidth / 2;
|
|
12400
|
-
let y = position.y + petSize / 2 - panelHeight / 2;
|
|
12401
|
-
switch (edge) {
|
|
12402
|
-
case "left":
|
|
12403
|
-
x = position.x + petSize + panelGap;
|
|
12404
|
-
break;
|
|
12405
|
-
case "right":
|
|
12406
|
-
x = position.x - panelWidth - panelGap;
|
|
12407
|
-
break;
|
|
12408
|
-
case "top":
|
|
12409
|
-
y = position.y + petSize + panelGap;
|
|
12410
|
-
break;
|
|
12411
|
-
case "bottom":
|
|
12412
|
-
y = position.y - panelHeight - panelGap;
|
|
12413
|
-
break;
|
|
12414
|
-
}
|
|
12415
|
-
return {
|
|
12416
|
-
x: Math.min(Math.max(x, margin), Math.max(margin, viewport.width - panelWidth - margin)),
|
|
12417
|
-
y: Math.min(Math.max(y, margin), Math.max(margin, viewport.height - panelHeight - margin))
|
|
12418
|
-
};
|
|
12419
|
-
}
|
|
12420
|
-
function latestCapturedLog(logs) {
|
|
12421
|
-
let latest = null;
|
|
12422
|
-
for (const log of logs) {
|
|
12423
|
-
if (latest === null || log.id > latest.id) latest = log;
|
|
12424
|
-
}
|
|
12425
|
-
return latest;
|
|
12426
|
-
}
|
|
12427
|
-
function logNeedsAttention(log) {
|
|
12428
|
-
const hasHttpError = log.responseStatus !== null && log.responseStatus >= 400;
|
|
12429
|
-
const hasStreamError = log.error !== null && log.error !== void 0 && log.error !== "";
|
|
12430
|
-
return hasHttpError || hasStreamError;
|
|
12431
|
-
}
|
|
12432
|
-
function resolveInspectorPetStatus(logs, nowMs) {
|
|
12433
|
-
const pendingCount = logs.filter((log) => log.responseStatus === null).length;
|
|
12434
|
-
const capturedCount = logs.length;
|
|
12435
|
-
if (pendingCount > 0) {
|
|
12436
|
-
return {
|
|
12437
|
-
mood: "active",
|
|
12438
|
-
label: `${String(pendingCount)} request${pendingCount === 1 ? "" : "s"} in flight`,
|
|
12439
|
-
pendingCount,
|
|
12440
|
-
capturedCount
|
|
12441
|
-
};
|
|
12442
|
-
}
|
|
12443
|
-
const latest = latestCapturedLog(logs);
|
|
12444
|
-
if (latest !== null && logNeedsAttention(latest)) {
|
|
12445
|
-
return {
|
|
12446
|
-
mood: "attention",
|
|
12447
|
-
label: "Latest request needs attention",
|
|
12448
|
-
pendingCount,
|
|
12449
|
-
capturedCount
|
|
12450
|
-
};
|
|
12451
|
-
}
|
|
12452
|
-
if (latest === null) {
|
|
12453
|
-
return {
|
|
12454
|
-
mood: "idle",
|
|
12455
|
-
label: "Waiting for traffic",
|
|
12456
|
-
pendingCount,
|
|
12457
|
-
capturedCount
|
|
12458
|
-
};
|
|
12459
|
-
}
|
|
12460
|
-
const latestTimestamp2 = Date.parse(latest.timestamp);
|
|
12461
|
-
if (Number.isFinite(latestTimestamp2) && nowMs - latestTimestamp2 >= INSPECTOR_PET_SLEEP_AFTER_MS) {
|
|
12462
|
-
return {
|
|
12463
|
-
mood: "sleeping",
|
|
12464
|
-
label: "All quiet",
|
|
12465
|
-
pendingCount,
|
|
12466
|
-
capturedCount
|
|
12467
|
-
};
|
|
12468
|
-
}
|
|
12469
|
-
return {
|
|
12470
|
-
mood: "idle",
|
|
12471
|
-
label: "Watching the session",
|
|
12472
|
-
pendingCount,
|
|
12473
|
-
capturedCount
|
|
12474
|
-
};
|
|
12475
|
-
}
|
|
12476
|
-
function createRod(start, end, radius, material) {
|
|
12477
|
-
const direction = end.clone().sub(start);
|
|
12478
|
-
const length = direction.length();
|
|
12479
|
-
const rod = new Mesh(new CylinderGeometry(radius, radius * 0.9, length, 12), material);
|
|
12480
|
-
rod.position.copy(start.clone().add(end).multiplyScalar(0.5));
|
|
12481
|
-
rod.quaternion.setFromUnitVectors(new Vector3(0, 1, 0), direction.normalize());
|
|
12482
|
-
return rod;
|
|
12483
|
-
}
|
|
12484
|
-
function addClaw(root, side, shellMaterial, accentMaterial) {
|
|
12485
|
-
const clawScale = side < 0 ? 1.5 : 0.68;
|
|
12486
|
-
const clawGroup = new Group();
|
|
12487
|
-
const pincers = [];
|
|
12488
|
-
root.add(clawGroup);
|
|
12489
|
-
const shoulder = new Vector3(side * 1.2, 0.25, -0.05);
|
|
12490
|
-
const wrist = new Vector3(side * (1.65 + clawScale * 0.18), 0.5, 0);
|
|
12491
|
-
const arm = createRod(shoulder, wrist, 0.16 * clawScale, accentMaterial);
|
|
12492
|
-
clawGroup.add(arm);
|
|
12493
|
-
const palm = new Mesh(new SphereGeometry(0.55, 24, 16), shellMaterial);
|
|
12494
|
-
palm.position.set(side * (1.95 + clawScale * 0.16), 0.62, 0.05);
|
|
12495
|
-
palm.scale.set(1.05 * clawScale, 0.72 * clawScale, 0.55 * clawScale);
|
|
12496
|
-
clawGroup.add(palm);
|
|
12497
|
-
for (const pincerDirection of [-1, 1]) {
|
|
12498
|
-
const pincer = new Mesh(new SphereGeometry(0.36, 20, 14), accentMaterial);
|
|
12499
|
-
pincer.position.set(
|
|
12500
|
-
side * (2.22 + clawScale * 0.26),
|
|
12501
|
-
0.62 + pincerDirection * 0.24 * clawScale,
|
|
12502
|
-
0.08
|
|
12503
|
-
);
|
|
12504
|
-
pincer.scale.set(1.05 * clawScale, 0.34 * clawScale, 0.42 * clawScale);
|
|
12505
|
-
pincer.rotation.z = pincerDirection * side * 0.42;
|
|
12506
|
-
clawGroup.add(pincer);
|
|
12507
|
-
pincers.push({
|
|
12508
|
-
direction: pincerDirection,
|
|
12509
|
-
mesh: pincer,
|
|
12510
|
-
restRotationZ: pincer.rotation.z,
|
|
12511
|
-
restY: pincer.position.y
|
|
12512
|
-
});
|
|
12513
|
-
}
|
|
12514
|
-
return { group: clawGroup, pincers, scale: clawScale };
|
|
12515
|
-
}
|
|
12516
|
-
function pinchPulse(cycleTime, start, duration) {
|
|
12517
|
-
const progress = (cycleTime - start) / duration;
|
|
12518
|
-
if (progress <= 0 || progress >= 1) return 0;
|
|
12519
|
-
return Math.sin(progress * Math.PI);
|
|
12520
|
-
}
|
|
12521
|
-
function dominantClawGrip(elapsed) {
|
|
12522
|
-
const cycleTime = elapsed % 6.8;
|
|
12523
|
-
return Math.max(pinchPulse(cycleTime, 0.72, 0.82), pinchPulse(cycleTime, 1.72, 0.68));
|
|
12524
|
-
}
|
|
12525
|
-
function addEyes(root, shellMaterial, eyeMaterial) {
|
|
12526
|
-
const eyes = [];
|
|
12527
|
-
for (const side of [-1, 1]) {
|
|
12528
|
-
const stalkStart = new Vector3(side * 0.48, 0.68, 0.05);
|
|
12529
|
-
const stalkEnd = new Vector3(side * 0.1, 0.82, 0.07);
|
|
12530
|
-
const eyeGroup = new Group();
|
|
12531
|
-
eyeGroup.position.copy(stalkStart);
|
|
12532
|
-
eyeGroup.add(createRod(new Vector3(0, 0, 0), stalkEnd, 0.1, shellMaterial));
|
|
12533
|
-
const eye = new Mesh(new SphereGeometry(0.24, 20, 16), eyeMaterial);
|
|
12534
|
-
eye.position.copy(stalkEnd);
|
|
12535
|
-
eye.scale.set(1, 1, 0.85);
|
|
12536
|
-
eyeGroup.add(eye);
|
|
12537
|
-
const pupil = new Mesh(
|
|
12538
|
-
new SphereGeometry(0.105, 16, 12),
|
|
12539
|
-
new MeshPhysicalMaterial({ color: 1120295, roughness: 0.25 })
|
|
12540
|
-
);
|
|
12541
|
-
const pupilRest = new Vector3(stalkEnd.x, stalkEnd.y, stalkEnd.z + 0.2);
|
|
12542
|
-
pupil.position.copy(pupilRest);
|
|
12543
|
-
eyeGroup.add(pupil);
|
|
12544
|
-
root.add(eyeGroup);
|
|
12545
|
-
eyes.push({
|
|
12546
|
-
group: eyeGroup,
|
|
12547
|
-
phase: side < 0 ? 0 : Math.PI / 3,
|
|
12548
|
-
pupil,
|
|
12549
|
-
pupilRest
|
|
12550
|
-
});
|
|
12551
|
-
}
|
|
12552
|
-
return eyes;
|
|
12553
|
-
}
|
|
12554
|
-
function addLegs(root, legMaterial) {
|
|
12555
|
-
const legs = [];
|
|
12556
|
-
for (const side of [-1, 1]) {
|
|
12557
|
-
for (let index = 0; index < 4; index += 1) {
|
|
12558
|
-
const leg = new Group();
|
|
12559
|
-
const baseY = -0.3 - index * 0.22;
|
|
12560
|
-
leg.position.set(side * (0.8 + index * 0.12), baseY, -0.18);
|
|
12561
|
-
leg.add(
|
|
12562
|
-
createRod(
|
|
12563
|
-
new Vector3(0, 0, 0),
|
|
12564
|
-
new Vector3(side * (0.62 + index * 0.06), -0.34, 0),
|
|
12565
|
-
0.095,
|
|
12566
|
-
legMaterial
|
|
12567
|
-
)
|
|
12568
|
-
);
|
|
12569
|
-
leg.add(
|
|
12570
|
-
createRod(
|
|
12571
|
-
new Vector3(side * (0.58 + index * 0.06), -0.31, 0),
|
|
12572
|
-
new Vector3(side * (1.02 + index * 0.08), -0.88 + index * 0.07, 0.04),
|
|
12573
|
-
0.075,
|
|
12574
|
-
legMaterial
|
|
12575
|
-
)
|
|
12576
|
-
);
|
|
12577
|
-
root.add(leg);
|
|
12578
|
-
legs.push({ group: leg, phase: index * Math.PI + (side > 0 ? Math.PI / 2 : 0), side });
|
|
12579
|
-
}
|
|
12580
|
-
}
|
|
12581
|
-
return legs;
|
|
12582
|
-
}
|
|
12583
|
-
function createCrabScene(scene) {
|
|
12584
|
-
const shellMaterial = new MeshPhysicalMaterial({
|
|
12585
|
-
color: 16096779,
|
|
12586
|
-
roughness: 0.34,
|
|
12587
|
-
metalness: 0.04,
|
|
12588
|
-
clearcoat: 0.78,
|
|
12589
|
-
clearcoatRoughness: 0.18,
|
|
12590
|
-
emissive: new Color(0),
|
|
12591
|
-
emissiveIntensity: 0
|
|
12592
|
-
});
|
|
12593
|
-
const accentMaterial = new MeshPhysicalMaterial({
|
|
12594
|
-
color: 16486972,
|
|
12595
|
-
roughness: 0.42,
|
|
12596
|
-
metalness: 0.02,
|
|
12597
|
-
clearcoat: 0.52,
|
|
12598
|
-
clearcoatRoughness: 0.28
|
|
12599
|
-
});
|
|
12600
|
-
const legMaterial = new MeshPhysicalMaterial({
|
|
12601
|
-
color: 14251782,
|
|
12602
|
-
roughness: 0.48,
|
|
12603
|
-
clearcoat: 0.35,
|
|
12604
|
-
clearcoatRoughness: 0.35
|
|
12605
|
-
});
|
|
12606
|
-
const eyeMaterial = new MeshPhysicalMaterial({
|
|
12607
|
-
color: 16776171,
|
|
12608
|
-
roughness: 0.22,
|
|
12609
|
-
clearcoat: 0.8,
|
|
12610
|
-
clearcoatRoughness: 0.12
|
|
12611
|
-
});
|
|
12612
|
-
const root = new Group();
|
|
12613
|
-
root.rotation.x = -0.12;
|
|
12614
|
-
root.rotation.y = -0.08;
|
|
12615
|
-
root.scale.setScalar(1.08);
|
|
12616
|
-
scene.add(root);
|
|
12617
|
-
const shadow = new Mesh(
|
|
12618
|
-
new CircleGeometry(1.65, 40),
|
|
12619
|
-
new MeshBasicMaterial({ color: 1120295, transparent: true, opacity: 0.16, depthWrite: false })
|
|
12620
|
-
);
|
|
12621
|
-
shadow.position.set(0, -1.33, -0.65);
|
|
12622
|
-
shadow.scale.set(1.4, 0.34, 1);
|
|
12623
|
-
root.add(shadow);
|
|
12624
|
-
const body = new Mesh(new SphereGeometry(1, 36, 24), shellMaterial);
|
|
12625
|
-
body.position.set(0, 0.02, 0);
|
|
12626
|
-
body.scale.set(1.58, 0.92, 0.68);
|
|
12627
|
-
root.add(body);
|
|
12628
|
-
const lowerShell = new Mesh(new SphereGeometry(0.92, 28, 20), accentMaterial);
|
|
12629
|
-
lowerShell.position.set(0, -0.48, 0.22);
|
|
12630
|
-
lowerShell.scale.set(1.28, 0.42, 0.56);
|
|
12631
|
-
root.add(lowerShell);
|
|
12632
|
-
const dominantClaw = addClaw(root, -1, shellMaterial, accentMaterial);
|
|
12633
|
-
addClaw(root, 1, shellMaterial, accentMaterial);
|
|
12634
|
-
const eyes = addEyes(root, shellMaterial, eyeMaterial);
|
|
12635
|
-
const legs = addLegs(root, legMaterial);
|
|
12636
|
-
scene.add(new AmbientLight(16775149, 1.65));
|
|
12637
|
-
scene.add(new HemisphereLight(16775149, 1515571, 2.15));
|
|
12638
|
-
const keyLight = new DirectionalLight(16777215, 3.6);
|
|
12639
|
-
keyLight.position.set(3.5, 4.5, 6);
|
|
12640
|
-
scene.add(keyLight);
|
|
12641
|
-
const fillLight = new DirectionalLight(16498468, 1.35);
|
|
12642
|
-
fillLight.position.set(-4, 1.5, 4);
|
|
12643
|
-
scene.add(fillLight);
|
|
12644
|
-
const rimLight = new PointLight(16096779, 1.8, 12, 2);
|
|
12645
|
-
rimLight.position.set(0, 1.8, 4.5);
|
|
12646
|
-
scene.add(rimLight);
|
|
12647
|
-
return { bodyMaterial: shellMaterial, dominantClaw, eyes, legs, rimLight, root };
|
|
12648
|
-
}
|
|
12649
|
-
function moodColor(mood) {
|
|
12650
|
-
switch (mood) {
|
|
12651
|
-
case "active":
|
|
12652
|
-
return 2282478;
|
|
12653
|
-
case "attention":
|
|
12654
|
-
return 15680580;
|
|
12655
|
-
case "idle":
|
|
12656
|
-
return 16096779;
|
|
12657
|
-
case "sleeping":
|
|
12658
|
-
return 9741240;
|
|
12659
|
-
}
|
|
12660
|
-
}
|
|
12661
|
-
function isDisposableMesh(object2) {
|
|
12662
|
-
return object2 instanceof Mesh;
|
|
12663
|
-
}
|
|
12664
|
-
function disposeScene(scene) {
|
|
12665
|
-
const materials = /* @__PURE__ */ new Set();
|
|
12666
|
-
scene.traverse((object2) => {
|
|
12667
|
-
if (!isDisposableMesh(object2)) return;
|
|
12668
|
-
object2.geometry.dispose();
|
|
12669
|
-
const material = object2.material;
|
|
12670
|
-
if (Array.isArray(material)) {
|
|
12671
|
-
for (const item of material) materials.add(item);
|
|
12672
|
-
return;
|
|
12673
|
-
}
|
|
12674
|
-
materials.add(material);
|
|
12675
|
-
});
|
|
12676
|
-
for (const material of materials) material.dispose();
|
|
12677
|
-
}
|
|
12678
|
-
function InspectorPetCrab3D({
|
|
12679
|
-
mood,
|
|
12680
|
-
moving,
|
|
12681
|
-
reduceMotion
|
|
12682
|
-
}) {
|
|
12683
|
-
const canvasRef = reactExports.useRef(null);
|
|
12684
|
-
const moodRef = reactExports.useRef(mood);
|
|
12685
|
-
const movingRef = reactExports.useRef(moving);
|
|
12686
|
-
const reduceMotionRef = reactExports.useRef(reduceMotion);
|
|
12687
|
-
const [renderFailed, setRenderFailed] = reactExports.useState(false);
|
|
12688
|
-
reactExports.useEffect(() => {
|
|
12689
|
-
moodRef.current = mood;
|
|
12690
|
-
}, [mood]);
|
|
12691
|
-
reactExports.useEffect(() => {
|
|
12692
|
-
movingRef.current = moving;
|
|
12693
|
-
}, [moving]);
|
|
12694
|
-
reactExports.useEffect(() => {
|
|
12695
|
-
reduceMotionRef.current = reduceMotion;
|
|
12696
|
-
}, [reduceMotion]);
|
|
12697
|
-
reactExports.useEffect(() => {
|
|
12698
|
-
const canvas = canvasRef.current;
|
|
12699
|
-
if (canvas === null) return void 0;
|
|
12700
|
-
let renderer;
|
|
12701
|
-
try {
|
|
12702
|
-
renderer = new WebGLRenderer({
|
|
12703
|
-
alpha: true,
|
|
12704
|
-
antialias: true,
|
|
12705
|
-
canvas,
|
|
12706
|
-
powerPreference: "low-power",
|
|
12707
|
-
preserveDrawingBuffer: true
|
|
12708
|
-
});
|
|
12709
|
-
} catch {
|
|
12710
|
-
setRenderFailed(true);
|
|
12711
|
-
return void 0;
|
|
12712
|
-
}
|
|
12713
|
-
renderer.setClearColor(0, 0);
|
|
12714
|
-
renderer.outputColorSpace = SRGBColorSpace;
|
|
12715
|
-
renderer.toneMapping = ACESFilmicToneMapping;
|
|
12716
|
-
renderer.toneMappingExposure = 1.18;
|
|
12717
|
-
const scene = new Scene();
|
|
12718
|
-
const camera = new OrthographicCamera(-3.65, 3.65, 3.65, -3.65, 0.1, 20);
|
|
12719
|
-
camera.position.set(0, 0.05, 8);
|
|
12720
|
-
camera.lookAt(0, 0, 0);
|
|
12721
|
-
const parts = createCrabScene(scene);
|
|
12722
|
-
const startedAt = window.performance.now();
|
|
12723
|
-
let lastFrameAt = 0;
|
|
12724
|
-
const renderFrame = (timestamp) => {
|
|
12725
|
-
if (timestamp - lastFrameAt < 32) return;
|
|
12726
|
-
lastFrameAt = timestamp;
|
|
12727
|
-
const elapsed = (timestamp - startedAt) / 1e3;
|
|
12728
|
-
const motionAllowed = !reduceMotionRef.current;
|
|
12729
|
-
const gait = movingRef.current ? 1 : moodRef.current === "active" ? 0.42 : 0;
|
|
12730
|
-
const idleMotion = motionAllowed ? Math.sin(elapsed * 0.85) : 0;
|
|
12731
|
-
const stepMotion = motionAllowed ? Math.sin(elapsed * 3.4) : 0;
|
|
12732
|
-
const clawGrip = motionAllowed ? dominantClawGrip(elapsed) : 0;
|
|
12733
|
-
parts.root.position.y = idleMotion * 0.035 + Math.abs(stepMotion) * 0.055 * gait;
|
|
12734
|
-
parts.root.rotation.y = -0.08 + idleMotion * 0.055;
|
|
12735
|
-
parts.root.rotation.z = stepMotion * 0.028 * gait;
|
|
12736
|
-
parts.dominantClaw.group.rotation.z = -clawGrip * 0.035;
|
|
12737
|
-
for (const pincer of parts.dominantClaw.pincers) {
|
|
12738
|
-
pincer.mesh.position.y = pincer.restY - pincer.direction * parts.dominantClaw.scale * 0.16 * clawGrip;
|
|
12739
|
-
pincer.mesh.rotation.z = pincer.restRotationZ * (1 - clawGrip * 0.72);
|
|
12740
|
-
}
|
|
12741
|
-
for (const leg of parts.legs) {
|
|
12742
|
-
leg.group.rotation.z = motionAllowed && gait > 0 ? Math.sin(elapsed * 4.25 + leg.phase) * 0.2 * leg.side * gait : 0;
|
|
12743
|
-
leg.group.rotation.x = motionAllowed && gait > 0 ? stepMotion * 0.045 * gait : 0;
|
|
12744
|
-
}
|
|
12745
|
-
for (const eye of parts.eyes) {
|
|
12746
|
-
const gaze = motionAllowed ? Math.sin(elapsed * 0.72 + eye.phase) : 0;
|
|
12747
|
-
const lift = motionAllowed ? Math.cos(elapsed * 0.9 + eye.phase) : 0;
|
|
12748
|
-
eye.group.rotation.z = gaze * 0.075;
|
|
12749
|
-
eye.group.rotation.x = lift * 0.025;
|
|
12750
|
-
eye.pupil.position.set(
|
|
12751
|
-
eye.pupilRest.x + gaze * 0.055,
|
|
12752
|
-
eye.pupilRest.y + lift * 0.025,
|
|
12753
|
-
eye.pupilRest.z
|
|
12754
|
-
);
|
|
12755
|
-
}
|
|
12756
|
-
const color = moodColor(moodRef.current);
|
|
12757
|
-
parts.rimLight.color.setHex(color);
|
|
12758
|
-
parts.rimLight.intensity = moodRef.current === "attention" ? 3.2 : 1.8;
|
|
12759
|
-
parts.bodyMaterial.emissive.setHex(color);
|
|
12760
|
-
parts.bodyMaterial.emissiveIntensity = moodRef.current === "active" ? 0.12 : 0.035;
|
|
12761
|
-
renderer.render(scene, camera);
|
|
12762
|
-
};
|
|
12763
|
-
const resize = () => {
|
|
12764
|
-
const width = Math.max(canvas.clientWidth, 1);
|
|
12765
|
-
const height = Math.max(canvas.clientHeight, 1);
|
|
12766
|
-
renderer.setDrawingBufferSize(width, height, Math.min(window.devicePixelRatio, 2));
|
|
12767
|
-
renderer.render(scene, camera);
|
|
12768
|
-
};
|
|
12769
|
-
const resizeObserver = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(resize);
|
|
12770
|
-
if (resizeObserver === null) {
|
|
12771
|
-
window.addEventListener("resize", resize);
|
|
12772
|
-
} else {
|
|
12773
|
-
resizeObserver.observe(canvas);
|
|
12774
|
-
}
|
|
12775
|
-
resize();
|
|
12776
|
-
const handleContextLost = (event) => {
|
|
12777
|
-
event.preventDefault();
|
|
12778
|
-
setRenderFailed(true);
|
|
12779
|
-
};
|
|
12780
|
-
canvas.addEventListener("webglcontextlost", handleContextLost);
|
|
12781
|
-
renderer.setAnimationLoop(renderFrame);
|
|
12782
|
-
return () => {
|
|
12783
|
-
renderer.setAnimationLoop(null);
|
|
12784
|
-
if (resizeObserver === null) {
|
|
12785
|
-
window.removeEventListener("resize", resize);
|
|
12786
|
-
} else {
|
|
12787
|
-
resizeObserver.disconnect();
|
|
12788
|
-
}
|
|
12789
|
-
canvas.removeEventListener("webglcontextlost", handleContextLost);
|
|
12790
|
-
disposeScene(scene);
|
|
12791
|
-
renderer.dispose();
|
|
12792
|
-
};
|
|
12793
|
-
}, []);
|
|
12794
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "relative flex size-24 items-center justify-center", "aria-hidden": "true", children: [
|
|
12190
|
+
] }),
|
|
12795
12191
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
12796
|
-
|
|
12192
|
+
ExecutionConfirmationDialog,
|
|
12797
12193
|
{
|
|
12798
|
-
|
|
12799
|
-
|
|
12800
|
-
|
|
12194
|
+
pending: pendingExecution,
|
|
12195
|
+
busy: confirmationBusy,
|
|
12196
|
+
onOpenChange: (confirmationOpen) => {
|
|
12197
|
+
if (!confirmationOpen && !confirmationBusy) setPendingExecution(null);
|
|
12198
|
+
},
|
|
12199
|
+
onConfirm: confirmPendingExecution
|
|
12801
12200
|
}
|
|
12802
|
-
)
|
|
12803
|
-
renderFailed && /* @__PURE__ */ jsxRuntimeExports.jsx(CrabLogo, { className: "size-22 text-amber-500 drop-shadow-[0_0_18px_rgba(245,158,11,0.28)]" })
|
|
12201
|
+
)
|
|
12804
12202
|
] });
|
|
12805
12203
|
}
|
|
12806
|
-
const INSPECTOR_PET_ROAMING_STORAGE_KEY = "agent-inspector.pet.roaming";
|
|
12807
|
-
const INSPECTOR_PET_MIN_PAUSE_MS = 11e3;
|
|
12808
|
-
const INSPECTOR_PET_PAUSE_WINDOW_MS = 9e3;
|
|
12809
|
-
const INSPECTOR_PET_SCUTTLE_MS = 7200;
|
|
12810
|
-
const INSPECTOR_PET_PANEL_DISMISS_MS = 6e3;
|
|
12811
|
-
const INSPECTOR_PET_REACTION_MS = 760;
|
|
12812
|
-
const INSPECTOR_PET_DRAG_THRESHOLD = 4;
|
|
12813
|
-
const INSPECTOR_PET_TOP_LAYER_Z_INDEX = 2147483647;
|
|
12814
|
-
function readViewport() {
|
|
12815
|
-
if (typeof window === "undefined") return { width: 1280, height: 720, scale: 1 };
|
|
12816
|
-
const rawScale = window.getComputedStyle(document.documentElement).getPropertyValue("--inspector-ui-scale");
|
|
12817
|
-
const parsedScale = Number.parseFloat(rawScale);
|
|
12818
|
-
const scale = Number.isFinite(parsedScale) && parsedScale > 0 ? parsedScale : 1;
|
|
12819
|
-
return {
|
|
12820
|
-
width: Math.max(window.innerWidth, INSPECTOR_PET_MARGIN * 2),
|
|
12821
|
-
height: Math.max(window.innerHeight, INSPECTOR_PET_MARGIN * 2),
|
|
12822
|
-
scale
|
|
12823
|
-
};
|
|
12824
|
-
}
|
|
12825
|
-
function readStoredRoaming() {
|
|
12826
|
-
if (typeof window === "undefined") return true;
|
|
12827
|
-
try {
|
|
12828
|
-
return window.localStorage.getItem(INSPECTOR_PET_ROAMING_STORAGE_KEY) !== "0";
|
|
12829
|
-
} catch {
|
|
12830
|
-
return true;
|
|
12831
|
-
}
|
|
12832
|
-
}
|
|
12833
|
-
function moodDotClass(mood) {
|
|
12834
|
-
switch (mood) {
|
|
12835
|
-
case "active":
|
|
12836
|
-
return "bg-cyan-400 shadow-[0_0_9px_rgba(34,211,238,0.65)]";
|
|
12837
|
-
case "attention":
|
|
12838
|
-
return "bg-red-500 shadow-[0_0_9px_rgba(239,68,68,0.55)]";
|
|
12839
|
-
case "idle":
|
|
12840
|
-
return "bg-amber-400 shadow-[0_0_8px_rgba(251,191,36,0.45)]";
|
|
12841
|
-
case "sleeping":
|
|
12842
|
-
return "bg-muted-foreground/45";
|
|
12843
|
-
}
|
|
12844
|
-
}
|
|
12845
|
-
function moodMotionClass(mood) {
|
|
12846
|
-
switch (mood) {
|
|
12847
|
-
case "active":
|
|
12848
|
-
return "inspector-pet-active";
|
|
12849
|
-
case "attention":
|
|
12850
|
-
return "inspector-pet-attention";
|
|
12851
|
-
case "idle":
|
|
12852
|
-
return "";
|
|
12853
|
-
case "sleeping":
|
|
12854
|
-
return "inspector-pet-sleeping";
|
|
12855
|
-
}
|
|
12856
|
-
}
|
|
12857
|
-
function InspectorPet({ logs }) {
|
|
12858
|
-
const [portalHost, setPortalHost] = reactExports.useState(null);
|
|
12859
|
-
const [viewport, setViewport] = reactExports.useState(readViewport);
|
|
12860
|
-
const [position, setPosition] = reactExports.useState({
|
|
12861
|
-
x: INSPECTOR_PET_MARGIN,
|
|
12862
|
-
y: INSPECTOR_PET_MARGIN
|
|
12863
|
-
});
|
|
12864
|
-
const [clockMs, setClockMs] = reactExports.useState(() => Date.now());
|
|
12865
|
-
const [scuttling, setScuttling] = reactExports.useState(false);
|
|
12866
|
-
const [panelTick, setPanelTick] = reactExports.useState(0);
|
|
12867
|
-
const [panelVisible, setPanelVisible] = reactExports.useState(false);
|
|
12868
|
-
const [reactionTick, setReactionTick] = reactExports.useState(0);
|
|
12869
|
-
const [reactionVisible, setReactionVisible] = reactExports.useState(false);
|
|
12870
|
-
const [dragging, setDragging] = reactExports.useState(false);
|
|
12871
|
-
const [roaming, setRoaming] = reactExports.useState(readStoredRoaming);
|
|
12872
|
-
const [reduceMotion, setReduceMotion] = reactExports.useState(false);
|
|
12873
|
-
const dragStateRef = reactExports.useRef(null);
|
|
12874
|
-
const dragOccurredRef = reactExports.useRef(false);
|
|
12875
|
-
const status = reactExports.useMemo(() => resolveInspectorPetStatus(logs, clockMs), [clockMs, logs]);
|
|
12876
|
-
const panelPosition = reactExports.useMemo(
|
|
12877
|
-
() => inspectorPetPanelPosition(position, viewport),
|
|
12878
|
-
[position, viewport]
|
|
12879
|
-
);
|
|
12880
|
-
reactExports.useEffect(() => setPortalHost(document.body), []);
|
|
12881
|
-
reactExports.useEffect(() => {
|
|
12882
|
-
const nextViewport = readViewport();
|
|
12883
|
-
setViewport(nextViewport);
|
|
12884
|
-
setPosition(randomInspectorPetEdgePosition(nextViewport, Math.random()));
|
|
12885
|
-
}, []);
|
|
12886
|
-
reactExports.useEffect(() => {
|
|
12887
|
-
const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
12888
|
-
const handleChange = (event) => setReduceMotion(event.matches);
|
|
12889
|
-
setReduceMotion(mediaQuery.matches);
|
|
12890
|
-
mediaQuery.addEventListener("change", handleChange);
|
|
12891
|
-
return () => mediaQuery.removeEventListener("change", handleChange);
|
|
12892
|
-
}, []);
|
|
12893
|
-
reactExports.useEffect(() => {
|
|
12894
|
-
const intervalId = window.setInterval(() => setClockMs(Date.now()), 15e3);
|
|
12895
|
-
return () => window.clearInterval(intervalId);
|
|
12896
|
-
}, []);
|
|
12897
|
-
reactExports.useEffect(() => {
|
|
12898
|
-
try {
|
|
12899
|
-
window.localStorage.setItem(INSPECTOR_PET_ROAMING_STORAGE_KEY, roaming ? "1" : "0");
|
|
12900
|
-
} catch {
|
|
12901
|
-
}
|
|
12902
|
-
}, [roaming]);
|
|
12903
|
-
reactExports.useEffect(() => {
|
|
12904
|
-
if (!roaming || dragging || reduceMotion) return void 0;
|
|
12905
|
-
let pauseTimeoutId = null;
|
|
12906
|
-
let scuttleTimeoutId = null;
|
|
12907
|
-
const scheduleScuttle = () => {
|
|
12908
|
-
const delay = INSPECTOR_PET_MIN_PAUSE_MS + Math.random() * INSPECTOR_PET_PAUSE_WINDOW_MS;
|
|
12909
|
-
pauseTimeoutId = window.setTimeout(() => {
|
|
12910
|
-
setScuttling(true);
|
|
12911
|
-
setPosition(
|
|
12912
|
-
(current) => nextInspectorPetWalkingPosition(current, viewport, Math.random(), Math.random())
|
|
12913
|
-
);
|
|
12914
|
-
scuttleTimeoutId = window.setTimeout(() => {
|
|
12915
|
-
setScuttling(false);
|
|
12916
|
-
scheduleScuttle();
|
|
12917
|
-
}, INSPECTOR_PET_SCUTTLE_MS);
|
|
12918
|
-
}, delay);
|
|
12919
|
-
};
|
|
12920
|
-
scheduleScuttle();
|
|
12921
|
-
return () => {
|
|
12922
|
-
if (pauseTimeoutId !== null) window.clearTimeout(pauseTimeoutId);
|
|
12923
|
-
if (scuttleTimeoutId !== null) window.clearTimeout(scuttleTimeoutId);
|
|
12924
|
-
};
|
|
12925
|
-
}, [dragging, reduceMotion, roaming, viewport]);
|
|
12926
|
-
reactExports.useEffect(() => {
|
|
12927
|
-
const handleResize = () => {
|
|
12928
|
-
const nextViewport = readViewport();
|
|
12929
|
-
setScuttling(false);
|
|
12930
|
-
setViewport(nextViewport);
|
|
12931
|
-
setPosition((current) => snapInspectorPetToEdge(current, nextViewport));
|
|
12932
|
-
};
|
|
12933
|
-
window.addEventListener("resize", handleResize);
|
|
12934
|
-
return () => window.removeEventListener("resize", handleResize);
|
|
12935
|
-
}, []);
|
|
12936
|
-
reactExports.useEffect(() => {
|
|
12937
|
-
if (!panelVisible) return void 0;
|
|
12938
|
-
const timeoutId = window.setTimeout(
|
|
12939
|
-
() => setPanelVisible(false),
|
|
12940
|
-
INSPECTOR_PET_PANEL_DISMISS_MS
|
|
12941
|
-
);
|
|
12942
|
-
return () => window.clearTimeout(timeoutId);
|
|
12943
|
-
}, [panelTick, panelVisible]);
|
|
12944
|
-
reactExports.useEffect(() => {
|
|
12945
|
-
if (!reactionVisible) return void 0;
|
|
12946
|
-
const timeoutId = window.setTimeout(() => setReactionVisible(false), INSPECTOR_PET_REACTION_MS);
|
|
12947
|
-
return () => window.clearTimeout(timeoutId);
|
|
12948
|
-
}, [reactionTick, reactionVisible]);
|
|
12949
|
-
const handlePet = reactExports.useCallback(() => {
|
|
12950
|
-
if (dragOccurredRef.current) {
|
|
12951
|
-
dragOccurredRef.current = false;
|
|
12952
|
-
return;
|
|
12953
|
-
}
|
|
12954
|
-
setClockMs(Date.now());
|
|
12955
|
-
setPanelTick((current) => current + 1);
|
|
12956
|
-
setPanelVisible(true);
|
|
12957
|
-
setReactionTick((current) => current + 1);
|
|
12958
|
-
setReactionVisible(true);
|
|
12959
|
-
}, []);
|
|
12960
|
-
const handlePointerDown = reactExports.useCallback((event) => {
|
|
12961
|
-
const rect = event.currentTarget.getBoundingClientRect();
|
|
12962
|
-
dragOccurredRef.current = false;
|
|
12963
|
-
dragStateRef.current = {
|
|
12964
|
-
pointerId: event.pointerId,
|
|
12965
|
-
offsetX: event.clientX - rect.left,
|
|
12966
|
-
offsetY: event.clientY - rect.top,
|
|
12967
|
-
startX: event.clientX,
|
|
12968
|
-
startY: event.clientY,
|
|
12969
|
-
moved: false
|
|
12970
|
-
};
|
|
12971
|
-
event.currentTarget.setPointerCapture(event.pointerId);
|
|
12972
|
-
setScuttling(false);
|
|
12973
|
-
setPanelVisible(false);
|
|
12974
|
-
setDragging(true);
|
|
12975
|
-
}, []);
|
|
12976
|
-
const handlePointerMove = reactExports.useCallback(
|
|
12977
|
-
(event) => {
|
|
12978
|
-
const dragState = dragStateRef.current;
|
|
12979
|
-
if (dragState === null || dragState.pointerId !== event.pointerId) return;
|
|
12980
|
-
const moved = dragState.moved || Math.abs(event.clientX - dragState.startX) >= INSPECTOR_PET_DRAG_THRESHOLD || Math.abs(event.clientY - dragState.startY) >= INSPECTOR_PET_DRAG_THRESHOLD;
|
|
12981
|
-
dragState.moved = moved;
|
|
12982
|
-
dragOccurredRef.current = moved;
|
|
12983
|
-
setPosition(
|
|
12984
|
-
clampInspectorPetPosition(
|
|
12985
|
-
{
|
|
12986
|
-
x: event.clientX - dragState.offsetX,
|
|
12987
|
-
y: event.clientY - dragState.offsetY
|
|
12988
|
-
},
|
|
12989
|
-
viewport
|
|
12990
|
-
)
|
|
12991
|
-
);
|
|
12992
|
-
},
|
|
12993
|
-
[viewport]
|
|
12994
|
-
);
|
|
12995
|
-
const handlePointerUp = reactExports.useCallback(
|
|
12996
|
-
(event) => {
|
|
12997
|
-
const dragState = dragStateRef.current;
|
|
12998
|
-
if (dragState === null || dragState.pointerId !== event.pointerId) return;
|
|
12999
|
-
if (event.currentTarget.hasPointerCapture(event.pointerId)) {
|
|
13000
|
-
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
13001
|
-
}
|
|
13002
|
-
dragOccurredRef.current = dragState.moved;
|
|
13003
|
-
dragStateRef.current = null;
|
|
13004
|
-
setDragging(false);
|
|
13005
|
-
setPosition((current) => snapInspectorPetToEdge(current, viewport));
|
|
13006
|
-
},
|
|
13007
|
-
[viewport]
|
|
13008
|
-
);
|
|
13009
|
-
const handlePointerCancel = reactExports.useCallback((event) => {
|
|
13010
|
-
if (event.currentTarget.hasPointerCapture(event.pointerId)) {
|
|
13011
|
-
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
13012
|
-
}
|
|
13013
|
-
dragStateRef.current = null;
|
|
13014
|
-
dragOccurredRef.current = false;
|
|
13015
|
-
setDragging(false);
|
|
13016
|
-
}, []);
|
|
13017
|
-
const handleToggleRoaming = reactExports.useCallback(() => {
|
|
13018
|
-
setScuttling(false);
|
|
13019
|
-
setRoaming((current) => !current);
|
|
13020
|
-
}, []);
|
|
13021
|
-
const petStyle = reactExports.useMemo(
|
|
13022
|
-
() => ({
|
|
13023
|
-
transform: `translate3d(${String(position.x)}px, ${String(position.y)}px, 0) scale(${dragging ? "1.04" : "1"})`,
|
|
13024
|
-
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)",
|
|
13025
|
-
touchAction: "none"
|
|
13026
|
-
}),
|
|
13027
|
-
[dragging, position.x, position.y, scuttling]
|
|
13028
|
-
);
|
|
13029
|
-
const panelStyle = reactExports.useMemo(
|
|
13030
|
-
() => ({ left: panelPosition.x, top: panelPosition.y }),
|
|
13031
|
-
[panelPosition.x, panelPosition.y]
|
|
13032
|
-
);
|
|
13033
|
-
const roamingLabel = roaming ? "Pause pet roaming" : "Resume pet roaming";
|
|
13034
|
-
if (portalHost === null) return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, {});
|
|
13035
|
-
return reactDomExports.createPortal(
|
|
13036
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
13037
|
-
"div",
|
|
13038
|
-
{
|
|
13039
|
-
className: "pointer-events-none fixed inset-0 isolate",
|
|
13040
|
-
style: { zIndex: INSPECTOR_PET_TOP_LAYER_Z_INDEX },
|
|
13041
|
-
"data-inspector-pet-layer": "true",
|
|
13042
|
-
children: [
|
|
13043
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
13044
|
-
"button",
|
|
13045
|
-
{
|
|
13046
|
-
type: "button",
|
|
13047
|
-
className: cn(
|
|
13048
|
-
"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)]",
|
|
13049
|
-
dragging ? "cursor-grabbing" : "cursor-grab"
|
|
13050
|
-
),
|
|
13051
|
-
style: petStyle,
|
|
13052
|
-
"data-pet-mood": status.mood,
|
|
13053
|
-
"data-pet-moving": scuttling ? "true" : "false",
|
|
13054
|
-
onClick: handlePet,
|
|
13055
|
-
onPointerDown: handlePointerDown,
|
|
13056
|
-
onPointerMove: handlePointerMove,
|
|
13057
|
-
onPointerUp: handlePointerUp,
|
|
13058
|
-
onPointerCancel: handlePointerCancel,
|
|
13059
|
-
"aria-label": `Inspector pet: ${status.label}`,
|
|
13060
|
-
title: status.label,
|
|
13061
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
13062
|
-
"span",
|
|
13063
|
-
{
|
|
13064
|
-
className: cn(
|
|
13065
|
-
"relative z-10 flex size-24 items-center justify-center",
|
|
13066
|
-
reactionVisible && "inspector-pet-patted"
|
|
13067
|
-
),
|
|
13068
|
-
"aria-hidden": "true",
|
|
13069
|
-
children: [
|
|
13070
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
13071
|
-
"span",
|
|
13072
|
-
{
|
|
13073
|
-
className: cn(
|
|
13074
|
-
"relative flex size-24 items-center justify-center",
|
|
13075
|
-
moodMotionClass(status.mood)
|
|
13076
|
-
),
|
|
13077
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "relative flex size-24 items-center justify-center", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
13078
|
-
InspectorPetCrab3D,
|
|
13079
|
-
{
|
|
13080
|
-
mood: status.mood,
|
|
13081
|
-
moving: scuttling && !dragging,
|
|
13082
|
-
reduceMotion
|
|
13083
|
-
}
|
|
13084
|
-
) })
|
|
13085
|
-
}
|
|
13086
|
-
),
|
|
13087
|
-
reactionVisible && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
13088
|
-
Heart,
|
|
13089
|
-
{
|
|
13090
|
-
className: "inspector-pet-heart absolute -right-2 -top-3 size-5 fill-amber-400 text-amber-400"
|
|
13091
|
-
},
|
|
13092
|
-
reactionTick
|
|
13093
|
-
)
|
|
13094
|
-
]
|
|
13095
|
-
}
|
|
13096
|
-
)
|
|
13097
|
-
}
|
|
13098
|
-
),
|
|
13099
|
-
panelVisible && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
13100
|
-
"div",
|
|
13101
|
-
{
|
|
13102
|
-
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",
|
|
13103
|
-
style: panelStyle,
|
|
13104
|
-
role: "status",
|
|
13105
|
-
"aria-live": "polite",
|
|
13106
|
-
children: [
|
|
13107
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
13108
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn("size-2 shrink-0 rounded-full", moodDotClass(status.mood)) }),
|
|
13109
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0 flex-1 truncate text-xs font-medium", children: status.label }),
|
|
13110
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
13111
|
-
"button",
|
|
13112
|
-
{
|
|
13113
|
-
type: "button",
|
|
13114
|
-
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",
|
|
13115
|
-
onClick: handleToggleRoaming,
|
|
13116
|
-
"aria-label": roamingLabel,
|
|
13117
|
-
title: roamingLabel,
|
|
13118
|
-
children: roaming ? /* @__PURE__ */ jsxRuntimeExports.jsx(Pause, { className: "size-3.5" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Play, { className: "size-3.5" })
|
|
13119
|
-
}
|
|
13120
|
-
)
|
|
13121
|
-
] }),
|
|
13122
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-1 flex items-center justify-between gap-3 font-mono text-[10px] text-muted-foreground", children: [
|
|
13123
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
13124
|
-
String(status.capturedCount),
|
|
13125
|
-
" captured"
|
|
13126
|
-
] }),
|
|
13127
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: status.pendingCount > 0 ? `${String(status.pendingCount)} active` : scuttling ? "Scuttling" : roaming ? "Resting" : "Paused" })
|
|
13128
|
-
] })
|
|
13129
|
-
]
|
|
13130
|
-
}
|
|
13131
|
-
)
|
|
13132
|
-
]
|
|
13133
|
-
}
|
|
13134
|
-
),
|
|
13135
|
-
portalHost
|
|
13136
|
-
);
|
|
13137
|
-
}
|
|
13138
12204
|
const DEFAULT_QUESTION = "Analyze the current Inspector session. What looks abnormal, slow, or likely to hang?";
|
|
13139
12205
|
function providerSupportsPiAgent(provider) {
|
|
13140
12206
|
return provider.openaiResponsesBaseUrl !== void 0 || provider.openaiBaseUrl !== void 0 || provider.anthropicBaseUrl !== void 0;
|
|
@@ -13192,7 +12258,10 @@ function PiAgentPanel({ currentSessionId, logCount }) {
|
|
|
13192
12258
|
};
|
|
13193
12259
|
void fetch("/api/pi-agent", {
|
|
13194
12260
|
method: "POST",
|
|
13195
|
-
headers: {
|
|
12261
|
+
headers: {
|
|
12262
|
+
"content-type": "application/json",
|
|
12263
|
+
"x-agent-inspector-csrf": "1"
|
|
12264
|
+
},
|
|
13196
12265
|
body: JSON.stringify(body)
|
|
13197
12266
|
}).then(async (response) => {
|
|
13198
12267
|
const raw = await response.text();
|
|
@@ -13269,35 +12338,412 @@ function PiAgentPanel({ currentSessionId, logCount }) {
|
|
|
13269
12338
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: loading ? "Thinking..." : "Ask Pi" })
|
|
13270
12339
|
]
|
|
13271
12340
|
}
|
|
13272
|
-
),
|
|
13273
|
-
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." }),
|
|
13274
|
-
status !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-2 break-words font-mono text-[10px] text-cyan-100/70", children: status }),
|
|
13275
|
-
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 }),
|
|
13276
|
-
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." })
|
|
12341
|
+
),
|
|
12342
|
+
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." }),
|
|
12343
|
+
status !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-2 break-words font-mono text-[10px] text-cyan-100/70", children: status }),
|
|
12344
|
+
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 }),
|
|
12345
|
+
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." })
|
|
12346
|
+
] });
|
|
12347
|
+
}
|
|
12348
|
+
function computeCacheTrends(groups) {
|
|
12349
|
+
const result = /* @__PURE__ */ new Map();
|
|
12350
|
+
for (const group of groups) {
|
|
12351
|
+
const logs = group.logs;
|
|
12352
|
+
for (let i = 1; i < logs.length; i++) {
|
|
12353
|
+
const prev = logs[i - 1];
|
|
12354
|
+
const curr = logs[i];
|
|
12355
|
+
if (prev === void 0 || curr === void 0) continue;
|
|
12356
|
+
result.set(curr.id, {
|
|
12357
|
+
creation: compareField(prev.cacheCreationInputTokens, curr.cacheCreationInputTokens),
|
|
12358
|
+
read: compareField(prev.cacheReadInputTokens, curr.cacheReadInputTokens)
|
|
12359
|
+
});
|
|
12360
|
+
}
|
|
12361
|
+
}
|
|
12362
|
+
return result;
|
|
12363
|
+
}
|
|
12364
|
+
function compareField(previous, current) {
|
|
12365
|
+
if (current === null) return null;
|
|
12366
|
+
if (previous === null) return null;
|
|
12367
|
+
if (current > previous) return { direction: "up", delta: current - previous };
|
|
12368
|
+
if (current < previous) return { direction: "down", delta: previous - current };
|
|
12369
|
+
return null;
|
|
12370
|
+
}
|
|
12371
|
+
function formatLastSuccess(lastSuccessAt) {
|
|
12372
|
+
if (lastSuccessAt === null) return null;
|
|
12373
|
+
return new Date(lastSuccessAt).toLocaleTimeString([], {
|
|
12374
|
+
hour: "2-digit",
|
|
12375
|
+
minute: "2-digit",
|
|
12376
|
+
second: "2-digit"
|
|
12377
|
+
});
|
|
12378
|
+
}
|
|
12379
|
+
function buildDescription(state, message, hasLogs) {
|
|
12380
|
+
const lastSuccess = formatLastSuccess(state.lastSuccessAt);
|
|
12381
|
+
const retry = state.retryCount > 0 ? ` Retry ${state.retryCount.toString()}.` : "";
|
|
12382
|
+
const retained = hasLogs ? " Captured logs remain visible." : "";
|
|
12383
|
+
const lastUpdate = lastSuccess === null ? "" : ` Last update ${lastSuccess}.`;
|
|
12384
|
+
return `${message}${lastUpdate}${retry}${retained}`;
|
|
12385
|
+
}
|
|
12386
|
+
function presentationForStatus(status, state, hasLogs) {
|
|
12387
|
+
switch (status) {
|
|
12388
|
+
case "connecting":
|
|
12389
|
+
return {
|
|
12390
|
+
label: "Connecting",
|
|
12391
|
+
description: buildDescription(state, "Waiting for the first live update.", hasLogs),
|
|
12392
|
+
toneClass: "border-cyan-400/20 bg-cyan-500/8 text-cyan-100",
|
|
12393
|
+
dotClass: "bg-cyan-300 animate-pulse motion-reduce:animate-none",
|
|
12394
|
+
canRetry: false,
|
|
12395
|
+
canStop: false
|
|
12396
|
+
};
|
|
12397
|
+
case "live":
|
|
12398
|
+
return {
|
|
12399
|
+
label: "Live",
|
|
12400
|
+
description: buildDescription(state, "Live updates are current.", hasLogs),
|
|
12401
|
+
toneClass: "border-emerald-400/20 bg-emerald-500/8 text-emerald-100",
|
|
12402
|
+
dotClass: "bg-emerald-300",
|
|
12403
|
+
canRetry: false,
|
|
12404
|
+
canStop: false
|
|
12405
|
+
};
|
|
12406
|
+
case "reconnecting":
|
|
12407
|
+
return {
|
|
12408
|
+
label: "Reconnecting",
|
|
12409
|
+
description: buildDescription(state, "Live updates were interrupted.", hasLogs),
|
|
12410
|
+
toneClass: "border-amber-400/20 bg-amber-500/8 text-amber-100",
|
|
12411
|
+
dotClass: "bg-amber-300 animate-pulse motion-reduce:animate-none",
|
|
12412
|
+
canRetry: true,
|
|
12413
|
+
canStop: true
|
|
12414
|
+
};
|
|
12415
|
+
case "stale":
|
|
12416
|
+
return {
|
|
12417
|
+
label: "Stale data",
|
|
12418
|
+
description: buildDescription(state, "Live updates have not resumed.", hasLogs),
|
|
12419
|
+
toneClass: "border-orange-400/25 bg-orange-500/10 text-orange-100",
|
|
12420
|
+
dotClass: "bg-orange-300",
|
|
12421
|
+
canRetry: true,
|
|
12422
|
+
canStop: true
|
|
12423
|
+
};
|
|
12424
|
+
case "offline":
|
|
12425
|
+
return {
|
|
12426
|
+
label: "Offline",
|
|
12427
|
+
description: buildDescription(
|
|
12428
|
+
state,
|
|
12429
|
+
state.errorMessage ?? "Live updates are paused.",
|
|
12430
|
+
hasLogs
|
|
12431
|
+
),
|
|
12432
|
+
toneClass: "border-slate-400/20 bg-slate-500/10 text-slate-200",
|
|
12433
|
+
dotClass: "bg-slate-400",
|
|
12434
|
+
canRetry: true,
|
|
12435
|
+
canStop: false
|
|
12436
|
+
};
|
|
12437
|
+
case "error":
|
|
12438
|
+
return {
|
|
12439
|
+
label: "Connection error",
|
|
12440
|
+
description: buildDescription(
|
|
12441
|
+
state,
|
|
12442
|
+
state.errorMessage ?? "The live stream reported a recoverable error.",
|
|
12443
|
+
hasLogs
|
|
12444
|
+
),
|
|
12445
|
+
toneClass: "border-red-400/25 bg-red-500/10 text-red-100",
|
|
12446
|
+
dotClass: "bg-red-300",
|
|
12447
|
+
canRetry: true,
|
|
12448
|
+
canStop: true
|
|
12449
|
+
};
|
|
12450
|
+
}
|
|
12451
|
+
}
|
|
12452
|
+
function LiveConnectionBadge({ state }) {
|
|
12453
|
+
const presentation = presentationForStatus(state.status, state, false);
|
|
12454
|
+
const lastSuccess = formatLastSuccess(state.lastSuccessAt);
|
|
12455
|
+
const retryLabel = state.retryCount > 0 ? `Retry ${state.retryCount.toString()}` : null;
|
|
12456
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
12457
|
+
"span",
|
|
12458
|
+
{
|
|
12459
|
+
role: "status",
|
|
12460
|
+
"aria-label": presentation.description,
|
|
12461
|
+
"data-connection-state": state.status,
|
|
12462
|
+
className: cn(
|
|
12463
|
+
"inline-flex h-7 max-w-full items-center gap-1.5 rounded-full border px-2.5 text-xs font-medium",
|
|
12464
|
+
presentation.toneClass
|
|
12465
|
+
),
|
|
12466
|
+
children: [
|
|
12467
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn("size-1.5 shrink-0 rounded-full", presentation.dotClass) }),
|
|
12468
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0", children: presentation.label }),
|
|
12469
|
+
retryLabel !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "hidden truncate text-current/70 sm:inline", children: retryLabel }),
|
|
12470
|
+
lastSuccess !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "hidden truncate font-mono text-[10px] text-current/65 md:inline", children: [
|
|
12471
|
+
"Last ",
|
|
12472
|
+
lastSuccess
|
|
12473
|
+
] })
|
|
12474
|
+
]
|
|
12475
|
+
}
|
|
12476
|
+
);
|
|
12477
|
+
}
|
|
12478
|
+
function LiveConnectionStatus({
|
|
12479
|
+
state,
|
|
12480
|
+
hasLogs,
|
|
12481
|
+
onRetry,
|
|
12482
|
+
onStop
|
|
12483
|
+
}) {
|
|
12484
|
+
const presentation = presentationForStatus(state.status, state, hasLogs);
|
|
12485
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
12486
|
+
"div",
|
|
12487
|
+
{
|
|
12488
|
+
role: "status",
|
|
12489
|
+
"aria-live": "polite",
|
|
12490
|
+
"data-connection-state": state.status,
|
|
12491
|
+
className: cn(
|
|
12492
|
+
"mt-2 flex flex-wrap items-center gap-x-3 gap-y-2 rounded-md border px-3 py-2 text-xs",
|
|
12493
|
+
presentation.toneClass
|
|
12494
|
+
),
|
|
12495
|
+
children: [
|
|
12496
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
|
|
12497
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn("size-2 shrink-0 rounded-full", presentation.dotClass) }),
|
|
12498
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0 font-semibold", children: presentation.label }),
|
|
12499
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0 text-current/75", children: presentation.description })
|
|
12500
|
+
] }),
|
|
12501
|
+
(presentation.canRetry || presentation.canStop) && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex shrink-0 items-center gap-1.5", children: [
|
|
12502
|
+
presentation.canRetry && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
12503
|
+
"button",
|
|
12504
|
+
{
|
|
12505
|
+
type: "button",
|
|
12506
|
+
onClick: onRetry,
|
|
12507
|
+
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",
|
|
12508
|
+
children: [
|
|
12509
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: "size-3" }),
|
|
12510
|
+
"Retry now"
|
|
12511
|
+
]
|
|
12512
|
+
}
|
|
12513
|
+
),
|
|
12514
|
+
presentation.canStop && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
12515
|
+
"button",
|
|
12516
|
+
{
|
|
12517
|
+
type: "button",
|
|
12518
|
+
onClick: onStop,
|
|
12519
|
+
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",
|
|
12520
|
+
children: [
|
|
12521
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(CircleStop, { className: "size-3" }),
|
|
12522
|
+
"Stop retrying"
|
|
12523
|
+
]
|
|
12524
|
+
}
|
|
12525
|
+
)
|
|
12526
|
+
] })
|
|
12527
|
+
]
|
|
12528
|
+
}
|
|
12529
|
+
);
|
|
12530
|
+
}
|
|
12531
|
+
function ApplicationBar({
|
|
12532
|
+
liveConnection,
|
|
12533
|
+
alertsAction,
|
|
12534
|
+
settingsAction
|
|
12535
|
+
}) {
|
|
12536
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
12537
|
+
"header",
|
|
12538
|
+
{
|
|
12539
|
+
"data-application-bar": "true",
|
|
12540
|
+
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",
|
|
12541
|
+
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: [
|
|
12542
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
12543
|
+
"a",
|
|
12544
|
+
{
|
|
12545
|
+
href: "/",
|
|
12546
|
+
"aria-label": "Agent Inspector home",
|
|
12547
|
+
className: "flex min-w-0 items-center gap-2 rounded-md focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none",
|
|
12548
|
+
children: [
|
|
12549
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(CrabLogo, { className: "size-7 shrink-0 text-amber-500" }),
|
|
12550
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "min-w-0", children: [
|
|
12551
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "block truncate text-sm font-bold leading-4", children: "Agent Inspector" }),
|
|
12552
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "hidden truncate text-[10px] font-medium text-muted-foreground md:block", children: "Local First. Evidence First." })
|
|
12553
|
+
] }),
|
|
12554
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "hidden shrink-0 font-mono text-[10px] text-muted-foreground lg:inline", children: [
|
|
12555
|
+
"v",
|
|
12556
|
+
packageJson.version
|
|
12557
|
+
] })
|
|
12558
|
+
]
|
|
12559
|
+
}
|
|
12560
|
+
),
|
|
12561
|
+
/* @__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(
|
|
12562
|
+
"span",
|
|
12563
|
+
{
|
|
12564
|
+
"data-connection-state": "stored",
|
|
12565
|
+
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",
|
|
12566
|
+
children: [
|
|
12567
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "size-1.5 shrink-0 rounded-full bg-slate-400" }),
|
|
12568
|
+
"Stored session"
|
|
12569
|
+
]
|
|
12570
|
+
}
|
|
12571
|
+
) : /* @__PURE__ */ jsxRuntimeExports.jsx(LiveConnectionBadge, { state: liveConnection }) }),
|
|
12572
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
12573
|
+
"nav",
|
|
12574
|
+
{
|
|
12575
|
+
"aria-label": "Application actions",
|
|
12576
|
+
className: "order-2 flex shrink-0 items-center justify-end gap-1 sm:order-3",
|
|
12577
|
+
children: [
|
|
12578
|
+
alertsAction,
|
|
12579
|
+
settingsAction
|
|
12580
|
+
]
|
|
12581
|
+
}
|
|
12582
|
+
)
|
|
12583
|
+
] })
|
|
12584
|
+
}
|
|
12585
|
+
);
|
|
12586
|
+
}
|
|
12587
|
+
function formatDurationSeconds(ms) {
|
|
12588
|
+
return `${Math.max(0, Math.ceil(ms / 1e3)).toString()}s`;
|
|
12589
|
+
}
|
|
12590
|
+
function SessionLoadProgressBar({
|
|
12591
|
+
progress
|
|
12592
|
+
}) {
|
|
12593
|
+
const elapsedRatio = Math.min(1, progress.elapsedMs / progress.timeoutMs);
|
|
12594
|
+
const percent = Math.max(4, Math.round(elapsedRatio * 100));
|
|
12595
|
+
const remainingMs = Math.max(0, progress.timeoutMs - progress.elapsedMs);
|
|
12596
|
+
const nearTimeout = elapsedRatio >= 0.75;
|
|
12597
|
+
const details = [
|
|
12598
|
+
progress.loadedLogs > 0 ? `${progress.loadedLogs.toString()} logs` : null,
|
|
12599
|
+
progress.loadedPages > 0 ? `${progress.loadedPages.toString()} page${progress.loadedPages === 1 ? "" : "s"}` : null,
|
|
12600
|
+
`${formatDurationSeconds(remainingMs)} before timeout`
|
|
12601
|
+
].filter((item) => item !== null);
|
|
12602
|
+
const valueText = `${progress.label}: ${details.join(", ")}`;
|
|
12603
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 space-y-1 px-1 pb-1", children: [
|
|
12604
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center justify-between gap-3 font-mono text-[10px] text-muted-foreground", children: [
|
|
12605
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0 truncate", children: progress.label }),
|
|
12606
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn("shrink-0 tabular-nums", nearTimeout && "text-amber-300"), children: details.join(" / ") })
|
|
12607
|
+
] }),
|
|
12608
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
12609
|
+
"div",
|
|
12610
|
+
{
|
|
12611
|
+
role: "progressbar",
|
|
12612
|
+
"aria-label": progress.label,
|
|
12613
|
+
"aria-valuemin": 0,
|
|
12614
|
+
"aria-valuemax": progress.timeoutMs,
|
|
12615
|
+
"aria-valuenow": Math.min(progress.elapsedMs, progress.timeoutMs),
|
|
12616
|
+
"aria-valuetext": valueText,
|
|
12617
|
+
className: "h-1.5 overflow-hidden rounded-full bg-white/[0.06]",
|
|
12618
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
12619
|
+
"div",
|
|
12620
|
+
{
|
|
12621
|
+
className: cn(
|
|
12622
|
+
"h-full rounded-full transition-all duration-300 motion-reduce:transition-none",
|
|
12623
|
+
nearTimeout ? "bg-amber-300/80" : "bg-cyan-300/70"
|
|
12624
|
+
),
|
|
12625
|
+
style: { width: `${percent.toString()}%` }
|
|
12626
|
+
}
|
|
12627
|
+
)
|
|
12628
|
+
}
|
|
12629
|
+
)
|
|
13277
12630
|
] });
|
|
13278
12631
|
}
|
|
13279
|
-
function
|
|
13280
|
-
|
|
13281
|
-
|
|
13282
|
-
|
|
13283
|
-
|
|
13284
|
-
|
|
13285
|
-
|
|
13286
|
-
|
|
13287
|
-
|
|
13288
|
-
|
|
13289
|
-
|
|
13290
|
-
|
|
12632
|
+
function preferredScrollBehavior(reducedMotion) {
|
|
12633
|
+
return reducedMotion ? "auto" : "smooth";
|
|
12634
|
+
}
|
|
12635
|
+
function browserPrefersReducedMotion() {
|
|
12636
|
+
if (typeof window === "undefined") return false;
|
|
12637
|
+
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
12638
|
+
}
|
|
12639
|
+
function createInitialLiveConnectionState() {
|
|
12640
|
+
return {
|
|
12641
|
+
status: "connecting",
|
|
12642
|
+
lastSuccessAt: null,
|
|
12643
|
+
retryCount: 0,
|
|
12644
|
+
errorMessage: null
|
|
12645
|
+
};
|
|
12646
|
+
}
|
|
12647
|
+
function reduceLiveConnectionState(state, event) {
|
|
12648
|
+
switch (event.type) {
|
|
12649
|
+
case "connect-requested":
|
|
12650
|
+
return {
|
|
12651
|
+
...state,
|
|
12652
|
+
status: state.lastSuccessAt === null ? "connecting" : state.status === "stale" ? "stale" : "reconnecting",
|
|
12653
|
+
errorMessage: null
|
|
12654
|
+
};
|
|
12655
|
+
case "message-received":
|
|
12656
|
+
return {
|
|
12657
|
+
status: "live",
|
|
12658
|
+
lastSuccessAt: event.at,
|
|
12659
|
+
retryCount: 0,
|
|
12660
|
+
errorMessage: null
|
|
12661
|
+
};
|
|
12662
|
+
case "connection-lost": {
|
|
12663
|
+
const retryCount = state.retryCount + 1;
|
|
12664
|
+
if (!event.online) {
|
|
12665
|
+
return {
|
|
12666
|
+
...state,
|
|
12667
|
+
status: "offline",
|
|
12668
|
+
retryCount,
|
|
12669
|
+
errorMessage: "Browser is offline."
|
|
12670
|
+
};
|
|
12671
|
+
}
|
|
12672
|
+
return {
|
|
12673
|
+
...state,
|
|
12674
|
+
status: state.lastSuccessAt === null ? "error" : "reconnecting",
|
|
12675
|
+
retryCount,
|
|
12676
|
+
errorMessage: event.message
|
|
12677
|
+
};
|
|
13291
12678
|
}
|
|
12679
|
+
case "stale-timeout":
|
|
12680
|
+
if (state.lastSuccessAt === null || state.status === "live" || state.status === "offline") {
|
|
12681
|
+
return state;
|
|
12682
|
+
}
|
|
12683
|
+
return { ...state, status: "stale" };
|
|
12684
|
+
case "browser-offline":
|
|
12685
|
+
return {
|
|
12686
|
+
...state,
|
|
12687
|
+
status: "offline",
|
|
12688
|
+
errorMessage: "Browser is offline."
|
|
12689
|
+
};
|
|
12690
|
+
case "stop-retrying":
|
|
12691
|
+
return {
|
|
12692
|
+
...state,
|
|
12693
|
+
status: "offline",
|
|
12694
|
+
errorMessage: "Automatic live updates are paused."
|
|
12695
|
+
};
|
|
12696
|
+
case "recoverable-error":
|
|
12697
|
+
return {
|
|
12698
|
+
...state,
|
|
12699
|
+
status: "error",
|
|
12700
|
+
errorMessage: event.message
|
|
12701
|
+
};
|
|
13292
12702
|
}
|
|
13293
|
-
return result;
|
|
13294
12703
|
}
|
|
13295
|
-
function
|
|
13296
|
-
if (
|
|
13297
|
-
|
|
13298
|
-
|
|
13299
|
-
|
|
13300
|
-
|
|
12704
|
+
function resolveLiveEmptyState(state) {
|
|
12705
|
+
if (state === void 0 || state.status === "live") return "empty";
|
|
12706
|
+
return state.status;
|
|
12707
|
+
}
|
|
12708
|
+
function getLiveEmptyStateCopy(state) {
|
|
12709
|
+
switch (state) {
|
|
12710
|
+
case "connecting":
|
|
12711
|
+
return {
|
|
12712
|
+
title: "Connecting to the live stream...",
|
|
12713
|
+
description: "Waiting for the first successful initialization before checking for logs.",
|
|
12714
|
+
showConnectionCommands: false
|
|
12715
|
+
};
|
|
12716
|
+
case "empty":
|
|
12717
|
+
return {
|
|
12718
|
+
title: "No logs captured yet.",
|
|
12719
|
+
description: "Connect an AI coding tool to capture its first request.",
|
|
12720
|
+
showConnectionCommands: true
|
|
12721
|
+
};
|
|
12722
|
+
case "reconnecting":
|
|
12723
|
+
return {
|
|
12724
|
+
title: "Reconnecting to live updates...",
|
|
12725
|
+
description: "The stream was interrupted. Agent Inspector is retrying automatically.",
|
|
12726
|
+
showConnectionCommands: false
|
|
12727
|
+
};
|
|
12728
|
+
case "stale":
|
|
12729
|
+
return {
|
|
12730
|
+
title: "Live data is stale.",
|
|
12731
|
+
description: "No logs are hidden; retry the connection to resume live updates.",
|
|
12732
|
+
showConnectionCommands: false
|
|
12733
|
+
};
|
|
12734
|
+
case "offline":
|
|
12735
|
+
return {
|
|
12736
|
+
title: "Live updates are offline.",
|
|
12737
|
+
description: "Check the browser and Inspector connection, then retry.",
|
|
12738
|
+
showConnectionCommands: false
|
|
12739
|
+
};
|
|
12740
|
+
case "error":
|
|
12741
|
+
return {
|
|
12742
|
+
title: "Live updates could not initialize.",
|
|
12743
|
+
description: "The error is recoverable. Retry without reloading the page.",
|
|
12744
|
+
showConnectionCommands: false
|
|
12745
|
+
};
|
|
12746
|
+
}
|
|
13301
12747
|
}
|
|
13302
12748
|
const COLLAPSED_CLIENTS_STORAGE_KEY = "agent-inspector.hierarchy.collapsedClients";
|
|
13303
12749
|
const COLLAPSED_PROCESSES_STORAGE_KEY = "agent-inspector.hierarchy.collapsedProcesses";
|
|
@@ -13468,13 +12914,15 @@ function countSessions(processes) {
|
|
|
13468
12914
|
return sessions;
|
|
13469
12915
|
}
|
|
13470
12916
|
function readStoredIdSet(storageKey) {
|
|
13471
|
-
if (typeof window === "undefined") return
|
|
12917
|
+
if (typeof window === "undefined") return null;
|
|
13472
12918
|
try {
|
|
13473
|
-
const
|
|
13474
|
-
if (
|
|
12919
|
+
const storedValue = window.localStorage.getItem(storageKey);
|
|
12920
|
+
if (storedValue === null) return null;
|
|
12921
|
+
const parsed = JSON.parse(storedValue);
|
|
12922
|
+
if (!Array.isArray(parsed)) return null;
|
|
13475
12923
|
return new Set(parsed.filter((value) => typeof value === "string"));
|
|
13476
12924
|
} catch {
|
|
13477
|
-
return
|
|
12925
|
+
return null;
|
|
13478
12926
|
}
|
|
13479
12927
|
}
|
|
13480
12928
|
function persistIdSet(storageKey, values) {
|
|
@@ -13491,6 +12939,18 @@ function removeIds(values, ids) {
|
|
|
13491
12939
|
}
|
|
13492
12940
|
return changed ? next : values;
|
|
13493
12941
|
}
|
|
12942
|
+
function buildDefaultCollapsedProcessIds(hierarchy) {
|
|
12943
|
+
const collapsedIds = /* @__PURE__ */ new Set();
|
|
12944
|
+
for (const clientGroup of hierarchy) {
|
|
12945
|
+
for (let index = 1; index < clientGroup.processes.length; index++) {
|
|
12946
|
+
const processGroup = clientGroup.processes[index];
|
|
12947
|
+
if (processGroup !== void 0 && !hasPendingLogs(processGroup.logs)) {
|
|
12948
|
+
collapsedIds.add(processGroup.id);
|
|
12949
|
+
}
|
|
12950
|
+
}
|
|
12951
|
+
}
|
|
12952
|
+
return collapsedIds;
|
|
12953
|
+
}
|
|
13494
12954
|
function shortProjectPath(projectFolder) {
|
|
13495
12955
|
if (projectFolder === null || projectFolder === "") return null;
|
|
13496
12956
|
const parts = projectFolder.replaceAll("\\", "/").split("/").filter((part) => part !== "");
|
|
@@ -13509,12 +12969,12 @@ function SummaryChip({
|
|
|
13509
12969
|
"span",
|
|
13510
12970
|
{
|
|
13511
12971
|
className: cn(
|
|
13512
|
-
"
|
|
12972
|
+
"inline-flex h-7 items-center gap-1 rounded-md bg-[var(--inspector-surface-low)] px-2 text-xs text-muted-foreground",
|
|
13513
12973
|
className
|
|
13514
12974
|
),
|
|
13515
12975
|
children: [
|
|
13516
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-[10px] uppercase text-
|
|
13517
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums text-
|
|
12976
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-[10px] uppercase text-muted-foreground/70", children: label }),
|
|
12977
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums text-foreground", children: value })
|
|
13518
12978
|
]
|
|
13519
12979
|
}
|
|
13520
12980
|
);
|
|
@@ -13524,12 +12984,12 @@ function AncestorActivityIndicator({ count }) {
|
|
|
13524
12984
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
13525
12985
|
"span",
|
|
13526
12986
|
{
|
|
13527
|
-
className: "relative inline-flex size-6 shrink-0 items-center justify-center rounded-md bg-
|
|
12987
|
+
className: "relative inline-flex size-6 shrink-0 items-center justify-center rounded-md bg-[var(--inspector-surface-medium)] text-[var(--inspector-status-watch)] ring-1 ring-border/50",
|
|
13528
12988
|
"aria-label": label,
|
|
13529
12989
|
title: label,
|
|
13530
12990
|
children: [
|
|
13531
12991
|
/* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-3 animate-spin" }),
|
|
13532
|
-
count > 1 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "absolute translate-x-2 -translate-y-2 rounded bg-
|
|
12992
|
+
count > 1 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "absolute translate-x-2 -translate-y-2 rounded bg-card px-0.5 font-mono text-[8px] tabular-nums text-[var(--inspector-status-watch)]", children: count })
|
|
13533
12993
|
]
|
|
13534
12994
|
}
|
|
13535
12995
|
);
|
|
@@ -13543,12 +13003,14 @@ function ConversationGroupList({
|
|
|
13543
13003
|
() => /* @__PURE__ */ new Set()
|
|
13544
13004
|
);
|
|
13545
13005
|
const [collapsedProcessIds, setCollapsedProcessIds] = reactExports.useState(
|
|
13546
|
-
() =>
|
|
13006
|
+
() => buildDefaultCollapsedProcessIds(hierarchy)
|
|
13547
13007
|
);
|
|
13548
13008
|
const [storedCollapseStateLoaded, setStoredCollapseStateLoaded] = reactExports.useState(false);
|
|
13549
13009
|
reactExports.useEffect(() => {
|
|
13550
|
-
|
|
13551
|
-
|
|
13010
|
+
const storedClientIds = readStoredIdSet(COLLAPSED_CLIENTS_STORAGE_KEY);
|
|
13011
|
+
const storedProcessIds = readStoredIdSet(COLLAPSED_PROCESSES_STORAGE_KEY);
|
|
13012
|
+
if (storedClientIds !== null) setCollapsedClientIds(storedClientIds);
|
|
13013
|
+
if (storedProcessIds !== null) setCollapsedProcessIds(storedProcessIds);
|
|
13552
13014
|
setStoredCollapseStateLoaded(true);
|
|
13553
13015
|
}, []);
|
|
13554
13016
|
reactExports.useEffect(() => {
|
|
@@ -13620,8 +13082,8 @@ function ClientGroupSection({
|
|
|
13620
13082
|
"section",
|
|
13621
13083
|
{
|
|
13622
13084
|
className: cn(
|
|
13623
|
-
"
|
|
13624
|
-
isWorking && "bg-card/
|
|
13085
|
+
"relative isolate overflow-hidden rounded-[8px] bg-card/65",
|
|
13086
|
+
isWorking && "bg-card/80"
|
|
13625
13087
|
),
|
|
13626
13088
|
"data-ide-group": group.id,
|
|
13627
13089
|
children: [
|
|
@@ -13629,29 +13091,22 @@ function ClientGroupSection({
|
|
|
13629
13091
|
"button",
|
|
13630
13092
|
{
|
|
13631
13093
|
type: "button",
|
|
13632
|
-
className: "grid w-full min-w-0 grid-cols-[2.25rem_minmax(0,1fr)_auto] items-center gap-2.5 px-3 py-2.5 text-left transition-colors hover:bg-
|
|
13094
|
+
className: "grid w-full min-w-0 grid-cols-[2.25rem_minmax(0,1fr)_auto] items-center gap-2.5 px-3 py-2.5 text-left transition-colors hover:bg-[var(--inspector-surface-low)] focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
13633
13095
|
onClick: onToggleClient,
|
|
13634
13096
|
"aria-expanded": !collapsed,
|
|
13635
13097
|
children: [
|
|
13636
|
-
group.client === "unknown" ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "
|
|
13637
|
-
ClientLogo,
|
|
13638
|
-
{
|
|
13639
|
-
client: group.client,
|
|
13640
|
-
className: "size-9 rounded-md text-cyan-100",
|
|
13641
|
-
decorative: true
|
|
13642
|
-
}
|
|
13643
|
-
),
|
|
13098
|
+
group.client === "unknown" ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "inline-flex size-9 shrink-0 items-center justify-center rounded-md bg-[var(--inspector-surface-low)] text-muted-foreground", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Monitor, { className: "size-4" }) }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ClientLogo, { client: group.client, className: "size-9 rounded-md", decorative: true }),
|
|
13644
13099
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "min-w-0", children: [
|
|
13645
13100
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [
|
|
13646
13101
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
13647
13102
|
"span",
|
|
13648
13103
|
{
|
|
13649
|
-
className: "truncate text-sm font-semibold text-
|
|
13104
|
+
className: "truncate text-sm font-semibold text-foreground",
|
|
13650
13105
|
title: group.userAgent ?? group.label,
|
|
13651
13106
|
children: group.label
|
|
13652
13107
|
}
|
|
13653
13108
|
),
|
|
13654
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "rounded bg-
|
|
13109
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "rounded bg-[var(--inspector-surface-medium)] px-1.5 py-0.5 font-mono text-[9px] uppercase text-muted-foreground", children: clientAppTypeLabel(group.client) }),
|
|
13655
13110
|
isWorking && /* @__PURE__ */ jsxRuntimeExports.jsx(AncestorActivityIndicator, { count: pendingTurnCount })
|
|
13656
13111
|
] }),
|
|
13657
13112
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "mt-1 flex flex-wrap items-center gap-x-3 gap-y-1 text-[11px] text-muted-foreground", children: [
|
|
@@ -13676,12 +13131,12 @@ function ClientGroupSection({
|
|
|
13676
13131
|
/* @__PURE__ */ jsxRuntimeExports.jsx(SummaryChip, { label: "IN", value: formatTokenCount(totals.inputTokens) }),
|
|
13677
13132
|
/* @__PURE__ */ jsxRuntimeExports.jsx(SummaryChip, { label: "OUT", value: formatTokenCount(totals.outputTokens) })
|
|
13678
13133
|
] }),
|
|
13679
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "
|
|
13134
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "inline-flex size-8 shrink-0 items-center justify-center rounded-md bg-[var(--inspector-surface-low)] text-muted-foreground transition-colors group-hover:bg-[var(--inspector-surface-medium)]", children: collapsed ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-4" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-4" }) })
|
|
13680
13135
|
] })
|
|
13681
13136
|
]
|
|
13682
13137
|
}
|
|
13683
13138
|
),
|
|
13684
|
-
!collapsed && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-
|
|
13139
|
+
!collapsed && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-0.5 px-2 pb-2 pt-0.5", children: group.processes.map((processGroup) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
13685
13140
|
ProcessGroupSection,
|
|
13686
13141
|
{
|
|
13687
13142
|
group: processGroup,
|
|
@@ -13707,20 +13162,20 @@ function ProcessGroupSection({
|
|
|
13707
13162
|
const logCount = group.logs.length;
|
|
13708
13163
|
const pendingTurnCount = countPendingTurns(group.logs);
|
|
13709
13164
|
const isWorking = pendingTurnCount > 0;
|
|
13710
|
-
const processLabel = group.clientPid !== null && group.clientPid !== void 0 ? `PID ${group.clientPid}` : "
|
|
13711
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "relative pl-
|
|
13165
|
+
const processLabel = group.clientPid !== null && group.clientPid !== void 0 ? `PID ${group.clientPid}` : "Process unavailable";
|
|
13166
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "relative pl-3", children: [
|
|
13712
13167
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
13713
13168
|
"button",
|
|
13714
13169
|
{
|
|
13715
13170
|
type: "button",
|
|
13716
|
-
className: "
|
|
13171
|
+
className: "grid w-full min-w-0 grid-cols-[2rem_minmax(0,1fr)_auto] items-center gap-2.5 rounded-md bg-[var(--inspector-surface-low)] px-2.5 py-2 text-left transition-colors hover:bg-[var(--inspector-surface-medium)] focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
13717
13172
|
onClick: onToggle,
|
|
13718
13173
|
"aria-expanded": !collapsed,
|
|
13719
13174
|
children: [
|
|
13720
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "
|
|
13175
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "inline-flex size-8 shrink-0 items-center justify-center text-[var(--inspector-status-watch)]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Cpu, { className: "size-4" }) }),
|
|
13721
13176
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "min-w-0", children: [
|
|
13722
13177
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: [
|
|
13723
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-xs font-semibold tabular-nums text-
|
|
13178
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-xs font-semibold tabular-nums text-foreground", children: processLabel }),
|
|
13724
13179
|
isWorking && /* @__PURE__ */ jsxRuntimeExports.jsx(AncestorActivityIndicator, { count: pendingTurnCount }),
|
|
13725
13180
|
projectLabel !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
13726
13181
|
"span",
|
|
@@ -13751,12 +13206,12 @@ function ProcessGroupSection({
|
|
|
13751
13206
|
/* @__PURE__ */ jsxRuntimeExports.jsx(SummaryChip, { label: "IN", value: formatTokenCount(totals.inputTokens) }),
|
|
13752
13207
|
/* @__PURE__ */ jsxRuntimeExports.jsx(SummaryChip, { label: "OUT", value: formatTokenCount(totals.outputTokens) })
|
|
13753
13208
|
] }),
|
|
13754
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "
|
|
13209
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "inline-flex size-7 shrink-0 items-center justify-center rounded-md bg-[var(--inspector-surface-low)] text-muted-foreground transition-colors hover:bg-[var(--inspector-surface-medium)]", children: collapsed ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-4" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-4" }) })
|
|
13755
13210
|
] })
|
|
13756
13211
|
]
|
|
13757
13212
|
}
|
|
13758
13213
|
),
|
|
13759
|
-
!collapsed && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1
|
|
13214
|
+
!collapsed && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1 pb-1 pl-3 pr-1 pt-1", children: group.sessions.map((session) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
13760
13215
|
ConversationGroup,
|
|
13761
13216
|
{
|
|
13762
13217
|
group: session,
|
|
@@ -13769,6 +13224,61 @@ function ProcessGroupSection({
|
|
|
13769
13224
|
)) })
|
|
13770
13225
|
] });
|
|
13771
13226
|
}
|
|
13227
|
+
const RAW_EXPORT_DIALOG_CLASS_NAME = "w-[calc(100%-1rem)] border-warning/30 bg-popover text-popover-foreground sm:max-w-lg";
|
|
13228
|
+
const RAW_EXPORT_RISK_ITEMS = [
|
|
13229
|
+
{
|
|
13230
|
+
label: "Headers",
|
|
13231
|
+
detail: "request and response headers, including authorization or cookie values"
|
|
13232
|
+
},
|
|
13233
|
+
{
|
|
13234
|
+
label: "Prompts",
|
|
13235
|
+
detail: "system instructions, user prompts, model responses, and conversation history"
|
|
13236
|
+
},
|
|
13237
|
+
{
|
|
13238
|
+
label: "Source content",
|
|
13239
|
+
detail: "source code, file contents, tool inputs, and tool output"
|
|
13240
|
+
},
|
|
13241
|
+
{
|
|
13242
|
+
label: "Secrets",
|
|
13243
|
+
detail: "API keys, access tokens, credentials, and other sensitive values"
|
|
13244
|
+
}
|
|
13245
|
+
];
|
|
13246
|
+
function RawExportWarning({
|
|
13247
|
+
onCancel,
|
|
13248
|
+
onExportRedacted,
|
|
13249
|
+
onConfirmRaw
|
|
13250
|
+
}) {
|
|
13251
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
13252
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(DialogHeader, { children: [
|
|
13253
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(DialogTitle, { children: "Export unredacted logs?" }),
|
|
13254
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(DialogDescription, { children: "Raw exports bypass Agent Inspector redaction and may expose sensitive captured data." })
|
|
13255
|
+
] }),
|
|
13256
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
13257
|
+
"div",
|
|
13258
|
+
{
|
|
13259
|
+
role: "alert",
|
|
13260
|
+
className: "rounded-md border border-warning/35 bg-warning/10 px-3 py-3 text-sm text-foreground",
|
|
13261
|
+
children: [
|
|
13262
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "font-medium", children: "The raw archive may include:" }),
|
|
13263
|
+
/* @__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: [
|
|
13264
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-semibold text-foreground", children: [
|
|
13265
|
+
item.label,
|
|
13266
|
+
":"
|
|
13267
|
+
] }),
|
|
13268
|
+
" ",
|
|
13269
|
+
item.detail
|
|
13270
|
+
] }, item.label)) }),
|
|
13271
|
+
/* @__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." })
|
|
13272
|
+
]
|
|
13273
|
+
}
|
|
13274
|
+
),
|
|
13275
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", children: [
|
|
13276
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: onCancel, children: "Cancel" }),
|
|
13277
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: onExportRedacted, children: "Export redacted instead" }),
|
|
13278
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Button, { type: "button", variant: "destructive", size: "sm", onClick: onConfirmRaw, children: "Export raw data" })
|
|
13279
|
+
] })
|
|
13280
|
+
] });
|
|
13281
|
+
}
|
|
13772
13282
|
const NAV_ATTR = "data-nav-id";
|
|
13773
13283
|
const NAV_ACTION_ATTR = "data-nav-action";
|
|
13774
13284
|
function findNavItems(container) {
|
|
@@ -15196,7 +14706,7 @@ function LogPaginationButton({
|
|
|
15196
14706
|
type: "button",
|
|
15197
14707
|
onClick,
|
|
15198
14708
|
disabled,
|
|
15199
|
-
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",
|
|
14709
|
+
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",
|
|
15200
14710
|
title,
|
|
15201
14711
|
children: [
|
|
15202
14712
|
icon,
|
|
@@ -15205,36 +14715,6 @@ function LogPaginationButton({
|
|
|
15205
14715
|
}
|
|
15206
14716
|
);
|
|
15207
14717
|
}
|
|
15208
|
-
function formatDurationSeconds(ms) {
|
|
15209
|
-
return `${Math.max(0, Math.ceil(ms / 1e3)).toString()}s`;
|
|
15210
|
-
}
|
|
15211
|
-
function SessionLoadProgressBar({ progress }) {
|
|
15212
|
-
const elapsedRatio = Math.min(1, progress.elapsedMs / progress.timeoutMs);
|
|
15213
|
-
const percent = Math.max(4, Math.round(elapsedRatio * 100));
|
|
15214
|
-
const remainingMs = Math.max(0, progress.timeoutMs - progress.elapsedMs);
|
|
15215
|
-
const nearTimeout = elapsedRatio >= 0.75;
|
|
15216
|
-
const details = [
|
|
15217
|
-
progress.loadedLogs > 0 ? `${progress.loadedLogs.toString()} logs` : null,
|
|
15218
|
-
progress.loadedPages > 0 ? `${progress.loadedPages.toString()} page${progress.loadedPages === 1 ? "" : "s"}` : null,
|
|
15219
|
-
`${formatDurationSeconds(remainingMs)} before timeout`
|
|
15220
|
-
].filter((item) => item !== null);
|
|
15221
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 space-y-1 px-1 pb-1", children: [
|
|
15222
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center justify-between gap-3 font-mono text-[10px] text-muted-foreground", children: [
|
|
15223
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0 truncate", children: progress.label }),
|
|
15224
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn("shrink-0 tabular-nums", nearTimeout && "text-amber-300"), children: details.join(" / ") })
|
|
15225
|
-
] }),
|
|
15226
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-1.5 overflow-hidden rounded-full bg-white/[0.06]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
15227
|
-
"div",
|
|
15228
|
-
{
|
|
15229
|
-
className: cn(
|
|
15230
|
-
"h-full rounded-full transition-all duration-300",
|
|
15231
|
-
nearTimeout ? "bg-amber-300/80" : "bg-cyan-300/70"
|
|
15232
|
-
),
|
|
15233
|
-
style: { width: `${percent.toString()}%` }
|
|
15234
|
-
}
|
|
15235
|
-
) })
|
|
15236
|
-
] });
|
|
15237
|
-
}
|
|
15238
14718
|
function LogPaginationBar({
|
|
15239
14719
|
logs,
|
|
15240
14720
|
pagination,
|
|
@@ -15243,16 +14723,19 @@ function LogPaginationBar({
|
|
|
15243
14723
|
if (pagination === void 0) return null;
|
|
15244
14724
|
const disabled = pagination.isLoading;
|
|
15245
14725
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
15246
|
-
"
|
|
14726
|
+
"nav",
|
|
15247
14727
|
{
|
|
14728
|
+
"aria-label": "Session log pagination",
|
|
15248
14729
|
className: cn(
|
|
15249
14730
|
"flex min-h-9 flex-col gap-2 px-1 py-1 sm:flex-row sm:items-center",
|
|
15250
14731
|
embedded ? "border-t border-white/10 pt-2" : "border border-border bg-card shadow-sm mb-3 rounded-[8px] px-2"
|
|
15251
14732
|
),
|
|
15252
14733
|
children: [
|
|
15253
14734
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full min-w-0 px-1 font-mono text-[11px] text-muted-foreground sm:flex-1", children: [
|
|
15254
|
-
|
|
15255
|
-
|
|
14735
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { role: "status", "aria-live": "polite", "aria-atomic": "true", children: [
|
|
14736
|
+
formatPaginationStatus({ logs, pagination }),
|
|
14737
|
+
pagination.isLoading && logs.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ml-2", children: "Loading..." })
|
|
14738
|
+
] }),
|
|
15256
14739
|
pagination.loadProgress !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(SessionLoadProgressBar, { progress: pagination.loadProgress })
|
|
15257
14740
|
] }),
|
|
15258
14741
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex w-full items-center gap-1 overflow-x-auto sm:w-auto", children: [
|
|
@@ -15350,7 +14833,10 @@ function highlightLogTarget(target) {
|
|
|
15350
14833
|
function focusLogTarget(logId) {
|
|
15351
14834
|
const target = document.getElementById(`log-${String(logId)}`);
|
|
15352
14835
|
if (!(target instanceof HTMLElement)) return false;
|
|
15353
|
-
target.scrollIntoView({
|
|
14836
|
+
target.scrollIntoView({
|
|
14837
|
+
block: "center",
|
|
14838
|
+
behavior: preferredScrollBehavior(browserPrefersReducedMotion())
|
|
14839
|
+
});
|
|
15354
14840
|
target.focus({ preventScroll: true });
|
|
15355
14841
|
highlightLogTarget(target);
|
|
15356
14842
|
return true;
|
|
@@ -15377,14 +14863,14 @@ function CopyableCommand({ command }) {
|
|
|
15377
14863
|
setTimeout(() => setCopied(false), 2e3);
|
|
15378
14864
|
});
|
|
15379
14865
|
}, [command]);
|
|
15380
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", {
|
|
15381
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className:
|
|
14866
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { "data-command-example": "true", className: COPYABLE_COMMAND_CONTAINER_CLASS_NAME, children: [
|
|
14867
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: COPYABLE_COMMAND_TEXT_CLASS_NAME, children: command }),
|
|
15382
14868
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
15383
14869
|
"button",
|
|
15384
14870
|
{
|
|
15385
14871
|
type: "button",
|
|
15386
14872
|
onClick: handleCopy,
|
|
15387
|
-
className: "shrink-0 cursor-pointer text-muted-foreground transition-colors hover:text-foreground",
|
|
14873
|
+
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",
|
|
15388
14874
|
"aria-label": "Copy command",
|
|
15389
14875
|
children: copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-4" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-4" })
|
|
15390
14876
|
}
|
|
@@ -15416,46 +14902,6 @@ function SidebarMetric({ label, value }) {
|
|
|
15416
14902
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-0.5 truncate font-mono text-[10px] uppercase tracking-[0.12em] text-white/35", children: label })
|
|
15417
14903
|
] });
|
|
15418
14904
|
}
|
|
15419
|
-
const CRAB_VARIANT_COLORS = [
|
|
15420
|
-
"text-amber-500",
|
|
15421
|
-
"text-rose-500",
|
|
15422
|
-
"text-sky-500",
|
|
15423
|
-
"text-emerald-500",
|
|
15424
|
-
"text-violet-500",
|
|
15425
|
-
"text-orange-500",
|
|
15426
|
-
"text-cyan-500",
|
|
15427
|
-
"text-pink-500",
|
|
15428
|
-
"text-lime-500",
|
|
15429
|
-
"text-blue-500",
|
|
15430
|
-
"text-yellow-500",
|
|
15431
|
-
"text-fuchsia-500"
|
|
15432
|
-
];
|
|
15433
|
-
function CrabFamily({
|
|
15434
|
-
compact,
|
|
15435
|
-
entrancePhase
|
|
15436
|
-
}) {
|
|
15437
|
-
if (compact) {
|
|
15438
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(CrabLogo, { className: "size-14 text-amber-500" });
|
|
15439
|
-
}
|
|
15440
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex shrink-0 items-end gap-1 group cursor-default", "aria-hidden": "true", children: [
|
|
15441
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(CrabLogo, { className: "size-10 text-amber-500 transition-all duration-300 group-hover:scale-125 group-hover:-translate-y-1.5" }),
|
|
15442
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "hidden items-end gap-0.5 sm:flex", children: crabVariants.map((Crab, i) => {
|
|
15443
|
-
const color = CRAB_VARIANT_COLORS[i] ?? "text-amber-500";
|
|
15444
|
-
const entranceClass = entrancePhase === "hidden" ? "opacity-0 scale-0" : entrancePhase === "playing" ? "animate-crab-piano-pop" : "";
|
|
15445
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
15446
|
-
Crab,
|
|
15447
|
-
{
|
|
15448
|
-
className: `size-5 ${color} transition-all duration-300 ease-out group-hover:scale-125 group-hover:-translate-y-1 ${entranceClass}`,
|
|
15449
|
-
style: {
|
|
15450
|
-
transitionDelay: `${i * 50}ms`,
|
|
15451
|
-
...entrancePhase === "playing" ? { animationDelay: `${i * 400}ms` } : {}
|
|
15452
|
-
}
|
|
15453
|
-
},
|
|
15454
|
-
i
|
|
15455
|
-
);
|
|
15456
|
-
}) })
|
|
15457
|
-
] });
|
|
15458
|
-
}
|
|
15459
14905
|
function ThemeModeToggle() {
|
|
15460
14906
|
const { themeMode, setThemeMode } = useThemeMode();
|
|
15461
14907
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
@@ -15471,7 +14917,7 @@ function ThemeModeToggle() {
|
|
|
15471
14917
|
type: "button",
|
|
15472
14918
|
onClick: () => setThemeMode("light"),
|
|
15473
14919
|
className: cn(
|
|
15474
|
-
"inline-flex size-7 items-center justify-center rounded-[6px] text-muted-foreground transition-colors hover:text-foreground",
|
|
14920
|
+
"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",
|
|
15475
14921
|
themeMode === "light" && "bg-background text-foreground shadow-sm"
|
|
15476
14922
|
),
|
|
15477
14923
|
"aria-label": "Use light mode",
|
|
@@ -15486,7 +14932,7 @@ function ThemeModeToggle() {
|
|
|
15486
14932
|
type: "button",
|
|
15487
14933
|
onClick: () => setThemeMode("eye-care"),
|
|
15488
14934
|
className: cn(
|
|
15489
|
-
"inline-flex size-7 items-center justify-center rounded-[6px] text-muted-foreground transition-colors hover:text-foreground",
|
|
14935
|
+
"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",
|
|
15490
14936
|
themeMode === "eye-care" && "bg-background text-foreground shadow-sm"
|
|
15491
14937
|
),
|
|
15492
14938
|
"aria-label": "Use eye care mode",
|
|
@@ -15501,7 +14947,7 @@ function ThemeModeToggle() {
|
|
|
15501
14947
|
type: "button",
|
|
15502
14948
|
onClick: () => setThemeMode("dark"),
|
|
15503
14949
|
className: cn(
|
|
15504
|
-
"inline-flex size-7 items-center justify-center rounded-[6px] text-muted-foreground transition-colors hover:text-foreground",
|
|
14950
|
+
"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",
|
|
15505
14951
|
themeMode === "dark" && "bg-background text-foreground shadow-sm"
|
|
15506
14952
|
),
|
|
15507
14953
|
"aria-label": "Use dark mode",
|
|
@@ -15570,81 +15016,6 @@ function UiScaleControl({
|
|
|
15570
15016
|
}
|
|
15571
15017
|
);
|
|
15572
15018
|
}
|
|
15573
|
-
function BrandHeader({
|
|
15574
|
-
compact,
|
|
15575
|
-
crabEntrancePhase,
|
|
15576
|
-
currentSessionId,
|
|
15577
|
-
logCount,
|
|
15578
|
-
uiScalePreference,
|
|
15579
|
-
resolvedUiScale,
|
|
15580
|
-
onUiScaleChange
|
|
15581
|
-
}) {
|
|
15582
|
-
if (compact) {
|
|
15583
|
-
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: [
|
|
15584
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-fit items-start gap-3", children: [
|
|
15585
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(CrabFamily, { compact: true, entrancePhase: crabEntrancePhase }),
|
|
15586
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-fit", children: [
|
|
15587
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-fit flex-wrap items-baseline gap-x-2 gap-y-0.5", children: [
|
|
15588
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "whitespace-nowrap text-base font-bold", children: "Agent Inspector" }),
|
|
15589
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "hidden shrink-0 font-mono text-[11px] font-semibold text-muted-foreground sm:inline", children: [
|
|
15590
|
-
"v",
|
|
15591
|
-
packageJson.version
|
|
15592
|
-
] })
|
|
15593
|
-
] }),
|
|
15594
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "hidden text-[11px] font-semibold text-muted-foreground sm:block", children: "Local First. Evidence First." })
|
|
15595
|
-
] })
|
|
15596
|
-
] }),
|
|
15597
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [
|
|
15598
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(ThemeModeToggle, {}),
|
|
15599
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
15600
|
-
UiScaleControl,
|
|
15601
|
-
{
|
|
15602
|
-
preference: uiScalePreference,
|
|
15603
|
-
resolvedScale: resolvedUiScale,
|
|
15604
|
-
onChange: onUiScaleChange
|
|
15605
|
-
}
|
|
15606
|
-
),
|
|
15607
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(AlertsDialog, {}),
|
|
15608
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(GroupsDialog, {}),
|
|
15609
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(AgentLabDialog, { currentSessionId, logCount }),
|
|
15610
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(SettingsDialog, {})
|
|
15611
|
-
] })
|
|
15612
|
-
] }) });
|
|
15613
|
-
}
|
|
15614
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-start justify-between gap-x-4 gap-y-3 pb-6", children: [
|
|
15615
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "min-w-10 flex-1", "aria-hidden": "true" }),
|
|
15616
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("h1", { className: "flex min-w-fit flex-col items-center gap-2 text-center", children: [
|
|
15617
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex max-w-full flex-wrap items-end justify-center gap-x-2 gap-y-1", children: [
|
|
15618
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(CrabFamily, { compact: false, entrancePhase: crabEntrancePhase }),
|
|
15619
|
-
/* @__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: [
|
|
15620
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "whitespace-nowrap text-lg font-bold", children: "Agent Inspector" }),
|
|
15621
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "shrink-0 font-mono text-xs font-semibold text-muted-foreground", children: [
|
|
15622
|
-
"v",
|
|
15623
|
-
packageJson.version
|
|
15624
|
-
] })
|
|
15625
|
-
] }),
|
|
15626
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "size-4 shrink-0 text-muted-foreground/70", "aria-hidden": "true" }),
|
|
15627
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(McpLogo, { className: "size-10 shrink-0" })
|
|
15628
|
-
] }),
|
|
15629
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "max-w-full text-sm font-semibold text-muted-foreground", children: "Local First. Evidence First." })
|
|
15630
|
-
] }),
|
|
15631
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-1 justify-end gap-1", children: [
|
|
15632
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(ThemeModeToggle, {}),
|
|
15633
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
15634
|
-
UiScaleControl,
|
|
15635
|
-
{
|
|
15636
|
-
preference: uiScalePreference,
|
|
15637
|
-
resolvedScale: resolvedUiScale,
|
|
15638
|
-
onChange: onUiScaleChange
|
|
15639
|
-
}
|
|
15640
|
-
),
|
|
15641
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(AlertsDialog, {}),
|
|
15642
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(GroupsDialog, {}),
|
|
15643
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(AgentLabDialog, { currentSessionId, logCount }),
|
|
15644
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(SettingsDialog, {})
|
|
15645
|
-
] })
|
|
15646
|
-
] });
|
|
15647
|
-
}
|
|
15648
15019
|
const DETAILS_PANEL_COLLAPSED_STORAGE_KEY = "agent-inspector.detailsPanelCollapsed";
|
|
15649
15020
|
const INSPECTOR_PET_VISIBLE_STORAGE_KEY = "agent-inspector.pet.visible";
|
|
15650
15021
|
function readStoredDetailsPanelCollapsed() {
|
|
@@ -15968,8 +15339,12 @@ function ProxyViewer({
|
|
|
15968
15339
|
slowResponseThresholdSeconds,
|
|
15969
15340
|
timeDisplayFormat,
|
|
15970
15341
|
isLoading = false,
|
|
15342
|
+
liveConnection,
|
|
15343
|
+
onRetryLiveConnection,
|
|
15344
|
+
onStopLiveConnection,
|
|
15971
15345
|
pagination,
|
|
15972
15346
|
sessionLoadProgress,
|
|
15347
|
+
sessionLoadError,
|
|
15973
15348
|
sessionMemberships = [],
|
|
15974
15349
|
hideSessionFilter = false,
|
|
15975
15350
|
pinnedSessionId
|
|
@@ -15979,6 +15354,7 @@ function ProxyViewer({
|
|
|
15979
15354
|
const { uiScalePreference, resolvedUiScale, setUiScalePreference } = useUiScale();
|
|
15980
15355
|
const [exporting, setExporting] = reactExports.useState(null);
|
|
15981
15356
|
const [exportError, setExportError] = reactExports.useState(null);
|
|
15357
|
+
const [rawExportDialogOpen, setRawExportDialogOpen] = reactExports.useState(false);
|
|
15982
15358
|
const [importing, setImporting] = reactExports.useState(false);
|
|
15983
15359
|
const [importStatus, setImportStatus] = reactExports.useState(null);
|
|
15984
15360
|
const [importError, setImportError] = reactExports.useState(null);
|
|
@@ -15989,9 +15365,6 @@ function ProxyViewer({
|
|
|
15989
15365
|
const [petVisible, setPetVisible] = reactExports.useState(true);
|
|
15990
15366
|
const [petVisibilityStorageLoaded, setPetVisibilityStorageLoaded] = reactExports.useState(false);
|
|
15991
15367
|
const [comparePair, setComparePair] = reactExports.useState(null);
|
|
15992
|
-
const [crabEntrancePhase, setCrabEntrancePhase] = reactExports.useState(
|
|
15993
|
-
"hidden"
|
|
15994
|
-
);
|
|
15995
15368
|
const logListRef = reactExports.useRef(null);
|
|
15996
15369
|
const logListWrapperRef = reactExports.useRef(null);
|
|
15997
15370
|
const importInputRef = reactExports.useRef(null);
|
|
@@ -16013,17 +15386,6 @@ function ProxyViewer({
|
|
|
16013
15386
|
},
|
|
16014
15387
|
[]
|
|
16015
15388
|
);
|
|
16016
|
-
reactExports.useEffect(() => {
|
|
16017
|
-
const perCrabDuration = 400;
|
|
16018
|
-
const startDelay = 50;
|
|
16019
|
-
const playingDone = startDelay + crabVariants.length * perCrabDuration;
|
|
16020
|
-
const t1 = setTimeout(() => setCrabEntrancePhase("playing"), startDelay);
|
|
16021
|
-
const t2 = setTimeout(() => setCrabEntrancePhase("done"), playingDone);
|
|
16022
|
-
return () => {
|
|
16023
|
-
clearTimeout(t1);
|
|
16024
|
-
clearTimeout(t2);
|
|
16025
|
-
};
|
|
16026
|
-
}, []);
|
|
16027
15389
|
reactExports.useEffect(() => {
|
|
16028
15390
|
setDetailsPanelCollapsed(readStoredDetailsPanelCollapsed());
|
|
16029
15391
|
setDetailsPanelStorageLoaded(true);
|
|
@@ -16083,6 +15445,24 @@ function ProxyViewer({
|
|
|
16083
15445
|
},
|
|
16084
15446
|
[logs, onNotify]
|
|
16085
15447
|
);
|
|
15448
|
+
const handleExportRequest = reactExports.useCallback(
|
|
15449
|
+
(mode) => {
|
|
15450
|
+
if (exportRequiresConfirmation(mode)) {
|
|
15451
|
+
setRawExportDialogOpen(true);
|
|
15452
|
+
return;
|
|
15453
|
+
}
|
|
15454
|
+
void handleExport(mode);
|
|
15455
|
+
},
|
|
15456
|
+
[handleExport]
|
|
15457
|
+
);
|
|
15458
|
+
const handleExportRedactedInstead = reactExports.useCallback(() => {
|
|
15459
|
+
setRawExportDialogOpen(false);
|
|
15460
|
+
void handleExport("redacted");
|
|
15461
|
+
}, [handleExport]);
|
|
15462
|
+
const handleConfirmRawExport = reactExports.useCallback(() => {
|
|
15463
|
+
setRawExportDialogOpen(false);
|
|
15464
|
+
void handleExport("raw");
|
|
15465
|
+
}, [handleExport]);
|
|
16086
15466
|
const handleImportClick = reactExports.useCallback(() => {
|
|
16087
15467
|
importInputRef.current?.click();
|
|
16088
15468
|
}, []);
|
|
@@ -16194,6 +15574,8 @@ function ProxyViewer({
|
|
|
16194
15574
|
const sessionInputValue = selectedSession === "__all__" ? "" : selectedSession;
|
|
16195
15575
|
const sessionSelectValue = selectedSession === "__all__" || sessions.includes(selectedSession) ? selectedSession : "__typed__";
|
|
16196
15576
|
const activeScopeLabel = hasSessionContext && sessionContextScope !== null ? truncateSessionId(sessionContextScope.label) : selectedSession === "__all__" ? "All sessions" : truncateSessionId(selectedSession);
|
|
15577
|
+
const liveEmptyState = resolveLiveEmptyState(liveConnection);
|
|
15578
|
+
const liveEmptyStateCopy = getLiveEmptyStateCopy(liveEmptyState);
|
|
16197
15579
|
const slateStats = reactExports.useMemo(
|
|
16198
15580
|
() => buildSessionSlateStats({
|
|
16199
15581
|
logs,
|
|
@@ -16226,14 +15608,22 @@ function ProxyViewer({
|
|
|
16226
15608
|
[onSessionChange]
|
|
16227
15609
|
);
|
|
16228
15610
|
const labSessionId = pinnedSessionId !== void 0 ? pinnedSessionId : selectedSession === "__all__" ? null : selectedSession;
|
|
16229
|
-
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: [
|
|
15611
|
+
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: [
|
|
15612
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
15613
|
+
ApplicationBar,
|
|
15614
|
+
{
|
|
15615
|
+
liveConnection,
|
|
15616
|
+
alertsAction: /* @__PURE__ */ jsxRuntimeExports.jsx(AlertsDialog, {}),
|
|
15617
|
+
settingsAction: /* @__PURE__ */ jsxRuntimeExports.jsx(SettingsDialog, {})
|
|
15618
|
+
}
|
|
15619
|
+
),
|
|
16230
15620
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
16231
15621
|
"button",
|
|
16232
15622
|
{
|
|
16233
15623
|
type: "button",
|
|
16234
15624
|
onClick: toggleDetailsPanelCollapsed,
|
|
16235
15625
|
className: cn(
|
|
16236
|
-
"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",
|
|
15626
|
+
"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",
|
|
16237
15627
|
detailsPanelCollapsed ? "right-3" : "lg:right-[calc(21.25rem-0.875rem)] xl:right-[calc(22.5rem-0.875rem)]"
|
|
16238
15628
|
),
|
|
16239
15629
|
"aria-label": detailsPanelCollapsed ? "Show details panel" : "Hide details panel",
|
|
@@ -16244,7 +15634,7 @@ function ProxyViewer({
|
|
|
16244
15634
|
]
|
|
16245
15635
|
}
|
|
16246
15636
|
),
|
|
16247
|
-
petVisibilityStorageLoaded && petVisible && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
15637
|
+
petVisibilityStorageLoaded && petVisible && /* @__PURE__ */ jsxRuntimeExports.jsx(LazyFeatureBoundary, { feature: "Inspector Pet", children: /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntimeExports.jsx(LazyInspectorPet, { logs }) }) }),
|
|
16248
15638
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
16249
15639
|
"div",
|
|
16250
15640
|
{
|
|
@@ -16254,18 +15644,19 @@ function ProxyViewer({
|
|
|
16254
15644
|
),
|
|
16255
15645
|
children: [
|
|
16256
15646
|
!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: [
|
|
16257
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
16258
|
-
|
|
16259
|
-
|
|
16260
|
-
|
|
16261
|
-
|
|
16262
|
-
|
|
16263
|
-
|
|
16264
|
-
|
|
16265
|
-
|
|
16266
|
-
|
|
16267
|
-
}
|
|
16268
|
-
|
|
15647
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SidebarPanel, { label: "Tools", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [
|
|
15648
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ThemeModeToggle, {}),
|
|
15649
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
15650
|
+
UiScaleControl,
|
|
15651
|
+
{
|
|
15652
|
+
preference: uiScalePreference,
|
|
15653
|
+
resolvedScale: resolvedUiScale,
|
|
15654
|
+
onChange: setUiScalePreference
|
|
15655
|
+
}
|
|
15656
|
+
),
|
|
15657
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(GroupsDialog, {}),
|
|
15658
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(AgentLabDialog, { currentSessionId: labSessionId, logCount: logs.length })
|
|
15659
|
+
] }) }),
|
|
16269
15660
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(SidebarPanel, { label: "Session", children: [
|
|
16270
15661
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
16271
15662
|
/* @__PURE__ */ jsxRuntimeExports.jsx(SidebarMetric, { label: "Requests", value: logs.length }),
|
|
@@ -16333,7 +15724,7 @@ function ProxyViewer({
|
|
|
16333
15724
|
{
|
|
16334
15725
|
type: "button",
|
|
16335
15726
|
onClick: () => onSessionChange("__all__"),
|
|
16336
|
-
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",
|
|
15727
|
+
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",
|
|
16337
15728
|
"aria-label": "Clear session filter",
|
|
16338
15729
|
title: "Clear session filter",
|
|
16339
15730
|
children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "size-3.5" })
|
|
@@ -16341,7 +15732,14 @@ function ProxyViewer({
|
|
|
16341
15732
|
)
|
|
16342
15733
|
] }),
|
|
16343
15734
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(Select, { value: sessionSelectValue, onValueChange: handleSessionSelectChange, children: [
|
|
16344
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
15735
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
15736
|
+
SelectTrigger,
|
|
15737
|
+
{
|
|
15738
|
+
"aria-label": "Select a session",
|
|
15739
|
+
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)]",
|
|
15740
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue, { placeholder: "All sessions" })
|
|
15741
|
+
}
|
|
15742
|
+
),
|
|
16345
15743
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(SelectContent, { children: [
|
|
16346
15744
|
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: "__all__", children: "All sessions" }),
|
|
16347
15745
|
sessionSelectValue === "__typed__" && /* @__PURE__ */ jsxRuntimeExports.jsxs(SelectItem, { value: "__typed__", children: [
|
|
@@ -16353,7 +15751,14 @@ function ProxyViewer({
|
|
|
16353
15751
|
] })
|
|
16354
15752
|
] }),
|
|
16355
15753
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(Select, { value: selectedModel, onValueChange: onModelChange, children: [
|
|
16356
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
15754
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
15755
|
+
SelectTrigger,
|
|
15756
|
+
{
|
|
15757
|
+
"aria-label": "Select a model",
|
|
15758
|
+
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)]",
|
|
15759
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue, { placeholder: "All models" })
|
|
15760
|
+
}
|
|
15761
|
+
),
|
|
16357
15762
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(SelectContent, { children: [
|
|
16358
15763
|
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: "__all__", children: "All models" }),
|
|
16359
15764
|
models.map((m) => /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: m, children: m }, m))
|
|
@@ -16386,7 +15791,7 @@ function ProxyViewer({
|
|
|
16386
15791
|
type: "button",
|
|
16387
15792
|
onClick: handleImportClick,
|
|
16388
15793
|
disabled: importing,
|
|
16389
|
-
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",
|
|
15794
|
+
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",
|
|
16390
15795
|
title: "Import Agent Inspector export",
|
|
16391
15796
|
children: importing ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Importing..." }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
16392
15797
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Upload, { className: "size-3.5" }),
|
|
@@ -16400,10 +15805,10 @@ function ProxyViewer({
|
|
|
16400
15805
|
{
|
|
16401
15806
|
type: "button",
|
|
16402
15807
|
onClick: () => {
|
|
16403
|
-
|
|
15808
|
+
handleExportRequest("redacted");
|
|
16404
15809
|
},
|
|
16405
15810
|
disabled: exporting !== null,
|
|
16406
|
-
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",
|
|
15811
|
+
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",
|
|
16407
15812
|
title: "Export redacted logs as JSON ZIP",
|
|
16408
15813
|
children: exporting === "redacted" ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Exporting..." }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
16409
15814
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Download, { className: "size-3.5" }),
|
|
@@ -16416,10 +15821,10 @@ function ProxyViewer({
|
|
|
16416
15821
|
{
|
|
16417
15822
|
type: "button",
|
|
16418
15823
|
onClick: () => {
|
|
16419
|
-
|
|
15824
|
+
handleExportRequest("raw");
|
|
16420
15825
|
},
|
|
16421
15826
|
disabled: exporting !== null,
|
|
16422
|
-
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",
|
|
15827
|
+
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",
|
|
16423
15828
|
title: "Export raw logs without redaction",
|
|
16424
15829
|
children: exporting === "raw" ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Exporting..." }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
16425
15830
|
/* @__PURE__ */ jsxRuntimeExports.jsx(FileBraces, { className: "size-3.5" }),
|
|
@@ -16433,10 +15838,18 @@ function ProxyViewer({
|
|
|
16433
15838
|
type: "button",
|
|
16434
15839
|
onClick: handleReloadCurrentSession,
|
|
16435
15840
|
disabled: isLoading,
|
|
16436
|
-
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",
|
|
15841
|
+
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",
|
|
16437
15842
|
title: "Reload this session from stored logs",
|
|
16438
15843
|
children: [
|
|
16439
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
15844
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
15845
|
+
RefreshCw,
|
|
15846
|
+
{
|
|
15847
|
+
className: cn(
|
|
15848
|
+
"size-3.5",
|
|
15849
|
+
isLoading && "animate-spin motion-reduce:animate-none"
|
|
15850
|
+
)
|
|
15851
|
+
}
|
|
15852
|
+
),
|
|
16440
15853
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: reloadSessionLabel })
|
|
16441
15854
|
]
|
|
16442
15855
|
}
|
|
@@ -16447,7 +15860,7 @@ function ProxyViewer({
|
|
|
16447
15860
|
type: "button",
|
|
16448
15861
|
onClick: handleClearCurrentView,
|
|
16449
15862
|
disabled: !canClearCurrentView,
|
|
16450
|
-
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",
|
|
15863
|
+
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",
|
|
16451
15864
|
title: "Clear the current view. Stored logs remain reloadable.",
|
|
16452
15865
|
children: [
|
|
16453
15866
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" }),
|
|
@@ -16461,7 +15874,7 @@ function ProxyViewer({
|
|
|
16461
15874
|
type: "button",
|
|
16462
15875
|
onClick: handleRequestDeleteCurrentView,
|
|
16463
15876
|
disabled: !canDeleteCurrentView || deletingCurrentView,
|
|
16464
|
-
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",
|
|
15877
|
+
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",
|
|
16465
15878
|
title: "Delete persisted history for the selected session.",
|
|
16466
15879
|
children: [
|
|
16467
15880
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" }),
|
|
@@ -16471,15 +15884,50 @@ function ProxyViewer({
|
|
|
16471
15884
|
)
|
|
16472
15885
|
] }),
|
|
16473
15886
|
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 }) }),
|
|
15887
|
+
sessionLoadError !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
15888
|
+
"div",
|
|
15889
|
+
{
|
|
15890
|
+
role: "alert",
|
|
15891
|
+
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",
|
|
15892
|
+
children: [
|
|
15893
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "min-w-0 flex-1", children: [
|
|
15894
|
+
"Session logs could not be loaded. ",
|
|
15895
|
+
sessionLoadError,
|
|
15896
|
+
" Existing logs remain visible."
|
|
15897
|
+
] }),
|
|
15898
|
+
onReloadSession !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
15899
|
+
"button",
|
|
15900
|
+
{
|
|
15901
|
+
type: "button",
|
|
15902
|
+
onClick: handleReloadCurrentSession,
|
|
15903
|
+
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",
|
|
15904
|
+
children: [
|
|
15905
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: "size-3" }),
|
|
15906
|
+
"Retry"
|
|
15907
|
+
]
|
|
15908
|
+
}
|
|
15909
|
+
)
|
|
15910
|
+
]
|
|
15911
|
+
}
|
|
15912
|
+
),
|
|
16474
15913
|
/* @__PURE__ */ jsxRuntimeExports.jsx(LogPaginationBar, { logs, pagination, embedded: true }),
|
|
16475
15914
|
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 }),
|
|
16476
15915
|
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 }),
|
|
16477
|
-
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 })
|
|
15916
|
+
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 }),
|
|
15917
|
+
liveConnection !== void 0 && liveConnection.status !== "live" && onRetryLiveConnection !== void 0 && onStopLiveConnection !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
15918
|
+
LiveConnectionStatus,
|
|
15919
|
+
{
|
|
15920
|
+
state: liveConnection,
|
|
15921
|
+
hasLogs: logs.length > 0,
|
|
15922
|
+
onRetry: onRetryLiveConnection,
|
|
15923
|
+
onStop: onStopLiveConnection
|
|
15924
|
+
}
|
|
15925
|
+
)
|
|
16478
15926
|
] }),
|
|
16479
15927
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-4 lg:px-5", children: [
|
|
16480
15928
|
/* @__PURE__ */ jsxRuntimeExports.jsx(SessionOpeningSlate, { stats: slateStats }),
|
|
16481
15929
|
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: [
|
|
16482
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-medium", children: isLoading ? "Loading session data..." : "No logs loaded for this session" }),
|
|
15930
|
+
/* @__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" }),
|
|
16483
15931
|
/* @__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) }),
|
|
16484
15932
|
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 }) }),
|
|
16485
15933
|
sessionMemberships.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-left", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SessionMembershipPanel, { memberships: sessionMemberships }) }),
|
|
@@ -16491,7 +15939,7 @@ function ProxyViewer({
|
|
|
16491
15939
|
{
|
|
16492
15940
|
type: "button",
|
|
16493
15941
|
onClick: handleReloadCurrentSession,
|
|
16494
|
-
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",
|
|
15942
|
+
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",
|
|
16495
15943
|
children: [
|
|
16496
15944
|
/* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: "size-3.5" }),
|
|
16497
15945
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Load session" })
|
|
@@ -16502,7 +15950,7 @@ function ProxyViewer({
|
|
|
16502
15950
|
"a",
|
|
16503
15951
|
{
|
|
16504
15952
|
href: "/",
|
|
16505
|
-
className: "inline-flex h-8 items-center rounded-md px-3 text-xs text-muted-foreground underline transition-colors hover:text-foreground",
|
|
15953
|
+
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",
|
|
16506
15954
|
children: "Back to all sessions"
|
|
16507
15955
|
}
|
|
16508
15956
|
) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -16510,26 +15958,30 @@ function ProxyViewer({
|
|
|
16510
15958
|
{
|
|
16511
15959
|
type: "button",
|
|
16512
15960
|
onClick: () => onSessionChange("__all__"),
|
|
16513
|
-
className: "inline-flex h-8 items-center rounded-md px-3 text-xs text-muted-foreground underline transition-colors hover:text-foreground",
|
|
15961
|
+
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",
|
|
16514
15962
|
children: "Show all sessions"
|
|
16515
15963
|
}
|
|
16516
15964
|
)
|
|
16517
15965
|
] })
|
|
16518
15966
|
] })
|
|
16519
15967
|
] }) }) : /* @__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: [
|
|
16520
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm", children:
|
|
16521
|
-
|
|
16522
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
16523
|
-
|
|
16524
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
16525
|
-
|
|
16526
|
-
|
|
15968
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-medium", children: liveEmptyStateCopy.title }),
|
|
15969
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mx-auto max-w-xl text-xs leading-relaxed text-muted-foreground", children: liveEmptyStateCopy.description }),
|
|
15970
|
+
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." }),
|
|
15971
|
+
liveEmptyStateCopy.showConnectionCommands && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
15972
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center gap-2", children: [
|
|
15973
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(CopyableCommand, { command: "ANTHROPIC_BASE_URL=http://localhost:9527/proxy <your-tool>" }),
|
|
15974
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(CopyableCommand, { command: "OPENAI_BASE_URL=http://localhost:9527/proxy <your-tool>" })
|
|
15975
|
+
] }),
|
|
15976
|
+
/* @__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." })
|
|
15977
|
+
] })
|
|
16527
15978
|
] }) }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
16528
15979
|
"div",
|
|
16529
15980
|
{
|
|
16530
15981
|
ref: logListWrapperRef,
|
|
16531
15982
|
tabIndex: 0,
|
|
16532
|
-
|
|
15983
|
+
"aria-label": "Captured logs",
|
|
15984
|
+
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",
|
|
16533
15985
|
children: [
|
|
16534
15986
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: logListRef, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
16535
15987
|
ConversationGroupList,
|
|
@@ -16555,6 +16007,14 @@ function ProxyViewer({
|
|
|
16555
16007
|
]
|
|
16556
16008
|
}
|
|
16557
16009
|
),
|
|
16010
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Dialog, { open: rawExportDialogOpen, onOpenChange: setRawExportDialogOpen, children: /* @__PURE__ */ jsxRuntimeExports.jsx(DialogContent, { className: RAW_EXPORT_DIALOG_CLASS_NAME, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
16011
|
+
RawExportWarning,
|
|
16012
|
+
{
|
|
16013
|
+
onCancel: () => setRawExportDialogOpen(false),
|
|
16014
|
+
onExportRedacted: handleExportRedactedInstead,
|
|
16015
|
+
onConfirmRaw: handleConfirmRawExport
|
|
16016
|
+
}
|
|
16017
|
+
) }) }),
|
|
16558
16018
|
/* @__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: [
|
|
16559
16019
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(DialogHeader, { children: [
|
|
16560
16020
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(DialogTitle, { children: [
|
|
@@ -16593,7 +16053,7 @@ function ProxyViewer({
|
|
|
16593
16053
|
)
|
|
16594
16054
|
] })
|
|
16595
16055
|
] }) }),
|
|
16596
|
-
comparePair !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
16056
|
+
comparePair !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(LazyFeatureBoundary, { feature: "Compare", children: /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
16597
16057
|
LazyCompareDrawer,
|
|
16598
16058
|
{
|
|
16599
16059
|
left: comparePair[0],
|
|
@@ -16602,7 +16062,7 @@ function ProxyViewer({
|
|
|
16602
16062
|
rightDisplayNumber: displayNumberForLog(comparePair[1], displayNumberByLogId),
|
|
16603
16063
|
onClose: closeCompare
|
|
16604
16064
|
}
|
|
16605
|
-
) })
|
|
16065
|
+
) }) })
|
|
16606
16066
|
] });
|
|
16607
16067
|
}
|
|
16608
16068
|
function filterLogs(logs, selectedSession, selectedModel) {
|
|
@@ -16699,11 +16159,12 @@ const SESSION_RELOAD_PAGE_LIMIT = 500;
|
|
|
16699
16159
|
const MAX_SESSION_RELOAD_PAGES = 200;
|
|
16700
16160
|
const SESSION_LOGS_FETCH_TIMEOUT_MS = 2e4;
|
|
16701
16161
|
const SESSION_MEMBERSHIP_FETCH_TIMEOUT_MS = 1e4;
|
|
16162
|
+
const SSE_RECONNECT_DELAY_MS = 3e3;
|
|
16163
|
+
const SSE_STALE_AFTER_MS = 1e4;
|
|
16702
16164
|
function buildLogsStreamUrl(sessionId) {
|
|
16703
|
-
const params = new URLSearchParams();
|
|
16165
|
+
const params = new URLSearchParams({ compact: "1" });
|
|
16704
16166
|
if (sessionId !== void 0) {
|
|
16705
16167
|
params.set("sessionId", sessionId);
|
|
16706
|
-
params.set("compact", "1");
|
|
16707
16168
|
}
|
|
16708
16169
|
const query = params.toString();
|
|
16709
16170
|
return query.length > 0 ? `/api/logs/stream?${query}` : "/api/logs/stream";
|
|
@@ -16783,9 +16244,10 @@ function ProxyViewerContainer({
|
|
|
16783
16244
|
const [selectedModel, setSelectedModel] = reactExports.useState("__all__");
|
|
16784
16245
|
const [knownSessions, setKnownSessions] = reactExports.useState([]);
|
|
16785
16246
|
const { notice, showToast, dismissToast } = useTransientToast();
|
|
16786
|
-
const [
|
|
16247
|
+
const [liveConnection, setLiveConnection] = reactExports.useState(createInitialLiveConnectionState);
|
|
16787
16248
|
const [logPage, setLogPage] = reactExports.useState(null);
|
|
16788
16249
|
const [sessionPageLoading, setSessionPageLoading] = reactExports.useState(initialSessionId !== void 0);
|
|
16250
|
+
const [sessionLoadError, setSessionLoadError] = reactExports.useState(null);
|
|
16789
16251
|
const [sessionLoadProgress, setSessionLoadProgress] = reactExports.useState(
|
|
16790
16252
|
void 0
|
|
16791
16253
|
);
|
|
@@ -16793,6 +16255,8 @@ function ProxyViewerContainer({
|
|
|
16793
16255
|
const [, startLogTransition] = reactExports.useTransition();
|
|
16794
16256
|
const eventSourceRef = reactExports.useRef(null);
|
|
16795
16257
|
const reconnectTimeoutRef = reactExports.useRef(null);
|
|
16258
|
+
const staleTimeoutRef = reactExports.useRef(null);
|
|
16259
|
+
const automaticRetryEnabledRef = reactExports.useRef(true);
|
|
16796
16260
|
const handledHashRef = reactExports.useRef(null);
|
|
16797
16261
|
const sessionPageRequestIdRef = reactExports.useRef(0);
|
|
16798
16262
|
const sessionLoadStartedAtRef = reactExports.useRef(null);
|
|
@@ -16891,7 +16355,11 @@ function ProxyViewerContainer({
|
|
|
16891
16355
|
if (eventSourceRef.current) {
|
|
16892
16356
|
eventSourceRef.current.close();
|
|
16893
16357
|
}
|
|
16894
|
-
|
|
16358
|
+
if (reconnectTimeoutRef.current !== null) {
|
|
16359
|
+
clearTimeout(reconnectTimeoutRef.current);
|
|
16360
|
+
reconnectTimeoutRef.current = null;
|
|
16361
|
+
}
|
|
16362
|
+
setLiveConnection((state) => reduceLiveConnectionState(state, { type: "connect-requested" }));
|
|
16895
16363
|
const es = new EventSource(buildLogsStreamUrl(initialSessionId));
|
|
16896
16364
|
eventSourceRef.current = es;
|
|
16897
16365
|
es.onmessage = (event) => {
|
|
@@ -16900,6 +16368,12 @@ function ProxyViewerContainer({
|
|
|
16900
16368
|
const parsed = JSON.parse(rawData);
|
|
16901
16369
|
const updateResult = SSEUpdateSchema.safeParse(parsed);
|
|
16902
16370
|
if (!updateResult.success) {
|
|
16371
|
+
setLiveConnection(
|
|
16372
|
+
(state) => reduceLiveConnectionState(state, {
|
|
16373
|
+
type: "recoverable-error",
|
|
16374
|
+
message: "The live stream returned invalid data."
|
|
16375
|
+
})
|
|
16376
|
+
);
|
|
16903
16377
|
showErrorToast("Failed to parse SSE data");
|
|
16904
16378
|
return;
|
|
16905
16379
|
}
|
|
@@ -16916,7 +16390,13 @@ function ProxyViewerContainer({
|
|
|
16916
16390
|
return nextLogs;
|
|
16917
16391
|
});
|
|
16918
16392
|
setKnownSessions((prev) => mergeSessionIds(prev, extractSessions(update.logs)));
|
|
16919
|
-
|
|
16393
|
+
if (staleTimeoutRef.current !== null) {
|
|
16394
|
+
clearTimeout(staleTimeoutRef.current);
|
|
16395
|
+
staleTimeoutRef.current = null;
|
|
16396
|
+
}
|
|
16397
|
+
setLiveConnection(
|
|
16398
|
+
(state) => reduceLiveConnectionState(state, { type: "message-received", at: Date.now() })
|
|
16399
|
+
);
|
|
16920
16400
|
dismissToast();
|
|
16921
16401
|
} else if (update.type === "update") {
|
|
16922
16402
|
setKnownSessions((prev) => {
|
|
@@ -16924,27 +16404,73 @@ function ProxyViewerContainer({
|
|
|
16924
16404
|
return mergeSessionIds(prev, [update.log.sessionId]);
|
|
16925
16405
|
});
|
|
16926
16406
|
scheduleUpdate(update.log);
|
|
16407
|
+
if (staleTimeoutRef.current !== null) {
|
|
16408
|
+
clearTimeout(staleTimeoutRef.current);
|
|
16409
|
+
staleTimeoutRef.current = null;
|
|
16410
|
+
}
|
|
16411
|
+
setLiveConnection(
|
|
16412
|
+
(state) => reduceLiveConnectionState(state, { type: "message-received", at: Date.now() })
|
|
16413
|
+
);
|
|
16927
16414
|
}
|
|
16928
16415
|
} catch {
|
|
16416
|
+
setLiveConnection(
|
|
16417
|
+
(state) => reduceLiveConnectionState(state, {
|
|
16418
|
+
type: "recoverable-error",
|
|
16419
|
+
message: "The live stream returned malformed JSON."
|
|
16420
|
+
})
|
|
16421
|
+
);
|
|
16929
16422
|
showErrorToast("Failed to parse SSE data");
|
|
16930
16423
|
}
|
|
16931
16424
|
};
|
|
16932
16425
|
es.onerror = () => {
|
|
16933
|
-
|
|
16934
|
-
|
|
16426
|
+
const online = navigator.onLine;
|
|
16427
|
+
setLiveConnection(
|
|
16428
|
+
(state) => reduceLiveConnectionState(state, {
|
|
16429
|
+
type: "connection-lost",
|
|
16430
|
+
online,
|
|
16431
|
+
message: "The live stream disconnected."
|
|
16432
|
+
})
|
|
16433
|
+
);
|
|
16935
16434
|
es.close();
|
|
16936
|
-
if (
|
|
16937
|
-
|
|
16435
|
+
if (!online || !automaticRetryEnabledRef.current) return;
|
|
16436
|
+
if (staleTimeoutRef.current === null) {
|
|
16437
|
+
staleTimeoutRef.current = setTimeout(() => {
|
|
16438
|
+
staleTimeoutRef.current = null;
|
|
16439
|
+
setLiveConnection((state) => reduceLiveConnectionState(state, { type: "stale-timeout" }));
|
|
16440
|
+
}, SSE_STALE_AFTER_MS);
|
|
16938
16441
|
}
|
|
16939
|
-
reconnectTimeoutRef.current = setTimeout(connectSSE,
|
|
16442
|
+
reconnectTimeoutRef.current = setTimeout(connectSSE, SSE_RECONNECT_DELAY_MS);
|
|
16940
16443
|
};
|
|
16941
16444
|
}, [dismissToast, initialSessionId, scheduleUpdate, showErrorToast]);
|
|
16445
|
+
const retryLiveConnection = reactExports.useCallback(() => {
|
|
16446
|
+
automaticRetryEnabledRef.current = true;
|
|
16447
|
+
if (reconnectTimeoutRef.current !== null) {
|
|
16448
|
+
clearTimeout(reconnectTimeoutRef.current);
|
|
16449
|
+
reconnectTimeoutRef.current = null;
|
|
16450
|
+
}
|
|
16451
|
+
connectSSE();
|
|
16452
|
+
}, [connectSSE]);
|
|
16453
|
+
const stopLiveConnection = reactExports.useCallback(() => {
|
|
16454
|
+
automaticRetryEnabledRef.current = false;
|
|
16455
|
+
eventSourceRef.current?.close();
|
|
16456
|
+
eventSourceRef.current = null;
|
|
16457
|
+
if (reconnectTimeoutRef.current !== null) {
|
|
16458
|
+
clearTimeout(reconnectTimeoutRef.current);
|
|
16459
|
+
reconnectTimeoutRef.current = null;
|
|
16460
|
+
}
|
|
16461
|
+
if (staleTimeoutRef.current !== null) {
|
|
16462
|
+
clearTimeout(staleTimeoutRef.current);
|
|
16463
|
+
staleTimeoutRef.current = null;
|
|
16464
|
+
}
|
|
16465
|
+
setLiveConnection((state) => reduceLiveConnectionState(state, { type: "stop-retrying" }));
|
|
16466
|
+
}, []);
|
|
16942
16467
|
const loadSessionPage = reactExports.useCallback(
|
|
16943
16468
|
(request) => {
|
|
16944
16469
|
if (initialSessionId === void 0) return;
|
|
16945
16470
|
const requestId = sessionPageRequestIdRef.current + 1;
|
|
16946
16471
|
sessionPageRequestIdRef.current = requestId;
|
|
16947
16472
|
setSessionPageLoading(true);
|
|
16473
|
+
setSessionLoadError(null);
|
|
16948
16474
|
startSessionLoadProgress("Loading session logs", requestId);
|
|
16949
16475
|
dismissToast();
|
|
16950
16476
|
void fetchSessionLogsPage(initialSessionId, request).then((page) => {
|
|
@@ -16955,15 +16481,16 @@ function ProxyViewerContainer({
|
|
|
16955
16481
|
setLogPage(page);
|
|
16956
16482
|
setSelectedSession(initialSessionId);
|
|
16957
16483
|
setSessionPageLoading(false);
|
|
16484
|
+
setSessionLoadError(null);
|
|
16958
16485
|
stopSessionLoadProgress();
|
|
16959
16486
|
dismissToast();
|
|
16960
16487
|
}).catch((err) => {
|
|
16961
16488
|
if (sessionPageRequestIdRef.current !== requestId) return;
|
|
16962
|
-
setAllLogs([]);
|
|
16963
|
-
setLogPage(null);
|
|
16964
16489
|
setSessionPageLoading(false);
|
|
16965
16490
|
stopSessionLoadProgress();
|
|
16966
|
-
|
|
16491
|
+
const message = err instanceof Error ? err.message : "Failed to load session logs";
|
|
16492
|
+
setSessionLoadError(message);
|
|
16493
|
+
showErrorToast(message);
|
|
16967
16494
|
});
|
|
16968
16495
|
},
|
|
16969
16496
|
[
|
|
@@ -16979,6 +16506,7 @@ function ProxyViewerContainer({
|
|
|
16979
16506
|
const requestId = sessionPageRequestIdRef.current + 1;
|
|
16980
16507
|
sessionPageRequestIdRef.current = requestId;
|
|
16981
16508
|
setSessionPageLoading(true);
|
|
16509
|
+
setSessionLoadError(null);
|
|
16982
16510
|
startSessionLoadProgress("Reloading full session", requestId);
|
|
16983
16511
|
dismissToast();
|
|
16984
16512
|
void (async () => {
|
|
@@ -17014,6 +16542,7 @@ function ProxyViewerContainer({
|
|
|
17014
16542
|
});
|
|
17015
16543
|
setKnownSessions((prev) => mergeSessionIds(prev, [sessionId]));
|
|
17016
16544
|
setSessionPageLoading(false);
|
|
16545
|
+
setSessionLoadError(null);
|
|
17017
16546
|
stopSessionLoadProgress();
|
|
17018
16547
|
if (page.hasNewer) {
|
|
17019
16548
|
showToast({
|
|
@@ -17027,7 +16556,9 @@ function ProxyViewerContainer({
|
|
|
17027
16556
|
if (sessionPageRequestIdRef.current !== requestId) return;
|
|
17028
16557
|
setSessionPageLoading(false);
|
|
17029
16558
|
stopSessionLoadProgress();
|
|
17030
|
-
|
|
16559
|
+
const message = err instanceof Error ? err.message : "Failed to reload session logs";
|
|
16560
|
+
setSessionLoadError(message);
|
|
16561
|
+
showErrorToast(message);
|
|
17031
16562
|
});
|
|
17032
16563
|
},
|
|
17033
16564
|
[
|
|
@@ -17079,7 +16610,28 @@ function ProxyViewerContainer({
|
|
|
17079
16610
|
reactExports.useEffect(() => {
|
|
17080
16611
|
if (initialSessionId !== void 0) return void 0;
|
|
17081
16612
|
connectSSE();
|
|
16613
|
+
const handleOffline = () => {
|
|
16614
|
+
eventSourceRef.current?.close();
|
|
16615
|
+
eventSourceRef.current = null;
|
|
16616
|
+
if (reconnectTimeoutRef.current !== null) {
|
|
16617
|
+
clearTimeout(reconnectTimeoutRef.current);
|
|
16618
|
+
reconnectTimeoutRef.current = null;
|
|
16619
|
+
}
|
|
16620
|
+
if (staleTimeoutRef.current !== null) {
|
|
16621
|
+
clearTimeout(staleTimeoutRef.current);
|
|
16622
|
+
staleTimeoutRef.current = null;
|
|
16623
|
+
}
|
|
16624
|
+
setLiveConnection((state) => reduceLiveConnectionState(state, { type: "browser-offline" }));
|
|
16625
|
+
};
|
|
16626
|
+
const handleOnline = () => {
|
|
16627
|
+
if (!automaticRetryEnabledRef.current) return;
|
|
16628
|
+
connectSSE();
|
|
16629
|
+
};
|
|
16630
|
+
window.addEventListener("offline", handleOffline);
|
|
16631
|
+
window.addEventListener("online", handleOnline);
|
|
17082
16632
|
return () => {
|
|
16633
|
+
window.removeEventListener("offline", handleOffline);
|
|
16634
|
+
window.removeEventListener("online", handleOnline);
|
|
17083
16635
|
if (eventSourceRef.current) {
|
|
17084
16636
|
eventSourceRef.current.close();
|
|
17085
16637
|
eventSourceRef.current = null;
|
|
@@ -17088,6 +16640,10 @@ function ProxyViewerContainer({
|
|
|
17088
16640
|
clearTimeout(reconnectTimeoutRef.current);
|
|
17089
16641
|
reconnectTimeoutRef.current = null;
|
|
17090
16642
|
}
|
|
16643
|
+
if (staleTimeoutRef.current !== null) {
|
|
16644
|
+
clearTimeout(staleTimeoutRef.current);
|
|
16645
|
+
staleTimeoutRef.current = null;
|
|
16646
|
+
}
|
|
17091
16647
|
if (flushTimerRef.current !== null) {
|
|
17092
16648
|
clearTimeout(flushTimerRef.current);
|
|
17093
16649
|
flushTimerRef.current = null;
|
|
@@ -17112,7 +16668,10 @@ function ProxyViewerContainer({
|
|
|
17112
16668
|
const target = document.getElementById(targetId);
|
|
17113
16669
|
if (target !== null) {
|
|
17114
16670
|
handledHashRef.current = hash;
|
|
17115
|
-
target.scrollIntoView({
|
|
16671
|
+
target.scrollIntoView({
|
|
16672
|
+
block: "center",
|
|
16673
|
+
behavior: preferredScrollBehavior(browserPrefersReducedMotion())
|
|
16674
|
+
});
|
|
17116
16675
|
if (target instanceof HTMLElement) {
|
|
17117
16676
|
highlightedTarget = target;
|
|
17118
16677
|
target.setAttribute("data-deep-link-highlight", "true");
|
|
@@ -17372,9 +16931,13 @@ function ProxyViewerContainer({
|
|
|
17372
16931
|
onClearGroup: handleClearGroup,
|
|
17373
16932
|
onNotify: showToast,
|
|
17374
16933
|
onImportLogs: initialSessionId === void 0 ? handleImportLogs : void 0,
|
|
17375
|
-
isLoading: initialSessionId === void 0 ?
|
|
16934
|
+
isLoading: initialSessionId === void 0 ? liveConnection.status === "connecting" && liveConnection.lastSuccessAt === null || sessionPageLoading : sessionPageLoading,
|
|
16935
|
+
liveConnection: initialSessionId === void 0 ? liveConnection : void 0,
|
|
16936
|
+
onRetryLiveConnection: retryLiveConnection,
|
|
16937
|
+
onStopLiveConnection: stopLiveConnection,
|
|
17376
16938
|
pagination,
|
|
17377
16939
|
sessionLoadProgress,
|
|
16940
|
+
sessionLoadError: sessionLoadError ?? void 0,
|
|
17378
16941
|
sessionMemberships,
|
|
17379
16942
|
viewMode,
|
|
17380
16943
|
captureMode,
|
|
@@ -17392,40 +16955,34 @@ export {
|
|
|
17392
16955
|
Badge as B,
|
|
17393
16956
|
CONTEXT_USAGE_THRESHOLDS as C,
|
|
17394
16957
|
Dialog as D,
|
|
17395
|
-
CollapsibleContent as E,
|
|
17396
|
-
ScrollArea as F,
|
|
17397
|
-
LazyJsonViewer as G,
|
|
17398
|
-
safeJsonValue as H,
|
|
17399
|
-
parseJsonText as I,
|
|
17400
16958
|
LazyJsonViewerFromString as L,
|
|
17401
16959
|
ProxyViewerContainer as P,
|
|
17402
16960
|
ROLE_COLOR_CLASSES as R,
|
|
17403
16961
|
SegmentBar as S,
|
|
17404
16962
|
Tabs as T,
|
|
17405
16963
|
getConversationId as a,
|
|
17406
|
-
|
|
17407
|
-
|
|
17408
|
-
|
|
17409
|
-
|
|
17410
|
-
|
|
16964
|
+
DialogContent as b,
|
|
16965
|
+
DialogHeader as c,
|
|
16966
|
+
DialogTitle as d,
|
|
16967
|
+
TabsList as e,
|
|
16968
|
+
fetchJsonWithTimeout as f,
|
|
17411
16969
|
getLogFormatAdapter as g,
|
|
17412
|
-
|
|
17413
|
-
|
|
17414
|
-
|
|
17415
|
-
|
|
17416
|
-
|
|
17417
|
-
|
|
17418
|
-
|
|
17419
|
-
|
|
17420
|
-
|
|
17421
|
-
|
|
16970
|
+
TabsTrigger as h,
|
|
16971
|
+
TabsContent as i,
|
|
16972
|
+
TooltipProvider as j,
|
|
16973
|
+
Tooltip as k,
|
|
16974
|
+
TooltipTrigger as l,
|
|
16975
|
+
TooltipContent as m,
|
|
16976
|
+
dispatchLogFocusRequest as n,
|
|
16977
|
+
analyzeContextIntelligence as o,
|
|
16978
|
+
ANATOMY_ROLE_LABELS as p,
|
|
16979
|
+
Collapsible as q,
|
|
17422
16980
|
resolveLogFormat as r,
|
|
17423
|
-
|
|
17424
|
-
|
|
16981
|
+
CollapsibleTrigger as s,
|
|
16982
|
+
CollapsibleContent as t,
|
|
17425
16983
|
useProviders as u,
|
|
17426
|
-
|
|
17427
|
-
|
|
17428
|
-
|
|
17429
|
-
|
|
17430
|
-
CollapsibleTrigger as z
|
|
16984
|
+
ScrollArea as v,
|
|
16985
|
+
LazyJsonViewer as w,
|
|
16986
|
+
safeJsonValue as x,
|
|
16987
|
+
parseJsonText as y
|
|
17431
16988
|
};
|