@tonyclaw/agent-inspector 2.0.42 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.output/nitro.json +1 -1
- package/.output/public/assets/{CompareDrawer-Cfqxlo-U.js → CompareDrawer-VDpcSNGM.js} +1 -1
- package/.output/public/assets/ProxyViewerContainer-fsXSjqtm.js +117 -0
- package/.output/public/assets/{ReplayDialog-daRidZo_.js → ReplayDialog-CoDgTzHR.js} +1 -1
- package/.output/public/assets/RequestAnatomy-t3plgkPE.js +1 -0
- package/.output/public/assets/ResponseView-BYuKiNeG.js +1 -0
- package/.output/public/assets/{StreamingChunkSequence-nK-0LpbM.js → StreamingChunkSequence-DOdU38Is.js} +1 -1
- package/.output/public/assets/_sessionId-ew5QlyZ2.js +1 -0
- package/.output/public/assets/index-DFICWD6o.js +1 -0
- package/.output/public/assets/index-zLLCkAnF.css +1 -0
- package/.output/public/assets/{main-DOy_Q96H.js → main-DmzLt6ti.js} +2 -2
- package/.output/server/_libs/lucide-react.mjs +219 -178
- package/.output/server/{_sessionId-DtYRZHlM.mjs → _sessionId-CCN1UoEf.mjs} +3 -3
- package/.output/server/_ssr/{CompareDrawer-fy1ARwtx.mjs → CompareDrawer-DkSY3vxP.mjs} +4 -4
- package/.output/server/_ssr/{ProxyViewerContainer-9GJtCWCq.mjs → ProxyViewerContainer-OTh1V_Kh.mjs} +1034 -448
- package/.output/server/_ssr/{ReplayDialog-BrS7syOE.mjs → ReplayDialog-DhI6yxrR.mjs} +5 -5
- package/.output/server/_ssr/{RequestAnatomy-BtWt1cWY.mjs → RequestAnatomy-DN1SJVVL.mjs} +4 -4
- package/.output/server/_ssr/{ResponseView-CkKGYE6m.mjs → ResponseView-DW-kpJL5.mjs} +4 -4
- package/.output/server/_ssr/{StreamingChunkSequence-C7rB3osr.mjs → StreamingChunkSequence-BAE57Fae.mjs} +4 -4
- package/.output/server/_ssr/{index-D24WforP.mjs → index-C9ryJEna.mjs} +3 -3
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{router-CVqVjBzJ.mjs → router-DIIJGyML.mjs} +458 -10
- package/.output/server/{_tanstack-start-manifest_v-DSikvwru.mjs → _tanstack-start-manifest_v-C_v9-E5d.mjs} +1 -1
- package/.output/server/index.mjs +63 -63
- package/package.json +1 -1
- package/src/components/OnboardingBanner.tsx +74 -68
- package/src/components/ProxyViewer.tsx +942 -297
- package/src/components/ProxyViewerContainer.tsx +199 -5
- package/src/components/groups/GroupsDialog.tsx +11 -10
- package/src/components/proxy-viewer/LogEntry.tsx +107 -56
- package/src/components/proxy-viewer/LogEntryHeader.tsx +12 -6
- package/src/components/ui/crab-logo.tsx +0 -50
- package/src/components/ui/dialog.tsx +1 -1
- package/src/proxy/logIndex.ts +188 -1
- package/src/proxy/store.ts +405 -3
- package/src/routes/api/logs.ts +36 -0
- package/.output/public/assets/ProxyViewerContainer-CE9pAX4c.js +0 -117
- package/.output/public/assets/RequestAnatomy-CJ7EPQGQ.js +0 -1
- package/.output/public/assets/ResponseView-xBmr54hB.js +0 -1
- package/.output/public/assets/_sessionId-CbWEG5ej.js +0 -1
- package/.output/public/assets/index-BfGJEb-2.css +0 -1
- package/.output/public/assets/index-D1MkoT4l.js +0 -1
package/.output/server/_ssr/{ProxyViewerContainer-9GJtCWCq.mjs → ProxyViewerContainer-OTh1V_Kh.mjs}
RENAMED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { r as reactExports, j as jsxRuntimeExports, a as React } from "../_libs/react.mjs";
|
|
2
|
-
import { C as CapturedLogSchema, D as DEFAULT_CAPTURE_MODE, a as DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS, b as DEFAULT_PROVIDER_TEST_TIMEOUT_SECONDS, c as DEFAULT_TIME_DISPLAY_FORMAT,
|
|
2
|
+
import { I as InspectorGroupsListResponseSchema, C as CapturedLogSchema, D as DEFAULT_CAPTURE_MODE, a as DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS, b as DEFAULT_PROVIDER_TEST_TIMEOUT_SECONDS, c as DEFAULT_TIME_DISPLAY_FORMAT, d as RuntimeConfigSchema, v as packageJson, P as ProviderConfigSchema, f as apiFormatForPath, i as GroupEvidenceExportResultSchema, j as DeleteInspectorGroupResponseSchema, n as createPendingProviderTestResults, o as ProviderTestResultsSchema, q as createFailedProviderTestResults, M as MAX_SLOW_RESPONSE_THRESHOLD_SECONDS, r as MAX_PROVIDER_TEST_TIMEOUT_SECONDS, T as TimeDisplayFormatSchema, g as getSessionPath, p as parseOpenAIResponse, O as OpenAIRequestSchema, A as AnthropicResponseSchema$1, e as AnthropicRequestSchema, s as safeGetOwnProperty, t as resolveProviderContextWindow, m as maskApiKey, k as providerHasContextMetadata, l as findProviderModelMetadata, K as KnowledgeCandidateSchema, h as stripClaudeCodeBillingHeader, u as isPlainRecord, G as GroupEvidenceReadResponseSchema } from "./router-DIIJGyML.mjs";
|
|
3
3
|
import { u as useSWR, a as useSWRConfig } from "../_libs/swr.mjs";
|
|
4
4
|
import { J as JSZip } from "../_libs/jszip.mjs";
|
|
5
5
|
import { c as clsx } from "../_libs/clsx.mjs";
|
|
6
6
|
import { t as twMerge } from "../_libs/tailwind-merge.mjs";
|
|
7
7
|
import { c as cva } from "../_libs/class-variance-authority.mjs";
|
|
8
|
-
import { R as Root, T as Trigger$
|
|
8
|
+
import { R as Root, T as Trigger$1, C as Content, a as Close, b as Title, P as Portal$2, O as Overlay } from "../_libs/radix-ui__react-dialog.mjs";
|
|
9
9
|
import { d as diffJson, a as diffLines } from "../_libs/diff.mjs";
|
|
10
10
|
import { u as useWindowVirtualizer, a as useVirtualizer } from "../_libs/tanstack__react-virtual.mjs";
|
|
11
11
|
import { R as Root2, T as Trigger, I as Icon, V as Value, P as Portal, C as Content2, a as Viewport, b as Item, c as ItemIndicator, d as ItemText, S as ScrollUpButton, e as ScrollDownButton } from "../_libs/radix-ui__react-select.mjs";
|
|
12
|
-
import {
|
|
12
|
+
import { I as Info, C as ChevronDown, a as Check, X, D as Download, F as FileBraces, T as Trash2, P as Plus, A as ArrowLeft, b as ChevronUp, c as Copy, d as ChevronsLeft, e as ChevronLeft, f as ChevronRight, g as ChevronsRight, h as Clapperboard, S as Siren, G as Gauge, L as Layers, i as LoaderCircle, R as RefreshCw, j as Settings, U as Upload, k as Scan, l as CircleAlert, m as Terminal, n as ArrowUpRight, o as ArrowDownRight, p as User, q as Clock, M as MessageSquare, Z as Zap, E as ExternalLink, W as Wrench, r as TriangleAlert, B as Brain, s as EyeOff, t as Eye, u as RotateCw, v as Pencil, w as CircleX, x as ShieldCheck, y as Save, z as FileSearch, H as CircleCheck, J as CloudUpload, O as OctagonAlert, K as Radio, N as Globe, Q as FileTerminal, V as ChevronsUp, Y as ChevronsDown, _ as FileDiff, $ as History, a0 as RotateCcw, a1 as Search, a2 as GitCompareArrows, a3 as Minus, a4 as CircleCheckBig, a5 as ArrowUp, a6 as ArrowDown, a7 as CircleQuestionMark, a8 as Server, a9 as Lock, aa as Wifi, ab as WifiOff, ac as Ellipsis, ad as CodeXml, ae as Blocks, af as MousePointerClick, ag as FileText, ah as Rows3, ai as Columns2 } from "../_libs/lucide-react.mjs";
|
|
13
13
|
import { M as Markdown } from "../_libs/react-markdown.mjs";
|
|
14
14
|
import { u as union, d as object, a as array, l as literal, b as string, n as number, c as boolean, _ as _enum } from "../_libs/zod.mjs";
|
|
15
|
-
import { P as Provider, R as Root3, T as Trigger$1, a as Portal$1, C as Content2$1, A as Arrow2 } from "../_libs/radix-ui__react-tooltip.mjs";
|
|
16
15
|
import { S as Slot } from "../_libs/radix-ui__react-slot.mjs";
|
|
17
|
-
import { R as Root2$1, L as List, T as Trigger$
|
|
16
|
+
import { R as Root2$1, L as List, T as Trigger$2, C as Content$1 } from "../_libs/radix-ui__react-tabs.mjs";
|
|
17
|
+
import { P as Provider, R as Root3, T as Trigger$3, a as Portal$1, C as Content2$1, A as Arrow2 } from "../_libs/radix-ui__react-tooltip.mjs";
|
|
18
18
|
import { R as Root$1, C as CollapsibleContent$1, a as CollapsibleTrigger$1 } from "../_libs/radix-ui__react-collapsible.mjs";
|
|
19
19
|
import { R as Root$2, V as Viewport$1, C as Corner, S as ScrollAreaScrollbar, a as ScrollAreaThumb } from "../_libs/radix-ui__react-scroll-area.mjs";
|
|
20
20
|
const ApiErrorSchema = object({
|
|
@@ -196,69 +196,70 @@ function useOnboarding() {
|
|
|
196
196
|
}
|
|
197
197
|
function OnboardingBanner() {
|
|
198
198
|
const { hasSeenOnboarding, captureMode, isLoading, markSeen } = useOnboarding();
|
|
199
|
+
const [expanded, setExpanded] = reactExports.useState(false);
|
|
199
200
|
if (isLoading || hasSeenOnboarding) return null;
|
|
200
201
|
const isFullMode = captureMode === "full";
|
|
201
|
-
|
|
202
|
+
const modeLabel = isFullMode ? "Full" : "Simple";
|
|
203
|
+
const detailClass = expanded ? "grid" : "hidden sm:grid";
|
|
204
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
202
205
|
"div",
|
|
203
206
|
{
|
|
204
207
|
role: "note",
|
|
205
208
|
"aria-label": "Onboarding tip",
|
|
206
|
-
className: "mx-4 mt-2 mb-1
|
|
207
|
-
children: [
|
|
209
|
+
className: "mx-4 mt-2 mb-1 rounded-md border border-amber-500/30 bg-[#130d04] px-3 py-2 text-sm shadow-[0_12px_40px_rgba(0,0,0,0.16)]",
|
|
210
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-3", children: [
|
|
211
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Info, { className: "mt-0.5 size-4 shrink-0 text-amber-300", "aria-hidden": "true" }),
|
|
208
212
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
209
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
210
|
-
|
|
211
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
] }),
|
|
243
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("li", { children: [
|
|
244
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Agent setup" }),
|
|
245
|
-
": run ",
|
|
246
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: "agent-inspector onboard --status" }),
|
|
247
|
-
", then use ",
|
|
248
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: "/agent-inspector:onboard" }),
|
|
249
|
-
" in Claude Code or ask Codex to use",
|
|
250
|
-
" ",
|
|
251
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: "agent-inspector-onboard" }),
|
|
252
|
-
"."
|
|
253
|
-
] }),
|
|
254
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("li", { children: [
|
|
255
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Container networking" }),
|
|
256
|
-
": if the AI tool runs outside this Inspector container or host, replace ",
|
|
257
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: "localhost" }),
|
|
258
|
-
" with a reachable address."
|
|
259
|
-
] })
|
|
260
|
-
] })
|
|
213
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: [
|
|
214
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium text-amber-200", children: "Inspector ready" }),
|
|
215
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "rounded border border-amber-400/30 bg-amber-400/10 px-1.5 py-0.5 font-mono text-[10px] uppercase text-amber-100", children: modeLabel }),
|
|
216
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "hidden truncate text-xs text-muted-foreground sm:inline", children: isFullMode ? "Raw headers, raw response, and SSE chunks are being captured." : "Request, response, tool, timing, token, replay, and memory signals are active." })
|
|
217
|
+
] }),
|
|
218
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1 text-xs leading-relaxed text-muted-foreground sm:hidden", children: isFullMode ? "Full diagnostics are active." : "Core capture is active with lower overhead." }),
|
|
219
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
220
|
+
"div",
|
|
221
|
+
{
|
|
222
|
+
className: `${detailClass} mt-2 gap-x-4 gap-y-1 text-xs leading-relaxed text-muted-foreground sm:grid-cols-3`,
|
|
223
|
+
children: [
|
|
224
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
225
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Mode" }),
|
|
226
|
+
": ",
|
|
227
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: captureMode }),
|
|
228
|
+
" is fixed until restart."
|
|
229
|
+
] }),
|
|
230
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
231
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Diagnostics" }),
|
|
232
|
+
": use",
|
|
233
|
+
" ",
|
|
234
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: isFullMode ? "agent-inspector --mode simple" : "agent-inspector --mode full" }),
|
|
235
|
+
"."
|
|
236
|
+
] }),
|
|
237
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
238
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Network" }),
|
|
239
|
+
": replace ",
|
|
240
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: "localhost" }),
|
|
241
|
+
" when containers differ."
|
|
242
|
+
] })
|
|
243
|
+
]
|
|
244
|
+
}
|
|
245
|
+
)
|
|
261
246
|
] }),
|
|
247
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
248
|
+
"button",
|
|
249
|
+
{
|
|
250
|
+
type: "button",
|
|
251
|
+
onClick: () => setExpanded((value) => !value),
|
|
252
|
+
className: "inline-flex h-8 shrink-0 items-center gap-1 rounded-md border border-amber-500/30 px-2 text-xs text-amber-200 transition-colors hover:bg-amber-500/10 sm:hidden",
|
|
253
|
+
"aria-expanded": expanded,
|
|
254
|
+
"aria-label": expanded ? "Hide onboarding details" : "Show onboarding details",
|
|
255
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
256
|
+
ChevronDown,
|
|
257
|
+
{
|
|
258
|
+
className: `size-3.5 transition-transform ${expanded ? "rotate-180" : ""}`
|
|
259
|
+
}
|
|
260
|
+
)
|
|
261
|
+
}
|
|
262
|
+
),
|
|
262
263
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
263
264
|
"button",
|
|
264
265
|
{
|
|
@@ -266,7 +267,7 @@ function OnboardingBanner() {
|
|
|
266
267
|
onClick: () => {
|
|
267
268
|
void markSeen();
|
|
268
269
|
},
|
|
269
|
-
className: "
|
|
270
|
+
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",
|
|
270
271
|
"aria-label": "Dismiss onboarding tip",
|
|
271
272
|
children: [
|
|
272
273
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-3.5" }),
|
|
@@ -286,7 +287,7 @@ function OnboardingBanner() {
|
|
|
286
287
|
children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "size-3.5" })
|
|
287
288
|
}
|
|
288
289
|
)
|
|
289
|
-
]
|
|
290
|
+
] })
|
|
290
291
|
}
|
|
291
292
|
);
|
|
292
293
|
}
|
|
@@ -613,7 +614,7 @@ function Dialog({
|
|
|
613
614
|
function DialogTrigger({
|
|
614
615
|
...props
|
|
615
616
|
}) {
|
|
616
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(Trigger$
|
|
617
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Trigger$1, { "data-slot": "dialog-trigger", ...props });
|
|
617
618
|
}
|
|
618
619
|
function DialogPortal({
|
|
619
620
|
...props
|
|
@@ -629,7 +630,7 @@ function DialogOverlay({
|
|
|
629
630
|
{
|
|
630
631
|
"data-slot": "dialog-overlay",
|
|
631
632
|
className: cn(
|
|
632
|
-
"fixed inset-0 z-
|
|
633
|
+
"fixed inset-0 z-40 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
633
634
|
className
|
|
634
635
|
),
|
|
635
636
|
...props
|
|
@@ -1749,7 +1750,7 @@ function Tooltip({ ...props }) {
|
|
|
1749
1750
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(Root3, { "data-slot": "tooltip", ...props });
|
|
1750
1751
|
}
|
|
1751
1752
|
function TooltipTrigger({ ...props }) {
|
|
1752
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(Trigger$
|
|
1753
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Trigger$3, { "data-slot": "tooltip-trigger", ...props });
|
|
1753
1754
|
}
|
|
1754
1755
|
function TooltipContent({
|
|
1755
1756
|
className,
|
|
@@ -1885,7 +1886,7 @@ function TabsTrigger({
|
|
|
1885
1886
|
...props
|
|
1886
1887
|
}) {
|
|
1887
1888
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
1888
|
-
Trigger$
|
|
1889
|
+
Trigger$2,
|
|
1889
1890
|
{
|
|
1890
1891
|
"data-slot": "tabs-trigger",
|
|
1891
1892
|
className: cn(
|
|
@@ -1937,19 +1938,19 @@ function useCopyFeedback(text) {
|
|
|
1937
1938
|
return { copied, copy };
|
|
1938
1939
|
}
|
|
1939
1940
|
const LazyCompareDrawer = reactExports.lazy(
|
|
1940
|
-
() => import("./CompareDrawer-
|
|
1941
|
+
() => import("./CompareDrawer-DkSY3vxP.mjs").then((m) => ({ default: m.CompareDrawer }))
|
|
1941
1942
|
);
|
|
1942
1943
|
const LazyReplayDialog = reactExports.lazy(
|
|
1943
|
-
() => import("./ReplayDialog-
|
|
1944
|
+
() => import("./ReplayDialog-DhI6yxrR.mjs").then((m) => ({ default: m.ReplayDialog }))
|
|
1944
1945
|
);
|
|
1945
1946
|
const LazyRequestAnatomy = reactExports.lazy(
|
|
1946
|
-
() => import("./RequestAnatomy-
|
|
1947
|
+
() => import("./RequestAnatomy-DN1SJVVL.mjs").then((m) => ({ default: m.RequestAnatomy }))
|
|
1947
1948
|
);
|
|
1948
1949
|
const LazyResponseView = reactExports.lazy(
|
|
1949
|
-
() => import("./ResponseView-
|
|
1950
|
+
() => import("./ResponseView-DW-kpJL5.mjs").then((m) => ({ default: m.ResponseView }))
|
|
1950
1951
|
);
|
|
1951
1952
|
const LazyStreamingChunkSequence = reactExports.lazy(
|
|
1952
|
-
() => import("./StreamingChunkSequence-
|
|
1953
|
+
() => import("./StreamingChunkSequence-BAE57Fae.mjs").then((m) => ({
|
|
1953
1954
|
default: m.StreamingChunkSequence
|
|
1954
1955
|
}))
|
|
1955
1956
|
);
|
|
@@ -2402,7 +2403,7 @@ const LogEntryHeader = reactExports.memo(function({
|
|
|
2402
2403
|
"data-nav-id": `log-${log.id}`,
|
|
2403
2404
|
"data-nav-action": expanded ? "collapse" : "expand",
|
|
2404
2405
|
className: cn(
|
|
2405
|
-
"flex items-center gap-2 px-3 py-1 cursor-pointer transition-colors",
|
|
2406
|
+
"flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1 px-3 py-1.5 cursor-pointer transition-colors",
|
|
2406
2407
|
"hover:bg-muted/50",
|
|
2407
2408
|
"select-none",
|
|
2408
2409
|
"focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:outline-none"
|
|
@@ -2491,24 +2492,30 @@ const LogEntryHeader = reactExports.memo(function({
|
|
|
2491
2492
|
] }) }),
|
|
2492
2493
|
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Output token throughput after first chunk" })
|
|
2493
2494
|
] }),
|
|
2494
|
-
hasTokens && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1 text-xs shrink-0", children: [
|
|
2495
|
+
hasTokens && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 items-center gap-1 text-xs sm:shrink-0", children: [
|
|
2495
2496
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Zap, { className: "size-3 text-muted-foreground" }),
|
|
2496
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono tabular-nums", children: [
|
|
2497
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 flex-wrap items-center gap-x-1 font-mono tabular-nums", children: [
|
|
2497
2498
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
2498
2499
|
"span",
|
|
2499
2500
|
{
|
|
2500
|
-
className:
|
|
2501
|
+
className: cn(
|
|
2502
|
+
"whitespace-nowrap",
|
|
2503
|
+
log.inputTokens !== null ? "text-blue-400" : "text-muted-foreground"
|
|
2504
|
+
),
|
|
2501
2505
|
children: [
|
|
2502
2506
|
"IN ",
|
|
2503
2507
|
log.inputTokens !== null ? formatTokens(log.inputTokens) : "—"
|
|
2504
2508
|
]
|
|
2505
2509
|
}
|
|
2506
2510
|
),
|
|
2507
|
-
"
|
|
2511
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground", children: "/" }),
|
|
2508
2512
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
2509
2513
|
"span",
|
|
2510
2514
|
{
|
|
2511
|
-
className:
|
|
2515
|
+
className: cn(
|
|
2516
|
+
"whitespace-nowrap",
|
|
2517
|
+
log.outputTokens !== null ? "text-amber-400" : "text-muted-foreground"
|
|
2518
|
+
),
|
|
2512
2519
|
children: [
|
|
2513
2520
|
"OUT ",
|
|
2514
2521
|
log.outputTokens !== null ? formatTokens(log.outputTokens) : "—"
|
|
@@ -3505,6 +3512,9 @@ function resolveFocusedTab(tab, anatomySegments) {
|
|
|
3505
3512
|
return "request";
|
|
3506
3513
|
}
|
|
3507
3514
|
}
|
|
3515
|
+
function shouldHydrateLogBody(log) {
|
|
3516
|
+
return log.bodyContentMode === "compact" || log.bodyContentMode === "truncated";
|
|
3517
|
+
}
|
|
3508
3518
|
function DiffToggleButton({
|
|
3509
3519
|
active,
|
|
3510
3520
|
onClick
|
|
@@ -3561,40 +3571,43 @@ const LogEntry = reactExports.memo(function({
|
|
|
3561
3571
|
const [requestDiff, setRequestDiff] = reactExports.useState(false);
|
|
3562
3572
|
const [activeTab, setActiveTab] = reactExports.useState("request");
|
|
3563
3573
|
const [expandToPath, setExpandToPath] = reactExports.useState(null);
|
|
3574
|
+
const [hydratedLog, setHydratedLog] = reactExports.useState(null);
|
|
3575
|
+
const [bodyHydrationState, setBodyHydrationState] = reactExports.useState("idle");
|
|
3564
3576
|
const requestJsonRef = reactExports.useRef(null);
|
|
3565
|
-
const
|
|
3577
|
+
const displayLog = hydratedLog ?? log;
|
|
3578
|
+
const resolvedFormat = resolveLogFormat(displayLog);
|
|
3566
3579
|
const adapter = getLogFormatAdapter(resolvedFormat);
|
|
3567
3580
|
const requestAnalysis = reactExports.useMemo(
|
|
3568
|
-
() => adapter.analyzeRequest(
|
|
3569
|
-
[adapter,
|
|
3581
|
+
() => adapter.analyzeRequest(displayLog.rawRequestBody),
|
|
3582
|
+
[adapter, displayLog.rawRequestBody]
|
|
3570
3583
|
);
|
|
3571
3584
|
const responseAnalysis = reactExports.useMemo(
|
|
3572
|
-
() => adapter.analyzeResponse(
|
|
3573
|
-
[adapter,
|
|
3585
|
+
() => adapter.analyzeResponse(displayLog.responseText),
|
|
3586
|
+
[adapter, displayLog.responseText]
|
|
3574
3587
|
);
|
|
3575
3588
|
const strippedRequestBody = reactExports.useMemo(() => {
|
|
3576
|
-
if (!strip || resolvedFormat !== "anthropic" ||
|
|
3589
|
+
if (!strip || resolvedFormat !== "anthropic" || displayLog.rawRequestBody === null) {
|
|
3577
3590
|
return null;
|
|
3578
3591
|
}
|
|
3579
|
-
return stripClaudeCodeBillingHeader(
|
|
3580
|
-
}, [
|
|
3581
|
-
const displayedRequestBody = strippedRequestBody ??
|
|
3592
|
+
return stripClaudeCodeBillingHeader(displayLog.rawRequestBody).body;
|
|
3593
|
+
}, [displayLog.rawRequestBody, resolvedFormat, strip]);
|
|
3594
|
+
const displayedRequestBody = strippedRequestBody ?? displayLog.rawRequestBody;
|
|
3582
3595
|
const requestExpansion = useJsonBulkExpansion(displayedRequestBody);
|
|
3583
|
-
const rawRequestExpansion = useJsonBulkExpansion(
|
|
3584
|
-
const responseExpansion = useJsonBulkExpansion(
|
|
3596
|
+
const rawRequestExpansion = useJsonBulkExpansion(displayLog.rawRequestBody);
|
|
3597
|
+
const responseExpansion = useJsonBulkExpansion(displayLog.responseText);
|
|
3585
3598
|
const headersText = reactExports.useMemo(
|
|
3586
|
-
() =>
|
|
3587
|
-
[
|
|
3599
|
+
() => displayLog.headers && Object.keys(displayLog.headers).length > 0 ? JSON.stringify(displayLog.headers, null, 2) : null,
|
|
3600
|
+
[displayLog.headers]
|
|
3588
3601
|
);
|
|
3589
3602
|
const rawHeadersText = reactExports.useMemo(
|
|
3590
|
-
() =>
|
|
3591
|
-
[
|
|
3603
|
+
() => displayLog.rawHeaders && Object.keys(displayLog.rawHeaders).length > 0 ? JSON.stringify(displayLog.rawHeaders, null, 2) : null,
|
|
3604
|
+
[displayLog.rawHeaders]
|
|
3592
3605
|
);
|
|
3593
3606
|
const requestCopy = useCopyFeedback(displayedRequestBody);
|
|
3594
|
-
const rawRequestCopy = useCopyFeedback(
|
|
3607
|
+
const rawRequestCopy = useCopyFeedback(displayLog.rawRequestBody);
|
|
3595
3608
|
const headersCopy = useCopyFeedback(headersText);
|
|
3596
3609
|
const rawHeadersCopy = useCopyFeedback(rawHeadersText);
|
|
3597
|
-
const responseCopy = useCopyFeedback(
|
|
3610
|
+
const responseCopy = useCopyFeedback(displayLog.responseText);
|
|
3598
3611
|
const tabActions = reactExports.useMemo(
|
|
3599
3612
|
() => ({
|
|
3600
3613
|
request: {
|
|
@@ -3614,15 +3627,15 @@ const LogEntry = reactExports.memo(function({
|
|
|
3614
3627
|
resolvedFormat,
|
|
3615
3628
|
viewMode,
|
|
3616
3629
|
strip,
|
|
3617
|
-
|
|
3630
|
+
displayLog.rawRequestBody !== null
|
|
3618
3631
|
) ? { active: requestDiff, onToggle: () => setRequestDiff(!requestDiff) } : void 0,
|
|
3619
3632
|
diffWithPrevious: onCompareWithPrevious === void 0 ? void 0 : () => {
|
|
3620
|
-
onCompareWithPrevious(
|
|
3633
|
+
onCompareWithPrevious(displayLog);
|
|
3621
3634
|
}
|
|
3622
3635
|
},
|
|
3623
3636
|
"raw-request": {
|
|
3624
3637
|
copyLabel: "Copy raw request",
|
|
3625
|
-
copyText:
|
|
3638
|
+
copyText: displayLog.rawRequestBody,
|
|
3626
3639
|
copyCopied: rawRequestCopy.copied,
|
|
3627
3640
|
onCopy: rawRequestCopy.copy,
|
|
3628
3641
|
expansion: {
|
|
@@ -3648,7 +3661,7 @@ const LogEntry = reactExports.memo(function({
|
|
|
3648
3661
|
},
|
|
3649
3662
|
raw: {
|
|
3650
3663
|
copyLabel: "Copy response",
|
|
3651
|
-
copyText:
|
|
3664
|
+
copyText: displayLog.responseText,
|
|
3652
3665
|
copyCopied: responseCopy.copied,
|
|
3653
3666
|
onCopy: responseCopy.copy,
|
|
3654
3667
|
expansion: {
|
|
@@ -3663,14 +3676,15 @@ const LogEntry = reactExports.memo(function({
|
|
|
3663
3676
|
requestCopy,
|
|
3664
3677
|
requestExpansion,
|
|
3665
3678
|
requestDiff,
|
|
3666
|
-
|
|
3679
|
+
displayLog,
|
|
3680
|
+
displayLog.rawRequestBody,
|
|
3667
3681
|
rawRequestCopy,
|
|
3668
3682
|
rawRequestExpansion,
|
|
3669
3683
|
headersText,
|
|
3670
3684
|
headersCopy,
|
|
3671
3685
|
rawHeadersText,
|
|
3672
3686
|
rawHeadersCopy,
|
|
3673
|
-
|
|
3687
|
+
displayLog.responseText,
|
|
3674
3688
|
responseCopy,
|
|
3675
3689
|
responseExpansion,
|
|
3676
3690
|
resolvedFormat,
|
|
@@ -3687,7 +3701,7 @@ const LogEntry = reactExports.memo(function({
|
|
|
3687
3701
|
() => parseRequestTools(requestExpansion.parsedData),
|
|
3688
3702
|
[requestExpansion.parsedData]
|
|
3689
3703
|
);
|
|
3690
|
-
const warnings =
|
|
3704
|
+
const warnings = displayLog.warnings ?? [];
|
|
3691
3705
|
const anatomyPaths = reactExports.useMemo(() => {
|
|
3692
3706
|
if (anatomySegments === null) return void 0;
|
|
3693
3707
|
return new Set(anatomySegments.map((s) => s.path));
|
|
@@ -3706,6 +3720,28 @@ const LogEntry = reactExports.memo(function({
|
|
|
3706
3720
|
}
|
|
3707
3721
|
setExpanded(nextExpanded);
|
|
3708
3722
|
}, [anatomySegments, expanded]);
|
|
3723
|
+
reactExports.useEffect(() => {
|
|
3724
|
+
setHydratedLog(null);
|
|
3725
|
+
setBodyHydrationState("idle");
|
|
3726
|
+
}, [log.id]);
|
|
3727
|
+
reactExports.useEffect(() => {
|
|
3728
|
+
if (!expanded) return;
|
|
3729
|
+
if (!shouldHydrateLogBody(log)) return;
|
|
3730
|
+
if (hydratedLog !== null || bodyHydrationState !== "idle") return;
|
|
3731
|
+
let cancelled = false;
|
|
3732
|
+
setBodyHydrationState("loading");
|
|
3733
|
+
void fetchJson(`/api/logs/${String(log.id)}`, CapturedLogSchema).then((fullLog) => {
|
|
3734
|
+
if (cancelled) return;
|
|
3735
|
+
setHydratedLog(fullLog);
|
|
3736
|
+
setBodyHydrationState("idle");
|
|
3737
|
+
}).catch(() => {
|
|
3738
|
+
if (cancelled) return;
|
|
3739
|
+
setBodyHydrationState("failed");
|
|
3740
|
+
});
|
|
3741
|
+
return () => {
|
|
3742
|
+
cancelled = true;
|
|
3743
|
+
};
|
|
3744
|
+
}, [bodyHydrationState, expanded, hydratedLog, log.bodyContentMode, log.id]);
|
|
3709
3745
|
reactExports.useEffect(() => {
|
|
3710
3746
|
const handleLogFocusRequest = (event) => {
|
|
3711
3747
|
const request = readLogFocusRequest(event);
|
|
@@ -3724,7 +3760,7 @@ const LogEntry = reactExports.memo(function({
|
|
|
3724
3760
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3725
3761
|
LogEntryHeader,
|
|
3726
3762
|
{
|
|
3727
|
-
log,
|
|
3763
|
+
log: displayLog,
|
|
3728
3764
|
messageCount: requestAnalysis.messageCount,
|
|
3729
3765
|
toolCount: requestAnalysis.toolCount,
|
|
3730
3766
|
expanded,
|
|
@@ -3749,15 +3785,17 @@ const LogEntry = reactExports.memo(function({
|
|
|
3749
3785
|
viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "raw", children: "Raw Response" }),
|
|
3750
3786
|
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "parsed", children: "Response" })
|
|
3751
3787
|
] }),
|
|
3752
|
-
shouldShowRawRequestTab(resolvedFormat, viewMode, strip) && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "raw-request", children: activeTab === "raw-request" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-4 pt-1 pb-3", children:
|
|
3788
|
+
shouldShowRawRequestTab(resolvedFormat, viewMode, strip) && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "raw-request", children: activeTab === "raw-request" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-4 pt-1 pb-3", children: displayLog.rawRequestBody === null ? /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground italic", children: "No request body" }) : rawRequestExpansion.parsedData !== null ? /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3753
3789
|
LazyJsonViewer,
|
|
3754
3790
|
{
|
|
3755
3791
|
data: rawRequestExpansion.parsedData,
|
|
3756
3792
|
bulkDepth: rawRequestExpansion.bulkDepth,
|
|
3757
3793
|
bulkRevision: rawRequestExpansion.bulkRevision
|
|
3758
3794
|
}
|
|
3759
|
-
) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "font-mono text-xs whitespace-pre-wrap break-words", children:
|
|
3795
|
+
) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "font-mono text-xs whitespace-pre-wrap break-words", children: displayLog.rawRequestBody }) }) }),
|
|
3760
3796
|
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "request", children: activeTab === "request" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 pt-1 pb-3", children: [
|
|
3797
|
+
bodyHydrationState === "loading" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-3 rounded border border-border bg-muted/30 p-3 text-xs text-muted-foreground", children: "Loading full request and response bodies..." }),
|
|
3798
|
+
bodyHydrationState === "failed" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-3 rounded border border-amber-500/30 bg-amber-500/10 p-3 text-xs text-amber-200", children: "Full request and response bodies could not be loaded. Compact metadata is still available." }),
|
|
3761
3799
|
warnings.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-3 rounded border border-amber-500/30 bg-amber-500/10 p-3 text-xs", children: [
|
|
3762
3800
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 font-semibold text-amber-300", children: [
|
|
3763
3801
|
/* @__PURE__ */ jsxRuntimeExports.jsx(TriangleAlert, { className: "size-3.5" }),
|
|
@@ -3775,7 +3813,7 @@ const LogEntry = reactExports.memo(function({
|
|
|
3775
3813
|
requestDiff ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3776
3814
|
RequestDiffContent,
|
|
3777
3815
|
{
|
|
3778
|
-
rawBody:
|
|
3816
|
+
rawBody: displayLog.rawRequestBody,
|
|
3779
3817
|
displayedBody: displayedRequestBody,
|
|
3780
3818
|
emptyLabel: "No transformation applied; raw and sent request bodies are identical."
|
|
3781
3819
|
}
|
|
@@ -3794,8 +3832,8 @@ const LogEntry = reactExports.memo(function({
|
|
|
3794
3832
|
LazyRequestAnatomy,
|
|
3795
3833
|
{
|
|
3796
3834
|
parsed: requestExpansion.parsedData,
|
|
3797
|
-
inputTokens:
|
|
3798
|
-
model:
|
|
3835
|
+
inputTokens: displayLog.inputTokens ?? null,
|
|
3836
|
+
model: displayLog.model,
|
|
3799
3837
|
segments: anatomySegments,
|
|
3800
3838
|
onSegmentActivate: jumpToAnatomySegment
|
|
3801
3839
|
}
|
|
@@ -3803,7 +3841,7 @@ const LogEntry = reactExports.memo(function({
|
|
|
3803
3841
|
viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "headers", children: activeTab === "headers" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 pt-1 pb-3", children: [
|
|
3804
3842
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex justify-end gap-2 mb-2", children: shouldShowHeadersDiffButton(
|
|
3805
3843
|
viewMode,
|
|
3806
|
-
|
|
3844
|
+
displayLog.rawHeaders !== void 0 && Object.keys(displayLog.rawHeaders).length > 0
|
|
3807
3845
|
) && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3808
3846
|
DiffToggleButton,
|
|
3809
3847
|
{
|
|
@@ -3817,11 +3855,11 @@ const LogEntry = reactExports.memo(function({
|
|
|
3817
3855
|
headersDiff ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3818
3856
|
HeadersDiffContent,
|
|
3819
3857
|
{
|
|
3820
|
-
rawHeaders:
|
|
3821
|
-
headers:
|
|
3858
|
+
rawHeaders: displayLog.rawHeaders,
|
|
3859
|
+
headers: displayLog.headers,
|
|
3822
3860
|
emptyLabel: "No transformation applied; raw and processed headers are identical."
|
|
3823
3861
|
}
|
|
3824
|
-
) :
|
|
3862
|
+
) : displayLog.headers && Object.keys(displayLog.headers).length > 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1 font-mono text-xs", children: Object.entries(displayLog.headers).sort(([a], [b]) => a.localeCompare(b)).map(([key, value]) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
|
|
3825
3863
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-blue-600 dark:text-blue-400 font-semibold shrink-0", children: [
|
|
3826
3864
|
key,
|
|
3827
3865
|
":"
|
|
@@ -3829,7 +3867,7 @@ const LogEntry = reactExports.memo(function({
|
|
|
3829
3867
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground truncate", title: value, children: value })
|
|
3830
3868
|
] }, key)) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground italic", children: "No headers captured" })
|
|
3831
3869
|
] }) }),
|
|
3832
|
-
viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "raw-headers", children: activeTab === "raw-headers" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-4 pt-1 pb-3", children:
|
|
3870
|
+
viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "raw-headers", children: activeTab === "raw-headers" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-4 pt-1 pb-3", children: displayLog.rawHeaders && Object.keys(displayLog.rawHeaders).length > 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1 font-mono text-xs", children: Object.entries(displayLog.rawHeaders).sort(([a], [b]) => a.localeCompare(b)).map(([key, value]) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
|
|
3833
3871
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-blue-600 dark:text-blue-400 font-semibold shrink-0", children: [
|
|
3834
3872
|
key,
|
|
3835
3873
|
":"
|
|
@@ -3837,44 +3875,44 @@ const LogEntry = reactExports.memo(function({
|
|
|
3837
3875
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground truncate", title: value, children: value })
|
|
3838
3876
|
] }, key)) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground italic", children: "No raw headers captured" }) }) }),
|
|
3839
3877
|
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "raw", children: activeTab === "raw" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 pt-1 pb-3 space-y-3", children: [
|
|
3840
|
-
|
|
3878
|
+
displayLog.error !== void 0 && displayLog.error !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded border border-destructive/50 bg-destructive/10 p-3 text-xs", children: [
|
|
3841
3879
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-semibold text-destructive mb-1", children: "SSE Error" }),
|
|
3842
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-muted-foreground font-mono", children:
|
|
3880
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-muted-foreground font-mono", children: displayLog.error })
|
|
3843
3881
|
] }),
|
|
3844
|
-
|
|
3882
|
+
displayLog.responseText !== null ? /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3845
3883
|
LazyJsonViewerFromString,
|
|
3846
3884
|
{
|
|
3847
|
-
text:
|
|
3885
|
+
text: displayLog.responseText,
|
|
3848
3886
|
defaultExpandDepth: 0,
|
|
3849
3887
|
bulkDepth: responseExpansion.bulkDepth,
|
|
3850
3888
|
bulkRevision: responseExpansion.bulkRevision
|
|
3851
3889
|
}
|
|
3852
3890
|
) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground italic", children: "No response" }),
|
|
3853
|
-
|
|
3891
|
+
displayLog.streaming === true && /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3854
3892
|
LazyStreamingChunkSequence,
|
|
3855
3893
|
{
|
|
3856
|
-
logId:
|
|
3857
|
-
truncated:
|
|
3894
|
+
logId: displayLog.id,
|
|
3895
|
+
truncated: displayLog.streamingChunksPath !== null
|
|
3858
3896
|
}
|
|
3859
3897
|
) })
|
|
3860
3898
|
] }) }),
|
|
3861
3899
|
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "parsed", children: activeTab === "parsed" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-4 pt-1 pb-3", children: /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(TabFallback, {}), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3862
3900
|
LazyResponseView,
|
|
3863
3901
|
{
|
|
3864
|
-
responseText:
|
|
3865
|
-
responseStatus:
|
|
3866
|
-
streaming:
|
|
3867
|
-
inputTokens:
|
|
3868
|
-
outputTokens:
|
|
3869
|
-
cacheCreationInputTokens:
|
|
3870
|
-
cacheReadInputTokens:
|
|
3902
|
+
responseText: displayLog.responseText,
|
|
3903
|
+
responseStatus: displayLog.responseStatus,
|
|
3904
|
+
streaming: displayLog.streaming,
|
|
3905
|
+
inputTokens: displayLog.inputTokens,
|
|
3906
|
+
outputTokens: displayLog.outputTokens,
|
|
3907
|
+
cacheCreationInputTokens: displayLog.cacheCreationInputTokens,
|
|
3908
|
+
cacheReadInputTokens: displayLog.cacheReadInputTokens,
|
|
3871
3909
|
apiFormat: resolvedFormat,
|
|
3872
|
-
error:
|
|
3910
|
+
error: displayLog.error
|
|
3873
3911
|
}
|
|
3874
3912
|
) }) }) })
|
|
3875
3913
|
] }) })
|
|
3876
3914
|
] }),
|
|
3877
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntimeExports.jsx(LazyReplayDialog, { log, open: replayOpen, onOpenChange: setReplayOpen }) })
|
|
3915
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntimeExports.jsx(LazyReplayDialog, { log: displayLog, open: replayOpen, onOpenChange: setReplayOpen }) })
|
|
3878
3916
|
] });
|
|
3879
3917
|
});
|
|
3880
3918
|
function ThreadConnector({
|
|
@@ -5314,74 +5352,7 @@ function CrabLogo({ className }) {
|
|
|
5314
5352
|
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "6.5", y1: "16", x2: "4.5", y2: "19.5" }),
|
|
5315
5353
|
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "9", y1: "17.5", x2: "8", y2: "20.5" }),
|
|
5316
5354
|
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "15", y1: "17.5", x2: "16", y2: "20.5" }),
|
|
5317
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "17.5", y1: "16", x2: "19.5", y2: "19.5" })
|
|
5318
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("g", { children: [
|
|
5319
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5320
|
-
"path",
|
|
5321
|
-
{
|
|
5322
|
-
d: "M5.6 17.7 L8.4 15.4 L10.8 18 C9.1 18.9 7.2 18.8 5.6 17.7 Z",
|
|
5323
|
-
fill: "#2f6b3f",
|
|
5324
|
-
stroke: "none",
|
|
5325
|
-
opacity: "0.95"
|
|
5326
|
-
}
|
|
5327
|
-
),
|
|
5328
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5329
|
-
"path",
|
|
5330
|
-
{
|
|
5331
|
-
d: "M6.9 17.5 L8.4 16 L9.8 17.7 C8.9 18.1 7.8 18.1 6.9 17.5 Z",
|
|
5332
|
-
fill: "#6fb36f",
|
|
5333
|
-
stroke: "none",
|
|
5334
|
-
opacity: "0.95"
|
|
5335
|
-
}
|
|
5336
|
-
),
|
|
5337
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M8.4 16 L8.4 18.4", stroke: "#d6b45f", strokeWidth: "0.34" }),
|
|
5338
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "10.6", cy: "17.75", r: "0.36", fill: "#c2412d", stroke: "none" })
|
|
5339
|
-
] }),
|
|
5340
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("g", { children: [
|
|
5341
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5342
|
-
"path",
|
|
5343
|
-
{
|
|
5344
|
-
d: "M8 16.5 L11.9 13.6 L15.8 16.8 C13.3 18.4 10.4 18.3 8 16.5 Z",
|
|
5345
|
-
fill: "#2f6b3f",
|
|
5346
|
-
stroke: "none",
|
|
5347
|
-
opacity: "0.97"
|
|
5348
|
-
}
|
|
5349
|
-
),
|
|
5350
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5351
|
-
"path",
|
|
5352
|
-
{
|
|
5353
|
-
d: "M9.8 16.3 L11.9 14.4 L14.3 16.5 C12.8 17.4 11.3 17.4 9.8 16.3 Z",
|
|
5354
|
-
fill: "#6fb36f",
|
|
5355
|
-
stroke: "none",
|
|
5356
|
-
opacity: "0.95"
|
|
5357
|
-
}
|
|
5358
|
-
),
|
|
5359
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M11.9 14.3 L11.9 17.8", stroke: "#d6b45f", strokeWidth: "0.42" }),
|
|
5360
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M9.8 16.3 C11.2 15.8 12.9 15.9 14.3 16.5", stroke: "#9fca78", strokeWidth: "0.36" }),
|
|
5361
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "15.6", cy: "16.75", r: "0.43", fill: "#c2412d", stroke: "none" })
|
|
5362
|
-
] }),
|
|
5363
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("g", { children: [
|
|
5364
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5365
|
-
"path",
|
|
5366
|
-
{
|
|
5367
|
-
d: "M13.6 18.1 L16.2 15.7 L18.5 18.2 C17.1 19.1 15.2 19 13.6 18.1 Z",
|
|
5368
|
-
fill: "#2f6b3f",
|
|
5369
|
-
stroke: "none",
|
|
5370
|
-
opacity: "0.95"
|
|
5371
|
-
}
|
|
5372
|
-
),
|
|
5373
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5374
|
-
"path",
|
|
5375
|
-
{
|
|
5376
|
-
d: "M14.8 17.9 L16.2 16.3 L17.5 18 C16.6 18.4 15.7 18.4 14.8 17.9 Z",
|
|
5377
|
-
fill: "#6fb36f",
|
|
5378
|
-
stroke: "none",
|
|
5379
|
-
opacity: "0.95"
|
|
5380
|
-
}
|
|
5381
|
-
),
|
|
5382
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M16.2 16.3 L16.2 18.6", stroke: "#d6b45f", strokeWidth: "0.34" }),
|
|
5383
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "18.35", cy: "18.15", r: "0.36", fill: "#c2412d", stroke: "none" })
|
|
5384
|
-
] })
|
|
5355
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "17.5", y1: "16", x2: "19.5", y2: "19.5" })
|
|
5385
5356
|
]
|
|
5386
5357
|
}
|
|
5387
5358
|
);
|
|
@@ -6217,21 +6188,24 @@ function MemberRow({ row }) {
|
|
|
6217
6188
|
const errors = session?.errorCount ?? null;
|
|
6218
6189
|
const tokens = session?.tokenUsage.total ?? null;
|
|
6219
6190
|
const firstChunkMs = log?.firstChunkMs ?? null;
|
|
6191
|
+
const sessionLabel = firstNonEmpty(member.label, member.sessionId);
|
|
6220
6192
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("tr", { className: "border-b border-border last:border-0", children: [
|
|
6221
6193
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("td", { className: "max-w-56 px-3 py-2", children: [
|
|
6222
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
6223
|
-
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
|
|
6233
|
-
|
|
6234
|
-
|
|
6194
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
6195
|
+
"a",
|
|
6196
|
+
{
|
|
6197
|
+
href: sessionPath,
|
|
6198
|
+
target: "_blank",
|
|
6199
|
+
rel: "noreferrer",
|
|
6200
|
+
className: "inline-flex max-w-full min-w-0 items-center gap-2 rounded-sm font-mono text-xs text-primary outline-none hover:underline focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
6201
|
+
"aria-label": `Open session ${sessionLabel}`,
|
|
6202
|
+
title: `Open session ${sessionLabel}`,
|
|
6203
|
+
children: [
|
|
6204
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0 truncate", children: sessionLabel }),
|
|
6205
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ExternalLink, { className: "size-3 shrink-0 text-muted-foreground" })
|
|
6206
|
+
]
|
|
6207
|
+
}
|
|
6208
|
+
),
|
|
6235
6209
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-0.5 truncate text-[11px] text-muted-foreground", children: displayText(member.agent) })
|
|
6236
6210
|
] }),
|
|
6237
6211
|
/* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "max-w-52 px-3 py-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "block truncate", children: providerModel(member) }) }),
|
|
@@ -10226,6 +10200,114 @@ function getFirstUserAgent(logs) {
|
|
|
10226
10200
|
}
|
|
10227
10201
|
return null;
|
|
10228
10202
|
}
|
|
10203
|
+
function hasLogFailure(log) {
|
|
10204
|
+
if (log.error !== null && log.error !== void 0 && log.error.length > 0) return true;
|
|
10205
|
+
return log.responseStatus !== null && log.responseStatus >= 400;
|
|
10206
|
+
}
|
|
10207
|
+
function getModelLabel(logs) {
|
|
10208
|
+
const models = /* @__PURE__ */ new Set();
|
|
10209
|
+
for (const log of logs) {
|
|
10210
|
+
if (log.model !== null && log.model.length > 0) {
|
|
10211
|
+
models.add(log.model);
|
|
10212
|
+
}
|
|
10213
|
+
}
|
|
10214
|
+
const sorted = [...models].sort();
|
|
10215
|
+
if (sorted.length === 0) return "Model unknown";
|
|
10216
|
+
if (sorted.length === 1) return sorted[0] ?? "Model unknown";
|
|
10217
|
+
return `${sorted.length} models`;
|
|
10218
|
+
}
|
|
10219
|
+
function buildSessionSlateStats({
|
|
10220
|
+
logs,
|
|
10221
|
+
isLoading,
|
|
10222
|
+
timeDisplayFormat,
|
|
10223
|
+
slowResponseThresholdSeconds
|
|
10224
|
+
}) {
|
|
10225
|
+
let failures = 0;
|
|
10226
|
+
let slow = 0;
|
|
10227
|
+
let totalIn = 0;
|
|
10228
|
+
let totalOut = 0;
|
|
10229
|
+
const slowThresholdMs = slowResponseThresholdSeconds * 1e3;
|
|
10230
|
+
for (const log of logs) {
|
|
10231
|
+
if (hasLogFailure(log)) failures += 1;
|
|
10232
|
+
if (slowResponseThresholdSeconds > 0 && log.elapsedMs !== null && log.elapsedMs >= slowThresholdMs) {
|
|
10233
|
+
slow += 1;
|
|
10234
|
+
}
|
|
10235
|
+
if (log.inputTokens !== null) totalIn += log.inputTokens;
|
|
10236
|
+
if (log.outputTokens !== null) totalOut += log.outputTokens;
|
|
10237
|
+
}
|
|
10238
|
+
const status = isLoading ? "rolling" : failures > 0 ? "failed" : slow > 0 ? "watch" : "clear";
|
|
10239
|
+
const statusLabel2 = status === "rolling" ? "Rolling" : status === "failed" ? "Failure" : status === "watch" ? "Watch" : "Clear";
|
|
10240
|
+
return {
|
|
10241
|
+
status,
|
|
10242
|
+
statusLabel: statusLabel2,
|
|
10243
|
+
modelLabel: getModelLabel(logs),
|
|
10244
|
+
requests: logs.length,
|
|
10245
|
+
failures,
|
|
10246
|
+
slow,
|
|
10247
|
+
timeRange: formatTimeRange(logs, timeDisplayFormat),
|
|
10248
|
+
tokenLabel: `${formatTokens(totalIn)} in / ${formatTokens(totalOut)} out`
|
|
10249
|
+
};
|
|
10250
|
+
}
|
|
10251
|
+
function slateStatusClass(status) {
|
|
10252
|
+
switch (status) {
|
|
10253
|
+
case "rolling":
|
|
10254
|
+
return "border-cyan-400/35 bg-cyan-500/10 text-cyan-200";
|
|
10255
|
+
case "failed":
|
|
10256
|
+
return "border-red-400/35 bg-red-500/10 text-red-100";
|
|
10257
|
+
case "watch":
|
|
10258
|
+
return "border-amber-300/35 bg-amber-400/10 text-amber-100";
|
|
10259
|
+
case "clear":
|
|
10260
|
+
return "border-emerald-400/30 bg-emerald-500/10 text-emerald-100";
|
|
10261
|
+
}
|
|
10262
|
+
}
|
|
10263
|
+
function SessionOpeningSlate({ stats }) {
|
|
10264
|
+
if (stats.requests === 0) return null;
|
|
10265
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-4 rounded-md border border-border bg-[#0c0d0f] shadow-[0_14px_50px_rgba(0,0,0,0.25)]", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-0 md:grid-cols-[minmax(220px,1.2fr)_repeat(4,minmax(120px,1fr))]", children: [
|
|
10266
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "col-span-2 border-b border-border/70 px-4 py-3 md:col-span-1 md:border-b-0 md:border-r", children: [
|
|
10267
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-[10px] font-semibold uppercase text-muted-foreground", children: [
|
|
10268
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Clapperboard, { className: "size-3.5 text-cyan-300" }),
|
|
10269
|
+
"Opening Slate"
|
|
10270
|
+
] }),
|
|
10271
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 min-w-0 truncate font-mono text-sm font-semibold text-foreground", children: stats.modelLabel }),
|
|
10272
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1 truncate font-mono text-[11px] text-muted-foreground", children: stats.timeRange ?? "Timeline pending" })
|
|
10273
|
+
] }),
|
|
10274
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-r border-b border-border/70 px-4 py-3 md:border-b-0", children: [
|
|
10275
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[10px] uppercase text-muted-foreground", children: "Status" }),
|
|
10276
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10277
|
+
"div",
|
|
10278
|
+
{
|
|
10279
|
+
className: cn(
|
|
10280
|
+
"mt-2 inline-flex h-7 items-center rounded-md border px-2.5 font-mono text-xs font-semibold",
|
|
10281
|
+
slateStatusClass(stats.status)
|
|
10282
|
+
),
|
|
10283
|
+
children: stats.statusLabel
|
|
10284
|
+
}
|
|
10285
|
+
)
|
|
10286
|
+
] }),
|
|
10287
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-b border-border/70 px-4 py-3 md:border-b-0 md:border-r", children: [
|
|
10288
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[10px] uppercase text-muted-foreground", children: "Requests" }),
|
|
10289
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 font-mono text-xl font-semibold text-foreground", children: stats.requests })
|
|
10290
|
+
] }),
|
|
10291
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-r border-border/70 px-4 py-3 md:border-r", children: [
|
|
10292
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 text-[10px] uppercase text-muted-foreground", children: [
|
|
10293
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Siren, { className: "size-3 text-red-300" }),
|
|
10294
|
+
"Failure"
|
|
10295
|
+
] }),
|
|
10296
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 font-mono text-xl font-semibold text-red-100", children: stats.failures })
|
|
10297
|
+
] }),
|
|
10298
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-3", children: [
|
|
10299
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 text-[10px] uppercase text-muted-foreground", children: [
|
|
10300
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Gauge, { className: "size-3 text-amber-200" }),
|
|
10301
|
+
"Tempo"
|
|
10302
|
+
] }),
|
|
10303
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-2 font-mono text-sm font-semibold text-foreground", children: [
|
|
10304
|
+
stats.slow,
|
|
10305
|
+
" slow"
|
|
10306
|
+
] }),
|
|
10307
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1 truncate font-mono text-[11px] text-muted-foreground", children: stats.tokenLabel })
|
|
10308
|
+
] })
|
|
10309
|
+
] }) });
|
|
10310
|
+
}
|
|
10229
10311
|
function resolveSessionContextScope({
|
|
10230
10312
|
pinnedSessionId,
|
|
10231
10313
|
selectedSession,
|
|
@@ -10298,6 +10380,258 @@ function formatContextWindow(summary) {
|
|
|
10298
10380
|
if (tokens === null) return "Context window unknown";
|
|
10299
10381
|
return `Context window ${formatContextWindowTokens(tokens)}`;
|
|
10300
10382
|
}
|
|
10383
|
+
const MEMBER_METADATA_KEYS = [
|
|
10384
|
+
"score",
|
|
10385
|
+
"decision",
|
|
10386
|
+
"final_status",
|
|
10387
|
+
"validation_pass_ratio",
|
|
10388
|
+
"semantic_memory_score",
|
|
10389
|
+
"opencode_exit",
|
|
10390
|
+
"actual_model",
|
|
10391
|
+
"run_dir",
|
|
10392
|
+
"workspace",
|
|
10393
|
+
"project_dir",
|
|
10394
|
+
"work_dir"
|
|
10395
|
+
];
|
|
10396
|
+
function formatMetadataValue(value) {
|
|
10397
|
+
if (typeof value === "string") return value.length > 0 ? value : null;
|
|
10398
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
10399
|
+
if (value === null) return null;
|
|
10400
|
+
return JSON.stringify(value);
|
|
10401
|
+
}
|
|
10402
|
+
function formatMemberMetadata(member, key) {
|
|
10403
|
+
if (member === null) return null;
|
|
10404
|
+
const value = member.metadata[key];
|
|
10405
|
+
if (value === void 0) return null;
|
|
10406
|
+
return formatMetadataValue(value);
|
|
10407
|
+
}
|
|
10408
|
+
function evidenceChipClass(value) {
|
|
10409
|
+
const normalized = value.toLowerCase();
|
|
10410
|
+
if (normalized.includes("reject") || normalized.includes("fail") || normalized.includes("error")) {
|
|
10411
|
+
return "border-red-400/35 bg-red-500/10 text-red-100";
|
|
10412
|
+
}
|
|
10413
|
+
if (normalized.includes("partial") || normalized.includes("pending") || normalized.includes("slow")) {
|
|
10414
|
+
return "border-amber-300/35 bg-amber-400/10 text-amber-100";
|
|
10415
|
+
}
|
|
10416
|
+
if (normalized.includes("pass") || normalized.includes("complete") || normalized.includes("accept")) {
|
|
10417
|
+
return "border-emerald-400/30 bg-emerald-500/10 text-emerald-100";
|
|
10418
|
+
}
|
|
10419
|
+
return "border-border/70 bg-background/70 text-muted-foreground";
|
|
10420
|
+
}
|
|
10421
|
+
function getMemberMetadataRows(member) {
|
|
10422
|
+
const rows = [];
|
|
10423
|
+
for (const key of MEMBER_METADATA_KEYS) {
|
|
10424
|
+
const value = member.metadata[key];
|
|
10425
|
+
if (value === void 0) continue;
|
|
10426
|
+
const formatted = formatMetadataValue(value);
|
|
10427
|
+
if (formatted !== null) rows.push({ key, value: formatted });
|
|
10428
|
+
}
|
|
10429
|
+
return rows;
|
|
10430
|
+
}
|
|
10431
|
+
function SessionMembershipPanel({
|
|
10432
|
+
memberships,
|
|
10433
|
+
defaultOpen = false
|
|
10434
|
+
}) {
|
|
10435
|
+
const [open, setOpen] = reactExports.useState(defaultOpen);
|
|
10436
|
+
if (memberships.length === 0) return null;
|
|
10437
|
+
const primary = memberships[0];
|
|
10438
|
+
const primaryMember = primary?.member ?? null;
|
|
10439
|
+
const score = formatMemberMetadata(primaryMember, "score");
|
|
10440
|
+
const decision = formatMemberMetadata(primaryMember, "decision");
|
|
10441
|
+
const finalStatus = formatMemberMetadata(primaryMember, "final_status");
|
|
10442
|
+
const summaryChips = [
|
|
10443
|
+
score === null ? null : { label: `score ${score}`, value: score },
|
|
10444
|
+
decision === null ? null : { label: decision, value: decision },
|
|
10445
|
+
finalStatus === null ? null : { label: finalStatus, value: finalStatus },
|
|
10446
|
+
primaryMember?.model === null || primaryMember?.model === void 0 ? null : { label: primaryMember.model, value: primaryMember.model }
|
|
10447
|
+
].filter(
|
|
10448
|
+
(value) => value !== null && value.label.length > 0 && value.value.length > 0
|
|
10449
|
+
);
|
|
10450
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-3 overflow-hidden rounded-md border border-border bg-[#0c0d0f] text-xs", children: [
|
|
10451
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
10452
|
+
"button",
|
|
10453
|
+
{
|
|
10454
|
+
type: "button",
|
|
10455
|
+
onClick: () => setOpen((value) => !value),
|
|
10456
|
+
className: "flex w-full items-center gap-3 px-3 py-2 text-left transition-colors hover:bg-muted/30",
|
|
10457
|
+
"aria-expanded": open,
|
|
10458
|
+
children: [
|
|
10459
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
10460
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: [
|
|
10461
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-semibold text-foreground", children: "Case File" }),
|
|
10462
|
+
primary !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate text-muted-foreground", title: primary.groupTitle, children: primary.groupTitle }),
|
|
10463
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono text-[10px] uppercase text-muted-foreground", children: [
|
|
10464
|
+
memberships.length,
|
|
10465
|
+
" group",
|
|
10466
|
+
memberships.length === 1 ? "" : "s"
|
|
10467
|
+
] })
|
|
10468
|
+
] }),
|
|
10469
|
+
summaryChips.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1 flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: summaryChips.slice(0, 4).map((chip) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10470
|
+
"span",
|
|
10471
|
+
{
|
|
10472
|
+
className: cn(
|
|
10473
|
+
"rounded border px-1.5 py-0.5 font-mono text-[10px]",
|
|
10474
|
+
evidenceChipClass(chip.value)
|
|
10475
|
+
),
|
|
10476
|
+
children: chip.label
|
|
10477
|
+
},
|
|
10478
|
+
chip.label
|
|
10479
|
+
)) })
|
|
10480
|
+
] }),
|
|
10481
|
+
open ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronUp, { className: "size-4 shrink-0 text-muted-foreground" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-4 shrink-0 text-muted-foreground" })
|
|
10482
|
+
]
|
|
10483
|
+
}
|
|
10484
|
+
),
|
|
10485
|
+
open && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-2 border-t border-border/70 px-3 py-2", children: memberships.map((membership) => {
|
|
10486
|
+
const member = membership.member;
|
|
10487
|
+
const metadataRows = getMemberMetadataRows(member);
|
|
10488
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0", children: [
|
|
10489
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: [
|
|
10490
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10491
|
+
"span",
|
|
10492
|
+
{
|
|
10493
|
+
className: "truncate font-medium text-foreground",
|
|
10494
|
+
title: membership.groupTitle,
|
|
10495
|
+
children: membership.groupTitle
|
|
10496
|
+
}
|
|
10497
|
+
),
|
|
10498
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-[10px] uppercase text-muted-foreground", children: membership.groupStatus }),
|
|
10499
|
+
member.status !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono text-[10px] text-muted-foreground", children: [
|
|
10500
|
+
"member ",
|
|
10501
|
+
member.status
|
|
10502
|
+
] })
|
|
10503
|
+
] }),
|
|
10504
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-1 flex min-w-0 flex-wrap items-center gap-x-3 gap-y-1 text-muted-foreground", children: [
|
|
10505
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono", title: member.sessionId, children: truncateSessionId(member.sessionId) }),
|
|
10506
|
+
member.label !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: member.label }),
|
|
10507
|
+
member.provider !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: member.provider }),
|
|
10508
|
+
member.model !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono", children: member.model }),
|
|
10509
|
+
member.runId !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono", title: member.runId, children: [
|
|
10510
|
+
"run ",
|
|
10511
|
+
truncateSessionId(member.runId)
|
|
10512
|
+
] })
|
|
10513
|
+
] }),
|
|
10514
|
+
metadataRows.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 grid gap-1 sm:grid-cols-2 xl:grid-cols-3", children: metadataRows.map((row) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
10515
|
+
"div",
|
|
10516
|
+
{
|
|
10517
|
+
className: "min-w-0 rounded border border-border/60 px-2 py-1",
|
|
10518
|
+
children: [
|
|
10519
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-mono text-[10px] text-muted-foreground", children: row.key }),
|
|
10520
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10521
|
+
"div",
|
|
10522
|
+
{
|
|
10523
|
+
className: "truncate font-mono text-[11px] text-foreground",
|
|
10524
|
+
title: row.value,
|
|
10525
|
+
children: row.value
|
|
10526
|
+
}
|
|
10527
|
+
)
|
|
10528
|
+
]
|
|
10529
|
+
},
|
|
10530
|
+
row.key
|
|
10531
|
+
)) })
|
|
10532
|
+
] }, `${membership.groupId}:${member.id}`);
|
|
10533
|
+
}) })
|
|
10534
|
+
] });
|
|
10535
|
+
}
|
|
10536
|
+
function formatPaginationStatus({
|
|
10537
|
+
logs,
|
|
10538
|
+
pagination
|
|
10539
|
+
}) {
|
|
10540
|
+
if (pagination.isLoading && logs.length === 0) return "Loading logs...";
|
|
10541
|
+
if (logs.length === 0) return "No logs on this page";
|
|
10542
|
+
const first = logs[0];
|
|
10543
|
+
const last = logs[logs.length - 1];
|
|
10544
|
+
const range = first === void 0 || last === void 0 ? "Current page" : `#${first.id}-#${last.id}`;
|
|
10545
|
+
const total = pagination.total === null ? "logs" : `${pagination.total} logs`;
|
|
10546
|
+
return `Showing ${range} of ${total}`;
|
|
10547
|
+
}
|
|
10548
|
+
function LogPaginationButton({
|
|
10549
|
+
label,
|
|
10550
|
+
title,
|
|
10551
|
+
icon,
|
|
10552
|
+
disabled,
|
|
10553
|
+
onClick
|
|
10554
|
+
}) {
|
|
10555
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
10556
|
+
"button",
|
|
10557
|
+
{
|
|
10558
|
+
type: "button",
|
|
10559
|
+
onClick,
|
|
10560
|
+
disabled,
|
|
10561
|
+
className: "inline-flex h-8 items-center gap-1.5 rounded-md px-2.5 text-xs text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:cursor-not-allowed disabled:opacity-45",
|
|
10562
|
+
title,
|
|
10563
|
+
children: [
|
|
10564
|
+
icon,
|
|
10565
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: label })
|
|
10566
|
+
]
|
|
10567
|
+
}
|
|
10568
|
+
);
|
|
10569
|
+
}
|
|
10570
|
+
function LogPaginationBar({
|
|
10571
|
+
logs,
|
|
10572
|
+
pagination,
|
|
10573
|
+
embedded = false
|
|
10574
|
+
}) {
|
|
10575
|
+
if (pagination === void 0) return null;
|
|
10576
|
+
const disabled = pagination.isLoading;
|
|
10577
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
10578
|
+
"div",
|
|
10579
|
+
{
|
|
10580
|
+
className: cn(
|
|
10581
|
+
"flex min-h-9 flex-col gap-2 px-1 py-1 sm:flex-row sm:items-center",
|
|
10582
|
+
embedded ? "border-t border-border/70 pt-2" : "mb-3 rounded-md border border-border bg-muted/10 px-2"
|
|
10583
|
+
),
|
|
10584
|
+
children: [
|
|
10585
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full min-w-0 px-1 font-mono text-[11px] text-muted-foreground sm:flex-1", children: [
|
|
10586
|
+
formatPaginationStatus({ logs, pagination }),
|
|
10587
|
+
pagination.isLoading && logs.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ml-2", children: "Loading..." })
|
|
10588
|
+
] }),
|
|
10589
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex w-full items-center gap-1 overflow-x-auto sm:w-auto", children: [
|
|
10590
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10591
|
+
LogPaginationButton,
|
|
10592
|
+
{
|
|
10593
|
+
label: "Oldest",
|
|
10594
|
+
title: "Load the oldest logs in this session",
|
|
10595
|
+
icon: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronsLeft, { className: "size-3.5" }),
|
|
10596
|
+
disabled: disabled || !pagination.hasOlder,
|
|
10597
|
+
onClick: pagination.onOldest
|
|
10598
|
+
}
|
|
10599
|
+
),
|
|
10600
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10601
|
+
LogPaginationButton,
|
|
10602
|
+
{
|
|
10603
|
+
label: "Older",
|
|
10604
|
+
title: "Load older logs",
|
|
10605
|
+
icon: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronLeft, { className: "size-3.5" }),
|
|
10606
|
+
disabled: disabled || !pagination.hasOlder,
|
|
10607
|
+
onClick: pagination.onOlder
|
|
10608
|
+
}
|
|
10609
|
+
),
|
|
10610
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10611
|
+
LogPaginationButton,
|
|
10612
|
+
{
|
|
10613
|
+
label: "Newer",
|
|
10614
|
+
title: "Load newer logs",
|
|
10615
|
+
icon: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-3.5" }),
|
|
10616
|
+
disabled: disabled || !pagination.hasNewer,
|
|
10617
|
+
onClick: pagination.onNewer
|
|
10618
|
+
}
|
|
10619
|
+
),
|
|
10620
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10621
|
+
LogPaginationButton,
|
|
10622
|
+
{
|
|
10623
|
+
label: "Newest",
|
|
10624
|
+
title: "Load the newest logs in this session",
|
|
10625
|
+
icon: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronsRight, { className: "size-3.5" }),
|
|
10626
|
+
disabled: disabled || !pagination.hasNewer,
|
|
10627
|
+
onClick: pagination.onNewest
|
|
10628
|
+
}
|
|
10629
|
+
)
|
|
10630
|
+
] })
|
|
10631
|
+
]
|
|
10632
|
+
}
|
|
10633
|
+
);
|
|
10634
|
+
}
|
|
10301
10635
|
function formatRequestCount(count) {
|
|
10302
10636
|
return `${count} ${count === 1 ? "request" : "requests"}`;
|
|
10303
10637
|
}
|
|
@@ -10383,36 +10717,7 @@ function CopyableCommand({ command }) {
|
|
|
10383
10717
|
onClick: handleCopy,
|
|
10384
10718
|
className: "text-muted-foreground hover:text-foreground transition-colors shrink-0 cursor-pointer",
|
|
10385
10719
|
"aria-label": "Copy command",
|
|
10386
|
-
children: copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10387
|
-
"svg",
|
|
10388
|
-
{
|
|
10389
|
-
width: "16",
|
|
10390
|
-
height: "16",
|
|
10391
|
-
viewBox: "0 0 24 24",
|
|
10392
|
-
fill: "none",
|
|
10393
|
-
stroke: "currentColor",
|
|
10394
|
-
strokeWidth: "2",
|
|
10395
|
-
strokeLinecap: "round",
|
|
10396
|
-
strokeLinejoin: "round",
|
|
10397
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M20 6 9 17l-5-5" })
|
|
10398
|
-
}
|
|
10399
|
-
) : /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
10400
|
-
"svg",
|
|
10401
|
-
{
|
|
10402
|
-
width: "16",
|
|
10403
|
-
height: "16",
|
|
10404
|
-
viewBox: "0 0 24 24",
|
|
10405
|
-
fill: "none",
|
|
10406
|
-
stroke: "currentColor",
|
|
10407
|
-
strokeWidth: "2",
|
|
10408
|
-
strokeLinecap: "round",
|
|
10409
|
-
strokeLinejoin: "round",
|
|
10410
|
-
children: [
|
|
10411
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("rect", { width: "14", height: "14", x: "8", y: "8", rx: "2", ry: "2" }),
|
|
10412
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" })
|
|
10413
|
-
]
|
|
10414
|
-
}
|
|
10415
|
-
)
|
|
10720
|
+
children: copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-4" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-4" })
|
|
10416
10721
|
}
|
|
10417
10722
|
)
|
|
10418
10723
|
] });
|
|
@@ -10427,6 +10732,98 @@ function McpReadyBadge() {
|
|
|
10427
10732
|
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { sideOffset: 8, className: "max-w-[320px] text-left leading-relaxed", children: "Coding agents can inspect logs, replay requests, test providers, and debug sessions through MCP at /api/mcp." })
|
|
10428
10733
|
] }) });
|
|
10429
10734
|
}
|
|
10735
|
+
const CRAB_VARIANT_COLORS = [
|
|
10736
|
+
"text-amber-500",
|
|
10737
|
+
"text-rose-500",
|
|
10738
|
+
"text-sky-500",
|
|
10739
|
+
"text-emerald-500",
|
|
10740
|
+
"text-violet-500",
|
|
10741
|
+
"text-orange-500",
|
|
10742
|
+
"text-cyan-500",
|
|
10743
|
+
"text-pink-500",
|
|
10744
|
+
"text-lime-500",
|
|
10745
|
+
"text-blue-500",
|
|
10746
|
+
"text-yellow-500",
|
|
10747
|
+
"text-fuchsia-500"
|
|
10748
|
+
];
|
|
10749
|
+
function CrabFamily({
|
|
10750
|
+
compact,
|
|
10751
|
+
entrancePhase
|
|
10752
|
+
}) {
|
|
10753
|
+
if (compact) {
|
|
10754
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(CrabLogo, { className: "size-7 text-amber-500" });
|
|
10755
|
+
}
|
|
10756
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex shrink-0 items-end gap-1 group cursor-default", "aria-hidden": "true", children: [
|
|
10757
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(CrabLogo, { className: "size-10 text-amber-500 transition-all duration-300 group-hover:scale-125 group-hover:-translate-y-1.5" }),
|
|
10758
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "hidden items-end gap-0.5 sm:flex", children: crabVariants.map((Crab, i) => {
|
|
10759
|
+
const color = CRAB_VARIANT_COLORS[i] ?? "text-amber-500";
|
|
10760
|
+
const entranceClass = entrancePhase === "hidden" ? "opacity-0 scale-0" : entrancePhase === "playing" ? "animate-crab-piano-pop" : "";
|
|
10761
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10762
|
+
Crab,
|
|
10763
|
+
{
|
|
10764
|
+
className: `size-5 ${color} transition-all duration-300 ease-out group-hover:scale-125 group-hover:-translate-y-1 ${entranceClass}`,
|
|
10765
|
+
style: {
|
|
10766
|
+
transitionDelay: `${i * 50}ms`,
|
|
10767
|
+
...entrancePhase === "playing" ? { animationDelay: `${i * 400}ms` } : {}
|
|
10768
|
+
}
|
|
10769
|
+
},
|
|
10770
|
+
i
|
|
10771
|
+
);
|
|
10772
|
+
}) })
|
|
10773
|
+
] });
|
|
10774
|
+
}
|
|
10775
|
+
function BrandHeader({
|
|
10776
|
+
compact,
|
|
10777
|
+
crabEntrancePhase
|
|
10778
|
+
}) {
|
|
10779
|
+
if (compact) {
|
|
10780
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "pb-3", children: [
|
|
10781
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
|
|
10782
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-start gap-2", children: [
|
|
10783
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(CrabFamily, { compact: true, entrancePhase: crabEntrancePhase }),
|
|
10784
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0", children: [
|
|
10785
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-baseline gap-2", children: [
|
|
10786
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate text-base font-bold", children: "Inspector" }),
|
|
10787
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "hidden shrink-0 font-mono text-[11px] font-semibold text-muted-foreground sm:inline", children: [
|
|
10788
|
+
"v",
|
|
10789
|
+
packageJson.version
|
|
10790
|
+
] })
|
|
10791
|
+
] }),
|
|
10792
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "hidden text-[11px] font-semibold text-muted-foreground sm:block", children: "Local First. Evidence First." })
|
|
10793
|
+
] })
|
|
10794
|
+
] }),
|
|
10795
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [
|
|
10796
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(GroupsDialog, {}),
|
|
10797
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SettingsDialog, {})
|
|
10798
|
+
] })
|
|
10799
|
+
] }),
|
|
10800
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 hidden sm:block", children: /* @__PURE__ */ jsxRuntimeExports.jsx(McpReadyBadge, {}) })
|
|
10801
|
+
] });
|
|
10802
|
+
}
|
|
10803
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-[1fr_auto_1fr] items-start gap-3 pb-6", children: [
|
|
10804
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", {}),
|
|
10805
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("h1", { className: "flex min-w-0 flex-col items-center gap-2 text-center", children: [
|
|
10806
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex max-w-[calc(100vw-7rem)] items-end gap-2 whitespace-nowrap", children: [
|
|
10807
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(CrabFamily, { compact: false, entrancePhase: crabEntrancePhase }),
|
|
10808
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 items-baseline gap-2 pl-1", children: [
|
|
10809
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate text-lg font-bold", children: "Agent Inspector" }),
|
|
10810
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "shrink-0 font-mono text-xs font-semibold text-muted-foreground", children: [
|
|
10811
|
+
"v",
|
|
10812
|
+
packageJson.version
|
|
10813
|
+
] })
|
|
10814
|
+
] }),
|
|
10815
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "size-4 shrink-0 text-muted-foreground/70", "aria-hidden": "true" }),
|
|
10816
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(McpLogo, { className: "size-10 shrink-0" })
|
|
10817
|
+
] }),
|
|
10818
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "max-w-[calc(100vw-7rem)] text-sm font-semibold text-muted-foreground", children: "Local First. Evidence First." }),
|
|
10819
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(McpReadyBadge, {})
|
|
10820
|
+
] }),
|
|
10821
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "justify-self-end flex items-center gap-1", children: [
|
|
10822
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(GroupsDialog, {}),
|
|
10823
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SettingsDialog, {})
|
|
10824
|
+
] })
|
|
10825
|
+
] });
|
|
10826
|
+
}
|
|
10430
10827
|
function SessionContextLogButton({ label, logId }) {
|
|
10431
10828
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
10432
10829
|
"button",
|
|
@@ -10611,6 +11008,15 @@ function SessionContextSummaryPanel({
|
|
|
10611
11008
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "max-h-52 overflow-y-auto pr-1", children: summary.models.map((modelSummary) => /* @__PURE__ */ jsxRuntimeExports.jsx(SessionModelContextRow, { summary: modelSummary }, modelSummary.model)) })
|
|
10612
11009
|
] });
|
|
10613
11010
|
}
|
|
11011
|
+
function formatSessionContextOverview(summary) {
|
|
11012
|
+
const riskCount = summary.models.filter((model) => model.latest.health.level === "risk").length;
|
|
11013
|
+
if (riskCount > 0) return `${riskCount} risk`;
|
|
11014
|
+
const optimizableCount = summary.models.filter(
|
|
11015
|
+
(model) => model.latest.health.level === "optimizable"
|
|
11016
|
+
).length;
|
|
11017
|
+
if (optimizableCount > 0) return `${optimizableCount} optimizable`;
|
|
11018
|
+
return `${summary.models.length} model${summary.models.length === 1 ? "" : "s"}`;
|
|
11019
|
+
}
|
|
10614
11020
|
function SessionContextBar({
|
|
10615
11021
|
label,
|
|
10616
11022
|
logs,
|
|
@@ -10621,11 +11027,16 @@ function SessionContextBar({
|
|
|
10621
11027
|
showBackLink
|
|
10622
11028
|
}) {
|
|
10623
11029
|
const [copied, setCopied] = reactExports.useState(false);
|
|
11030
|
+
const [detailsOpen, setDetailsOpen] = reactExports.useState(false);
|
|
10624
11031
|
const timeRange = reactExports.useMemo(
|
|
10625
11032
|
() => formatTimeRange(logs, timeDisplayFormat),
|
|
10626
11033
|
[logs, timeDisplayFormat]
|
|
10627
11034
|
);
|
|
10628
11035
|
const userAgent = reactExports.useMemo(() => getFirstUserAgent(logs), [logs]);
|
|
11036
|
+
const contextOverview = reactExports.useMemo(
|
|
11037
|
+
() => formatSessionContextOverview(contextSummary),
|
|
11038
|
+
[contextSummary]
|
|
11039
|
+
);
|
|
10629
11040
|
const handleCopyLink = reactExports.useCallback(() => {
|
|
10630
11041
|
void copyTextToClipboard(window.location.href).then((success) => {
|
|
10631
11042
|
if (!success) return;
|
|
@@ -10633,8 +11044,8 @@ function SessionContextBar({
|
|
|
10633
11044
|
setTimeout(() => setCopied(false), 2e3);
|
|
10634
11045
|
});
|
|
10635
11046
|
}, []);
|
|
10636
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-
|
|
10637
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-
|
|
11047
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-3 rounded-md border border-border bg-muted/15 px-3 py-2 text-xs", children: [
|
|
11048
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
10638
11049
|
showBackLink && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10639
11050
|
"a",
|
|
10640
11051
|
{
|
|
@@ -10645,7 +11056,7 @@ function SessionContextBar({
|
|
|
10645
11056
|
children: /* @__PURE__ */ jsxRuntimeExports.jsx(ArrowLeft, { className: "size-3.5" })
|
|
10646
11057
|
}
|
|
10647
11058
|
),
|
|
10648
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-
|
|
11059
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-[180px] flex-1", children: [
|
|
10649
11060
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
10650
11061
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono font-semibold text-purple-400/90 truncate", title: label, children: truncateSessionId(label) }),
|
|
10651
11062
|
userAgent !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -10672,6 +11083,20 @@ function SessionContextBar({
|
|
|
10672
11083
|
] })
|
|
10673
11084
|
] })
|
|
10674
11085
|
] }),
|
|
11086
|
+
contextSummary.models.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
11087
|
+
"button",
|
|
11088
|
+
{
|
|
11089
|
+
type: "button",
|
|
11090
|
+
onClick: () => setDetailsOpen((value) => !value),
|
|
11091
|
+
className: "inline-flex h-8 shrink-0 items-center gap-1.5 rounded-md border border-border bg-background/60 px-2.5 font-mono text-[11px] text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
11092
|
+
"aria-expanded": detailsOpen,
|
|
11093
|
+
title: detailsOpen ? "Hide context details" : "Show context details",
|
|
11094
|
+
children: [
|
|
11095
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: contextOverview }),
|
|
11096
|
+
detailsOpen ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronUp, { className: "size-3.5" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-3.5" })
|
|
11097
|
+
]
|
|
11098
|
+
}
|
|
11099
|
+
),
|
|
10675
11100
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10676
11101
|
"button",
|
|
10677
11102
|
{
|
|
@@ -10684,7 +11109,7 @@ function SessionContextBar({
|
|
|
10684
11109
|
}
|
|
10685
11110
|
)
|
|
10686
11111
|
] }),
|
|
10687
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(SessionContextSummaryPanel, { summary: contextSummary })
|
|
11112
|
+
detailsOpen && /* @__PURE__ */ jsxRuntimeExports.jsx(SessionContextSummaryPanel, { summary: contextSummary })
|
|
10688
11113
|
] });
|
|
10689
11114
|
}
|
|
10690
11115
|
function ProxyViewer({
|
|
@@ -10703,6 +11128,9 @@ function ProxyViewer({
|
|
|
10703
11128
|
strip,
|
|
10704
11129
|
slowResponseThresholdSeconds,
|
|
10705
11130
|
timeDisplayFormat,
|
|
11131
|
+
isLoading = false,
|
|
11132
|
+
pagination,
|
|
11133
|
+
sessionMemberships = [],
|
|
10706
11134
|
hideSessionFilter = false,
|
|
10707
11135
|
pinnedSessionId
|
|
10708
11136
|
}) {
|
|
@@ -10775,6 +11203,17 @@ function ProxyViewer({
|
|
|
10775
11203
|
const cacheTrends = reactExports.useMemo(() => computeCacheTrends(groups), [groups]);
|
|
10776
11204
|
const comparisonPredecessors = reactExports.useMemo(() => buildValidPredecessors(groups), [groups]);
|
|
10777
11205
|
const exportActionVisibility = getExportActionVisibility(captureMode, logs.length);
|
|
11206
|
+
const isPinnedSessionPage = pinnedSessionId !== void 0;
|
|
11207
|
+
const activeScopeLabel = hasSessionContext && sessionContextScope !== null ? truncateSessionId(sessionContextScope.label) : selectedSession === "__all__" ? "All sessions" : truncateSessionId(selectedSession);
|
|
11208
|
+
const slateStats = reactExports.useMemo(
|
|
11209
|
+
() => buildSessionSlateStats({
|
|
11210
|
+
logs,
|
|
11211
|
+
isLoading,
|
|
11212
|
+
timeDisplayFormat,
|
|
11213
|
+
slowResponseThresholdSeconds
|
|
11214
|
+
}),
|
|
11215
|
+
[isLoading, logs, slowResponseThresholdSeconds, timeDisplayFormat]
|
|
11216
|
+
);
|
|
10778
11217
|
const handleCompareWithPrevious = reactExports.useCallback(
|
|
10779
11218
|
(log) => {
|
|
10780
11219
|
const predecessor = comparisonPredecessors.get(log.id);
|
|
@@ -10782,218 +11221,207 @@ function ProxyViewer({
|
|
|
10782
11221
|
},
|
|
10783
11222
|
[comparisonPredecessors]
|
|
10784
11223
|
);
|
|
10785
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "
|
|
10786
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "
|
|
10787
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
10788
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10789
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("
|
|
10790
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("
|
|
11224
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-h-screen bg-[#070809] text-foreground", children: [
|
|
11225
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mx-auto grid min-h-screen max-w-[1920px] grid-cols-1 lg:grid-cols-[340px_minmax(0,1fr)] xl:grid-cols-[360px_minmax(0,1fr)]", children: [
|
|
11226
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("aside", { className: "border-b border-border bg-[#090a0c] lg:sticky lg:top-0 lg:h-screen lg:overflow-y-auto lg:border-b-0 lg:border-r", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4 p-4", children: [
|
|
11227
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(BrandHeader, { compact: true, crabEntrancePhase }),
|
|
11228
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-3 gap-2 border-y border-border/70 py-3", children: [
|
|
11229
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0", children: [
|
|
11230
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-mono text-lg font-semibold text-foreground", children: logs.length }),
|
|
11231
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[10px] uppercase text-muted-foreground", children: "Requests" })
|
|
11232
|
+
] }),
|
|
11233
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0", children: [
|
|
11234
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-mono text-lg font-semibold text-foreground", children: formatTokens(hasSessionContext ? sessionContextTotalIn : totalIn) }),
|
|
11235
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[10px] uppercase text-muted-foreground", children: "Input" })
|
|
11236
|
+
] }),
|
|
11237
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0", children: [
|
|
11238
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-mono text-lg font-semibold text-foreground", children: formatTokens(hasSessionContext ? sessionContextTotalOut : totalOut) }),
|
|
11239
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[10px] uppercase text-muted-foreground", children: "Output" })
|
|
11240
|
+
] })
|
|
11241
|
+
] }),
|
|
11242
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
|
|
11243
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[10px] font-semibold uppercase tracking-normal text-muted-foreground", children: "Workspace" }),
|
|
11244
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-md border border-border bg-[#0c0d0f] px-3 py-2", children: [
|
|
11245
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
11246
|
+
"div",
|
|
11247
|
+
{
|
|
11248
|
+
className: "font-mono text-xs font-semibold text-purple-300",
|
|
11249
|
+
title: activeScopeLabel,
|
|
11250
|
+
children: activeScopeLabel
|
|
11251
|
+
}
|
|
11252
|
+
),
|
|
11253
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1 text-[11px] text-muted-foreground", children: isPinnedSessionPage ? "Session workspace" : "Live workspace" })
|
|
11254
|
+
] })
|
|
11255
|
+
] }),
|
|
11256
|
+
hasSessionContext && sessionContextScope !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
11257
|
+
SessionContextBar,
|
|
11258
|
+
{
|
|
11259
|
+
label: sessionContextScope.label,
|
|
11260
|
+
logs: sessionContextLogs,
|
|
11261
|
+
totalIn: sessionContextTotalIn,
|
|
11262
|
+
totalOut: sessionContextTotalOut,
|
|
11263
|
+
timeDisplayFormat,
|
|
11264
|
+
contextSummary: sessionContextSummary,
|
|
11265
|
+
showBackLink: sessionContextScope.showBackLink
|
|
11266
|
+
}
|
|
11267
|
+
),
|
|
11268
|
+
hasSessionContext && pinnedSessionId !== void 0 && sessionMemberships.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(SessionMembershipPanel, { memberships: sessionMemberships }),
|
|
11269
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
|
|
11270
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[10px] font-semibold uppercase tracking-normal text-muted-foreground", children: "Filters" }),
|
|
11271
|
+
!hideSessionFilter && /* @__PURE__ */ jsxRuntimeExports.jsxs(Select, { value: selectedSession, onValueChange: onSessionChange, children: [
|
|
11272
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectTrigger, { className: "h-9 w-full text-xs", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue, { placeholder: "All sessions" }) }),
|
|
11273
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(SelectContent, { children: [
|
|
11274
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: "__all__", children: "All sessions" }),
|
|
11275
|
+
sessions.map((s) => /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: s, children: truncateSessionId(s) }, s))
|
|
11276
|
+
] })
|
|
11277
|
+
] }),
|
|
11278
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(Select, { value: selectedModel, onValueChange: onModelChange, children: [
|
|
11279
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectTrigger, { className: "h-9 w-full text-xs", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue, { placeholder: "All models" }) }),
|
|
11280
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(SelectContent, { children: [
|
|
11281
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: "__all__", children: "All models" }),
|
|
11282
|
+
models.map((m) => /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: m, children: m }, m))
|
|
11283
|
+
] })
|
|
11284
|
+
] }),
|
|
11285
|
+
captureMode === "full" ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid h-9 grid-cols-2 overflow-hidden rounded-md border border-border", children: [
|
|
11286
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
11287
|
+
"button",
|
|
11288
|
+
{
|
|
11289
|
+
type: "button",
|
|
11290
|
+
onClick: () => onViewModeChange("simple"),
|
|
11291
|
+
className: cn(
|
|
11292
|
+
"text-xs transition-colors",
|
|
11293
|
+
viewMode === "simple" ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted/50"
|
|
11294
|
+
),
|
|
11295
|
+
children: "Simple"
|
|
11296
|
+
}
|
|
11297
|
+
),
|
|
11298
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
11299
|
+
"button",
|
|
11300
|
+
{
|
|
11301
|
+
type: "button",
|
|
11302
|
+
onClick: () => onViewModeChange("full"),
|
|
11303
|
+
className: cn(
|
|
11304
|
+
"text-xs transition-colors",
|
|
11305
|
+
viewMode === "full" ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted/50"
|
|
11306
|
+
),
|
|
11307
|
+
children: "Full"
|
|
11308
|
+
}
|
|
11309
|
+
)
|
|
11310
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex h-9 items-center rounded-md border border-border bg-muted px-3 text-xs text-foreground", children: "Simple" })
|
|
11311
|
+
] })
|
|
11312
|
+
] }) }),
|
|
11313
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("main", { className: "min-w-0", children: [
|
|
11314
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sticky top-0 z-30 border-b border-border bg-[#08090b]/95 px-4 py-3 shadow-[0_12px_40px_rgba(0,0,0,0.24)] backdrop-blur lg:px-5", children: [
|
|
11315
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
11316
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-[180px] flex-1", children: [
|
|
11317
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm font-semibold text-foreground", children: "Logs" }),
|
|
11318
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-0.5 font-mono text-[11px] text-muted-foreground", children: activeScopeLabel })
|
|
11319
|
+
] }),
|
|
11320
|
+
exportActionVisibility.redacted && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
11321
|
+
"button",
|
|
11322
|
+
{
|
|
11323
|
+
type: "button",
|
|
11324
|
+
onClick: () => {
|
|
11325
|
+
void handleExport("redacted");
|
|
11326
|
+
},
|
|
11327
|
+
disabled: exporting !== null,
|
|
11328
|
+
className: "inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
|
11329
|
+
title: "Export redacted logs as JSON ZIP",
|
|
11330
|
+
children: exporting === "redacted" ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Exporting..." }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
11331
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Download, { className: "size-3.5" }),
|
|
11332
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Export" })
|
|
11333
|
+
] })
|
|
11334
|
+
}
|
|
11335
|
+
),
|
|
11336
|
+
exportActionVisibility.raw && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
11337
|
+
"button",
|
|
11338
|
+
{
|
|
11339
|
+
type: "button",
|
|
11340
|
+
onClick: () => {
|
|
11341
|
+
void handleExport("raw");
|
|
11342
|
+
},
|
|
11343
|
+
disabled: exporting !== null,
|
|
11344
|
+
className: "inline-flex h-8 items-center gap-1.5 rounded-md px-2.5 text-xs text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
|
11345
|
+
title: "Export raw logs without redaction",
|
|
11346
|
+
children: exporting === "raw" ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Exporting..." }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
11347
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(FileBraces, { className: "size-3.5" }),
|
|
11348
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Raw" })
|
|
11349
|
+
] })
|
|
11350
|
+
}
|
|
11351
|
+
),
|
|
10791
11352
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
10792
|
-
"
|
|
11353
|
+
"button",
|
|
10793
11354
|
{
|
|
10794
|
-
|
|
10795
|
-
|
|
11355
|
+
type: "button",
|
|
11356
|
+
onClick: onClearAll,
|
|
11357
|
+
className: "inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
11358
|
+
title: "Clear all logs",
|
|
10796
11359
|
children: [
|
|
10797
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10798
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", {
|
|
10799
|
-
const color = [
|
|
10800
|
-
"text-amber-500",
|
|
10801
|
-
"text-rose-500",
|
|
10802
|
-
"text-sky-500",
|
|
10803
|
-
"text-emerald-500",
|
|
10804
|
-
"text-violet-500",
|
|
10805
|
-
"text-orange-500",
|
|
10806
|
-
"text-cyan-500",
|
|
10807
|
-
"text-pink-500",
|
|
10808
|
-
"text-lime-500",
|
|
10809
|
-
"text-blue-500",
|
|
10810
|
-
"text-yellow-500",
|
|
10811
|
-
"text-fuchsia-500"
|
|
10812
|
-
][i];
|
|
10813
|
-
const entranceClass = crabEntrancePhase === "hidden" ? "opacity-0 scale-0" : crabEntrancePhase === "playing" ? "animate-crab-piano-pop" : "";
|
|
10814
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10815
|
-
Crab,
|
|
10816
|
-
{
|
|
10817
|
-
className: `size-5 ${color} transition-all duration-300 ease-out group-hover:scale-125 group-hover:-translate-y-1 ${entranceClass}`,
|
|
10818
|
-
style: {
|
|
10819
|
-
transitionDelay: `${i * 50}ms`,
|
|
10820
|
-
...crabEntrancePhase === "playing" ? { animationDelay: `${i * 400}ms` } : {}
|
|
10821
|
-
}
|
|
10822
|
-
},
|
|
10823
|
-
i
|
|
10824
|
-
);
|
|
10825
|
-
}) })
|
|
11360
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" }),
|
|
11361
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Clear" })
|
|
10826
11362
|
]
|
|
10827
11363
|
}
|
|
10828
|
-
)
|
|
10829
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 items-baseline gap-2 pl-1", children: [
|
|
10830
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate text-lg font-bold", children: "Agent Inspector" }),
|
|
10831
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "shrink-0 font-mono text-xs font-semibold text-muted-foreground", children: [
|
|
10832
|
-
"v",
|
|
10833
|
-
packageJson.version
|
|
10834
|
-
] })
|
|
10835
|
-
] }),
|
|
10836
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "size-4 shrink-0 text-muted-foreground/70", "aria-hidden": "true" }),
|
|
10837
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(McpLogo, { className: "size-10 shrink-0" })
|
|
11364
|
+
)
|
|
10838
11365
|
] }),
|
|
10839
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10840
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10841
|
-
] }),
|
|
10842
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "justify-self-end flex items-center gap-1", children: [
|
|
10843
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(GroupsDialog, {}),
|
|
10844
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(SettingsDialog, {})
|
|
10845
|
-
] })
|
|
10846
|
-
] }),
|
|
10847
|
-
hasSessionContext && sessionContextScope !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10848
|
-
SessionContextBar,
|
|
10849
|
-
{
|
|
10850
|
-
label: sessionContextScope.label,
|
|
10851
|
-
logs: sessionContextLogs,
|
|
10852
|
-
totalIn: sessionContextTotalIn,
|
|
10853
|
-
totalOut: sessionContextTotalOut,
|
|
10854
|
-
timeDisplayFormat,
|
|
10855
|
-
contextSummary: sessionContextSummary,
|
|
10856
|
-
showBackLink: sessionContextScope.showBackLink
|
|
10857
|
-
}
|
|
10858
|
-
),
|
|
10859
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3 mb-4", children: [
|
|
10860
|
-
!hideSessionFilter && /* @__PURE__ */ jsxRuntimeExports.jsxs(Select, { value: selectedSession, onValueChange: onSessionChange, children: [
|
|
10861
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectTrigger, { className: "flex-1 max-w-[350px] text-xs", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue, { placeholder: "All sessions" }) }),
|
|
10862
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(SelectContent, { children: [
|
|
10863
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: "__all__", children: "All sessions" }),
|
|
10864
|
-
sessions.map((s) => /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: s, children: truncateSessionId(s) }, s))
|
|
10865
|
-
] })
|
|
11366
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(LogPaginationBar, { logs, pagination, embedded: true }),
|
|
11367
|
+
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 })
|
|
10866
11368
|
] }),
|
|
10867
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
10868
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10869
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
10870
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10871
|
-
|
|
10872
|
-
|
|
10873
|
-
|
|
10874
|
-
|
|
10875
|
-
|
|
10876
|
-
|
|
10877
|
-
|
|
10878
|
-
|
|
10879
|
-
|
|
10880
|
-
|
|
10881
|
-
|
|
10882
|
-
|
|
10883
|
-
|
|
10884
|
-
|
|
10885
|
-
|
|
11369
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-4 lg:px-5", children: [
|
|
11370
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SessionOpeningSlate, { stats: slateStats }),
|
|
11371
|
+
logs.length === 0 ? selectedSession !== "__all__" ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "py-16 text-center text-muted-foreground", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mx-auto max-w-xl space-y-4 rounded-md border border-border bg-muted/10 px-4 py-8", children: [
|
|
11372
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-medium", children: isLoading ? "Loading session data..." : "Session not found" }),
|
|
11373
|
+
/* @__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) }),
|
|
11374
|
+
sessionMemberships.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-left", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SessionMembershipPanel, { memberships: sessionMemberships }) }),
|
|
11375
|
+
!isLoading && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-xs", children: [
|
|
11376
|
+
"This session may have been cleared or never existed.",
|
|
11377
|
+
" ",
|
|
11378
|
+
hideSessionFilter ? /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "/", className: "underline transition-colors hover:text-foreground", children: "Back to all sessions" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
11379
|
+
"button",
|
|
11380
|
+
{
|
|
11381
|
+
type: "button",
|
|
11382
|
+
onClick: () => onSessionChange("__all__"),
|
|
11383
|
+
className: "underline transition-colors hover:text-foreground",
|
|
11384
|
+
children: "Show all sessions"
|
|
11385
|
+
}
|
|
11386
|
+
)
|
|
11387
|
+
] })
|
|
11388
|
+
] }) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "py-16 text-center text-muted-foreground", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mx-auto max-w-2xl space-y-4 rounded-md border border-border bg-muted/10 px-4 py-8", children: [
|
|
11389
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm", children: "No requests captured yet." }),
|
|
11390
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center gap-2", children: [
|
|
11391
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(CopyableCommand, { command: "ANTHROPIC_BASE_URL=http://localhost:25947/proxy <your-tool>" }),
|
|
11392
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(CopyableCommand, { command: "OPENAI_BASE_URL=http://localhost:25947/proxy <your-tool>" })
|
|
11393
|
+
] }),
|
|
11394
|
+
/* @__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." })
|
|
11395
|
+
] }) }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
11396
|
+
"div",
|
|
10886
11397
|
{
|
|
10887
|
-
|
|
10888
|
-
|
|
10889
|
-
className:
|
|
10890
|
-
children:
|
|
11398
|
+
ref: logListWrapperRef,
|
|
11399
|
+
tabIndex: 0,
|
|
11400
|
+
className: "flex flex-col gap-2 focus:outline-none",
|
|
11401
|
+
children: [
|
|
11402
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: logListRef, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
11403
|
+
ConversationGroupList,
|
|
11404
|
+
{
|
|
11405
|
+
groups,
|
|
11406
|
+
viewMode,
|
|
11407
|
+
strip,
|
|
11408
|
+
slowResponseThresholdSeconds,
|
|
11409
|
+
cacheTrends,
|
|
11410
|
+
onCompareWithPrevious: handleCompareWithPrevious,
|
|
11411
|
+
comparisonPredecessors,
|
|
11412
|
+
onClearGroup,
|
|
11413
|
+
standalone: groups.length === 1,
|
|
11414
|
+
hasPinnedSessionContext: hasSessionContext,
|
|
11415
|
+
timeDisplayFormat
|
|
11416
|
+
}
|
|
11417
|
+
) }),
|
|
11418
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-3", children: /* @__PURE__ */ jsxRuntimeExports.jsx(LogPaginationBar, { logs, pagination }) })
|
|
11419
|
+
]
|
|
10891
11420
|
}
|
|
10892
11421
|
)
|
|
10893
|
-
] })
|
|
10894
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1" }),
|
|
10895
|
-
!hasSessionContext && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground text-xs font-mono", children: [
|
|
10896
|
-
logs.length,
|
|
10897
|
-
" request",
|
|
10898
|
-
logs.length !== 1 ? "s" : "",
|
|
10899
|
-
totalIn > 0 || totalOut > 0 ? ` - ${formatTokens(totalIn)} in / ${formatTokens(totalOut)} out` : ""
|
|
10900
|
-
] }),
|
|
10901
|
-
exportActionVisibility.redacted && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10902
|
-
"button",
|
|
10903
|
-
{
|
|
10904
|
-
type: "button",
|
|
10905
|
-
onClick: () => {
|
|
10906
|
-
void handleExport("redacted");
|
|
10907
|
-
},
|
|
10908
|
-
disabled: exporting !== null,
|
|
10909
|
-
className: "h-8 px-3 text-xs text-muted-foreground hover:text-foreground transition-colors cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed inline-flex items-center gap-1.5 rounded-md hover:bg-muted",
|
|
10910
|
-
title: "Export redacted logs as JSON ZIP",
|
|
10911
|
-
children: exporting === "redacted" ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Exporting..." }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
10912
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(Download, { className: "size-3.5" }),
|
|
10913
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Export" })
|
|
10914
|
-
] })
|
|
10915
|
-
}
|
|
10916
|
-
),
|
|
10917
|
-
exportActionVisibility.raw && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10918
|
-
"button",
|
|
10919
|
-
{
|
|
10920
|
-
type: "button",
|
|
10921
|
-
onClick: () => {
|
|
10922
|
-
void handleExport("raw");
|
|
10923
|
-
},
|
|
10924
|
-
disabled: exporting !== null,
|
|
10925
|
-
className: "h-8 px-2.5 text-xs text-muted-foreground hover:text-foreground transition-colors cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed inline-flex items-center gap-1.5 rounded-md hover:bg-muted",
|
|
10926
|
-
title: "Export raw logs without redaction",
|
|
10927
|
-
children: exporting === "raw" ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Exporting..." }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
10928
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(FileBraces, { className: "size-3.5" }),
|
|
10929
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Raw" })
|
|
10930
|
-
] })
|
|
10931
|
-
}
|
|
10932
|
-
),
|
|
10933
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
10934
|
-
"button",
|
|
10935
|
-
{
|
|
10936
|
-
type: "button",
|
|
10937
|
-
onClick: onClearAll,
|
|
10938
|
-
className: "h-8 px-3 text-xs text-muted-foreground hover:text-foreground transition-colors cursor-pointer inline-flex items-center gap-1.5 rounded-md hover:bg-muted",
|
|
10939
|
-
title: "Clear all logs",
|
|
10940
|
-
children: [
|
|
10941
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "size-3.5" }),
|
|
10942
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Clear" })
|
|
10943
|
-
]
|
|
10944
|
-
}
|
|
10945
|
-
)
|
|
10946
|
-
] }),
|
|
10947
|
-
exportError !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-4 rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-xs text-destructive", children: exportError })
|
|
10948
|
-
] }),
|
|
10949
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: logs.length === 0 ? selectedSession !== "__all__" ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center text-muted-foreground py-16 space-y-4", children: [
|
|
10950
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-medium", children: "Session not found" }),
|
|
10951
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs font-mono bg-muted px-3 py-1 rounded inline-block max-w-[500px] break-all", children: truncateSessionId(selectedSession) }),
|
|
10952
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-xs", children: [
|
|
10953
|
-
"This session may have been cleared or never existed.",
|
|
10954
|
-
" ",
|
|
10955
|
-
hideSessionFilter ? /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "/", className: "underline hover:text-foreground transition-colors", children: "Back to all sessions" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10956
|
-
"button",
|
|
10957
|
-
{
|
|
10958
|
-
type: "button",
|
|
10959
|
-
onClick: () => onSessionChange("__all__"),
|
|
10960
|
-
className: "underline hover:text-foreground transition-colors",
|
|
10961
|
-
children: "Show all sessions"
|
|
10962
|
-
}
|
|
10963
|
-
)
|
|
11422
|
+
] })
|
|
10964
11423
|
] })
|
|
10965
|
-
] })
|
|
10966
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm", children: "No requests captured yet." }),
|
|
10967
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs", children: "Route AI coding tools through the proxy:" }),
|
|
10968
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center gap-2", children: [
|
|
10969
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(CopyableCommand, { command: "ANTHROPIC_BASE_URL=http://localhost:25947/proxy <your-tool>" }),
|
|
10970
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(CopyableCommand, { command: "OPENAI_BASE_URL=http://localhost:25947/proxy <your-tool>" })
|
|
10971
|
-
] }),
|
|
10972
|
-
/* @__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." })
|
|
10973
|
-
] }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10974
|
-
"div",
|
|
10975
|
-
{
|
|
10976
|
-
ref: logListWrapperRef,
|
|
10977
|
-
tabIndex: 0,
|
|
10978
|
-
className: "flex flex-col gap-2 focus:outline-none",
|
|
10979
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: logListRef, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
10980
|
-
ConversationGroupList,
|
|
10981
|
-
{
|
|
10982
|
-
groups,
|
|
10983
|
-
viewMode,
|
|
10984
|
-
strip,
|
|
10985
|
-
slowResponseThresholdSeconds,
|
|
10986
|
-
cacheTrends,
|
|
10987
|
-
onCompareWithPrevious: handleCompareWithPrevious,
|
|
10988
|
-
comparisonPredecessors,
|
|
10989
|
-
onClearGroup,
|
|
10990
|
-
standalone: groups.length === 1,
|
|
10991
|
-
hasPinnedSessionContext: hasSessionContext,
|
|
10992
|
-
timeDisplayFormat
|
|
10993
|
-
}
|
|
10994
|
-
) })
|
|
10995
|
-
}
|
|
10996
|
-
) }),
|
|
11424
|
+
] }),
|
|
10997
11425
|
comparePair !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntimeExports.jsx(LazyCompareDrawer, { left: comparePair[0], right: comparePair[1], onClose: closeCompare }) })
|
|
10998
11426
|
] });
|
|
10999
11427
|
}
|
|
@@ -11007,6 +11435,34 @@ const SSEUpdateSchema = union([
|
|
|
11007
11435
|
log: CapturedLogSchema
|
|
11008
11436
|
})
|
|
11009
11437
|
]);
|
|
11438
|
+
const LogCursorPageSchema = object({
|
|
11439
|
+
logs: array(CapturedLogSchema),
|
|
11440
|
+
total: number().int().nonnegative(),
|
|
11441
|
+
limit: number().int().positive(),
|
|
11442
|
+
hasOlder: boolean(),
|
|
11443
|
+
hasNewer: boolean(),
|
|
11444
|
+
oldestLogId: number().int().positive().nullable(),
|
|
11445
|
+
newestLogId: number().int().positive().nullable()
|
|
11446
|
+
});
|
|
11447
|
+
function buildSessionMembershipEvidence(groups, sessionId) {
|
|
11448
|
+
const memberships = [];
|
|
11449
|
+
for (const group of groups) {
|
|
11450
|
+
for (const member of group.members) {
|
|
11451
|
+
if (member.sessionId !== sessionId) continue;
|
|
11452
|
+
memberships.push({
|
|
11453
|
+
groupId: group.id,
|
|
11454
|
+
groupTitle: group.title,
|
|
11455
|
+
groupKind: group.kind,
|
|
11456
|
+
groupStatus: group.status,
|
|
11457
|
+
groupTask: group.task,
|
|
11458
|
+
groupProject: group.project,
|
|
11459
|
+
groupEvidence: group.evidence,
|
|
11460
|
+
member
|
|
11461
|
+
});
|
|
11462
|
+
}
|
|
11463
|
+
}
|
|
11464
|
+
return memberships;
|
|
11465
|
+
}
|
|
11010
11466
|
function extractSessions(logs) {
|
|
11011
11467
|
const set = /* @__PURE__ */ new Set();
|
|
11012
11468
|
for (const l of logs) {
|
|
@@ -11033,10 +11489,35 @@ const DEBOUNCE_MS = 50;
|
|
|
11033
11489
|
const HASH_SCROLL_ATTEMPTS = 12;
|
|
11034
11490
|
const HASH_HIGHLIGHT_MS = 1800;
|
|
11035
11491
|
const MAX_CLIENT_LOGS = 500;
|
|
11492
|
+
const SESSION_PAGE_LIMIT = 100;
|
|
11036
11493
|
function buildLogsStreamUrl(sessionId) {
|
|
11037
|
-
|
|
11038
|
-
|
|
11039
|
-
|
|
11494
|
+
const params = new URLSearchParams();
|
|
11495
|
+
if (sessionId !== void 0) {
|
|
11496
|
+
params.set("sessionId", sessionId);
|
|
11497
|
+
params.set("compact", "1");
|
|
11498
|
+
}
|
|
11499
|
+
const query = params.toString();
|
|
11500
|
+
return query.length > 0 ? `/api/logs/stream?${query}` : "/api/logs/stream";
|
|
11501
|
+
}
|
|
11502
|
+
function buildSessionLogsPageUrl(sessionId, request) {
|
|
11503
|
+
const params = new URLSearchParams({
|
|
11504
|
+
cursor: "1",
|
|
11505
|
+
compact: "1",
|
|
11506
|
+
limit: String(SESSION_PAGE_LIMIT),
|
|
11507
|
+
sessionId
|
|
11508
|
+
});
|
|
11509
|
+
switch (request.kind) {
|
|
11510
|
+
case "oldest":
|
|
11511
|
+
params.set("anchor", "oldest");
|
|
11512
|
+
break;
|
|
11513
|
+
case "older":
|
|
11514
|
+
params.set("beforeLogId", String(request.beforeLogId));
|
|
11515
|
+
break;
|
|
11516
|
+
case "newer":
|
|
11517
|
+
params.set("afterLogId", String(request.afterLogId));
|
|
11518
|
+
break;
|
|
11519
|
+
}
|
|
11520
|
+
return `/api/logs?${params.toString()}`;
|
|
11040
11521
|
}
|
|
11041
11522
|
function buildLogIndex(logs) {
|
|
11042
11523
|
const idx = /* @__PURE__ */ new Map();
|
|
@@ -11058,9 +11539,14 @@ function ProxyViewerContainer({
|
|
|
11058
11539
|
const [selectedModel, setSelectedModel] = reactExports.useState("__all__");
|
|
11059
11540
|
const [viewMode, setViewMode] = reactExports.useState("simple");
|
|
11060
11541
|
const [error, setError] = reactExports.useState(null);
|
|
11542
|
+
const [streamInitialized, setStreamInitialized] = reactExports.useState(initialSessionId === void 0);
|
|
11543
|
+
const [logPage, setLogPage] = reactExports.useState(null);
|
|
11544
|
+
const [sessionPageLoading, setSessionPageLoading] = reactExports.useState(initialSessionId !== void 0);
|
|
11545
|
+
const [sessionMemberships, setSessionMemberships] = reactExports.useState([]);
|
|
11061
11546
|
const eventSourceRef = reactExports.useRef(null);
|
|
11062
11547
|
const reconnectTimeoutRef = reactExports.useRef(null);
|
|
11063
11548
|
const handledHashRef = reactExports.useRef(null);
|
|
11549
|
+
const sessionPageRequestIdRef = reactExports.useRef(0);
|
|
11064
11550
|
const logIndexRef = reactExports.useRef(/* @__PURE__ */ new Map());
|
|
11065
11551
|
const pendingUpdatesRef = reactExports.useRef([]);
|
|
11066
11552
|
const flushTimerRef = reactExports.useRef(null);
|
|
@@ -11104,6 +11590,7 @@ function ProxyViewerContainer({
|
|
|
11104
11590
|
if (eventSourceRef.current) {
|
|
11105
11591
|
eventSourceRef.current.close();
|
|
11106
11592
|
}
|
|
11593
|
+
setStreamInitialized(false);
|
|
11107
11594
|
const es = new EventSource(buildLogsStreamUrl(initialSessionId));
|
|
11108
11595
|
eventSourceRef.current = es;
|
|
11109
11596
|
es.onmessage = (event) => {
|
|
@@ -11125,6 +11612,7 @@ function ProxyViewerContainer({
|
|
|
11125
11612
|
const nextLogs = trimClientLogs(update.logs);
|
|
11126
11613
|
logIndexRef.current = buildLogIndex(nextLogs);
|
|
11127
11614
|
setAllLogs(nextLogs);
|
|
11615
|
+
setStreamInitialized(true);
|
|
11128
11616
|
setError(null);
|
|
11129
11617
|
} else if (update.type === "update") {
|
|
11130
11618
|
scheduleUpdate(update.log);
|
|
@@ -11135,6 +11623,7 @@ function ProxyViewerContainer({
|
|
|
11135
11623
|
};
|
|
11136
11624
|
es.onerror = () => {
|
|
11137
11625
|
setError("SSE connection lost, reconnecting...");
|
|
11626
|
+
setStreamInitialized(true);
|
|
11138
11627
|
es.close();
|
|
11139
11628
|
if (reconnectTimeoutRef.current !== null) {
|
|
11140
11629
|
clearTimeout(reconnectTimeoutRef.current);
|
|
@@ -11142,7 +11631,59 @@ function ProxyViewerContainer({
|
|
|
11142
11631
|
reconnectTimeoutRef.current = setTimeout(connectSSE, 3e3);
|
|
11143
11632
|
};
|
|
11144
11633
|
}, [initialSessionId, scheduleUpdate]);
|
|
11634
|
+
const loadSessionPage = reactExports.useCallback(
|
|
11635
|
+
(request) => {
|
|
11636
|
+
if (initialSessionId === void 0) return;
|
|
11637
|
+
const requestId = sessionPageRequestIdRef.current + 1;
|
|
11638
|
+
sessionPageRequestIdRef.current = requestId;
|
|
11639
|
+
setSessionPageLoading(true);
|
|
11640
|
+
setError(null);
|
|
11641
|
+
void fetchJson(buildSessionLogsPageUrl(initialSessionId, request), LogCursorPageSchema).then((page) => {
|
|
11642
|
+
if (sessionPageRequestIdRef.current !== requestId) return;
|
|
11643
|
+
const nextLogs = page.logs;
|
|
11644
|
+
logIndexRef.current = buildLogIndex(nextLogs);
|
|
11645
|
+
setAllLogs(nextLogs);
|
|
11646
|
+
setLogPage(page);
|
|
11647
|
+
setSelectedSession(initialSessionId);
|
|
11648
|
+
setSessionPageLoading(false);
|
|
11649
|
+
setError(null);
|
|
11650
|
+
}).catch((err) => {
|
|
11651
|
+
if (sessionPageRequestIdRef.current !== requestId) return;
|
|
11652
|
+
setAllLogs([]);
|
|
11653
|
+
setLogPage(null);
|
|
11654
|
+
setSessionPageLoading(false);
|
|
11655
|
+
setError(err instanceof Error ? err.message : "Failed to load session logs");
|
|
11656
|
+
});
|
|
11657
|
+
},
|
|
11658
|
+
[initialSessionId]
|
|
11659
|
+
);
|
|
11145
11660
|
reactExports.useEffect(() => {
|
|
11661
|
+
if (initialSessionId === void 0) {
|
|
11662
|
+
setSessionMemberships([]);
|
|
11663
|
+
return;
|
|
11664
|
+
}
|
|
11665
|
+
let cancelled = false;
|
|
11666
|
+
void fetch("/api/groups").then(async (response) => {
|
|
11667
|
+
if (!response.ok) return null;
|
|
11668
|
+
const raw = await response.json();
|
|
11669
|
+
const parsed = InspectorGroupsListResponseSchema.safeParse(raw);
|
|
11670
|
+
return parsed.success ? parsed.data.groups : null;
|
|
11671
|
+
}).then((groups) => {
|
|
11672
|
+
if (cancelled || groups === null) return;
|
|
11673
|
+
setSessionMemberships(buildSessionMembershipEvidence(groups, initialSessionId));
|
|
11674
|
+
}).catch(() => {
|
|
11675
|
+
if (!cancelled) setSessionMemberships([]);
|
|
11676
|
+
});
|
|
11677
|
+
return () => {
|
|
11678
|
+
cancelled = true;
|
|
11679
|
+
};
|
|
11680
|
+
}, [initialSessionId]);
|
|
11681
|
+
reactExports.useEffect(() => {
|
|
11682
|
+
if (initialSessionId === void 0) return;
|
|
11683
|
+
loadSessionPage({ kind: "newest" });
|
|
11684
|
+
}, [initialSessionId, loadSessionPage]);
|
|
11685
|
+
reactExports.useEffect(() => {
|
|
11686
|
+
if (initialSessionId !== void 0) return void 0;
|
|
11146
11687
|
connectSSE();
|
|
11147
11688
|
return () => {
|
|
11148
11689
|
if (eventSourceRef.current) {
|
|
@@ -11158,7 +11699,7 @@ function ProxyViewerContainer({
|
|
|
11158
11699
|
flushTimerRef.current = null;
|
|
11159
11700
|
}
|
|
11160
11701
|
};
|
|
11161
|
-
}, [connectSSE]);
|
|
11702
|
+
}, [connectSSE, initialSessionId]);
|
|
11162
11703
|
reactExports.useEffect(() => {
|
|
11163
11704
|
const hash = window.location.hash;
|
|
11164
11705
|
if (!hash.startsWith("#log-")) return;
|
|
@@ -11257,6 +11798,48 @@ function ProxyViewerContainer({
|
|
|
11257
11798
|
})();
|
|
11258
11799
|
}, []);
|
|
11259
11800
|
const { strip, captureMode, slowResponseThresholdSeconds, timeDisplayFormat } = useStripConfig();
|
|
11801
|
+
const loadOldestPage = reactExports.useCallback(() => {
|
|
11802
|
+
loadSessionPage({ kind: "oldest" });
|
|
11803
|
+
}, [loadSessionPage]);
|
|
11804
|
+
const loadNewestPage = reactExports.useCallback(() => {
|
|
11805
|
+
loadSessionPage({ kind: "newest" });
|
|
11806
|
+
}, [loadSessionPage]);
|
|
11807
|
+
const loadOlderPage = reactExports.useCallback(() => {
|
|
11808
|
+
const firstLog = allLogs[0];
|
|
11809
|
+
const beforeLogId = logPage?.oldestLogId ?? firstLog?.id ?? null;
|
|
11810
|
+
if (beforeLogId === null) return;
|
|
11811
|
+
loadSessionPage({ kind: "older", beforeLogId });
|
|
11812
|
+
}, [allLogs, loadSessionPage, logPage]);
|
|
11813
|
+
const loadNewerPage = reactExports.useCallback(() => {
|
|
11814
|
+
const lastLog = allLogs[allLogs.length - 1];
|
|
11815
|
+
const afterLogId = logPage?.newestLogId ?? lastLog?.id ?? null;
|
|
11816
|
+
if (afterLogId === null) return;
|
|
11817
|
+
loadSessionPage({ kind: "newer", afterLogId });
|
|
11818
|
+
}, [allLogs, loadSessionPage, logPage]);
|
|
11819
|
+
const pagination = reactExports.useMemo(() => {
|
|
11820
|
+
if (initialSessionId === void 0) return void 0;
|
|
11821
|
+
return {
|
|
11822
|
+
isLoading: sessionPageLoading,
|
|
11823
|
+
total: logPage?.total ?? null,
|
|
11824
|
+
pageSize: logPage?.limit ?? SESSION_PAGE_LIMIT,
|
|
11825
|
+
hasOlder: logPage?.hasOlder ?? false,
|
|
11826
|
+
hasNewer: logPage?.hasNewer ?? false,
|
|
11827
|
+
oldestLogId: logPage?.oldestLogId ?? null,
|
|
11828
|
+
newestLogId: logPage?.newestLogId ?? null,
|
|
11829
|
+
onOldest: loadOldestPage,
|
|
11830
|
+
onOlder: loadOlderPage,
|
|
11831
|
+
onNewer: loadNewerPage,
|
|
11832
|
+
onNewest: loadNewestPage
|
|
11833
|
+
};
|
|
11834
|
+
}, [
|
|
11835
|
+
initialSessionId,
|
|
11836
|
+
loadNewestPage,
|
|
11837
|
+
loadNewerPage,
|
|
11838
|
+
loadOlderPage,
|
|
11839
|
+
loadOldestPage,
|
|
11840
|
+
logPage,
|
|
11841
|
+
sessionPageLoading
|
|
11842
|
+
]);
|
|
11260
11843
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
11261
11844
|
error !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fixed top-4 right-4 bg-destructive text-destructive-foreground px-4 py-2 rounded-md text-sm z-50", children: error }),
|
|
11262
11845
|
/* @__PURE__ */ jsxRuntimeExports.jsx(OnboardingBanner, {}),
|
|
@@ -11272,6 +11855,9 @@ function ProxyViewerContainer({
|
|
|
11272
11855
|
onModelChange: setSelectedModel,
|
|
11273
11856
|
onClearAll: handleClearAll,
|
|
11274
11857
|
onClearGroup: handleClearGroup,
|
|
11858
|
+
isLoading: initialSessionId === void 0 ? !streamInitialized : sessionPageLoading,
|
|
11859
|
+
pagination,
|
|
11860
|
+
sessionMemberships,
|
|
11275
11861
|
viewMode,
|
|
11276
11862
|
onViewModeChange: setViewMode,
|
|
11277
11863
|
captureMode,
|