@tonyclaw/llm-inspector 1.14.6 → 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-Dp5657Eq.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/_libs/radix-ui__react-tooltip.mjs +1 -1
- package/.output/server/_ssr/{index-D2yS8VvO.mjs → index-9uTJ4xYR.mjs} +813 -595
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{router-DCfjmmJu.mjs → router-BKnjB_zi.mjs} +2 -2
- package/.output/server/{_tanstack-start-manifest_v-DupqJc5d.mjs → _tanstack-start-manifest_v-IsglLVKy.mjs} +1 -1
- package/.output/server/index.mjs +26 -26
- package/package.json +1 -1
- package/src/components/ProxyViewer.tsx +114 -146
- package/src/components/providers/ImportWizardDialog.tsx +6 -0
- package/src/components/providers/ProviderCard.tsx +79 -26
- package/src/components/providers/ProviderForm.tsx +37 -22
- package/src/components/providers/ProvidersPanel.tsx +118 -58
- 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/components/ui/confirm-dialog.tsx +51 -0
- package/src/lib/stopReason.ts +57 -0
- package/.output/public/assets/index-BFNoWwFI.css +0 -1
- package/.output/public/assets/index-LH-YtFEM.js +0 -105
|
@@ -1,21 +1,21 @@
|
|
|
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 {
|
|
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";
|
|
17
18
|
import { S as Slot } from "../_libs/radix-ui__react-slot.mjs";
|
|
18
|
-
import { P as Provider, R as Root3, T as Trigger$3, a as Portal$2, C as Content2$1, A as Arrow2 } from "../_libs/radix-ui__react-tooltip.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";
|
|
21
21
|
import { R as Root$3, V as Viewport$1, C as Corner, S as ScrollAreaScrollbar, a as ScrollAreaThumb } from "../_libs/radix-ui__react-scroll-area.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(
|
|
@@ -3015,6 +3178,10 @@ function ImportWizardDialog({
|
|
|
3015
3178
|
return;
|
|
3016
3179
|
}
|
|
3017
3180
|
const result = parsed.data;
|
|
3181
|
+
setProviders(
|
|
3182
|
+
(prev) => prev.map((p, i) => selected.has(i) ? { ...p, alreadyExists: true } : p)
|
|
3183
|
+
);
|
|
3184
|
+
setSelected(/* @__PURE__ */ new Set());
|
|
3018
3185
|
if (result.errors !== void 0 && result.errors.length > 0 && result.message !== void 0) {
|
|
3019
3186
|
setImportResult(result.message);
|
|
3020
3187
|
} else {
|
|
@@ -3109,6 +3276,35 @@ function ImportWizardDialog({
|
|
|
3109
3276
|
] })
|
|
3110
3277
|
] }) });
|
|
3111
3278
|
}
|
|
3279
|
+
function ConfirmDialog({
|
|
3280
|
+
open,
|
|
3281
|
+
onOpenChange,
|
|
3282
|
+
title,
|
|
3283
|
+
description,
|
|
3284
|
+
confirmLabel = "Confirm",
|
|
3285
|
+
variant = "default",
|
|
3286
|
+
onConfirm
|
|
3287
|
+
}) {
|
|
3288
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogContent, { children: [
|
|
3289
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(DialogHeader, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(DialogTitle, { children: title }) }),
|
|
3290
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-muted-foreground", children: description }),
|
|
3291
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-end gap-2 pt-2", children: [
|
|
3292
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Button, { variant: "outline", size: "sm", onClick: () => onOpenChange(false), children: "Cancel" }),
|
|
3293
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3294
|
+
Button,
|
|
3295
|
+
{
|
|
3296
|
+
variant,
|
|
3297
|
+
size: "sm",
|
|
3298
|
+
onClick: () => {
|
|
3299
|
+
onConfirm();
|
|
3300
|
+
onOpenChange(false);
|
|
3301
|
+
},
|
|
3302
|
+
children: confirmLabel
|
|
3303
|
+
}
|
|
3304
|
+
)
|
|
3305
|
+
] })
|
|
3306
|
+
] }) });
|
|
3307
|
+
}
|
|
3112
3308
|
function maskApiKey(apiKey) {
|
|
3113
3309
|
if (apiKey.length <= 8) return "••••••••";
|
|
3114
3310
|
return apiKey.slice(0, 4) + "••••••••" + apiKey.slice(-4);
|
|
@@ -3175,20 +3371,26 @@ function TestStatus({ result }) {
|
|
|
3175
3371
|
}
|
|
3176
3372
|
if (result.cacheCreationInputTokens !== void 0 && result.cacheCreationInputTokens > 0) {
|
|
3177
3373
|
tokenParts.push(
|
|
3178
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
3179
|
-
"
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
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")
|
|
3183
3382
|
);
|
|
3184
3383
|
}
|
|
3185
3384
|
if (result.cacheReadInputTokens !== void 0 && result.cacheReadInputTokens > 0) {
|
|
3186
3385
|
tokenParts.push(
|
|
3187
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
3188
|
-
"
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
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")
|
|
3192
3394
|
);
|
|
3193
3395
|
}
|
|
3194
3396
|
const displayTokens = [];
|
|
@@ -3196,15 +3398,18 @@ function TestStatus({ result }) {
|
|
|
3196
3398
|
if (i > 0) displayTokens.push(", ");
|
|
3197
3399
|
displayTokens.push(tokenParts[i]);
|
|
3198
3400
|
}
|
|
3199
|
-
return /* @__PURE__ */ jsxRuntimeExports.
|
|
3200
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
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
|
+
] }) });
|
|
3208
3413
|
}
|
|
3209
3414
|
const error = result.error;
|
|
3210
3415
|
const errorMessage = error?.message ?? "Connection failed";
|
|
@@ -3214,17 +3419,22 @@ function TestStatus({ result }) {
|
|
|
3214
3419
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1 shrink-0", children: [
|
|
3215
3420
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 text-xs text-red-600 max-w-[200px]", children: [
|
|
3216
3421
|
getErrorIcon(errorType),
|
|
3217
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3218
|
-
|
|
3219
|
-
"
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
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
|
+
] }) })
|
|
3228
3438
|
] }),
|
|
3229
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: [
|
|
3230
3440
|
errorHint !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-1", children: errorHint }),
|
|
@@ -3295,8 +3505,14 @@ function ProviderCard({
|
|
|
3295
3505
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
|
|
3296
3506
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [
|
|
3297
3507
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium truncate", children: provider.name }),
|
|
3298
|
-
provider.source === "company" && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3299
|
-
|
|
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
|
+
] }) })
|
|
3300
3516
|
] }),
|
|
3301
3517
|
docsUrl !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
3302
3518
|
"a",
|
|
@@ -3775,24 +3991,30 @@ function ProviderForm({ provider, onSubmit, onCancel }) {
|
|
|
3775
3991
|
] }),
|
|
3776
3992
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
|
|
3777
3993
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-1 border-b border-border", children: [
|
|
3778
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
"
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
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
|
+
] }) })
|
|
3796
4018
|
] }),
|
|
3797
4019
|
errors.format !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-destructive", children: errors.format })
|
|
3798
4020
|
] }),
|
|
@@ -3900,6 +4122,8 @@ function ProvidersPanel({
|
|
|
3900
4122
|
const [configPathCopied, setConfigPathCopied] = reactExports.useState(false);
|
|
3901
4123
|
const [highlightedProviderId, setHighlightedProviderId] = reactExports.useState(null);
|
|
3902
4124
|
const [showImportWizard, setShowImportWizard] = reactExports.useState(false);
|
|
4125
|
+
const [confirmOpen, setConfirmOpen] = reactExports.useState(false);
|
|
4126
|
+
const [deletingProviderId, setDeletingProviderId] = reactExports.useState(null);
|
|
3903
4127
|
const [sourceFilter, setSourceFilter] = reactExports.useState("all");
|
|
3904
4128
|
const listScrollRef = reactExports.useRef(null);
|
|
3905
4129
|
const highlightTimeoutRef = reactExports.useRef(null);
|
|
@@ -4088,7 +4312,12 @@ function ProvidersPanel({
|
|
|
4088
4312
|
})();
|
|
4089
4313
|
}
|
|
4090
4314
|
function handleDeleteProvider(providerId) {
|
|
4091
|
-
|
|
4315
|
+
setDeletingProviderId(providerId);
|
|
4316
|
+
setConfirmOpen(true);
|
|
4317
|
+
}
|
|
4318
|
+
function executeDelete() {
|
|
4319
|
+
const providerId = deletingProviderId;
|
|
4320
|
+
if (providerId === null) return;
|
|
4092
4321
|
void (async () => {
|
|
4093
4322
|
let res;
|
|
4094
4323
|
try {
|
|
@@ -4182,32 +4411,38 @@ function ProvidersPanel({
|
|
|
4182
4411
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between sticky top-0 z-10 bg-background pb-2", children: [
|
|
4183
4412
|
/* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-lg font-medium", children: "Providers" }),
|
|
4184
4413
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
4185
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
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
|
+
] }) }),
|
|
4211
4446
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4212
4447
|
"input",
|
|
4213
4448
|
{
|
|
@@ -4218,19 +4453,22 @@ function ProvidersPanel({
|
|
|
4218
4453
|
style: { display: "none" }
|
|
4219
4454
|
}
|
|
4220
4455
|
),
|
|
4221
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4456
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
4457
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
4458
|
+
Button,
|
|
4459
|
+
{
|
|
4460
|
+
variant: "outline",
|
|
4461
|
+
size: "sm",
|
|
4462
|
+
onClick: () => setShowImportWizard(true),
|
|
4463
|
+
className: "gap-1",
|
|
4464
|
+
children: [
|
|
4465
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Scan, { className: "size-3" }),
|
|
4466
|
+
"Scan"
|
|
4467
|
+
]
|
|
4468
|
+
}
|
|
4469
|
+
) }),
|
|
4470
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Detect and import provider configs from Claude Code and OpenCode" })
|
|
4471
|
+
] }) }),
|
|
4234
4472
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(Button, { onClick: () => setShowForm(true), size: "sm", className: "gap-1", children: [
|
|
4235
4473
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "size-4" }),
|
|
4236
4474
|
"Add Provider"
|
|
@@ -4240,21 +4478,23 @@ function ProvidersPanel({
|
|
|
4240
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: [
|
|
4241
4479
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0", children: "Config:" }),
|
|
4242
4480
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono truncate", title: configPath, children: configPath }),
|
|
4243
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
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
|
+
] }) })
|
|
4258
4498
|
] }),
|
|
4259
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: [
|
|
4260
4500
|
/* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "size-4 shrink-0" }),
|
|
@@ -4267,16 +4507,18 @@ function ProvidersPanel({
|
|
|
4267
4507
|
"Add Your First Provider"
|
|
4268
4508
|
] })
|
|
4269
4509
|
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-3", children: [
|
|
4270
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex gap-1 border-b border-border", children: ["all", "personal", "company"].map((tab) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
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)) }),
|
|
4280
4522
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: listScrollRef, className: "space-y-3", children: filteredProviders.map((provider) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4281
4523
|
ProviderCard,
|
|
4282
4524
|
{
|
|
@@ -4305,6 +4547,18 @@ function ProvidersPanel({
|
|
|
4305
4547
|
}
|
|
4306
4548
|
}
|
|
4307
4549
|
}
|
|
4550
|
+
),
|
|
4551
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4552
|
+
ConfirmDialog,
|
|
4553
|
+
{
|
|
4554
|
+
open: confirmOpen,
|
|
4555
|
+
onOpenChange: setConfirmOpen,
|
|
4556
|
+
title: "Delete Provider",
|
|
4557
|
+
description: "Are you sure you want to delete this provider? This action cannot be undone.",
|
|
4558
|
+
confirmLabel: "Delete",
|
|
4559
|
+
variant: "destructive",
|
|
4560
|
+
onConfirm: executeDelete
|
|
4561
|
+
}
|
|
4308
4562
|
)
|
|
4309
4563
|
] });
|
|
4310
4564
|
}
|
|
@@ -4435,22 +4689,25 @@ function ProxySettingsTab() {
|
|
|
4435
4689
|
" and overrides the env var for subsequent requests."
|
|
4436
4690
|
] })
|
|
4437
4691
|
] }),
|
|
4438
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
4439
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
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
|
+
] }) }),
|
|
4454
4711
|
error !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-xs text-destructive", children: [
|
|
4455
4712
|
"Failed to save: ",
|
|
4456
4713
|
error
|
|
@@ -5418,9 +5675,8 @@ function ProxyViewer({
|
|
|
5418
5675
|
}) {
|
|
5419
5676
|
const { totalIn, totalOut } = computeTokenSummary(logs);
|
|
5420
5677
|
const [groupedView, setGroupedView] = reactExports.useState(true);
|
|
5678
|
+
const [groupViewMode, setGroupViewMode] = reactExports.useState("thread");
|
|
5421
5679
|
const [exporting, setExporting] = reactExports.useState(false);
|
|
5422
|
-
const [selectedLogIds, setSelectedLogIds] = reactExports.useState([]);
|
|
5423
|
-
const [compareOpen, setCompareOpen] = reactExports.useState(false);
|
|
5424
5680
|
const [comparePair, setComparePair] = reactExports.useState(null);
|
|
5425
5681
|
const handleExport = reactExports.useCallback(async () => {
|
|
5426
5682
|
setExporting(true);
|
|
@@ -5431,76 +5687,26 @@ function ProxyViewer({
|
|
|
5431
5687
|
}
|
|
5432
5688
|
}, [logs]);
|
|
5433
5689
|
const parentRef = reactExports.useRef(null);
|
|
5434
|
-
const handleToggleSelect = reactExports.useCallback((logId) => {
|
|
5435
|
-
setSelectedLogIds((prev) => {
|
|
5436
|
-
if (prev.includes(logId)) {
|
|
5437
|
-
return prev.filter((id) => id !== logId);
|
|
5438
|
-
}
|
|
5439
|
-
if (prev.length < 2) {
|
|
5440
|
-
return [...prev, logId];
|
|
5441
|
-
}
|
|
5442
|
-
const newer = prev[1];
|
|
5443
|
-
if (newer === void 0) return prev;
|
|
5444
|
-
return [newer, logId];
|
|
5445
|
-
});
|
|
5446
|
-
}, []);
|
|
5447
5690
|
reactExports.useEffect(() => {
|
|
5448
|
-
|
|
5449
|
-
setCompareOpen(false);
|
|
5691
|
+
setComparePair(null);
|
|
5450
5692
|
}, [selectedSession, selectedModel]);
|
|
5451
|
-
const selectedSet = reactExports.useMemo(() => new Set(selectedLogIds), [selectedLogIds]);
|
|
5452
|
-
const openCompare = reactExports.useCallback(() => {
|
|
5453
|
-
if (selectedLogIds.length !== 2) return;
|
|
5454
|
-
const [idA, idB] = selectedLogIds;
|
|
5455
|
-
if (idA === void 0 || idB === void 0) return;
|
|
5456
|
-
const logA = logs.find((l) => l.id === idA);
|
|
5457
|
-
const logB = logs.find((l) => l.id === idB);
|
|
5458
|
-
if (logA === void 0 || logB === void 0) return;
|
|
5459
|
-
setComparePair([logA, logB]);
|
|
5460
|
-
setCompareOpen(true);
|
|
5461
|
-
}, [selectedLogIds, logs]);
|
|
5462
5693
|
const closeCompare = reactExports.useCallback(() => {
|
|
5463
|
-
|
|
5694
|
+
setComparePair(null);
|
|
5464
5695
|
}, []);
|
|
5465
|
-
const
|
|
5466
|
-
|
|
5467
|
-
|
|
5468
|
-
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
|
|
5472
|
-
|
|
5473
|
-
|
|
5474
|
-
|
|
5475
|
-
const sameSession = getConversationId(logA) === getConversationId(logB);
|
|
5476
|
-
let elapsed = "";
|
|
5477
|
-
if (logA.timestamp !== null && logB.timestamp !== null) {
|
|
5478
|
-
const a = Date.parse(logA.timestamp);
|
|
5479
|
-
const b = Date.parse(logB.timestamp);
|
|
5480
|
-
if (!Number.isNaN(a) && !Number.isNaN(b)) {
|
|
5481
|
-
const ms = Math.abs(b - a);
|
|
5482
|
-
elapsed = formatElapsed2(ms);
|
|
5483
|
-
}
|
|
5484
|
-
}
|
|
5485
|
-
return {
|
|
5486
|
-
logA,
|
|
5487
|
-
logB,
|
|
5488
|
-
sameSession,
|
|
5489
|
-
elapsed
|
|
5490
|
-
};
|
|
5491
|
-
}, [selectedLogIds, logs]);
|
|
5492
|
-
function formatElapsed2(ms) {
|
|
5493
|
-
if (ms < 1e3) return `${ms}ms`;
|
|
5494
|
-
const sec = Math.floor(ms / 1e3);
|
|
5495
|
-
if (sec < 60) return `${sec}s`;
|
|
5496
|
-
const min = Math.floor(sec / 60);
|
|
5497
|
-
if (min < 60) return `${min}m`;
|
|
5498
|
-
const hr = Math.floor(min / 60);
|
|
5499
|
-
return `${hr}h${min % 60}m`;
|
|
5500
|
-
}
|
|
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
|
+
);
|
|
5501
5706
|
const groups = reactExports.useMemo(() => groupLogsByConversation(logs), [logs]);
|
|
5502
5707
|
const cacheTrends = reactExports.useMemo(() => computeCacheTrends(groups), [groups]);
|
|
5503
|
-
const
|
|
5708
|
+
const stopReasons = reactExports.useMemo(() => logs.map((log) => extractStopReason(log)), [logs]);
|
|
5709
|
+
const renderGroups = logs.length > 0 && groupedView && groups.length > 1;
|
|
5504
5710
|
const rowVirtualizer = useVirtualizer({
|
|
5505
5711
|
count: renderGroups ? groups.length : logs.length,
|
|
5506
5712
|
getScrollElement: () => parentRef.current,
|
|
@@ -5520,26 +5726,29 @@ function ProxyViewer({
|
|
|
5520
5726
|
] })
|
|
5521
5727
|
] })
|
|
5522
5728
|
] }),
|
|
5523
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
5524
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5525
|
-
|
|
5526
|
-
|
|
5527
|
-
|
|
5528
|
-
|
|
5529
|
-
|
|
5530
|
-
|
|
5531
|
-
|
|
5532
|
-
|
|
5533
|
-
|
|
5534
|
-
|
|
5535
|
-
|
|
5536
|
-
|
|
5537
|
-
|
|
5538
|
-
|
|
5539
|
-
|
|
5540
|
-
|
|
5541
|
-
|
|
5542
|
-
|
|
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
|
+
] }) }),
|
|
5543
5752
|
/* @__PURE__ */ jsxRuntimeExports.jsx(SettingsDialog, {}),
|
|
5544
5753
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground text-xs font-mono", children: [
|
|
5545
5754
|
logs.length,
|
|
@@ -5610,6 +5819,28 @@ function ProxyViewer({
|
|
|
5610
5819
|
children: /* @__PURE__ */ jsxRuntimeExports.jsx(List, { className: "size-4" })
|
|
5611
5820
|
}
|
|
5612
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
|
+
)
|
|
5613
5844
|
] })
|
|
5614
5845
|
] }),
|
|
5615
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: [
|
|
@@ -5647,8 +5878,8 @@ function ProxyViewer({
|
|
|
5647
5878
|
viewMode,
|
|
5648
5879
|
strip,
|
|
5649
5880
|
cacheTrends,
|
|
5650
|
-
|
|
5651
|
-
|
|
5881
|
+
onCompareWithPrevious: handleCompareWithPrevious,
|
|
5882
|
+
defaultGroupViewMode: groupViewMode
|
|
5652
5883
|
}
|
|
5653
5884
|
)
|
|
5654
5885
|
},
|
|
@@ -5657,6 +5888,7 @@ function ProxyViewer({
|
|
|
5657
5888
|
} else {
|
|
5658
5889
|
const log = logs[virtualRow.index];
|
|
5659
5890
|
if (log === void 0) return null;
|
|
5891
|
+
const idx = virtualRow.index;
|
|
5660
5892
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5661
5893
|
"div",
|
|
5662
5894
|
{
|
|
@@ -5669,15 +5901,34 @@ function ProxyViewer({
|
|
|
5669
5901
|
width: "100%",
|
|
5670
5902
|
transform: `translateY(${virtualRow.start}px)`
|
|
5671
5903
|
},
|
|
5672
|
-
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(
|
|
5673
5925
|
LogEntry,
|
|
5674
5926
|
{
|
|
5675
5927
|
log,
|
|
5676
5928
|
viewMode,
|
|
5677
5929
|
strip,
|
|
5678
5930
|
cacheTrend: cacheTrends.get(log.id) ?? null,
|
|
5679
|
-
|
|
5680
|
-
onToggleSelect: handleToggleSelect
|
|
5931
|
+
onCompareWithPrevious: () => handleCompareWithPrevious(log)
|
|
5681
5932
|
}
|
|
5682
5933
|
)
|
|
5683
5934
|
},
|
|
@@ -5687,40 +5938,7 @@ function ProxyViewer({
|
|
|
5687
5938
|
})
|
|
5688
5939
|
}
|
|
5689
5940
|
) }) }),
|
|
5690
|
-
|
|
5691
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(GitCompareArrows, { className: "size-4 text-amber-400 shrink-0" }),
|
|
5692
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground font-mono", children: [
|
|
5693
|
-
"#",
|
|
5694
|
-
selectedSummary.logA.id,
|
|
5695
|
-
" ↔ #",
|
|
5696
|
-
selectedSummary.logB.id,
|
|
5697
|
-
" · ",
|
|
5698
|
-
selectedSummary.sameSession ? "same session" : "different sessions",
|
|
5699
|
-
selectedSummary.elapsed !== "" && ` · ${selectedSummary.elapsed} apart`
|
|
5700
|
-
] }),
|
|
5701
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
5702
|
-
"button",
|
|
5703
|
-
{
|
|
5704
|
-
type: "button",
|
|
5705
|
-
onClick: clearSelection,
|
|
5706
|
-
className: "text-muted-foreground hover:text-foreground transition-colors cursor-pointer inline-flex items-center gap-1",
|
|
5707
|
-
children: [
|
|
5708
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "size-3" }),
|
|
5709
|
-
"Clear"
|
|
5710
|
-
]
|
|
5711
|
-
}
|
|
5712
|
-
),
|
|
5713
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5714
|
-
"button",
|
|
5715
|
-
{
|
|
5716
|
-
type: "button",
|
|
5717
|
-
onClick: openCompare,
|
|
5718
|
-
className: "bg-amber-400 text-amber-950 hover:bg-amber-300 transition-colors px-3 py-1 rounded font-medium cursor-pointer",
|
|
5719
|
-
children: "Compare 2 logs"
|
|
5720
|
-
}
|
|
5721
|
-
)
|
|
5722
|
-
] }),
|
|
5723
|
-
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 })
|
|
5724
5942
|
] });
|
|
5725
5943
|
}
|
|
5726
5944
|
object({
|