@tonyclaw/llm-inspector 1.18.0 → 1.18.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.output/nitro.json +1 -1
- package/.output/public/assets/CompareDrawer-C-4ypEWs.js +1 -0
- package/.output/public/assets/ProxyViewerContainer-WRenRpeh.js +101 -0
- package/.output/public/assets/ReplayDialog-CyBKOgba.js +1 -0
- package/.output/public/assets/RequestAnatomy-C0IrVQ3q.js +1 -0
- package/.output/public/assets/ResponseView-MogToC4i.js +1 -0
- package/.output/public/assets/StreamingChunkSequence-ClhUhT-s.js +1 -0
- package/.output/public/assets/_sessionId-BO47oA3Z.js +1 -0
- package/.output/public/assets/index-BRvz6-L6.css +1 -0
- package/.output/public/assets/index-Btw8ec7-.js +1 -0
- package/.output/public/assets/{json-viewer-D-z1r1Pp.js → json-viewer-BicGakI5.js} +1 -1
- package/.output/public/assets/{main-CZJ63sQh.js → main-Be2qqUUW.js} +8 -7
- package/.output/server/_libs/lucide-react.mjs +23 -17
- package/.output/server/_sessionId-DhKJIdQC.mjs +122 -0
- package/.output/server/_ssr/{CompareDrawer-BJr-913n.mjs → CompareDrawer-BGUgukJ8.mjs} +57 -57
- package/.output/server/_ssr/{index-C7I_Qgt0.mjs → ProxyViewerContainer--3K3o3Sm.mjs} +277 -191
- package/.output/server/_ssr/{ReplayDialog-BwmToGuR.mjs → ReplayDialog-Bo86xZI4.mjs} +57 -57
- package/.output/server/_ssr/{RequestAnatomy-BmMiPRPB.mjs → RequestAnatomy-jRU5qgwB.mjs} +4 -4
- package/.output/server/_ssr/{ResponseView-ZB9-8Raw.mjs → ResponseView-DdO_-79a.mjs} +5 -5
- package/.output/server/_ssr/{StreamingChunkSequence-DWm4CQWC.mjs → StreamingChunkSequence-BigLwhh4.mjs} +57 -57
- package/.output/server/_ssr/index-BHG6vOnr.mjs +117 -0
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{json-viewer-D9XETzwp.mjs → json-viewer-B4c_WjXD.mjs} +4 -4
- package/.output/server/_ssr/{router-711KpGkz.mjs → router-DVixpJO-.mjs} +79 -22
- package/.output/server/_tanstack-start-manifest_v-BbvWUF4v.mjs +4 -0
- package/.output/server/index.mjs +70 -56
- package/README.md +109 -59
- package/package.json +1 -1
- package/src/assets/logos/mcp.png +0 -0
- package/src/components/ProxyViewer.tsx +240 -64
- package/src/components/ProxyViewerContainer.tsx +42 -11
- package/src/components/proxy-viewer/ConversationGroup.tsx +1 -8
- package/src/components/proxy-viewer/ConversationHeader.tsx +35 -7
- package/src/components/ui/mcp-logo.tsx +20 -0
- package/src/lib/sessionUrl.ts +44 -0
- package/src/routes/session/$sessionId.tsx +23 -0
- package/.output/public/assets/CompareDrawer-BpwZCB6M.js +0 -1
- package/.output/public/assets/ReplayDialog-Clratkzl.js +0 -1
- package/.output/public/assets/RequestAnatomy-EtiX0r_G.js +0 -1
- package/.output/public/assets/ResponseView-CJqxo-EN.js +0 -1
- package/.output/public/assets/StreamingChunkSequence-BIbRqQiV.js +0 -1
- package/.output/public/assets/index-B-0F9n1w.js +0 -101
- package/.output/public/assets/index-DoGvsnbA.css +0 -1
- package/.output/server/_tanstack-start-manifest_v-noQw0Vmw.mjs +0 -4
|
@@ -1,115 +1,19 @@
|
|
|
1
1
|
import { r as reactExports, j as jsxRuntimeExports, a as React } from "../_libs/react.mjs";
|
|
2
|
-
import { C as CapturedLogSchema, D as DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS,
|
|
2
|
+
import { C as CapturedLogSchema, D as DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS, a as RuntimeConfigSchema, r as requestFormatForPath, c as createPendingProviderTestResults, P as ProviderTestResultsSchema, d as createFailedProviderTestResults, M as MAX_SLOW_RESPONSE_THRESHOLD_SECONDS, g as getSessionPath, e as ProviderConfigSchema, s as stripClaudeCodeBillingHeader, p as parseOpenAIResponse, O as OpenAIRequestSchema, A as AnthropicResponseSchema$1, b as AnthropicRequestSchema } from "./router-DVixpJO-.mjs";
|
|
3
3
|
import { u as useSWR, a as useSWRConfig } from "../_libs/swr.mjs";
|
|
4
4
|
import { J as JSZip } from "../_libs/jszip.mjs";
|
|
5
5
|
import { c as clsx } from "../_libs/clsx.mjs";
|
|
6
6
|
import { t as twMerge } from "../_libs/tailwind-merge.mjs";
|
|
7
7
|
import { c as cva } from "../_libs/class-variance-authority.mjs";
|
|
8
|
-
import { R as Root, T as Trigger$
|
|
8
|
+
import { R as Root, T as Trigger$2, C as Content, a as Close, b as Title, P as Portal$2, O as Overlay } from "../_libs/radix-ui__react-dialog.mjs";
|
|
9
9
|
import { d as diffJson, a as diffLines } from "../_libs/diff.mjs";
|
|
10
10
|
import { u as useVirtualizer } from "../_libs/tanstack__react-virtual.mjs";
|
|
11
11
|
import { R as Root2, T as Trigger, I as Icon, V as Value, P as Portal, C as Content2, a as Viewport, b as Item, c as ItemIndicator, d as ItemText, S as ScrollUpButton, e as ScrollDownButton } from "../_libs/radix-ui__react-select.mjs";
|
|
12
|
-
import { C as Check, X, D as Download, S as Settings,
|
|
12
|
+
import { C as Check, X, P as Plus, D as Download, S as Settings, A as ArrowLeft, a as Copy, b as ChevronDown, U as Upload, c as Scan, d as CircleAlert, e as ChevronUp, L as LoaderCircle, f as ChevronRight, g as User, h as Clock, M as MessageSquare, Z as Zap, E as ExternalLink, T as Trash2, i as TriangleAlert, j as EyeOff, k as Eye, R as RotateCw, l as Pencil, G as GitCompareArrows, m as Minus, n as CircleCheckBig, O as OctagonAlert, W as Wrench, o as Globe, F as FileTerminal, p as Radio, q as ChevronsUp, r as ChevronsDown, s as RotateCcw, t as CircleQuestionMark, u as Server, v as Gauge, w as Lock, x as Wifi, y as WifiOff, z as ArrowUp, B as ArrowDown, H as Rows3, I as Columns2 } from "../_libs/lucide-react.mjs";
|
|
13
13
|
import { u as union, d as object, a as array, l as literal, b as string, n as number, c as boolean, _ as _enum } from "../_libs/zod.mjs";
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
14
|
+
import { P as Provider, R as Root3, T as Trigger$1, a as Portal$1, C as Content2$1, A as Arrow2 } from "../_libs/radix-ui__react-tooltip.mjs";
|
|
15
|
+
import { R as Root2$1, L as List, T as Trigger$3, C as Content$1 } from "../_libs/radix-ui__react-tabs.mjs";
|
|
16
16
|
import { S as Slot } from "../_libs/radix-ui__react-slot.mjs";
|
|
17
|
-
import "../_libs/tanstack__react-router.mjs";
|
|
18
|
-
import "../_libs/tiny-warning.mjs";
|
|
19
|
-
import "../_libs/tanstack__router-core.mjs";
|
|
20
|
-
import "../_libs/cookie-es.mjs";
|
|
21
|
-
import "../_libs/tanstack__history.mjs";
|
|
22
|
-
import "../_libs/tiny-invariant.mjs";
|
|
23
|
-
import "../_libs/seroval.mjs";
|
|
24
|
-
import "../_libs/seroval-plugins.mjs";
|
|
25
|
-
import "node:stream/web";
|
|
26
|
-
import "node:stream";
|
|
27
|
-
import "../_libs/react-dom.mjs";
|
|
28
|
-
import "util";
|
|
29
|
-
import "async_hooks";
|
|
30
|
-
import "stream";
|
|
31
|
-
import "crypto";
|
|
32
|
-
import "../_libs/isbot.mjs";
|
|
33
|
-
import "node:fs";
|
|
34
|
-
import "node:fs/promises";
|
|
35
|
-
import "node:buffer";
|
|
36
|
-
import "node:path";
|
|
37
|
-
import "../_libs/conf.mjs";
|
|
38
|
-
import "node:util";
|
|
39
|
-
import "node:process";
|
|
40
|
-
import "node:crypto";
|
|
41
|
-
import "node:assert";
|
|
42
|
-
import "../_libs/dot-prop.mjs";
|
|
43
|
-
import "../_libs/env-paths.mjs";
|
|
44
|
-
import "node:os";
|
|
45
|
-
import "../_libs/atomically.mjs";
|
|
46
|
-
import "../_libs/stubborn-fs.mjs";
|
|
47
|
-
import "../_libs/stubborn-utils.mjs";
|
|
48
|
-
import "../_libs/when-exit.mjs";
|
|
49
|
-
import "../_libs/ajv.mjs";
|
|
50
|
-
import "../_libs/fast-deep-equal.mjs";
|
|
51
|
-
import "../_libs/json-schema-traverse.mjs";
|
|
52
|
-
import "../_libs/fast-uri.mjs";
|
|
53
|
-
import "../_libs/ajv-formats.mjs";
|
|
54
|
-
import "../_libs/debounce-fn.mjs";
|
|
55
|
-
import "../_libs/mimic-function.mjs";
|
|
56
|
-
import "../_libs/semver.mjs";
|
|
57
|
-
import "../_libs/uint8array-extras.mjs";
|
|
58
|
-
import "node:child_process";
|
|
59
|
-
import "node:worker_threads";
|
|
60
|
-
import "../_libs/modelcontextprotocol__server.mjs";
|
|
61
|
-
import "../_libs/use-sync-external-store.mjs";
|
|
62
|
-
import "../_libs/dequal.mjs";
|
|
63
|
-
import "../_libs/readable-stream.mjs";
|
|
64
|
-
import "events";
|
|
65
|
-
import "node:string_decoder";
|
|
66
|
-
import "../_libs/process-nextick-args.mjs";
|
|
67
|
-
import "../_libs/isarray.mjs";
|
|
68
|
-
import "../_libs/safe-buffer.mjs";
|
|
69
|
-
import "buffer";
|
|
70
|
-
import "../_libs/core-util-is.mjs";
|
|
71
|
-
import "../_libs/inherits.mjs";
|
|
72
|
-
import "../_libs/util-deprecate.mjs";
|
|
73
|
-
import "../_libs/lie.mjs";
|
|
74
|
-
import "../_libs/immediate.mjs";
|
|
75
|
-
import "../_libs/setimmediate.mjs";
|
|
76
|
-
import "../_libs/pako.mjs";
|
|
77
|
-
import "../_libs/radix-ui__primitive.mjs";
|
|
78
|
-
import "../_libs/radix-ui__react-compose-refs.mjs";
|
|
79
|
-
import "../_libs/radix-ui__react-context.mjs";
|
|
80
|
-
import "../_libs/radix-ui__react-id.mjs";
|
|
81
|
-
import "../_libs/@radix-ui/react-use-layout-effect+[...].mjs";
|
|
82
|
-
import "../_libs/@radix-ui/react-use-controllable-state+[...].mjs";
|
|
83
|
-
import "../_libs/@radix-ui/react-dismissable-layer+[...].mjs";
|
|
84
|
-
import "../_libs/radix-ui__react-primitive.mjs";
|
|
85
|
-
import "../_libs/@radix-ui/react-use-callback-ref+[...].mjs";
|
|
86
|
-
import "../_libs/@radix-ui/react-use-escape-keydown+[...].mjs";
|
|
87
|
-
import "../_libs/radix-ui__react-focus-scope.mjs";
|
|
88
|
-
import "../_libs/radix-ui__react-portal.mjs";
|
|
89
|
-
import "../_libs/radix-ui__react-presence.mjs";
|
|
90
|
-
import "../_libs/radix-ui__react-focus-guards.mjs";
|
|
91
|
-
import "../_libs/react-remove-scroll.mjs";
|
|
92
|
-
import "tslib";
|
|
93
|
-
import "../_libs/react-remove-scroll-bar.mjs";
|
|
94
|
-
import "../_libs/react-style-singleton.mjs";
|
|
95
|
-
import "../_libs/get-nonce.mjs";
|
|
96
|
-
import "../_libs/use-sidecar.mjs";
|
|
97
|
-
import "../_libs/use-callback-ref.mjs";
|
|
98
|
-
import "../_libs/aria-hidden.mjs";
|
|
99
|
-
import "../_libs/tanstack__virtual-core.mjs";
|
|
100
|
-
import "../_libs/radix-ui__number.mjs";
|
|
101
|
-
import "../_libs/radix-ui__react-collection.mjs";
|
|
102
|
-
import "../_libs/radix-ui__react-direction.mjs";
|
|
103
|
-
import "../_libs/radix-ui__react-popper.mjs";
|
|
104
|
-
import "../_libs/floating-ui__react-dom.mjs";
|
|
105
|
-
import "../_libs/floating-ui__dom.mjs";
|
|
106
|
-
import "../_libs/floating-ui__core.mjs";
|
|
107
|
-
import "../_libs/floating-ui__utils.mjs";
|
|
108
|
-
import "../_libs/radix-ui__react-arrow.mjs";
|
|
109
|
-
import "../_libs/radix-ui__react-use-size.mjs";
|
|
110
|
-
import "../_libs/radix-ui__react-use-previous.mjs";
|
|
111
|
-
import "../_libs/@radix-ui/react-visually-hidden+[...].mjs";
|
|
112
|
-
import "../_libs/radix-ui__react-roving-focus.mjs";
|
|
113
17
|
const ApiErrorSchema = object({
|
|
114
18
|
error: string()
|
|
115
19
|
});
|
|
@@ -371,7 +275,7 @@ function getStatusCategory(status) {
|
|
|
371
275
|
if (status >= 500) return "server_error";
|
|
372
276
|
return "pending";
|
|
373
277
|
}
|
|
374
|
-
const version = "1.18.
|
|
278
|
+
const version = "1.18.2";
|
|
375
279
|
const packageJson = {
|
|
376
280
|
version
|
|
377
281
|
};
|
|
@@ -418,12 +322,12 @@ function Dialog({
|
|
|
418
322
|
function DialogTrigger({
|
|
419
323
|
...props
|
|
420
324
|
}) {
|
|
421
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(Trigger$
|
|
325
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Trigger$2, { "data-slot": "dialog-trigger", ...props });
|
|
422
326
|
}
|
|
423
327
|
function DialogPortal({
|
|
424
328
|
...props
|
|
425
329
|
}) {
|
|
426
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(Portal$
|
|
330
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Portal$2, { "data-slot": "dialog-portal", ...props });
|
|
427
331
|
}
|
|
428
332
|
function DialogOverlay({
|
|
429
333
|
className,
|
|
@@ -590,6 +494,13 @@ function ConversationHeader({
|
|
|
590
494
|
if (onClear === void 0) return;
|
|
591
495
|
setConfirmOpen(true);
|
|
592
496
|
};
|
|
497
|
+
const handleOpenInNewTab = reactExports.useCallback(
|
|
498
|
+
(e) => {
|
|
499
|
+
e.stopPropagation();
|
|
500
|
+
window.open(getSessionPath(conversationId), "_blank", "noopener,noreferrer");
|
|
501
|
+
},
|
|
502
|
+
[conversationId]
|
|
503
|
+
);
|
|
593
504
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
594
505
|
"div",
|
|
595
506
|
{
|
|
@@ -619,7 +530,7 @@ function ConversationHeader({
|
|
|
619
530
|
{
|
|
620
531
|
className: "text-purple-400/90 font-mono text-xs font-semibold shrink-0",
|
|
621
532
|
title: conversationId,
|
|
622
|
-
children: conversationId.length > 24 ? conversationId.slice(0, 12) + "
|
|
533
|
+
children: conversationId.startsWith("PID:") || conversationId.includes("|") ? conversationId : conversationId.length > 24 ? conversationId.slice(0, 12) + "..." + conversationId.slice(-12) : conversationId
|
|
623
534
|
}
|
|
624
535
|
),
|
|
625
536
|
userAgent !== null && userAgent !== void 0 && userAgent !== "" && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
@@ -671,6 +582,22 @@ function ConversationHeader({
|
|
|
671
582
|
] })
|
|
672
583
|
] }),
|
|
673
584
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1 min-w-0" }),
|
|
585
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
586
|
+
"button",
|
|
587
|
+
{
|
|
588
|
+
type: "button",
|
|
589
|
+
onClick: handleOpenInNewTab,
|
|
590
|
+
onKeyDown: (e) => {
|
|
591
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
592
|
+
handleOpenInNewTab(e);
|
|
593
|
+
}
|
|
594
|
+
},
|
|
595
|
+
"aria-label": `Open session ${conversationId} in a new tab`,
|
|
596
|
+
title: "Open this session in a new tab",
|
|
597
|
+
className: "text-muted-foreground hover:text-foreground transition-colors shrink-0 inline-flex items-center justify-center size-8 rounded hover:bg-muted cursor-pointer",
|
|
598
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(ExternalLink, { className: "size-3.5" })
|
|
599
|
+
}
|
|
600
|
+
),
|
|
674
601
|
onClear !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
675
602
|
"button",
|
|
676
603
|
{
|
|
@@ -1120,8 +1047,8 @@ const crabVariants = [
|
|
|
1120
1047
|
Crab11,
|
|
1121
1048
|
Crab12
|
|
1122
1049
|
];
|
|
1123
|
-
function getCrabVariant(
|
|
1124
|
-
return crabVariants[Math.abs(
|
|
1050
|
+
function getCrabVariant(index) {
|
|
1051
|
+
return crabVariants[Math.abs(index) % crabVariants.length] ?? Crab1;
|
|
1125
1052
|
}
|
|
1126
1053
|
function getInteriorCrabVariantIndex(seed) {
|
|
1127
1054
|
const interiorCount = crabVariants.length - 2;
|
|
@@ -1229,7 +1156,7 @@ function Tooltip({ ...props }) {
|
|
|
1229
1156
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(Root3, { "data-slot": "tooltip", ...props });
|
|
1230
1157
|
}
|
|
1231
1158
|
function TooltipTrigger({ ...props }) {
|
|
1232
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(Trigger$
|
|
1159
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Trigger$1, { "data-slot": "tooltip-trigger", ...props });
|
|
1233
1160
|
}
|
|
1234
1161
|
function TooltipContent({
|
|
1235
1162
|
className,
|
|
@@ -1237,7 +1164,7 @@ function TooltipContent({
|
|
|
1237
1164
|
children,
|
|
1238
1165
|
...props
|
|
1239
1166
|
}) {
|
|
1240
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(Portal$
|
|
1167
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Portal$1, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
1241
1168
|
Content2$1,
|
|
1242
1169
|
{
|
|
1243
1170
|
"data-slot": "tooltip-content",
|
|
@@ -1396,7 +1323,7 @@ function TabsTrigger({
|
|
|
1396
1323
|
...props
|
|
1397
1324
|
}) {
|
|
1398
1325
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
1399
|
-
Trigger$
|
|
1326
|
+
Trigger$3,
|
|
1400
1327
|
{
|
|
1401
1328
|
"data-slot": "tabs-trigger",
|
|
1402
1329
|
className: cn(
|
|
@@ -1424,27 +1351,27 @@ function TabsContent({
|
|
|
1424
1351
|
);
|
|
1425
1352
|
}
|
|
1426
1353
|
const LazyCompareDrawer = reactExports.lazy(
|
|
1427
|
-
() => import("./CompareDrawer-
|
|
1354
|
+
() => import("./CompareDrawer-BGUgukJ8.mjs").then((m) => ({ default: m.CompareDrawer }))
|
|
1428
1355
|
);
|
|
1429
1356
|
const LazyReplayDialog = reactExports.lazy(
|
|
1430
|
-
() => import("./ReplayDialog-
|
|
1357
|
+
() => import("./ReplayDialog-Bo86xZI4.mjs").then((m) => ({ default: m.ReplayDialog }))
|
|
1431
1358
|
);
|
|
1432
1359
|
const LazyRequestAnatomy = reactExports.lazy(
|
|
1433
|
-
() => import("./RequestAnatomy-
|
|
1360
|
+
() => import("./RequestAnatomy-jRU5qgwB.mjs").then((m) => ({ default: m.RequestAnatomy }))
|
|
1434
1361
|
);
|
|
1435
1362
|
const LazyResponseView = reactExports.lazy(
|
|
1436
|
-
() => import("./ResponseView-
|
|
1363
|
+
() => import("./ResponseView-DdO_-79a.mjs").then((m) => ({ default: m.ResponseView }))
|
|
1437
1364
|
);
|
|
1438
1365
|
const LazyStreamingChunkSequence = reactExports.lazy(
|
|
1439
|
-
() => import("./StreamingChunkSequence-
|
|
1366
|
+
() => import("./StreamingChunkSequence-BigLwhh4.mjs").then((m) => ({
|
|
1440
1367
|
default: m.StreamingChunkSequence
|
|
1441
1368
|
}))
|
|
1442
1369
|
);
|
|
1443
1370
|
const LazyJsonViewer = reactExports.lazy(
|
|
1444
|
-
() => import("./json-viewer-
|
|
1371
|
+
() => import("./json-viewer-B4c_WjXD.mjs").then((m) => ({ default: m.JsonViewer }))
|
|
1445
1372
|
);
|
|
1446
1373
|
const LazyJsonViewerFromString = reactExports.lazy(
|
|
1447
|
-
() => import("./json-viewer-
|
|
1374
|
+
() => import("./json-viewer-B4c_WjXD.mjs").then((m) => ({ default: m.JsonViewerFromString }))
|
|
1448
1375
|
);
|
|
1449
1376
|
const HIGHLIGHT_DURATION_MS = 1200;
|
|
1450
1377
|
const MAX_HIGHLIGHT_ATTEMPTS = 12;
|
|
@@ -2244,12 +2171,12 @@ const anthropicLogFormatAdapter = {
|
|
|
2244
2171
|
}
|
|
2245
2172
|
}
|
|
2246
2173
|
if (Array.isArray(body.messages)) {
|
|
2247
|
-
body.messages.forEach((message,
|
|
2174
|
+
body.messages.forEach((message, index) => {
|
|
2248
2175
|
if (message === null || typeof message !== "object") return;
|
|
2249
2176
|
const m = message;
|
|
2250
2177
|
const role = m.role === "user" || m.role === "assistant" ? m.role : "user";
|
|
2251
2178
|
const text = contentToText$1(m.content);
|
|
2252
|
-
segments.push(segment$1(role, `[${
|
|
2179
|
+
segments.push(segment$1(role, `[${index}] ${role}`, text, `/messages/${index}`));
|
|
2253
2180
|
});
|
|
2254
2181
|
}
|
|
2255
2182
|
if (Array.isArray(body.tools) && body.tools.length > 0) {
|
|
@@ -2350,12 +2277,12 @@ const openAILogFormatAdapter = {
|
|
|
2350
2277
|
const body = parsed;
|
|
2351
2278
|
const segments = [];
|
|
2352
2279
|
if (Array.isArray(body.messages)) {
|
|
2353
|
-
body.messages.forEach((message,
|
|
2280
|
+
body.messages.forEach((message, index) => {
|
|
2354
2281
|
if (message === null || typeof message !== "object") return;
|
|
2355
2282
|
const m = message;
|
|
2356
2283
|
const role = m.role === "user" || m.role === "assistant" || m.role === "system" || m.role === "tool" ? m.role : "user";
|
|
2357
2284
|
const text = messageToText(m);
|
|
2358
|
-
segments.push(segment(role, `[${
|
|
2285
|
+
segments.push(segment(role, `[${index}] ${role}`, text, `/messages/${index}`));
|
|
2359
2286
|
});
|
|
2360
2287
|
}
|
|
2361
2288
|
if (Array.isArray(body.tools) && body.tools.length > 0) {
|
|
@@ -2859,9 +2786,9 @@ function buildTurnGroups(logs) {
|
|
|
2859
2786
|
function buildValidPredecessors(groups) {
|
|
2860
2787
|
const predecessors = /* @__PURE__ */ new Map();
|
|
2861
2788
|
for (const group of groups) {
|
|
2862
|
-
for (let
|
|
2863
|
-
const current = group.logs[
|
|
2864
|
-
const previous = group.logs[
|
|
2789
|
+
for (let index = 1; index < group.logs.length; index += 1) {
|
|
2790
|
+
const current = group.logs[index];
|
|
2791
|
+
const previous = group.logs[index - 1];
|
|
2865
2792
|
if (current === void 0 || previous === void 0) continue;
|
|
2866
2793
|
const currentFormat = resolveLogFormat(current);
|
|
2867
2794
|
const previousFormat = resolveLogFormat(previous);
|
|
@@ -3166,12 +3093,11 @@ const ConversationGroup = reactExports.memo(function({
|
|
|
3166
3093
|
const mixed = hasMixedApiFormat(group.logs);
|
|
3167
3094
|
const isLoading = group.logs.some((log) => log.responseStatus === null);
|
|
3168
3095
|
const turnGroups = reactExports.useMemo(() => buildTurnGroups(group.logs), [group.logs]);
|
|
3169
|
-
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;
|
|
3170
3096
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-2", children: [
|
|
3171
3097
|
!standalone && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3172
3098
|
ConversationHeader,
|
|
3173
3099
|
{
|
|
3174
|
-
conversationId:
|
|
3100
|
+
conversationId: group.conversationId,
|
|
3175
3101
|
startTime,
|
|
3176
3102
|
endTime,
|
|
3177
3103
|
totalCalls: group.logs.length,
|
|
@@ -3230,6 +3156,18 @@ function CrabLogo({ className }) {
|
|
|
3230
3156
|
}
|
|
3231
3157
|
);
|
|
3232
3158
|
}
|
|
3159
|
+
const McpLogoPng = "data:image/png;base64,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";
|
|
3160
|
+
function McpLogo({ className }) {
|
|
3161
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3162
|
+
"img",
|
|
3163
|
+
{
|
|
3164
|
+
src: McpLogoPng,
|
|
3165
|
+
alt: "Model Context Protocol",
|
|
3166
|
+
"aria-hidden": "true",
|
|
3167
|
+
className: cn("inline-block size-8 object-contain invert", className)
|
|
3168
|
+
}
|
|
3169
|
+
);
|
|
3170
|
+
}
|
|
3233
3171
|
function Select({
|
|
3234
3172
|
...props
|
|
3235
3173
|
}) {
|
|
@@ -3489,13 +3427,13 @@ function ImportWizardDialog({
|
|
|
3489
3427
|
scan();
|
|
3490
3428
|
}
|
|
3491
3429
|
}, [open, scan]);
|
|
3492
|
-
const toggleProvider = reactExports.useCallback((
|
|
3430
|
+
const toggleProvider = reactExports.useCallback((index) => {
|
|
3493
3431
|
setSelected((prev) => {
|
|
3494
3432
|
const next = new Set(prev);
|
|
3495
|
-
if (next.has(
|
|
3496
|
-
next.delete(
|
|
3433
|
+
if (next.has(index)) {
|
|
3434
|
+
next.delete(index);
|
|
3497
3435
|
} else {
|
|
3498
|
-
next.add(
|
|
3436
|
+
next.add(index);
|
|
3499
3437
|
}
|
|
3500
3438
|
return next;
|
|
3501
3439
|
});
|
|
@@ -4020,10 +3958,10 @@ function ProviderForm({ provider, onSubmit, onCancel }) {
|
|
|
4020
3958
|
const modelRowRefs = reactExports.useRef([]);
|
|
4021
3959
|
reactExports.useEffect(() => {
|
|
4022
3960
|
if (openModelDropdown === null) return;
|
|
4023
|
-
const
|
|
3961
|
+
const index = openModelDropdown;
|
|
4024
3962
|
function handleClick(e) {
|
|
4025
3963
|
if (!(e.target instanceof Node)) return;
|
|
4026
|
-
const ref = modelRowRefs.current[
|
|
3964
|
+
const ref = modelRowRefs.current[index];
|
|
4027
3965
|
if (ref !== null && ref !== void 0 && !ref.contains(e.target)) {
|
|
4028
3966
|
setOpenModelDropdown(null);
|
|
4029
3967
|
}
|
|
@@ -5132,8 +5070,8 @@ function focusAndScroll(el) {
|
|
|
5132
5070
|
el.focus({ preventScroll: true });
|
|
5133
5071
|
el.scrollIntoView({ block: "nearest", behavior: "smooth" });
|
|
5134
5072
|
}
|
|
5135
|
-
function safeItemAt(items,
|
|
5136
|
-
const el = items[
|
|
5073
|
+
function safeItemAt(items, index) {
|
|
5074
|
+
const el = items[index];
|
|
5137
5075
|
return el ?? null;
|
|
5138
5076
|
}
|
|
5139
5077
|
function isEditableTarget(target) {
|
|
@@ -5263,6 +5201,25 @@ function computeTokenSummary(logs) {
|
|
|
5263
5201
|
}
|
|
5264
5202
|
return { totalIn, totalOut };
|
|
5265
5203
|
}
|
|
5204
|
+
function formatTimeRange(logs) {
|
|
5205
|
+
const first = logs[0];
|
|
5206
|
+
const last = logs[logs.length - 1];
|
|
5207
|
+
if (first === void 0 || last === void 0) return null;
|
|
5208
|
+
const format = (iso) => new Date(iso).toLocaleTimeString([], {
|
|
5209
|
+
hour: "2-digit",
|
|
5210
|
+
minute: "2-digit",
|
|
5211
|
+
second: "2-digit"
|
|
5212
|
+
});
|
|
5213
|
+
return `${format(first.timestamp)} - ${format(last.timestamp)}`;
|
|
5214
|
+
}
|
|
5215
|
+
function getFirstUserAgent(logs) {
|
|
5216
|
+
for (const log of logs) {
|
|
5217
|
+
if (log.userAgent !== null && log.userAgent !== void 0 && log.userAgent !== "") {
|
|
5218
|
+
return log.userAgent;
|
|
5219
|
+
}
|
|
5220
|
+
}
|
|
5221
|
+
return null;
|
|
5222
|
+
}
|
|
5266
5223
|
function CopyableCommand({ command }) {
|
|
5267
5224
|
const [copied, setCopied] = reactExports.useState(false);
|
|
5268
5225
|
const handleCopy = reactExports.useCallback(() => {
|
|
@@ -5314,6 +5271,82 @@ function CopyableCommand({ command }) {
|
|
|
5314
5271
|
)
|
|
5315
5272
|
] });
|
|
5316
5273
|
}
|
|
5274
|
+
function McpReadyBadge() {
|
|
5275
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
5276
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex h-7 items-center gap-2 rounded-md border border-cyan-400/30 bg-cyan-500/10 px-2.5 font-mono text-[11px] font-medium text-cyan-300 shadow-[0_0_16px_rgba(34,211,238,0.08)]", children: [
|
|
5277
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "size-1.5 rounded-full bg-emerald-300 shadow-[0_0_8px_rgba(110,231,183,0.8)]" }),
|
|
5278
|
+
"MCP Ready",
|
|
5279
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "hidden text-cyan-200/70 sm:inline", children: "/api/mcp" })
|
|
5280
|
+
] }) }),
|
|
5281
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { sideOffset: 8, className: "max-w-[320px] text-left leading-relaxed", children: "Coding agents can inspect logs, replay requests, test providers, and debug sessions through MCP at /api/mcp." })
|
|
5282
|
+
] }) });
|
|
5283
|
+
}
|
|
5284
|
+
function SessionContextBar({
|
|
5285
|
+
sessionId,
|
|
5286
|
+
logs,
|
|
5287
|
+
totalIn,
|
|
5288
|
+
totalOut
|
|
5289
|
+
}) {
|
|
5290
|
+
const [copied, setCopied] = reactExports.useState(false);
|
|
5291
|
+
const timeRange = reactExports.useMemo(() => formatTimeRange(logs), [logs]);
|
|
5292
|
+
const userAgent = reactExports.useMemo(() => getFirstUserAgent(logs), [logs]);
|
|
5293
|
+
const handleCopyLink = reactExports.useCallback(() => {
|
|
5294
|
+
void window.navigator.clipboard.writeText(window.location.href).then(() => {
|
|
5295
|
+
setCopied(true);
|
|
5296
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
5297
|
+
});
|
|
5298
|
+
}, []);
|
|
5299
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-4 flex items-center gap-3 border border-border rounded-md bg-muted/20 px-3 py-2 text-xs", children: [
|
|
5300
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5301
|
+
"a",
|
|
5302
|
+
{
|
|
5303
|
+
href: "/",
|
|
5304
|
+
className: "inline-flex size-8 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
5305
|
+
"aria-label": "Back to all sessions",
|
|
5306
|
+
title: "Back to all sessions",
|
|
5307
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(ArrowLeft, { className: "size-3.5" })
|
|
5308
|
+
}
|
|
5309
|
+
),
|
|
5310
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
5311
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
5312
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono font-semibold text-purple-400/90 truncate", title: sessionId, children: truncateSessionId(sessionId) }),
|
|
5313
|
+
userAgent !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5314
|
+
"span",
|
|
5315
|
+
{
|
|
5316
|
+
className: "font-mono text-muted-foreground truncate max-w-[220px]",
|
|
5317
|
+
title: userAgent,
|
|
5318
|
+
children: userAgent
|
|
5319
|
+
}
|
|
5320
|
+
)
|
|
5321
|
+
] }),
|
|
5322
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-1 flex flex-wrap items-center gap-x-3 gap-y-1 text-muted-foreground", children: [
|
|
5323
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
5324
|
+
logs.length,
|
|
5325
|
+
" request",
|
|
5326
|
+
logs.length !== 1 ? "s" : ""
|
|
5327
|
+
] }),
|
|
5328
|
+
timeRange !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: timeRange }),
|
|
5329
|
+
(totalIn > 0 || totalOut > 0) && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono", children: [
|
|
5330
|
+
formatTokens(totalIn),
|
|
5331
|
+
" in / ",
|
|
5332
|
+
formatTokens(totalOut),
|
|
5333
|
+
" out"
|
|
5334
|
+
] })
|
|
5335
|
+
] })
|
|
5336
|
+
] }),
|
|
5337
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5338
|
+
"button",
|
|
5339
|
+
{
|
|
5340
|
+
type: "button",
|
|
5341
|
+
onClick: handleCopyLink,
|
|
5342
|
+
className: "inline-flex size-8 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
5343
|
+
"aria-label": copied ? "Copied session link" : "Copy session link",
|
|
5344
|
+
title: copied ? "Copied session link" : "Copy session link",
|
|
5345
|
+
children: copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-3.5" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-3.5" })
|
|
5346
|
+
}
|
|
5347
|
+
)
|
|
5348
|
+
] });
|
|
5349
|
+
}
|
|
5317
5350
|
function ProxyViewer({
|
|
5318
5351
|
logs,
|
|
5319
5352
|
sessions,
|
|
@@ -5327,7 +5360,9 @@ function ProxyViewer({
|
|
|
5327
5360
|
viewMode,
|
|
5328
5361
|
onViewModeChange,
|
|
5329
5362
|
strip,
|
|
5330
|
-
slowResponseThresholdSeconds
|
|
5363
|
+
slowResponseThresholdSeconds,
|
|
5364
|
+
hideSessionFilter = false,
|
|
5365
|
+
pinnedSessionId
|
|
5331
5366
|
}) {
|
|
5332
5367
|
const { totalIn, totalOut } = reactExports.useMemo(() => computeTokenSummary(logs), [logs]);
|
|
5333
5368
|
const [exporting, setExporting] = reactExports.useState(false);
|
|
@@ -5349,6 +5384,14 @@ function ProxyViewer({
|
|
|
5349
5384
|
clearTimeout(t2);
|
|
5350
5385
|
};
|
|
5351
5386
|
}, []);
|
|
5387
|
+
reactExports.useEffect(() => {
|
|
5388
|
+
if (pinnedSessionId === void 0) {
|
|
5389
|
+
document.title = "LLM Inspector";
|
|
5390
|
+
return;
|
|
5391
|
+
}
|
|
5392
|
+
const requestLabel = logs.length === 1 ? "1 req" : `${logs.length} req`;
|
|
5393
|
+
document.title = `${truncateSessionId(pinnedSessionId)} - ${requestLabel} - LLM Inspector`;
|
|
5394
|
+
}, [logs.length, pinnedSessionId]);
|
|
5352
5395
|
const handleExport = reactExports.useCallback(async () => {
|
|
5353
5396
|
setExporting(true);
|
|
5354
5397
|
try {
|
|
@@ -5374,51 +5417,66 @@ function ProxyViewer({
|
|
|
5374
5417
|
[comparisonPredecessors]
|
|
5375
5418
|
);
|
|
5376
5419
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "max-w-[1400px] xl:max-w-[1600px] 2xl:max-w-[1800px] mx-auto px-6 pb-6", children: [
|
|
5377
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "
|
|
5378
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
5379
|
-
|
|
5380
|
-
|
|
5381
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
5420
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-[1fr_auto_1fr] items-start gap-3 pt-6 pb-8", children: [
|
|
5421
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", {}),
|
|
5422
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("h1", { className: "flex min-w-0 flex-col items-center gap-2 text-center", children: [
|
|
5423
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex max-w-[calc(100vw-7rem)] items-end gap-2 whitespace-nowrap", children: [
|
|
5424
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex shrink-0 items-end gap-1 group cursor-default", "aria-hidden": "true", children: [
|
|
5425
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(CrabLogo, { className: "size-10 text-amber-500 transition-all duration-300 group-hover:scale-125 group-hover:-translate-y-1.5" }),
|
|
5426
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "hidden items-end gap-0.5 sm:flex", children: crabVariants.map((Crab, i) => {
|
|
5427
|
+
const color = [
|
|
5428
|
+
"text-amber-500",
|
|
5429
|
+
"text-rose-500",
|
|
5430
|
+
"text-sky-500",
|
|
5431
|
+
"text-emerald-500",
|
|
5432
|
+
"text-violet-500",
|
|
5433
|
+
"text-orange-500",
|
|
5434
|
+
"text-cyan-500",
|
|
5435
|
+
"text-pink-500",
|
|
5436
|
+
"text-lime-500",
|
|
5437
|
+
"text-blue-500",
|
|
5438
|
+
"text-yellow-500",
|
|
5439
|
+
"text-fuchsia-500"
|
|
5440
|
+
][i];
|
|
5441
|
+
const entranceClass = crabEntrancePhase === "hidden" ? "opacity-0 scale-0" : crabEntrancePhase === "playing" ? "animate-crab-piano-pop" : "";
|
|
5442
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5443
|
+
Crab,
|
|
5444
|
+
{
|
|
5445
|
+
className: `size-5 ${color} transition-all duration-300 ease-out group-hover:scale-125 group-hover:-translate-y-1 ${entranceClass}`,
|
|
5446
|
+
style: {
|
|
5447
|
+
transitionDelay: `${i * 50}ms`,
|
|
5448
|
+
...crabEntrancePhase === "playing" ? { animationDelay: `${i * 400}ms` } : {}
|
|
5449
|
+
}
|
|
5450
|
+
},
|
|
5451
|
+
i
|
|
5452
|
+
);
|
|
5453
|
+
}) })
|
|
5454
|
+
] }),
|
|
5455
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 items-baseline gap-2 pl-1", children: [
|
|
5456
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate text-lg font-bold", children: "LLM Inspector" }),
|
|
5457
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "shrink-0 font-mono text-xs font-semibold text-muted-foreground", children: [
|
|
5458
|
+
"v",
|
|
5459
|
+
packageJson.version
|
|
5460
|
+
] })
|
|
5461
|
+
] }),
|
|
5462
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "size-4 shrink-0 text-muted-foreground/70", "aria-hidden": "true" }),
|
|
5463
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(McpLogo, { className: "size-10 shrink-0" })
|
|
5409
5464
|
] }),
|
|
5410
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
5411
|
-
"LLM Inspector",
|
|
5412
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xs text-muted-foreground font-mono", children: [
|
|
5413
|
-
"v",
|
|
5414
|
-
packageJson.version
|
|
5415
|
-
] })
|
|
5416
|
-
] })
|
|
5465
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(McpReadyBadge, {})
|
|
5417
5466
|
] }),
|
|
5418
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "
|
|
5467
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "justify-self-end", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SettingsDialog, {}) })
|
|
5419
5468
|
] }),
|
|
5469
|
+
pinnedSessionId !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5470
|
+
SessionContextBar,
|
|
5471
|
+
{
|
|
5472
|
+
sessionId: pinnedSessionId,
|
|
5473
|
+
logs,
|
|
5474
|
+
totalIn,
|
|
5475
|
+
totalOut
|
|
5476
|
+
}
|
|
5477
|
+
),
|
|
5420
5478
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3 mb-4", children: [
|
|
5421
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(Select, { value: selectedSession, onValueChange: onSessionChange, children: [
|
|
5479
|
+
!hideSessionFilter && /* @__PURE__ */ jsxRuntimeExports.jsxs(Select, { value: selectedSession, onValueChange: onSessionChange, children: [
|
|
5422
5480
|
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectTrigger, { className: "flex-1 max-w-[350px] text-xs", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue, { placeholder: "All sessions" }) }),
|
|
5423
5481
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(SelectContent, { children: [
|
|
5424
5482
|
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: "__all__", children: "All sessions" }),
|
|
@@ -5486,7 +5544,23 @@ function ProxyViewer({
|
|
|
5486
5544
|
}
|
|
5487
5545
|
)
|
|
5488
5546
|
] }),
|
|
5489
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: logs.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center text-muted-foreground py-16 space-y-4", children: [
|
|
5547
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: logs.length === 0 ? selectedSession !== "__all__" ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center text-muted-foreground py-16 space-y-4", children: [
|
|
5548
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-medium", children: "Session not found" }),
|
|
5549
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs font-mono bg-muted px-3 py-1 rounded inline-block max-w-[500px] break-all", children: truncateSessionId(selectedSession) }),
|
|
5550
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-xs", children: [
|
|
5551
|
+
"This session may have been cleared or never existed.",
|
|
5552
|
+
" ",
|
|
5553
|
+
hideSessionFilter ? /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "/", className: "underline hover:text-foreground transition-colors", children: "Back to all sessions" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5554
|
+
"button",
|
|
5555
|
+
{
|
|
5556
|
+
type: "button",
|
|
5557
|
+
onClick: () => onSessionChange("__all__"),
|
|
5558
|
+
className: "underline hover:text-foreground transition-colors",
|
|
5559
|
+
children: "Show all sessions"
|
|
5560
|
+
}
|
|
5561
|
+
)
|
|
5562
|
+
] })
|
|
5563
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center text-muted-foreground py-16 space-y-4", children: [
|
|
5490
5564
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm", children: "No requests captured yet." }),
|
|
5491
5565
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs", children: "Route AI coding tools through the proxy:" }),
|
|
5492
5566
|
/* @__PURE__ */ jsxRuntimeExports.jsx(CopyableCommand, { command: "LLM_BASE_URL=http://localhost:25947/proxy <your-tool>" })
|
|
@@ -5549,9 +5623,16 @@ function filterLogs(logs, selectedSession, selectedModel) {
|
|
|
5549
5623
|
});
|
|
5550
5624
|
}
|
|
5551
5625
|
const DEBOUNCE_MS = 50;
|
|
5552
|
-
function
|
|
5626
|
+
function buildLogsStreamUrl(sessionId) {
|
|
5627
|
+
if (sessionId === void 0) return "/api/logs/stream";
|
|
5628
|
+
const params = new URLSearchParams({ sessionId });
|
|
5629
|
+
return `/api/logs/stream?${params.toString()}`;
|
|
5630
|
+
}
|
|
5631
|
+
function ProxyViewerContainer({
|
|
5632
|
+
initialSessionId
|
|
5633
|
+
} = {}) {
|
|
5553
5634
|
const [allLogs, setAllLogs] = reactExports.useState([]);
|
|
5554
|
-
const [selectedSession, setSelectedSession] = reactExports.useState("__all__");
|
|
5635
|
+
const [selectedSession, setSelectedSession] = reactExports.useState(initialSessionId ?? "__all__");
|
|
5555
5636
|
const [selectedModel, setSelectedModel] = reactExports.useState("__all__");
|
|
5556
5637
|
const [viewMode, setViewMode] = reactExports.useState("simple");
|
|
5557
5638
|
const [error, setError] = reactExports.useState(null);
|
|
@@ -5598,7 +5679,7 @@ function ProxyViewerContainer() {
|
|
|
5598
5679
|
if (eventSourceRef.current) {
|
|
5599
5680
|
eventSourceRef.current.close();
|
|
5600
5681
|
}
|
|
5601
|
-
const es = new EventSource(
|
|
5682
|
+
const es = new EventSource(buildLogsStreamUrl(initialSessionId));
|
|
5602
5683
|
eventSourceRef.current = es;
|
|
5603
5684
|
es.onmessage = (event) => {
|
|
5604
5685
|
try {
|
|
@@ -5639,7 +5720,7 @@ function ProxyViewerContainer() {
|
|
|
5639
5720
|
}
|
|
5640
5721
|
reconnectTimeoutRef.current = setTimeout(connectSSE, 3e3);
|
|
5641
5722
|
};
|
|
5642
|
-
}, [scheduleUpdate]);
|
|
5723
|
+
}, [initialSessionId, scheduleUpdate]);
|
|
5643
5724
|
reactExports.useEffect(() => {
|
|
5644
5725
|
connectSSE();
|
|
5645
5726
|
return () => {
|
|
@@ -5658,9 +5739,17 @@ function ProxyViewerContainer() {
|
|
|
5658
5739
|
};
|
|
5659
5740
|
}, [connectSSE]);
|
|
5660
5741
|
const handleClearAll = reactExports.useCallback(() => {
|
|
5742
|
+
if (initialSessionId !== void 0 && allLogs.length === 0) return;
|
|
5661
5743
|
void (async () => {
|
|
5662
5744
|
try {
|
|
5663
|
-
const
|
|
5745
|
+
const body = initialSessionId === void 0 ? void 0 : JSON.stringify({ ids: allLogs.map((log) => log.id) });
|
|
5746
|
+
const res = await fetch("/api/logs", {
|
|
5747
|
+
method: "DELETE",
|
|
5748
|
+
...body === void 0 ? {} : {
|
|
5749
|
+
headers: { "Content-Type": "application/json" },
|
|
5750
|
+
body
|
|
5751
|
+
}
|
|
5752
|
+
});
|
|
5664
5753
|
if (!res.ok) {
|
|
5665
5754
|
setError("Failed to clear logs");
|
|
5666
5755
|
return;
|
|
@@ -5672,7 +5761,7 @@ function ProxyViewerContainer() {
|
|
|
5672
5761
|
setError(err instanceof Error ? err.message : "Unknown error clearing logs");
|
|
5673
5762
|
}
|
|
5674
5763
|
})();
|
|
5675
|
-
}, []);
|
|
5764
|
+
}, [allLogs, initialSessionId]);
|
|
5676
5765
|
const handleClearGroup = reactExports.useCallback((ids) => {
|
|
5677
5766
|
if (ids.length === 0) return;
|
|
5678
5767
|
void (async () => {
|
|
@@ -5722,19 +5811,17 @@ function ProxyViewerContainer() {
|
|
|
5722
5811
|
viewMode,
|
|
5723
5812
|
onViewModeChange: setViewMode,
|
|
5724
5813
|
strip,
|
|
5725
|
-
slowResponseThresholdSeconds
|
|
5814
|
+
slowResponseThresholdSeconds,
|
|
5815
|
+
hideSessionFilter: initialSessionId !== void 0,
|
|
5816
|
+
pinnedSessionId: initialSessionId
|
|
5726
5817
|
}
|
|
5727
5818
|
)
|
|
5728
5819
|
] });
|
|
5729
5820
|
}
|
|
5730
|
-
const SplitComponent = ProxyViewerContainer;
|
|
5731
|
-
const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
5732
|
-
__proto__: null,
|
|
5733
|
-
component: SplitComponent
|
|
5734
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
5735
5821
|
export {
|
|
5736
5822
|
Badge as B,
|
|
5737
5823
|
Dialog as D,
|
|
5824
|
+
ProxyViewerContainer as P,
|
|
5738
5825
|
Tabs as T,
|
|
5739
5826
|
getConversationId as a,
|
|
5740
5827
|
DialogContent as b,
|
|
@@ -5754,6 +5841,5 @@ export {
|
|
|
5754
5841
|
getStatusCategory as p,
|
|
5755
5842
|
parseJsonText as q,
|
|
5756
5843
|
resolveLogFormat as r,
|
|
5757
|
-
safeJsonValue as s
|
|
5758
|
-
index as t
|
|
5844
|
+
safeJsonValue as s
|
|
5759
5845
|
};
|