@tonyclaw/llm-inspector 1.14.7 → 1.14.8
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/index-CdnotuLh.js +105 -0
- package/.output/public/assets/index-vP91146S.css +1 -0
- package/.output/public/assets/{main-BV7uNIIz.js → main-CJ4MreBr.js} +1 -1
- package/.output/server/_libs/lucide-react.mjs +87 -79
- package/.output/server/_libs/radix-ui__react-id.mjs +1 -1
- package/.output/server/_ssr/{index-BvHLASu8.mjs → index-9uTJ4xYR.mjs} +744 -581
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{router-lUOA8pi6.mjs → router-BKnjB_zi.mjs} +2 -2
- package/.output/server/{_tanstack-start-manifest_v-XNH7fVPN.mjs → _tanstack-start-manifest_v-IsglLVKy.mjs} +1 -1
- package/.output/server/index.mjs +28 -28
- package/package.json +1 -1
- package/src/components/ProxyViewer.tsx +114 -146
- package/src/components/providers/ProviderCard.tsx +79 -26
- package/src/components/providers/ProviderForm.tsx +37 -22
- package/src/components/providers/ProvidersPanel.tsx +79 -47
- package/src/components/providers/SettingsDialog.tsx +25 -15
- package/src/components/proxy-viewer/ConversationGroup.tsx +50 -10
- package/src/components/proxy-viewer/ConversationHeader.tsx +48 -2
- package/src/components/proxy-viewer/LogEntry.tsx +116 -45
- package/src/components/proxy-viewer/LogEntryHeader.tsx +89 -71
- package/src/components/proxy-viewer/ReplayDialog.tsx +16 -6
- package/src/components/proxy-viewer/StreamingChunkSequence.tsx +24 -16
- package/src/components/proxy-viewer/ThreadConnector.tsx +104 -0
- package/src/components/proxy-viewer/index.ts +2 -1
- package/src/lib/stopReason.ts +57 -0
- package/.output/public/assets/index-Cmi8TfeU.js +0 -105
- package/.output/public/assets/index-DXUNTCVh.css +0 -1
|
@@ -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, a as parseRequest, s as stripClaudeCodeBillingHeader, R as RuntimeConfigSchema, c as createPendingProviderTestResults, P as ProviderTestResultsSchema, b as createFailedProviderTestResults, d as ProviderConfigSchema, p as parseOpenAIResponse, I as InspectorResponseSchema } from "./router-
|
|
2
|
+
import { C as CapturedLogSchema, a as parseRequest, s as stripClaudeCodeBillingHeader, R as RuntimeConfigSchema, c as createPendingProviderTestResults, P as ProviderTestResultsSchema, b as createFailedProviderTestResults, d as ProviderConfigSchema, p as parseOpenAIResponse, I as InspectorResponseSchema } from "./router-BKnjB_zi.mjs";
|
|
3
3
|
import { u as useSWR, a as useSWRConfig } from "../_libs/swr.mjs";
|
|
4
4
|
import { u as useVirtualizer } from "../_libs/tanstack__react-virtual.mjs";
|
|
5
|
-
import { J as JSZip } from "../_libs/jszip.mjs";
|
|
6
5
|
import { c as clsx } from "../_libs/clsx.mjs";
|
|
7
6
|
import { t as twMerge } from "../_libs/tailwind-merge.mjs";
|
|
7
|
+
import { J as JSZip } from "../_libs/jszip.mjs";
|
|
8
8
|
import { c as cva } from "../_libs/class-variance-authority.mjs";
|
|
9
9
|
import { d as diffLines, a as diffJson } from "../_libs/diff.mjs";
|
|
10
|
-
import { R as Root, T as Trigger$
|
|
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";
|
|
10
|
+
import { R as Root, T as Trigger$2, C as Content, a as Close, b as Title, P as Portal$2, O as Overlay } from "../_libs/radix-ui__react-dialog.mjs";
|
|
11
|
+
import { R as Root2, T as Trigger$1, I as Icon, V as Value, P as Portal$1, C as Content2$1, 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
12
|
import "../_libs/modelcontextprotocol__server.mjs";
|
|
13
|
-
import { D as Download, L as LayoutGrid, a as List, G as
|
|
13
|
+
import { D as Download, L as LayoutGrid, a as List, G as GitBranch, S as Settings, C as ChevronDown, b as Check, c as GitCompareArrows, R as RotateCcw, X, U as Upload, d as Scan, P as Plus, e as Copy, f as CircleAlert, g as ChevronUp, h as LoaderCircle, i as ChevronRight, j as Clock, M as MessageSquare, Z as Zap, W as Wrench, k as Globe, l as User, F as FileTerminal, m as Radio, n as Rows3, o as Columns2, p as Minus, q as Pencil, E as Equal, r as EyeOff, s as Eye, t as ExternalLink, u as RotateCw, T as Trash2, A as ArrowUp, v as ArrowDown, w as TriangleAlert, x as CircleCheckBig, y as CircleStop, z as CircleQuestionMark, B as Server, H as Gauge, I as Lock, J as Wifi, K as WifiOff, N as ChevronsUp, O as ChevronsDown, Q as Brain, V as Terminal } from "../_libs/lucide-react.mjs";
|
|
14
14
|
import { M as Markdown } from "../_libs/react-markdown.mjs";
|
|
15
15
|
import { a as array, b as string, u as union, d as object, l as literal, n as number, c as boolean, _ as _enum } from "../_libs/zod.mjs";
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
16
|
+
import { P as Provider, R as Root3, T as Trigger, a as Portal, C as Content2, A as Arrow2 } from "../_libs/radix-ui__react-tooltip.mjs";
|
|
17
|
+
import { R as Root2$1, L as List$1, T as Trigger$3, C as Content$1 } from "../_libs/radix-ui__react-tabs.mjs";
|
|
18
18
|
import { S as Slot } from "../_libs/radix-ui__react-slot.mjs";
|
|
19
19
|
import { R as Root$1 } from "../_libs/radix-ui__react-separator.mjs";
|
|
20
20
|
import { R as Root$2, C as CollapsibleTrigger$1, a as CollapsibleContent$1 } from "../_libs/radix-ui__react-collapsible.mjs";
|
|
@@ -237,6 +237,63 @@ function useStripConfig() {
|
|
|
237
237
|
setStrip
|
|
238
238
|
};
|
|
239
239
|
}
|
|
240
|
+
function cn(...inputs) {
|
|
241
|
+
return twMerge(clsx(inputs));
|
|
242
|
+
}
|
|
243
|
+
function formatTokens(count) {
|
|
244
|
+
if (count >= 1048576) return (count / 1048576).toFixed(1).replace(/\.0$/, "") + "M";
|
|
245
|
+
if (count >= 1024) return (count / 1024).toFixed(1).replace(/\.0$/, "") + "K";
|
|
246
|
+
return count.toString();
|
|
247
|
+
}
|
|
248
|
+
function getStatusCategory(status) {
|
|
249
|
+
if (status === null) return "pending";
|
|
250
|
+
if (status >= 200 && status < 300) return "success";
|
|
251
|
+
if (status >= 400 && status < 500) return "client_error";
|
|
252
|
+
if (status >= 500) return "server_error";
|
|
253
|
+
return "pending";
|
|
254
|
+
}
|
|
255
|
+
function TooltipProvider({
|
|
256
|
+
delayDuration = 0,
|
|
257
|
+
...props
|
|
258
|
+
}) {
|
|
259
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
260
|
+
Provider,
|
|
261
|
+
{
|
|
262
|
+
"data-slot": "tooltip-provider",
|
|
263
|
+
delayDuration,
|
|
264
|
+
...props
|
|
265
|
+
}
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
function Tooltip({ ...props }) {
|
|
269
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Root3, { "data-slot": "tooltip", ...props });
|
|
270
|
+
}
|
|
271
|
+
function TooltipTrigger({ ...props }) {
|
|
272
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Trigger, { "data-slot": "tooltip-trigger", ...props });
|
|
273
|
+
}
|
|
274
|
+
function TooltipContent({
|
|
275
|
+
className,
|
|
276
|
+
sideOffset = 0,
|
|
277
|
+
children,
|
|
278
|
+
...props
|
|
279
|
+
}) {
|
|
280
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Portal, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
281
|
+
Content2,
|
|
282
|
+
{
|
|
283
|
+
"data-slot": "tooltip-content",
|
|
284
|
+
sideOffset,
|
|
285
|
+
className: cn(
|
|
286
|
+
"bg-foreground text-background animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance",
|
|
287
|
+
className
|
|
288
|
+
),
|
|
289
|
+
...props,
|
|
290
|
+
children: [
|
|
291
|
+
children,
|
|
292
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Arrow2, { className: "bg-foreground fill-foreground z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" })
|
|
293
|
+
]
|
|
294
|
+
}
|
|
295
|
+
) });
|
|
296
|
+
}
|
|
240
297
|
async function fetchStreamingChunks(logId) {
|
|
241
298
|
try {
|
|
242
299
|
const response = await fetch(`/api/logs/${logId}/chunks`);
|
|
@@ -276,24 +333,34 @@ async function exportLogsAsZip(logs) {
|
|
|
276
333
|
document.body.removeChild(anchor);
|
|
277
334
|
URL.revokeObjectURL(url);
|
|
278
335
|
}
|
|
279
|
-
const version = "1.14.
|
|
336
|
+
const version = "1.14.8";
|
|
280
337
|
const packageJson = {
|
|
281
338
|
version
|
|
282
339
|
};
|
|
283
|
-
function
|
|
284
|
-
return
|
|
285
|
-
}
|
|
286
|
-
function formatTokens(count) {
|
|
287
|
-
if (count >= 1048576) return (count / 1048576).toFixed(1).replace(/\.0$/, "") + "M";
|
|
288
|
-
if (count >= 1024) return (count / 1024).toFixed(1).replace(/\.0$/, "") + "K";
|
|
289
|
-
return count.toString();
|
|
340
|
+
function isRecord(value) {
|
|
341
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
290
342
|
}
|
|
291
|
-
function
|
|
292
|
-
if (
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
343
|
+
function extractStopReason(log) {
|
|
344
|
+
if (log.responseText === null) return null;
|
|
345
|
+
try {
|
|
346
|
+
let json = JSON.parse(log.responseText);
|
|
347
|
+
if (typeof json === "string") {
|
|
348
|
+
json = JSON.parse(json);
|
|
349
|
+
}
|
|
350
|
+
if (!isRecord(json)) return null;
|
|
351
|
+
if (log.apiFormat === "anthropic" && typeof json.stop_reason === "string") {
|
|
352
|
+
if (json.stop_reason === "end_turn" || json.stop_reason === "tool_use") {
|
|
353
|
+
return json.stop_reason;
|
|
354
|
+
}
|
|
355
|
+
return null;
|
|
356
|
+
}
|
|
357
|
+
if (log.apiFormat === "openai" && Array.isArray(json.choices) && json.choices.length > 0 && isRecord(json.choices[0]) && typeof json.choices[0].finish_reason === "string" && json.choices[0].finish_reason === "stop") {
|
|
358
|
+
return "stop";
|
|
359
|
+
}
|
|
360
|
+
return null;
|
|
361
|
+
} catch {
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
297
364
|
}
|
|
298
365
|
const badgeVariants = cva(
|
|
299
366
|
"inline-flex items-center justify-center rounded-full border border-transparent px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
|
|
@@ -349,7 +416,10 @@ function ConversationHeader({
|
|
|
349
416
|
apiFormat,
|
|
350
417
|
expanded,
|
|
351
418
|
onToggle,
|
|
352
|
-
hideApiFormat = false
|
|
419
|
+
hideApiFormat = false,
|
|
420
|
+
isLoading = false,
|
|
421
|
+
viewMode,
|
|
422
|
+
onToggleViewMode
|
|
353
423
|
}) {
|
|
354
424
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
355
425
|
"div",
|
|
@@ -370,7 +440,23 @@ function ConversationHeader({
|
|
|
370
440
|
}
|
|
371
441
|
},
|
|
372
442
|
children: [
|
|
373
|
-
expanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-4 text-muted-foreground shrink-0" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-4 text-muted-foreground shrink-0" }),
|
|
443
|
+
expanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-4 text-muted-foreground shrink-0" }) : isLoading ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-4 animate-spin text-muted-foreground shrink-0" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-4 text-muted-foreground shrink-0" }),
|
|
444
|
+
expanded && onToggleViewMode !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
445
|
+
"button",
|
|
446
|
+
{
|
|
447
|
+
type: "button",
|
|
448
|
+
onClick: (e) => {
|
|
449
|
+
e.stopPropagation();
|
|
450
|
+
onToggleViewMode();
|
|
451
|
+
},
|
|
452
|
+
className: cn(
|
|
453
|
+
"px-1.5 py-0.5 rounded text-[10px] font-mono transition-colors shrink-0 cursor-pointer",
|
|
454
|
+
viewMode === "thread" ? "bg-amber-500/15 text-amber-400 border border-amber-500/30" : "bg-muted text-muted-foreground border border-border hover:text-foreground"
|
|
455
|
+
),
|
|
456
|
+
title: viewMode === "thread" ? "Thread view — click for flat view" : "Flat view — click for thread view",
|
|
457
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(GitBranch, { className: "size-3" })
|
|
458
|
+
}
|
|
459
|
+
),
|
|
374
460
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
375
461
|
"span",
|
|
376
462
|
{
|
|
@@ -509,48 +595,6 @@ function Button({
|
|
|
509
595
|
}
|
|
510
596
|
);
|
|
511
597
|
}
|
|
512
|
-
function TooltipProvider({
|
|
513
|
-
delayDuration = 0,
|
|
514
|
-
...props
|
|
515
|
-
}) {
|
|
516
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
517
|
-
Provider,
|
|
518
|
-
{
|
|
519
|
-
"data-slot": "tooltip-provider",
|
|
520
|
-
delayDuration,
|
|
521
|
-
...props
|
|
522
|
-
}
|
|
523
|
-
);
|
|
524
|
-
}
|
|
525
|
-
function Tooltip({ ...props }) {
|
|
526
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(Root3, { "data-slot": "tooltip", ...props });
|
|
527
|
-
}
|
|
528
|
-
function TooltipTrigger({ ...props }) {
|
|
529
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(Trigger$3, { "data-slot": "tooltip-trigger", ...props });
|
|
530
|
-
}
|
|
531
|
-
function TooltipContent({
|
|
532
|
-
className,
|
|
533
|
-
sideOffset = 0,
|
|
534
|
-
children,
|
|
535
|
-
...props
|
|
536
|
-
}) {
|
|
537
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(Portal$2, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
538
|
-
Content2$1,
|
|
539
|
-
{
|
|
540
|
-
"data-slot": "tooltip-content",
|
|
541
|
-
sideOffset,
|
|
542
|
-
className: cn(
|
|
543
|
-
"bg-foreground text-background animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance",
|
|
544
|
-
className
|
|
545
|
-
),
|
|
546
|
-
...props,
|
|
547
|
-
children: [
|
|
548
|
-
children,
|
|
549
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(Arrow2, { className: "bg-foreground fill-foreground z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" })
|
|
550
|
-
]
|
|
551
|
-
}
|
|
552
|
-
) });
|
|
553
|
-
}
|
|
554
598
|
function classifyValue(value) {
|
|
555
599
|
if (value === null) return "null";
|
|
556
600
|
if (Array.isArray(value)) return "array";
|
|
@@ -953,7 +997,7 @@ function TabsTrigger({
|
|
|
953
997
|
...props
|
|
954
998
|
}) {
|
|
955
999
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
956
|
-
Trigger$
|
|
1000
|
+
Trigger$3,
|
|
957
1001
|
{
|
|
958
1002
|
"data-slot": "tabs-trigger",
|
|
959
1003
|
className: cn(
|
|
@@ -1415,9 +1459,7 @@ const LogEntryHeader = reactExports.memo(function({
|
|
|
1415
1459
|
expanded,
|
|
1416
1460
|
onToggle,
|
|
1417
1461
|
suppressApiFormatBadge = false,
|
|
1418
|
-
cacheTrend = null
|
|
1419
|
-
isSelected = false,
|
|
1420
|
-
onToggleSelect
|
|
1462
|
+
cacheTrend = null
|
|
1421
1463
|
}) {
|
|
1422
1464
|
const statusCategory = getStatusCategory(log.responseStatus);
|
|
1423
1465
|
const hasTokens = log.inputTokens !== null || log.outputTokens !== null;
|
|
@@ -1441,31 +1483,14 @@ const LogEntryHeader = reactExports.memo(function({
|
|
|
1441
1483
|
}
|
|
1442
1484
|
},
|
|
1443
1485
|
children: [
|
|
1444
|
-
onToggleSelect !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
1445
|
-
"button",
|
|
1446
|
-
{
|
|
1447
|
-
type: "button",
|
|
1448
|
-
onClick: (e) => {
|
|
1449
|
-
e.stopPropagation();
|
|
1450
|
-
onToggleSelect(log.id);
|
|
1451
|
-
},
|
|
1452
|
-
"aria-label": isSelected ? "Deselect for comparison" : "Select for comparison",
|
|
1453
|
-
"aria-pressed": isSelected,
|
|
1454
|
-
className: cn(
|
|
1455
|
-
"shrink-0 size-4 rounded-sm border flex items-center justify-center transition-colors cursor-pointer",
|
|
1456
|
-
isSelected ? "bg-amber-400 border-amber-400 text-amber-950" : "border-muted-foreground/40 hover:border-amber-400 hover:bg-amber-400/10"
|
|
1457
|
-
),
|
|
1458
|
-
children: isSelected && /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-3", strokeWidth: 3 })
|
|
1459
|
-
}
|
|
1460
|
-
),
|
|
1461
1486
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-blue-400/80 font-mono text-xs font-semibold tabular-nums shrink-0", children: [
|
|
1462
1487
|
"#",
|
|
1463
1488
|
log.id
|
|
1464
1489
|
] }),
|
|
1465
|
-
log.model !== null && /* @__PURE__ */ jsxRuntimeExports.
|
|
1466
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(ProviderLogo, { provider: detectProvider(log.model), className: "size-4
|
|
1467
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
1468
|
-
] }),
|
|
1490
|
+
log.model !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
1491
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ProviderLogo, { provider: detectProvider(log.model), className: "size-4" }) }) }),
|
|
1492
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: log.model })
|
|
1493
|
+
] }) }),
|
|
1469
1494
|
!suppressApiFormatBadge && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
1470
1495
|
Badge,
|
|
1471
1496
|
{
|
|
@@ -1524,28 +1549,40 @@ const LogEntryHeader = reactExports.memo(function({
|
|
|
1524
1549
|
)
|
|
1525
1550
|
] })
|
|
1526
1551
|
] }),
|
|
1527
|
-
log.cacheCreationInputTokens !== null && log.cacheCreationInputTokens > 0 && /* @__PURE__ */ jsxRuntimeExports.
|
|
1528
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
1529
|
-
|
|
1530
|
-
"
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1552
|
+
log.cacheCreationInputTokens !== null && log.cacheCreationInputTokens > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
1553
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1 text-xs shrink-0", children: [
|
|
1554
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(CacheTrendIndicator, { trend: cacheTrend?.creation ?? null }),
|
|
1555
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono tabular-nums text-emerald-400", children: [
|
|
1556
|
+
"Cache +",
|
|
1557
|
+
formatTokens(log.cacheCreationInputTokens)
|
|
1558
|
+
] })
|
|
1559
|
+
] }) }),
|
|
1560
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Tokens cached for reuse, reducing future API cost" })
|
|
1561
|
+
] }) }),
|
|
1562
|
+
log.cacheReadInputTokens !== null && log.cacheReadInputTokens > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
1563
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1 text-xs shrink-0", children: [
|
|
1564
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(CacheTrendIndicator, { trend: cacheTrend?.read ?? null }),
|
|
1565
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono tabular-nums text-purple-400", children: [
|
|
1566
|
+
"Cache ~",
|
|
1567
|
+
formatTokens(log.cacheReadInputTokens)
|
|
1568
|
+
] })
|
|
1569
|
+
] }) }),
|
|
1570
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Tokens served from cache, reducing API cost" })
|
|
1571
|
+
] }) }),
|
|
1572
|
+
messageCount !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
1573
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1 text-muted-foreground text-xs shrink-0", children: [
|
|
1574
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(MessageSquare, { className: "size-3" }),
|
|
1575
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", children: messageCount })
|
|
1576
|
+
] }) }),
|
|
1577
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Number of messages in the conversation" })
|
|
1578
|
+
] }) }),
|
|
1579
|
+
toolCount !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
1580
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1 text-muted-foreground text-xs shrink-0", children: [
|
|
1581
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Wrench, { className: "size-3" }),
|
|
1582
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", children: toolCount })
|
|
1583
|
+
] }) }),
|
|
1584
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Number of tools defined in the request" })
|
|
1585
|
+
] }) }),
|
|
1549
1586
|
log.origin !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
1550
1587
|
"span",
|
|
1551
1588
|
{
|
|
@@ -1568,21 +1605,20 @@ const LogEntryHeader = reactExports.memo(function({
|
|
|
1568
1605
|
]
|
|
1569
1606
|
}
|
|
1570
1607
|
),
|
|
1571
|
-
(log.clientPid !== null || log.clientProjectFolder !== null) && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
1572
|
-
"span",
|
|
1573
|
-
|
|
1574
|
-
className: "
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
}
|
|
1584
|
-
),
|
|
1585
|
-
log.streaming && /* @__PURE__ */ jsxRuntimeExports.jsx(Radio, { className: "size-3 text-muted-foreground/60 shrink-0" }),
|
|
1608
|
+
(log.clientPid !== null || log.clientProjectFolder !== null) && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
1609
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1 text-purple-400/80 text-xs shrink-0", children: [
|
|
1610
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(FileTerminal, { className: "size-3" }),
|
|
1611
|
+
log.clientProjectFolder !== null ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", children: log.clientProjectFolder }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono tabular-nums", children: [
|
|
1612
|
+
"PID ",
|
|
1613
|
+
log.clientPid
|
|
1614
|
+
] })
|
|
1615
|
+
] }) }),
|
|
1616
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: log.clientCwd !== null ? `PID: ${log.clientPid ?? "?"} CWD: ${log.clientCwd}` : `Process ID: ${log.clientPid ?? "?"}` })
|
|
1617
|
+
] }) }),
|
|
1618
|
+
log.streaming && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
1619
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Radio, { className: "size-3 text-muted-foreground/60 shrink-0" }) }),
|
|
1620
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Request used SSE streaming" })
|
|
1621
|
+
] }) }),
|
|
1586
1622
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1 min-w-0" }),
|
|
1587
1623
|
expanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-4 text-muted-foreground shrink-0" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-4 text-muted-foreground shrink-0" })
|
|
1588
1624
|
]
|
|
@@ -1597,12 +1633,12 @@ function Dialog({
|
|
|
1597
1633
|
function DialogTrigger({
|
|
1598
1634
|
...props
|
|
1599
1635
|
}) {
|
|
1600
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(Trigger$
|
|
1636
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Trigger$2, { "data-slot": "dialog-trigger", ...props });
|
|
1601
1637
|
}
|
|
1602
1638
|
function DialogPortal({
|
|
1603
1639
|
...props
|
|
1604
1640
|
}) {
|
|
1605
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(Portal$
|
|
1641
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Portal$2, { "data-slot": "dialog-portal", ...props });
|
|
1606
1642
|
}
|
|
1607
1643
|
function DialogOverlay({
|
|
1608
1644
|
className,
|
|
@@ -2167,15 +2203,18 @@ function ReplayDialog({ log, open, onOpenChange }) {
|
|
|
2167
2203
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(TabsContent, { value: "modified", className: "space-y-4", children: [
|
|
2168
2204
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
2169
2205
|
/* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-sm font-medium mb-2 block", children: "Request Body (JSON)" }),
|
|
2170
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2206
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
2207
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2208
|
+
"textarea",
|
|
2209
|
+
{
|
|
2210
|
+
className: "w-full h-64 p-3 font-mono text-xs bg-muted rounded-md border border-input resize-none focus:outline-none focus:ring-2 focus:ring-ring",
|
|
2211
|
+
value: modifiedBody,
|
|
2212
|
+
onChange: (e) => setModifiedBody(e.target.value),
|
|
2213
|
+
spellCheck: false
|
|
2214
|
+
}
|
|
2215
|
+
) }),
|
|
2216
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Edit the request body before re-sending to the provider" })
|
|
2217
|
+
] }) })
|
|
2179
2218
|
] }),
|
|
2180
2219
|
error !== null && error !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm text-destructive bg-destructive/10 px-3 py-2 rounded-md", children: error }),
|
|
2181
2220
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -2359,22 +2398,25 @@ function StreamingChunkSequence({
|
|
|
2359
2398
|
] });
|
|
2360
2399
|
}
|
|
2361
2400
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1", children: [
|
|
2362
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2401
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
2402
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
2403
|
+
"button",
|
|
2404
|
+
{
|
|
2405
|
+
type: "button",
|
|
2406
|
+
className: "flex items-center gap-1.5 text-xs text-muted-foreground hover:text-foreground transition-colors cursor-pointer",
|
|
2407
|
+
onClick: () => setContainerExpanded((v) => !v),
|
|
2408
|
+
children: [
|
|
2409
|
+
containerExpanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-3" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "size-3" }),
|
|
2410
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Raw SSE Events" }),
|
|
2411
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(Badge, { variant: "outline", className: "text-[9px] px-1 py-0 h-4 font-mono ml-1", children: [
|
|
2412
|
+
logId,
|
|
2413
|
+
truncated === true ? "+" : ""
|
|
2414
|
+
] })
|
|
2415
|
+
]
|
|
2416
|
+
}
|
|
2417
|
+
) }),
|
|
2418
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Server-Sent Events streaming chunks from the provider" })
|
|
2419
|
+
] }) }),
|
|
2378
2420
|
containerExpanded === true ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "rounded-md border border-border bg-muted/20 overflow-auto max-h-64", children: renderBody() }) : null
|
|
2379
2421
|
] });
|
|
2380
2422
|
}
|
|
@@ -2414,23 +2456,25 @@ function DiffToggleButton({
|
|
|
2414
2456
|
active,
|
|
2415
2457
|
onClick
|
|
2416
2458
|
}) {
|
|
2417
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2459
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
2460
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
2461
|
+
"button",
|
|
2462
|
+
{
|
|
2463
|
+
type: "button",
|
|
2464
|
+
onClick,
|
|
2465
|
+
"aria-pressed": active,
|
|
2466
|
+
className: cn(
|
|
2467
|
+
"flex items-center gap-1.5 text-xs px-2 py-1 rounded transition-colors",
|
|
2468
|
+
active ? "bg-primary/10 text-primary" : "text-muted-foreground hover:text-foreground hover:bg-muted"
|
|
2469
|
+
),
|
|
2470
|
+
children: [
|
|
2471
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(GitCompareArrows, { className: "size-3" }),
|
|
2472
|
+
active ? "Showing diff" : "Diff with Raw"
|
|
2473
|
+
]
|
|
2474
|
+
}
|
|
2475
|
+
) }),
|
|
2476
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: active ? "Hide diff view" : "Compare proxy output against the original raw version" })
|
|
2477
|
+
] }) });
|
|
2434
2478
|
}
|
|
2435
2479
|
const LogEntry = reactExports.memo(function({
|
|
2436
2480
|
log,
|
|
@@ -2438,8 +2482,7 @@ const LogEntry = reactExports.memo(function({
|
|
|
2438
2482
|
suppressApiFormatBadge = false,
|
|
2439
2483
|
strip,
|
|
2440
2484
|
cacheTrend = null,
|
|
2441
|
-
|
|
2442
|
-
onToggleSelect
|
|
2485
|
+
onCompareWithPrevious
|
|
2443
2486
|
}) {
|
|
2444
2487
|
const [expanded, setExpanded] = reactExports.useState(false);
|
|
2445
2488
|
const [requestCopied, setRequestCopied] = reactExports.useState(false);
|
|
@@ -2489,178 +2532,268 @@ const LogEntry = reactExports.memo(function({
|
|
|
2489
2532
|
});
|
|
2490
2533
|
}
|
|
2491
2534
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
2492
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2535
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border border-border rounded-lg mb-3 overflow-hidden", children: [
|
|
2536
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2537
|
+
LogEntryHeader,
|
|
2538
|
+
{
|
|
2539
|
+
log,
|
|
2540
|
+
parsedRequest,
|
|
2541
|
+
expanded,
|
|
2542
|
+
onToggle: () => setExpanded(!expanded),
|
|
2543
|
+
suppressApiFormatBadge,
|
|
2544
|
+
cacheTrend
|
|
2545
|
+
}
|
|
2546
|
+
),
|
|
2547
|
+
expanded && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { onClick: (e) => e.stopPropagation(), onKeyDown: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tabs, { defaultValue: "request", children: [
|
|
2548
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(TabsList, { className: "mx-4 mt-2", children: [
|
|
2549
|
+
viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
2550
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "raw-headers", children: "Raw Headers" }) }),
|
|
2551
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "HTTP headers received from the upstream provider" })
|
|
2552
|
+
] }) }),
|
|
2553
|
+
viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
2554
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "headers", children: "Headers" }) }),
|
|
2555
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Request and response headers sent and received" })
|
|
2556
|
+
] }) }),
|
|
2557
|
+
shouldShowRawRequestTab(log.apiFormat, viewMode, strip) && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
2558
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "raw-request", children: "Raw Request" }) }),
|
|
2559
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Exact HTTP request sent to the upstream provider" })
|
|
2560
|
+
] }) }),
|
|
2561
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "request", children: "Request" }),
|
|
2562
|
+
viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
2563
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "raw", children: "Raw Response" }) }),
|
|
2564
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Exact HTTP response from the upstream provider" })
|
|
2565
|
+
] }) }),
|
|
2566
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "parsed", children: "Response" })
|
|
2567
|
+
] }),
|
|
2568
|
+
shouldShowRawRequestTab(log.apiFormat, viewMode, strip) && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "raw-request", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-3", children: [
|
|
2569
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex justify-end mb-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2570
|
+
CopyButton,
|
|
2502
2571
|
{
|
|
2503
|
-
log,
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
suppressApiFormatBadge,
|
|
2508
|
-
cacheTrend,
|
|
2509
|
-
isSelected,
|
|
2510
|
-
onToggleSelect
|
|
2572
|
+
text: log.rawRequestBody,
|
|
2573
|
+
label: "Copy Raw Request",
|
|
2574
|
+
copied: rawRequestCopied,
|
|
2575
|
+
onCopy: handleCopyRawRequest
|
|
2511
2576
|
}
|
|
2512
|
-
),
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
viewMode
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
onCopy: handleCopyRawRequest
|
|
2530
|
-
}
|
|
2531
|
-
) }),
|
|
2532
|
-
log.rawRequestBody !== null ? /* @__PURE__ */ jsxRuntimeExports.jsx(JsonViewerFromString, { text: log.rawRequestBody, defaultExpandDepth: 1 }) : /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground italic", children: "No request body" })
|
|
2533
|
-
] }) }),
|
|
2534
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "request", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-3", children: [
|
|
2535
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-end gap-2 mb-2", children: [
|
|
2536
|
-
shouldShowRequestDiffButton(
|
|
2537
|
-
log.apiFormat,
|
|
2538
|
-
viewMode,
|
|
2539
|
-
strip,
|
|
2540
|
-
log.rawRequestBody !== null
|
|
2541
|
-
) && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2542
|
-
DiffToggleButton,
|
|
2543
|
-
{
|
|
2544
|
-
active: requestDiff,
|
|
2545
|
-
onClick: (e) => {
|
|
2546
|
-
e.stopPropagation();
|
|
2547
|
-
setRequestDiff(!requestDiff);
|
|
2548
|
-
}
|
|
2549
|
-
}
|
|
2550
|
-
),
|
|
2551
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
2552
|
-
Button,
|
|
2553
|
-
{
|
|
2554
|
-
variant: "outline",
|
|
2555
|
-
size: "sm",
|
|
2556
|
-
className: "h-7 text-xs",
|
|
2557
|
-
onClick: (e) => {
|
|
2558
|
-
e.stopPropagation();
|
|
2559
|
-
setReplayOpen(true);
|
|
2560
|
-
},
|
|
2561
|
-
children: [
|
|
2562
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(RotateCcw, { className: "size-3 mr-1" }),
|
|
2563
|
-
"Replay"
|
|
2564
|
-
]
|
|
2565
|
-
}
|
|
2566
|
-
),
|
|
2567
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2568
|
-
CopyButton,
|
|
2569
|
-
{
|
|
2570
|
-
text: displayedRequestBody,
|
|
2571
|
-
label: "Copy Request",
|
|
2572
|
-
copied: requestCopied,
|
|
2573
|
-
onCopy: handleCopyRequest
|
|
2574
|
-
}
|
|
2575
|
-
)
|
|
2576
|
-
] }),
|
|
2577
|
-
requestDiff ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2578
|
-
DiffView,
|
|
2579
|
-
{
|
|
2580
|
-
result: requestDiffResult,
|
|
2581
|
-
emptyLabel: "No transformation applied — raw and sent request bodies are identical."
|
|
2577
|
+
) }),
|
|
2578
|
+
log.rawRequestBody !== null ? /* @__PURE__ */ jsxRuntimeExports.jsx(JsonViewerFromString, { text: log.rawRequestBody, defaultExpandDepth: 1 }) : /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground italic", children: "No request body" })
|
|
2579
|
+
] }) }),
|
|
2580
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "request", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-3", children: [
|
|
2581
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-end gap-2 mb-2", children: [
|
|
2582
|
+
shouldShowRequestDiffButton(
|
|
2583
|
+
log.apiFormat,
|
|
2584
|
+
viewMode,
|
|
2585
|
+
strip,
|
|
2586
|
+
log.rawRequestBody !== null
|
|
2587
|
+
) && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2588
|
+
DiffToggleButton,
|
|
2589
|
+
{
|
|
2590
|
+
active: requestDiff,
|
|
2591
|
+
onClick: (e) => {
|
|
2592
|
+
e.stopPropagation();
|
|
2593
|
+
setRequestDiff(!requestDiff);
|
|
2582
2594
|
}
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2587
|
-
|
|
2588
|
-
log.rawHeaders !== void 0 && Object.keys(log.rawHeaders).length > 0
|
|
2589
|
-
) && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2590
|
-
DiffToggleButton,
|
|
2595
|
+
}
|
|
2596
|
+
),
|
|
2597
|
+
onCompareWithPrevious !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
2598
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
2599
|
+
Button,
|
|
2591
2600
|
{
|
|
2592
|
-
|
|
2601
|
+
variant: "outline",
|
|
2602
|
+
size: "sm",
|
|
2603
|
+
className: "h-7 text-xs",
|
|
2593
2604
|
onClick: (e) => {
|
|
2594
2605
|
e.stopPropagation();
|
|
2595
|
-
|
|
2596
|
-
}
|
|
2606
|
+
onCompareWithPrevious();
|
|
2607
|
+
},
|
|
2608
|
+
children: [
|
|
2609
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(GitCompareArrows, { className: "size-3 mr-1" }),
|
|
2610
|
+
"Diff with Previous"
|
|
2611
|
+
]
|
|
2597
2612
|
}
|
|
2598
2613
|
) }),
|
|
2599
|
-
|
|
2600
|
-
DiffView,
|
|
2601
|
-
{
|
|
2602
|
-
result: headersDiffResult,
|
|
2603
|
-
emptyLabel: "No transformation applied — raw and processed headers are identical."
|
|
2604
|
-
}
|
|
2605
|
-
) : log.headers && Object.keys(log.headers).length > 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1 font-mono text-xs", children: Object.entries(log.headers).sort(([a], [b]) => a.localeCompare(b)).map(([key, value]) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
|
|
2606
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-blue-600 dark:text-blue-400 font-semibold shrink-0", children: [
|
|
2607
|
-
key,
|
|
2608
|
-
":"
|
|
2609
|
-
] }),
|
|
2610
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground truncate", title: value, children: value })
|
|
2611
|
-
] }, key)) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground italic", children: "No headers captured" })
|
|
2614
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Compare this request with the immediately preceding one" })
|
|
2612
2615
|
] }) }),
|
|
2613
|
-
|
|
2614
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
2615
|
-
|
|
2616
|
-
":"
|
|
2617
|
-
] }),
|
|
2618
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground truncate", title: value, children: value })
|
|
2619
|
-
] }, key)) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground italic", children: "No raw headers captured" }) }) }),
|
|
2620
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "raw", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-3 space-y-3", children: [
|
|
2621
|
-
log.error !== void 0 && log.error !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded border border-destructive/50 bg-destructive/10 p-3 text-xs", children: [
|
|
2622
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-semibold text-destructive mb-1", children: "SSE Error" }),
|
|
2623
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-muted-foreground font-mono", children: log.error })
|
|
2624
|
-
] }),
|
|
2625
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2626
|
-
CopyButton,
|
|
2616
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
2617
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
2618
|
+
Button,
|
|
2627
2619
|
{
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2620
|
+
variant: "outline",
|
|
2621
|
+
size: "sm",
|
|
2622
|
+
className: "h-7 text-xs",
|
|
2623
|
+
onClick: (e) => {
|
|
2624
|
+
e.stopPropagation();
|
|
2625
|
+
setReplayOpen(true);
|
|
2626
|
+
},
|
|
2627
|
+
children: [
|
|
2628
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(RotateCcw, { className: "size-3 mr-1" }),
|
|
2629
|
+
"Replay"
|
|
2630
|
+
]
|
|
2632
2631
|
}
|
|
2633
2632
|
) }),
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2633
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Re-send this request to the provider" })
|
|
2634
|
+
] }) }),
|
|
2635
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2636
|
+
CopyButton,
|
|
2637
|
+
{
|
|
2638
|
+
text: displayedRequestBody,
|
|
2639
|
+
label: "Copy Request",
|
|
2640
|
+
copied: requestCopied,
|
|
2641
|
+
onCopy: handleCopyRequest
|
|
2642
|
+
}
|
|
2643
|
+
)
|
|
2644
|
+
] }),
|
|
2645
|
+
requestDiff ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2646
|
+
DiffView,
|
|
2647
|
+
{
|
|
2648
|
+
result: requestDiffResult,
|
|
2649
|
+
emptyLabel: "No transformation applied — raw and sent request bodies are identical."
|
|
2650
|
+
}
|
|
2651
|
+
) : displayedRequestBody !== null ? /* @__PURE__ */ jsxRuntimeExports.jsx(JsonViewerFromString, { text: displayedRequestBody, defaultExpandDepth: 1 }) : /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground italic", children: "No request body" })
|
|
2652
|
+
] }) }),
|
|
2653
|
+
viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "headers", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-3", children: [
|
|
2654
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex justify-end gap-2 mb-2", children: shouldShowHeadersDiffButton(
|
|
2655
|
+
viewMode,
|
|
2656
|
+
log.rawHeaders !== void 0 && Object.keys(log.rawHeaders).length > 0
|
|
2657
|
+
) && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2658
|
+
DiffToggleButton,
|
|
2659
|
+
{
|
|
2660
|
+
active: headersDiff,
|
|
2661
|
+
onClick: (e) => {
|
|
2662
|
+
e.stopPropagation();
|
|
2663
|
+
setHeadersDiff(!headersDiff);
|
|
2664
|
+
}
|
|
2665
|
+
}
|
|
2666
|
+
) }),
|
|
2667
|
+
headersDiff ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2668
|
+
DiffView,
|
|
2669
|
+
{
|
|
2670
|
+
result: headersDiffResult,
|
|
2671
|
+
emptyLabel: "No transformation applied — raw and processed headers are identical."
|
|
2672
|
+
}
|
|
2673
|
+
) : log.headers && Object.keys(log.headers).length > 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1 font-mono text-xs", children: Object.entries(log.headers).sort(([a], [b]) => a.localeCompare(b)).map(([key, value]) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
|
|
2674
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-blue-600 dark:text-blue-400 font-semibold shrink-0", children: [
|
|
2675
|
+
key,
|
|
2676
|
+
":"
|
|
2677
|
+
] }),
|
|
2678
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground truncate", title: value, children: value })
|
|
2679
|
+
] }, key)) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground italic", children: "No headers captured" })
|
|
2680
|
+
] }) }),
|
|
2681
|
+
viewMode === "full" && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "raw-headers", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-4 py-3", children: log.rawHeaders && Object.keys(log.rawHeaders).length > 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1 font-mono text-xs", children: Object.entries(log.rawHeaders).sort(([a], [b]) => a.localeCompare(b)).map(([key, value]) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
|
|
2682
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-blue-600 dark:text-blue-400 font-semibold shrink-0", children: [
|
|
2683
|
+
key,
|
|
2684
|
+
":"
|
|
2685
|
+
] }),
|
|
2686
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground truncate", title: value, children: value })
|
|
2687
|
+
] }, key)) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground italic", children: "No raw headers captured" }) }) }),
|
|
2688
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "raw", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-3 space-y-3", children: [
|
|
2689
|
+
log.error !== void 0 && log.error !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded border border-destructive/50 bg-destructive/10 p-3 text-xs", children: [
|
|
2690
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-semibold text-destructive mb-1", children: "SSE Error" }),
|
|
2691
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-muted-foreground font-mono", children: log.error })
|
|
2692
|
+
] }),
|
|
2693
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2694
|
+
CopyButton,
|
|
2695
|
+
{
|
|
2696
|
+
text: log.responseText,
|
|
2697
|
+
label: "Copy Response",
|
|
2698
|
+
copied: responseCopied,
|
|
2699
|
+
onCopy: handleCopyResponse
|
|
2700
|
+
}
|
|
2701
|
+
) }),
|
|
2702
|
+
log.responseText !== null ? /* @__PURE__ */ jsxRuntimeExports.jsx(JsonViewerFromString, { text: log.responseText, defaultExpandDepth: 1 }) : /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground italic", children: "No response" }),
|
|
2703
|
+
log.streaming === true && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2704
|
+
StreamingChunkSequence,
|
|
2705
|
+
{
|
|
2706
|
+
logId: log.id,
|
|
2707
|
+
truncated: log.streamingChunksPath !== null
|
|
2708
|
+
}
|
|
2709
|
+
)
|
|
2710
|
+
] }) }),
|
|
2711
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "parsed", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-4 py-3", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2712
|
+
ResponseView,
|
|
2713
|
+
{
|
|
2714
|
+
responseText: log.responseText,
|
|
2715
|
+
responseStatus: log.responseStatus,
|
|
2716
|
+
streaming: log.streaming,
|
|
2717
|
+
inputTokens: log.inputTokens,
|
|
2718
|
+
outputTokens: log.outputTokens,
|
|
2719
|
+
cacheCreationInputTokens: log.cacheCreationInputTokens,
|
|
2720
|
+
cacheReadInputTokens: log.cacheReadInputTokens,
|
|
2721
|
+
apiFormat: log.apiFormat,
|
|
2722
|
+
error: log.error
|
|
2723
|
+
}
|
|
2724
|
+
) }) })
|
|
2725
|
+
] }) })
|
|
2726
|
+
] }),
|
|
2727
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ReplayDialog, { log, open: replayOpen, onOpenChange: setReplayOpen })
|
|
2728
|
+
] });
|
|
2729
|
+
});
|
|
2730
|
+
function ThreadConnector({
|
|
2731
|
+
stopReason,
|
|
2732
|
+
isPending,
|
|
2733
|
+
isFirst,
|
|
2734
|
+
isLast
|
|
2735
|
+
}) {
|
|
2736
|
+
const isBoundary = stopReason === "end_turn" || stopReason === "stop";
|
|
2737
|
+
const isToolUse = stopReason === "tool_use";
|
|
2738
|
+
cn(
|
|
2739
|
+
"w-0.5 bg-muted-foreground/30",
|
|
2740
|
+
isPending && "border-dashed bg-transparent border-l-2 border-muted-foreground/20"
|
|
2741
|
+
);
|
|
2742
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-stretch h-full w-6 shrink-0 relative", children: [
|
|
2743
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "absolute left-1/2 -translate-x-1/2 w-0.5 top-0 flex flex-col items-center", children: [
|
|
2744
|
+
!isFirst && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2745
|
+
"div",
|
|
2746
|
+
{
|
|
2747
|
+
className: cn("w-0.5 grow", "bg-muted-foreground/30", "h-4"),
|
|
2748
|
+
style: { minHeight: "0.5rem" }
|
|
2749
|
+
}
|
|
2750
|
+
),
|
|
2751
|
+
isFirst && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-4" })
|
|
2752
|
+
] }),
|
|
2753
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute left-1/2 -translate-x-1/2 top-4 flex items-center justify-center z-10", children: isBoundary ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2754
|
+
"div",
|
|
2755
|
+
{
|
|
2756
|
+
className: cn(
|
|
2757
|
+
"size-2.5 rounded-full border-2",
|
|
2758
|
+
"bg-background border-amber-400",
|
|
2759
|
+
"shadow-[0_0_6px_rgba(251,191,36,0.4)]"
|
|
2760
|
+
),
|
|
2761
|
+
title: stopReason === "end_turn" ? "End of Turn (Anthropic)" : "End of Turn (OpenAI)"
|
|
2762
|
+
}
|
|
2763
|
+
) : isToolUse ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2764
|
+
"div",
|
|
2765
|
+
{
|
|
2766
|
+
className: "size-2 rounded-full bg-muted-foreground/25",
|
|
2767
|
+
title: "Tool Use — turn continues"
|
|
2768
|
+
}
|
|
2769
|
+
) : isPending ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2770
|
+
"div",
|
|
2771
|
+
{
|
|
2772
|
+
className: "size-2.5 rounded-full border-2 border-dashed border-muted-foreground/30 animate-pulse",
|
|
2773
|
+
title: "Response pending"
|
|
2774
|
+
}
|
|
2775
|
+
) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "size-1.5 rounded-full bg-muted-foreground/30" }) }),
|
|
2776
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
2777
|
+
"div",
|
|
2778
|
+
{
|
|
2779
|
+
className: "absolute left-1/2 -translate-x-1/2 w-0.5 top-4 flex flex-col items-center",
|
|
2780
|
+
style: { bottom: 0 },
|
|
2781
|
+
children: [
|
|
2782
|
+
!isBoundary && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2783
|
+
"div",
|
|
2784
|
+
{
|
|
2785
|
+
className: cn(
|
|
2786
|
+
"w-0.5 flex-1",
|
|
2787
|
+
isPending ? "border-dashed bg-transparent border-l-2 border-muted-foreground/20" : "bg-muted-foreground/30"
|
|
2641
2788
|
)
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
{
|
|
2646
|
-
responseText: log.responseText,
|
|
2647
|
-
responseStatus: log.responseStatus,
|
|
2648
|
-
streaming: log.streaming,
|
|
2649
|
-
inputTokens: log.inputTokens,
|
|
2650
|
-
outputTokens: log.outputTokens,
|
|
2651
|
-
cacheCreationInputTokens: log.cacheCreationInputTokens,
|
|
2652
|
-
cacheReadInputTokens: log.cacheReadInputTokens,
|
|
2653
|
-
apiFormat: log.apiFormat,
|
|
2654
|
-
error: log.error
|
|
2655
|
-
}
|
|
2656
|
-
) }) })
|
|
2657
|
-
] }) })
|
|
2789
|
+
}
|
|
2790
|
+
),
|
|
2791
|
+
isBoundary && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-0.5 h-4 bg-muted-foreground/10" })
|
|
2658
2792
|
]
|
|
2659
2793
|
}
|
|
2660
|
-
)
|
|
2661
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(ReplayDialog, { log, open: replayOpen, onOpenChange: setReplayOpen })
|
|
2794
|
+
)
|
|
2662
2795
|
] });
|
|
2663
|
-
}
|
|
2796
|
+
}
|
|
2664
2797
|
function computeStats(logs) {
|
|
2665
2798
|
let totalInput = 0;
|
|
2666
2799
|
let totalOutput = 0;
|
|
@@ -2675,14 +2808,20 @@ const ConversationGroup = reactExports.memo(function({
|
|
|
2675
2808
|
viewMode = "simple",
|
|
2676
2809
|
strip,
|
|
2677
2810
|
cacheTrends,
|
|
2678
|
-
|
|
2679
|
-
|
|
2811
|
+
onCompareWithPrevious,
|
|
2812
|
+
defaultGroupViewMode = "thread"
|
|
2680
2813
|
}) {
|
|
2681
2814
|
const [expanded, setExpanded] = reactExports.useState(false);
|
|
2815
|
+
const [groupViewMode, setGroupViewMode] = reactExports.useState(defaultGroupViewMode);
|
|
2816
|
+
reactExports.useEffect(() => {
|
|
2817
|
+
setGroupViewMode(defaultGroupViewMode);
|
|
2818
|
+
}, [defaultGroupViewMode]);
|
|
2682
2819
|
const stats = computeStats(group.logs);
|
|
2683
2820
|
const startTime = group.logs[0]?.timestamp ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
2684
2821
|
const endTime = group.logs[group.logs.length - 1]?.timestamp ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
2685
2822
|
const mixed = hasMixedApiFormat(group.logs);
|
|
2823
|
+
const isLoading = group.logs.some((log) => log.responseStatus === null);
|
|
2824
|
+
const stopReasons = reactExports.useMemo(() => group.logs.map((log) => extractStopReason(log)), [group.logs]);
|
|
2686
2825
|
const displayId = group.conversationId.startsWith("PID:") || group.conversationId.includes("|") ? group.conversationId : group.conversationId.length > 24 ? group.conversationId.slice(0, 12) + "…" + group.conversationId.slice(-12) : group.conversationId;
|
|
2687
2826
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-4", children: [
|
|
2688
2827
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -2697,10 +2836,13 @@ const ConversationGroup = reactExports.memo(function({
|
|
|
2697
2836
|
apiFormat: getGroupApiFormat(group.logs),
|
|
2698
2837
|
expanded,
|
|
2699
2838
|
onToggle: () => setExpanded(!expanded),
|
|
2700
|
-
hideApiFormat: mixed
|
|
2839
|
+
hideApiFormat: mixed,
|
|
2840
|
+
isLoading,
|
|
2841
|
+
viewMode: groupViewMode,
|
|
2842
|
+
onToggleViewMode: () => setGroupViewMode((prev) => prev === "thread" ? "flat" : "thread")
|
|
2701
2843
|
}
|
|
2702
2844
|
),
|
|
2703
|
-
expanded && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "pl-4 border-l-2 border-muted ml-3", children: group.logs.map((log) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2845
|
+
expanded && groupViewMode === "flat" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "pl-4 border-l-2 border-muted ml-3", children: group.logs.map((log) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2704
2846
|
LogEntry,
|
|
2705
2847
|
{
|
|
2706
2848
|
log,
|
|
@@ -2708,11 +2850,32 @@ const ConversationGroup = reactExports.memo(function({
|
|
|
2708
2850
|
suppressApiFormatBadge: !mixed,
|
|
2709
2851
|
strip,
|
|
2710
2852
|
cacheTrend: cacheTrends?.get(log.id) ?? null,
|
|
2711
|
-
|
|
2712
|
-
onToggleSelect
|
|
2853
|
+
onCompareWithPrevious: () => onCompareWithPrevious(log)
|
|
2713
2854
|
},
|
|
2714
2855
|
log.id
|
|
2715
|
-
)) })
|
|
2856
|
+
)) }),
|
|
2857
|
+
expanded && groupViewMode === "thread" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ml-3", children: group.logs.map((log, idx) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-stretch", children: [
|
|
2858
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2859
|
+
ThreadConnector,
|
|
2860
|
+
{
|
|
2861
|
+
stopReason: stopReasons[idx] ?? null,
|
|
2862
|
+
isPending: log.responseStatus === null,
|
|
2863
|
+
isFirst: idx === 0,
|
|
2864
|
+
isLast: idx === group.logs.length - 1
|
|
2865
|
+
}
|
|
2866
|
+
),
|
|
2867
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 min-w-0 mb-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2868
|
+
LogEntry,
|
|
2869
|
+
{
|
|
2870
|
+
log,
|
|
2871
|
+
viewMode,
|
|
2872
|
+
suppressApiFormatBadge: !mixed,
|
|
2873
|
+
strip,
|
|
2874
|
+
cacheTrend: cacheTrends?.get(log.id) ?? null,
|
|
2875
|
+
onCompareWithPrevious: () => onCompareWithPrevious(log)
|
|
2876
|
+
}
|
|
2877
|
+
) })
|
|
2878
|
+
] }, log.id)) })
|
|
2716
2879
|
] });
|
|
2717
2880
|
});
|
|
2718
2881
|
function CrabLogo({ className }) {
|
|
@@ -2760,7 +2923,7 @@ function SelectTrigger({
|
|
|
2760
2923
|
...props
|
|
2761
2924
|
}) {
|
|
2762
2925
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
2763
|
-
Trigger,
|
|
2926
|
+
Trigger$1,
|
|
2764
2927
|
{
|
|
2765
2928
|
"data-slot": "select-trigger",
|
|
2766
2929
|
"data-size": size,
|
|
@@ -2783,8 +2946,8 @@ function SelectContent({
|
|
|
2783
2946
|
align = "center",
|
|
2784
2947
|
...props
|
|
2785
2948
|
}) {
|
|
2786
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(Portal, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
2787
|
-
Content2,
|
|
2949
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Portal$1, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
2950
|
+
Content2$1,
|
|
2788
2951
|
{
|
|
2789
2952
|
"data-slot": "select-content",
|
|
2790
2953
|
className: cn(
|
|
@@ -3208,20 +3371,26 @@ function TestStatus({ result }) {
|
|
|
3208
3371
|
}
|
|
3209
3372
|
if (result.cacheCreationInputTokens !== void 0 && result.cacheCreationInputTokens > 0) {
|
|
3210
3373
|
tokenParts.push(
|
|
3211
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
3212
|
-
"
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3374
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
3375
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono tabular-nums text-emerald-400", children: [
|
|
3376
|
+
"+",
|
|
3377
|
+
result.cacheCreationInputTokens,
|
|
3378
|
+
" cache"
|
|
3379
|
+
] }) }),
|
|
3380
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Tokens cached for reuse, reducing future API cost" })
|
|
3381
|
+
] }) }, "cache-create")
|
|
3216
3382
|
);
|
|
3217
3383
|
}
|
|
3218
3384
|
if (result.cacheReadInputTokens !== void 0 && result.cacheReadInputTokens > 0) {
|
|
3219
3385
|
tokenParts.push(
|
|
3220
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
3221
|
-
"
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3386
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
3387
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono tabular-nums text-purple-400", children: [
|
|
3388
|
+
"~",
|
|
3389
|
+
result.cacheReadInputTokens,
|
|
3390
|
+
" cached"
|
|
3391
|
+
] }) }),
|
|
3392
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Tokens served from cache, reducing API cost" })
|
|
3393
|
+
] }) }, "cache-read")
|
|
3225
3394
|
);
|
|
3226
3395
|
}
|
|
3227
3396
|
const displayTokens = [];
|
|
@@ -3229,15 +3398,18 @@ function TestStatus({ result }) {
|
|
|
3229
3398
|
if (i > 0) displayTokens.push(", ");
|
|
3230
3399
|
displayTokens.push(tokenParts[i]);
|
|
3231
3400
|
}
|
|
3232
|
-
return /* @__PURE__ */ jsxRuntimeExports.
|
|
3233
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3401
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
3402
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 text-xs text-green-600 shrink-0", children: [
|
|
3403
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(CircleCheckBig, { className: "size-3" }),
|
|
3404
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Connected" }),
|
|
3405
|
+
tokenParts.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground", children: [
|
|
3406
|
+
"(",
|
|
3407
|
+
displayTokens,
|
|
3408
|
+
")"
|
|
3409
|
+
] })
|
|
3410
|
+
] }) }),
|
|
3411
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Connection test passed" })
|
|
3412
|
+
] }) });
|
|
3241
3413
|
}
|
|
3242
3414
|
const error = result.error;
|
|
3243
3415
|
const errorMessage = error?.message ?? "Connection failed";
|
|
@@ -3247,17 +3419,22 @@ function TestStatus({ result }) {
|
|
|
3247
3419
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1 shrink-0", children: [
|
|
3248
3420
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 text-xs text-red-600 max-w-[200px]", children: [
|
|
3249
3421
|
getErrorIcon(errorType),
|
|
3250
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3251
|
-
|
|
3252
|
-
"
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3422
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
3423
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate", children: errorMessage }) }),
|
|
3424
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Connection test failed" })
|
|
3425
|
+
] }) }),
|
|
3426
|
+
errorDetails !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
3427
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3428
|
+
"button",
|
|
3429
|
+
{
|
|
3430
|
+
type: "button",
|
|
3431
|
+
onClick: () => setShowDetails(!showDetails),
|
|
3432
|
+
className: "shrink-0 text-muted-foreground hover:text-foreground transition-colors",
|
|
3433
|
+
children: showDetails ? /* @__PURE__ */ jsxRuntimeExports.jsx(EyeOff, { className: "size-3" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Eye, { className: "size-3" })
|
|
3434
|
+
}
|
|
3435
|
+
) }),
|
|
3436
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: showDetails ? "Hide error details" : "Show detailed error information" })
|
|
3437
|
+
] }) })
|
|
3261
3438
|
] }),
|
|
3262
3439
|
showDetails && errorDetails !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-xs text-muted-foreground bg-muted/50 rounded p-2 max-w-[300px]", children: [
|
|
3263
3440
|
errorHint !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-1", children: errorHint }),
|
|
@@ -3328,8 +3505,14 @@ function ProviderCard({
|
|
|
3328
3505
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
|
|
3329
3506
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [
|
|
3330
3507
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium truncate", children: provider.name }),
|
|
3331
|
-
provider.source === "company" && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3332
|
-
|
|
3508
|
+
provider.source === "company" && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
3509
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs px-1.5 py-0.5 rounded bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400 shrink-0", children: "公司" }) }),
|
|
3510
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Company-provided API key" })
|
|
3511
|
+
] }) }),
|
|
3512
|
+
provider.source === "personal" && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
3513
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs px-1.5 py-0.5 rounded bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400 shrink-0", children: "个人" }) }),
|
|
3514
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Your personal API key" })
|
|
3515
|
+
] }) })
|
|
3333
3516
|
] }),
|
|
3334
3517
|
docsUrl !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
3335
3518
|
"a",
|
|
@@ -3808,24 +3991,30 @@ function ProviderForm({ provider, onSubmit, onCancel }) {
|
|
|
3808
3991
|
] }),
|
|
3809
3992
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
|
|
3810
3993
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-1 border-b border-border", children: [
|
|
3811
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
"
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3994
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
3995
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3996
|
+
"button",
|
|
3997
|
+
{
|
|
3998
|
+
type: "button",
|
|
3999
|
+
onClick: () => setActiveTab("anthropic"),
|
|
4000
|
+
className: `px-3 py-2 text-sm font-medium border-b-2 transition-colors ${activeTab === "anthropic" ? "border-primary text-primary" : "border-transparent text-muted-foreground hover:text-foreground"}`,
|
|
4001
|
+
children: "Anthropic Format"
|
|
4002
|
+
}
|
|
4003
|
+
) }),
|
|
4004
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Anthropic Messages API protocol" })
|
|
4005
|
+
] }) }),
|
|
4006
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
4007
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4008
|
+
"button",
|
|
4009
|
+
{
|
|
4010
|
+
type: "button",
|
|
4011
|
+
onClick: () => setActiveTab("openai"),
|
|
4012
|
+
className: `px-3 py-2 text-sm font-medium border-b-2 transition-colors ${activeTab === "openai" ? "border-primary text-primary" : "border-transparent text-muted-foreground hover:text-foreground"}`,
|
|
4013
|
+
children: "OpenAI Format"
|
|
4014
|
+
}
|
|
4015
|
+
) }),
|
|
4016
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "OpenAI Chat Completions API protocol" })
|
|
4017
|
+
] }) })
|
|
3829
4018
|
] }),
|
|
3830
4019
|
errors.format !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-destructive", children: errors.format })
|
|
3831
4020
|
] }),
|
|
@@ -4222,32 +4411,38 @@ function ProvidersPanel({
|
|
|
4222
4411
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between sticky top-0 z-10 bg-background pb-2", children: [
|
|
4223
4412
|
/* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-lg font-medium", children: "Providers" }),
|
|
4224
4413
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
4225
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4414
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
4415
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
4416
|
+
Button,
|
|
4417
|
+
{
|
|
4418
|
+
variant: "outline",
|
|
4419
|
+
size: "sm",
|
|
4420
|
+
onClick: () => handleExport(),
|
|
4421
|
+
className: "gap-1 hover:bg-muted",
|
|
4422
|
+
children: [
|
|
4423
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Download, { className: "size-3" }),
|
|
4424
|
+
"Export"
|
|
4425
|
+
]
|
|
4426
|
+
}
|
|
4427
|
+
) }),
|
|
4428
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Download providers as JSON for backup or sharing" })
|
|
4429
|
+
] }) }),
|
|
4430
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
4431
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
4432
|
+
Button,
|
|
4433
|
+
{
|
|
4434
|
+
variant: "outline",
|
|
4435
|
+
size: "sm",
|
|
4436
|
+
onClick: handleImportClick,
|
|
4437
|
+
className: "gap-1 hover:bg-muted",
|
|
4438
|
+
children: [
|
|
4439
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Upload, { className: "size-3" }),
|
|
4440
|
+
"Import"
|
|
4441
|
+
]
|
|
4442
|
+
}
|
|
4443
|
+
) }),
|
|
4444
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Import providers from an exported JSON file" })
|
|
4445
|
+
] }) }),
|
|
4251
4446
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4252
4447
|
"input",
|
|
4253
4448
|
{
|
|
@@ -4283,21 +4478,23 @@ function ProvidersPanel({
|
|
|
4283
4478
|
configPath !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground bg-muted/30 rounded-md px-3 py-2", children: [
|
|
4284
4479
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0", children: "Config:" }),
|
|
4285
4480
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono truncate", title: configPath, children: configPath }),
|
|
4286
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4481
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
4482
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4483
|
+
"button",
|
|
4484
|
+
{
|
|
4485
|
+
type: "button",
|
|
4486
|
+
onClick: () => {
|
|
4487
|
+
void window.navigator.clipboard.writeText(configPath).then(() => {
|
|
4488
|
+
setConfigPathCopied(true);
|
|
4489
|
+
setTimeout(() => setConfigPathCopied(false), 2e3);
|
|
4490
|
+
});
|
|
4491
|
+
},
|
|
4492
|
+
className: "shrink-0 ml-auto text-muted-foreground hover:text-foreground transition-colors",
|
|
4493
|
+
children: configPathCopied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-3 text-green-500" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-3" })
|
|
4494
|
+
}
|
|
4495
|
+
) }),
|
|
4496
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Copy config file path to clipboard" })
|
|
4497
|
+
] }) })
|
|
4301
4498
|
] }),
|
|
4302
4499
|
error !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-sm text-destructive bg-destructive/10 rounded-md px-3 py-2", children: [
|
|
4303
4500
|
/* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "size-4 shrink-0" }),
|
|
@@ -4310,16 +4507,18 @@ function ProvidersPanel({
|
|
|
4310
4507
|
"Add Your First Provider"
|
|
4311
4508
|
] })
|
|
4312
4509
|
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-3", children: [
|
|
4313
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex gap-1 border-b border-border", children: ["all", "personal", "company"].map((tab) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4510
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex gap-1 border-b border-border", children: ["all", "personal", "company"].map((tab) => /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
4511
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4512
|
+
"button",
|
|
4513
|
+
{
|
|
4514
|
+
type: "button",
|
|
4515
|
+
onClick: () => setSourceFilter(tab),
|
|
4516
|
+
className: `px-3 py-2 text-sm font-medium border-b-2 transition-colors ${sourceFilter === tab ? "border-primary text-primary" : "border-transparent text-muted-foreground hover:text-foreground"}`,
|
|
4517
|
+
children: tab === "all" ? "All" : tab === "personal" ? "Personal" : "Company"
|
|
4518
|
+
}
|
|
4519
|
+
) }),
|
|
4520
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: tab === "all" ? "Show all providers" : tab === "personal" ? "Providers you configured yourself" : "Providers set by your organization" })
|
|
4521
|
+
] }) }, tab)) }),
|
|
4323
4522
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: listScrollRef, className: "space-y-3", children: filteredProviders.map((provider) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4324
4523
|
ProviderCard,
|
|
4325
4524
|
{
|
|
@@ -4490,22 +4689,25 @@ function ProxySettingsTab() {
|
|
|
4490
4689
|
" and overrides the env var for subsequent requests."
|
|
4491
4690
|
] })
|
|
4492
4691
|
] }),
|
|
4493
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
4494
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4692
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
4693
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "flex items-center gap-3", children: [
|
|
4694
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4695
|
+
"input",
|
|
4696
|
+
{
|
|
4697
|
+
type: "checkbox",
|
|
4698
|
+
role: "switch",
|
|
4699
|
+
checked: strip,
|
|
4700
|
+
disabled: isLoading || pending,
|
|
4701
|
+
onChange: (e) => {
|
|
4702
|
+
void handleToggle(e.currentTarget.checked);
|
|
4703
|
+
},
|
|
4704
|
+
className: "size-4 cursor-pointer disabled:cursor-not-allowed disabled:opacity-50"
|
|
4705
|
+
}
|
|
4706
|
+
),
|
|
4707
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm", children: isLoading ? "Loading…" : strip ? "Stripping enabled" : "Stripping disabled" })
|
|
4708
|
+
] }) }),
|
|
4709
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Strip Claude Code billing header to improve cache hit rates" })
|
|
4710
|
+
] }) }),
|
|
4509
4711
|
error !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-xs text-destructive", children: [
|
|
4510
4712
|
"Failed to save: ",
|
|
4511
4713
|
error
|
|
@@ -5473,9 +5675,8 @@ function ProxyViewer({
|
|
|
5473
5675
|
}) {
|
|
5474
5676
|
const { totalIn, totalOut } = computeTokenSummary(logs);
|
|
5475
5677
|
const [groupedView, setGroupedView] = reactExports.useState(true);
|
|
5678
|
+
const [groupViewMode, setGroupViewMode] = reactExports.useState("thread");
|
|
5476
5679
|
const [exporting, setExporting] = reactExports.useState(false);
|
|
5477
|
-
const [selectedLogIds, setSelectedLogIds] = reactExports.useState([]);
|
|
5478
|
-
const [compareOpen, setCompareOpen] = reactExports.useState(false);
|
|
5479
5680
|
const [comparePair, setComparePair] = reactExports.useState(null);
|
|
5480
5681
|
const handleExport = reactExports.useCallback(async () => {
|
|
5481
5682
|
setExporting(true);
|
|
@@ -5486,76 +5687,26 @@ function ProxyViewer({
|
|
|
5486
5687
|
}
|
|
5487
5688
|
}, [logs]);
|
|
5488
5689
|
const parentRef = reactExports.useRef(null);
|
|
5489
|
-
const handleToggleSelect = reactExports.useCallback((logId) => {
|
|
5490
|
-
setSelectedLogIds((prev) => {
|
|
5491
|
-
if (prev.includes(logId)) {
|
|
5492
|
-
return prev.filter((id) => id !== logId);
|
|
5493
|
-
}
|
|
5494
|
-
if (prev.length < 2) {
|
|
5495
|
-
return [...prev, logId];
|
|
5496
|
-
}
|
|
5497
|
-
const newer = prev[1];
|
|
5498
|
-
if (newer === void 0) return prev;
|
|
5499
|
-
return [newer, logId];
|
|
5500
|
-
});
|
|
5501
|
-
}, []);
|
|
5502
5690
|
reactExports.useEffect(() => {
|
|
5503
|
-
|
|
5504
|
-
setCompareOpen(false);
|
|
5691
|
+
setComparePair(null);
|
|
5505
5692
|
}, [selectedSession, selectedModel]);
|
|
5506
|
-
const selectedSet = reactExports.useMemo(() => new Set(selectedLogIds), [selectedLogIds]);
|
|
5507
|
-
const openCompare = reactExports.useCallback(() => {
|
|
5508
|
-
if (selectedLogIds.length !== 2) return;
|
|
5509
|
-
const [idA, idB] = selectedLogIds;
|
|
5510
|
-
if (idA === void 0 || idB === void 0) return;
|
|
5511
|
-
const logA = logs.find((l) => l.id === idA);
|
|
5512
|
-
const logB = logs.find((l) => l.id === idB);
|
|
5513
|
-
if (logA === void 0 || logB === void 0) return;
|
|
5514
|
-
setComparePair([logA, logB]);
|
|
5515
|
-
setCompareOpen(true);
|
|
5516
|
-
}, [selectedLogIds, logs]);
|
|
5517
5693
|
const closeCompare = reactExports.useCallback(() => {
|
|
5518
|
-
|
|
5519
|
-
}, []);
|
|
5520
|
-
const clearSelection = reactExports.useCallback(() => {
|
|
5521
|
-
setSelectedLogIds([]);
|
|
5694
|
+
setComparePair(null);
|
|
5522
5695
|
}, []);
|
|
5523
|
-
const
|
|
5524
|
-
|
|
5525
|
-
|
|
5526
|
-
|
|
5527
|
-
|
|
5528
|
-
|
|
5529
|
-
|
|
5530
|
-
|
|
5531
|
-
|
|
5532
|
-
|
|
5533
|
-
const a = Date.parse(logA.timestamp);
|
|
5534
|
-
const b = Date.parse(logB.timestamp);
|
|
5535
|
-
if (!Number.isNaN(a) && !Number.isNaN(b)) {
|
|
5536
|
-
const ms = Math.abs(b - a);
|
|
5537
|
-
elapsed = formatElapsed2(ms);
|
|
5538
|
-
}
|
|
5539
|
-
}
|
|
5540
|
-
return {
|
|
5541
|
-
logA,
|
|
5542
|
-
logB,
|
|
5543
|
-
sameSession,
|
|
5544
|
-
elapsed
|
|
5545
|
-
};
|
|
5546
|
-
}, [selectedLogIds, logs]);
|
|
5547
|
-
function formatElapsed2(ms) {
|
|
5548
|
-
if (ms < 1e3) return `${ms}ms`;
|
|
5549
|
-
const sec = Math.floor(ms / 1e3);
|
|
5550
|
-
if (sec < 60) return `${sec}s`;
|
|
5551
|
-
const min = Math.floor(sec / 60);
|
|
5552
|
-
if (min < 60) return `${min}m`;
|
|
5553
|
-
const hr = Math.floor(min / 60);
|
|
5554
|
-
return `${hr}h${min % 60}m`;
|
|
5555
|
-
}
|
|
5696
|
+
const handleCompareWithPrevious = reactExports.useCallback(
|
|
5697
|
+
(log) => {
|
|
5698
|
+
const idx = logs.indexOf(log);
|
|
5699
|
+
if (idx <= 0) return;
|
|
5700
|
+
const predecessor = logs[idx - 1];
|
|
5701
|
+
if (predecessor === void 0) return;
|
|
5702
|
+
setComparePair([predecessor, log]);
|
|
5703
|
+
},
|
|
5704
|
+
[logs]
|
|
5705
|
+
);
|
|
5556
5706
|
const groups = reactExports.useMemo(() => groupLogsByConversation(logs), [logs]);
|
|
5557
5707
|
const cacheTrends = reactExports.useMemo(() => computeCacheTrends(groups), [groups]);
|
|
5558
|
-
const
|
|
5708
|
+
const stopReasons = reactExports.useMemo(() => logs.map((log) => extractStopReason(log)), [logs]);
|
|
5709
|
+
const renderGroups = logs.length > 0 && groupedView && groups.length > 1;
|
|
5559
5710
|
const rowVirtualizer = useVirtualizer({
|
|
5560
5711
|
count: renderGroups ? groups.length : logs.length,
|
|
5561
5712
|
getScrollElement: () => parentRef.current,
|
|
@@ -5575,26 +5726,29 @@ function ProxyViewer({
|
|
|
5575
5726
|
] })
|
|
5576
5727
|
] })
|
|
5577
5728
|
] }),
|
|
5578
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
5579
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5580
|
-
|
|
5581
|
-
|
|
5582
|
-
|
|
5583
|
-
|
|
5584
|
-
|
|
5585
|
-
|
|
5586
|
-
|
|
5587
|
-
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
|
|
5592
|
-
|
|
5593
|
-
|
|
5594
|
-
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
5729
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
5730
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center border border-border rounded-md overflow-hidden", children: [
|
|
5731
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5732
|
+
"button",
|
|
5733
|
+
{
|
|
5734
|
+
type: "button",
|
|
5735
|
+
onClick: () => onViewModeChange("simple"),
|
|
5736
|
+
className: `px-2 py-1 cursor-pointer transition-colors text-xs ${viewMode === "simple" ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted/50"}`,
|
|
5737
|
+
children: "Simple"
|
|
5738
|
+
}
|
|
5739
|
+
),
|
|
5740
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5741
|
+
"button",
|
|
5742
|
+
{
|
|
5743
|
+
type: "button",
|
|
5744
|
+
onClick: () => onViewModeChange("full"),
|
|
5745
|
+
className: `px-2 py-1 cursor-pointer transition-colors text-xs ${viewMode === "full" ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted/50"}`,
|
|
5746
|
+
children: "Full"
|
|
5747
|
+
}
|
|
5748
|
+
)
|
|
5749
|
+
] }) }),
|
|
5750
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Simple shows parsed output; Full adds raw headers and tokens" })
|
|
5751
|
+
] }) }),
|
|
5598
5752
|
/* @__PURE__ */ jsxRuntimeExports.jsx(SettingsDialog, {}),
|
|
5599
5753
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground text-xs font-mono", children: [
|
|
5600
5754
|
logs.length,
|
|
@@ -5665,6 +5819,28 @@ function ProxyViewer({
|
|
|
5665
5819
|
children: /* @__PURE__ */ jsxRuntimeExports.jsx(List, { className: "size-4" })
|
|
5666
5820
|
}
|
|
5667
5821
|
)
|
|
5822
|
+
] }),
|
|
5823
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center border border-border rounded-md overflow-hidden", children: [
|
|
5824
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5825
|
+
"button",
|
|
5826
|
+
{
|
|
5827
|
+
type: "button",
|
|
5828
|
+
onClick: () => setGroupViewMode("thread"),
|
|
5829
|
+
className: `px-2 py-1.5 cursor-pointer transition-colors ${groupViewMode === "thread" ? "bg-amber-500/15 text-amber-400 border-r border-amber-500/30" : "text-muted-foreground hover:bg-muted/50"}`,
|
|
5830
|
+
title: "Thread view (connected timeline)",
|
|
5831
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(GitBranch, { className: "size-4" })
|
|
5832
|
+
}
|
|
5833
|
+
),
|
|
5834
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5835
|
+
"button",
|
|
5836
|
+
{
|
|
5837
|
+
type: "button",
|
|
5838
|
+
onClick: () => setGroupViewMode("flat"),
|
|
5839
|
+
className: `px-2 py-1.5 cursor-pointer transition-colors ${groupViewMode === "flat" ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted/50"}`,
|
|
5840
|
+
title: "Flat view (card list)",
|
|
5841
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(List, { className: "size-4" })
|
|
5842
|
+
}
|
|
5843
|
+
)
|
|
5668
5844
|
] })
|
|
5669
5845
|
] }),
|
|
5670
5846
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 min-h-0 px-6 pb-6", children: logs.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center text-muted-foreground py-16 space-y-4", children: [
|
|
@@ -5702,8 +5878,8 @@ function ProxyViewer({
|
|
|
5702
5878
|
viewMode,
|
|
5703
5879
|
strip,
|
|
5704
5880
|
cacheTrends,
|
|
5705
|
-
|
|
5706
|
-
|
|
5881
|
+
onCompareWithPrevious: handleCompareWithPrevious,
|
|
5882
|
+
defaultGroupViewMode: groupViewMode
|
|
5707
5883
|
}
|
|
5708
5884
|
)
|
|
5709
5885
|
},
|
|
@@ -5712,6 +5888,7 @@ function ProxyViewer({
|
|
|
5712
5888
|
} else {
|
|
5713
5889
|
const log = logs[virtualRow.index];
|
|
5714
5890
|
if (log === void 0) return null;
|
|
5891
|
+
const idx = virtualRow.index;
|
|
5715
5892
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5716
5893
|
"div",
|
|
5717
5894
|
{
|
|
@@ -5724,15 +5901,34 @@ function ProxyViewer({
|
|
|
5724
5901
|
width: "100%",
|
|
5725
5902
|
transform: `translateY(${virtualRow.start}px)`
|
|
5726
5903
|
},
|
|
5727
|
-
children: /* @__PURE__ */ jsxRuntimeExports.
|
|
5904
|
+
children: groupViewMode === "thread" ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-stretch ml-3", children: [
|
|
5905
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5906
|
+
ThreadConnector,
|
|
5907
|
+
{
|
|
5908
|
+
stopReason: stopReasons[idx] ?? null,
|
|
5909
|
+
isPending: log.responseStatus === null,
|
|
5910
|
+
isFirst: idx === 0,
|
|
5911
|
+
isLast: idx === logs.length - 1
|
|
5912
|
+
}
|
|
5913
|
+
),
|
|
5914
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 min-w-0 mb-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5915
|
+
LogEntry,
|
|
5916
|
+
{
|
|
5917
|
+
log,
|
|
5918
|
+
viewMode,
|
|
5919
|
+
strip,
|
|
5920
|
+
cacheTrend: cacheTrends.get(log.id) ?? null,
|
|
5921
|
+
onCompareWithPrevious: () => handleCompareWithPrevious(log)
|
|
5922
|
+
}
|
|
5923
|
+
) })
|
|
5924
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5728
5925
|
LogEntry,
|
|
5729
5926
|
{
|
|
5730
5927
|
log,
|
|
5731
5928
|
viewMode,
|
|
5732
5929
|
strip,
|
|
5733
5930
|
cacheTrend: cacheTrends.get(log.id) ?? null,
|
|
5734
|
-
|
|
5735
|
-
onToggleSelect: handleToggleSelect
|
|
5931
|
+
onCompareWithPrevious: () => handleCompareWithPrevious(log)
|
|
5736
5932
|
}
|
|
5737
5933
|
)
|
|
5738
5934
|
},
|
|
@@ -5742,40 +5938,7 @@ function ProxyViewer({
|
|
|
5742
5938
|
})
|
|
5743
5939
|
}
|
|
5744
5940
|
) }) }),
|
|
5745
|
-
|
|
5746
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(GitCompareArrows, { className: "size-4 text-amber-400 shrink-0" }),
|
|
5747
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground font-mono", children: [
|
|
5748
|
-
"#",
|
|
5749
|
-
selectedSummary.logA.id,
|
|
5750
|
-
" ↔ #",
|
|
5751
|
-
selectedSummary.logB.id,
|
|
5752
|
-
" · ",
|
|
5753
|
-
selectedSummary.sameSession ? "same session" : "different sessions",
|
|
5754
|
-
selectedSummary.elapsed !== "" && ` · ${selectedSummary.elapsed} apart`
|
|
5755
|
-
] }),
|
|
5756
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
5757
|
-
"button",
|
|
5758
|
-
{
|
|
5759
|
-
type: "button",
|
|
5760
|
-
onClick: clearSelection,
|
|
5761
|
-
className: "text-muted-foreground hover:text-foreground transition-colors cursor-pointer inline-flex items-center gap-1",
|
|
5762
|
-
children: [
|
|
5763
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "size-3" }),
|
|
5764
|
-
"Clear"
|
|
5765
|
-
]
|
|
5766
|
-
}
|
|
5767
|
-
),
|
|
5768
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5769
|
-
"button",
|
|
5770
|
-
{
|
|
5771
|
-
type: "button",
|
|
5772
|
-
onClick: openCompare,
|
|
5773
|
-
className: "bg-amber-400 text-amber-950 hover:bg-amber-300 transition-colors px-3 py-1 rounded font-medium cursor-pointer",
|
|
5774
|
-
children: "Compare 2 logs"
|
|
5775
|
-
}
|
|
5776
|
-
)
|
|
5777
|
-
] }),
|
|
5778
|
-
compareOpen && comparePair !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(CompareDrawer, { left: comparePair[0], right: comparePair[1], onClose: closeCompare })
|
|
5941
|
+
comparePair !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(CompareDrawer, { left: comparePair[0], right: comparePair[1], onClose: closeCompare })
|
|
5779
5942
|
] });
|
|
5780
5943
|
}
|
|
5781
5944
|
object({
|