@tonyclaw/llm-inspector 1.18.0 → 1.18.1
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-CAhlM_Gq.js +1 -0
- package/.output/public/assets/ProxyViewerContainer--miVHNPZ.js +101 -0
- package/.output/public/assets/ReplayDialog-Bqu2f5HE.js +1 -0
- package/.output/public/assets/RequestAnatomy-CpVNH0CD.js +1 -0
- package/.output/public/assets/ResponseView-B_Gg37Lr.js +1 -0
- package/.output/public/assets/StreamingChunkSequence-E2M_SS1A.js +1 -0
- package/.output/public/assets/_sessionId-P9LgC1bF.js +1 -0
- package/.output/public/assets/index-C0wv3YP9.css +1 -0
- package/.output/public/assets/index-kboKku6a.js +1 -0
- package/.output/public/assets/{json-viewer-D-z1r1Pp.js → json-viewer-DqhA-ODG.js} +1 -1
- package/.output/public/assets/{main-CZJ63sQh.js → main-DpH7JlHv.js} +8 -7
- package/.output/server/_libs/lucide-react.mjs +3 -3
- package/.output/server/_sessionId-DcJ0RDNl.mjs +122 -0
- package/.output/server/_ssr/{CompareDrawer-BJr-913n.mjs → CompareDrawer-DajC3x7u.mjs} +55 -55
- package/.output/server/_ssr/{index-C7I_Qgt0.mjs → ProxyViewerContainer-C2dnFXoC.mjs} +87 -139
- package/.output/server/_ssr/{ReplayDialog-BwmToGuR.mjs → ReplayDialog-BnCLuA5z.mjs} +56 -56
- package/.output/server/_ssr/{RequestAnatomy-BmMiPRPB.mjs → RequestAnatomy-OHE3iT-f.mjs} +2 -2
- package/.output/server/_ssr/{ResponseView-ZB9-8Raw.mjs → ResponseView-NPshHwOv.mjs} +3 -3
- package/.output/server/_ssr/{StreamingChunkSequence-DWm4CQWC.mjs → StreamingChunkSequence-BfukoR7F.mjs} +55 -55
- package/.output/server/_ssr/index-CF8M0tsv.mjs +117 -0
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{json-viewer-D9XETzwp.mjs → json-viewer-CHBa-Oas.mjs} +2 -2
- package/.output/server/_ssr/{router-711KpGkz.mjs → router-B5hOtKSn.mjs} +64 -22
- package/.output/server/_tanstack-start-manifest_v-CFyWvIH6.mjs +4 -0
- package/.output/server/index.mjs +73 -59
- package/package.json +1 -1
- package/src/components/ProxyViewer.tsx +44 -18
- package/src/components/ProxyViewerContainer.tsx +18 -2
- package/src/components/proxy-viewer/ConversationGroup.tsx +1 -8
- package/src/components/proxy-viewer/ConversationHeader.tsx +47 -4
- package/src/routes/session/$sessionId.tsx +75 -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
|
@@ -101,6 +101,10 @@ export type ProxyViewerProps = {
|
|
|
101
101
|
strip: boolean;
|
|
102
102
|
/** Slow-response threshold in seconds. `0` disables the warning indicator. */
|
|
103
103
|
slowResponseThresholdSeconds: number;
|
|
104
|
+
/** Hide the session filter dropdown. Used on `/session/$id` routes where
|
|
105
|
+
* the session is already pinned by the URL and the dropdown would just
|
|
106
|
+
* fight the URL state. */
|
|
107
|
+
hideSessionFilter?: boolean;
|
|
104
108
|
};
|
|
105
109
|
|
|
106
110
|
export function ProxyViewer({
|
|
@@ -117,6 +121,7 @@ export function ProxyViewer({
|
|
|
117
121
|
onViewModeChange,
|
|
118
122
|
strip,
|
|
119
123
|
slowResponseThresholdSeconds,
|
|
124
|
+
hideSessionFilter = false,
|
|
120
125
|
}: ProxyViewerProps): JSX.Element {
|
|
121
126
|
const { totalIn, totalOut } = useMemo(() => computeTokenSummary(logs), [logs]);
|
|
122
127
|
const [exporting, setExporting] = useState(false);
|
|
@@ -226,19 +231,21 @@ export function ProxyViewer({
|
|
|
226
231
|
|
|
227
232
|
{/* Controls + Filters */}
|
|
228
233
|
<div className="flex items-center gap-3 mb-4">
|
|
229
|
-
|
|
230
|
-
<
|
|
231
|
-
<
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
<
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
{
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
234
|
+
{!hideSessionFilter && (
|
|
235
|
+
<Select value={selectedSession} onValueChange={onSessionChange}>
|
|
236
|
+
<SelectTrigger className="flex-1 max-w-[350px] text-xs">
|
|
237
|
+
<SelectValue placeholder="All sessions" />
|
|
238
|
+
</SelectTrigger>
|
|
239
|
+
<SelectContent>
|
|
240
|
+
<SelectItem value="__all__">All sessions</SelectItem>
|
|
241
|
+
{sessions.map((s) => (
|
|
242
|
+
<SelectItem key={s} value={s}>
|
|
243
|
+
{truncateSessionId(s)}
|
|
244
|
+
</SelectItem>
|
|
245
|
+
))}
|
|
246
|
+
</SelectContent>
|
|
247
|
+
</Select>
|
|
248
|
+
)}
|
|
242
249
|
<Select value={selectedModel} onValueChange={onModelChange}>
|
|
243
250
|
<SelectTrigger className="flex-1 max-w-[250px] text-xs">
|
|
244
251
|
<SelectValue placeholder="All models" />
|
|
@@ -316,11 +323,30 @@ export function ProxyViewer({
|
|
|
316
323
|
{/* Log list */}
|
|
317
324
|
<div>
|
|
318
325
|
{logs.length === 0 ? (
|
|
319
|
-
|
|
320
|
-
<
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
326
|
+
selectedSession !== "__all__" ? (
|
|
327
|
+
<div className="text-center text-muted-foreground py-16 space-y-4">
|
|
328
|
+
<p className="text-sm font-medium">Session not found</p>
|
|
329
|
+
<p className="text-xs font-mono bg-muted px-3 py-1 rounded inline-block max-w-[500px] break-all">
|
|
330
|
+
{truncateSessionId(selectedSession)}
|
|
331
|
+
</p>
|
|
332
|
+
<p className="text-xs">
|
|
333
|
+
This session may have been cleared or never existed.{" "}
|
|
334
|
+
<button
|
|
335
|
+
type="button"
|
|
336
|
+
onClick={() => onSessionChange("__all__")}
|
|
337
|
+
className="underline hover:text-foreground transition-colors"
|
|
338
|
+
>
|
|
339
|
+
Show all sessions
|
|
340
|
+
</button>
|
|
341
|
+
</p>
|
|
342
|
+
</div>
|
|
343
|
+
) : (
|
|
344
|
+
<div className="text-center text-muted-foreground py-16 space-y-4">
|
|
345
|
+
<p className="text-sm">No requests captured yet.</p>
|
|
346
|
+
<p className="text-xs">Route AI coding tools through the proxy:</p>
|
|
347
|
+
<CopyableCommand command="LLM_BASE_URL=http://localhost:25947/proxy <your-tool>" />
|
|
348
|
+
</div>
|
|
349
|
+
)
|
|
324
350
|
) : (
|
|
325
351
|
<div
|
|
326
352
|
ref={logListWrapperRef}
|
|
@@ -62,12 +62,26 @@ function filterLogs(
|
|
|
62
62
|
|
|
63
63
|
const DEBOUNCE_MS = 50;
|
|
64
64
|
|
|
65
|
-
export function ProxyViewerContainer(
|
|
65
|
+
export function ProxyViewerContainer({
|
|
66
|
+
initialSessionId,
|
|
67
|
+
}: {
|
|
68
|
+
/**
|
|
69
|
+
* Initial session filter. When the route is `/session/$id`, pass the URL
|
|
70
|
+
* param here so the page opens already scoped to that session. Default
|
|
71
|
+
* `__all__` keeps the existing "all sessions" behavior on `/`.
|
|
72
|
+
*
|
|
73
|
+
* NOTE: the value is only used as the initial state on mount. To pick up
|
|
74
|
+
* a new value (e.g. user navigates to a different `/session/$id`), the
|
|
75
|
+
* caller should also pass a `key` prop matching the session id, which
|
|
76
|
+
* forces a remount.
|
|
77
|
+
*/
|
|
78
|
+
initialSessionId?: string;
|
|
79
|
+
} = {}): JSX.Element {
|
|
66
80
|
// `allLogs` is the unfiltered set populated by the SSE. The single SSE
|
|
67
81
|
// connection never re-opens on filter change — we always carry the full
|
|
68
82
|
// set and derive the displayed view with `useMemo` below.
|
|
69
83
|
const [allLogs, setAllLogs] = useState<CapturedLog[]>([]);
|
|
70
|
-
const [selectedSession, setSelectedSession] = useState("__all__");
|
|
84
|
+
const [selectedSession, setSelectedSession] = useState(initialSessionId ?? "__all__");
|
|
71
85
|
const [selectedModel, setSelectedModel] = useState("__all__");
|
|
72
86
|
const [viewMode, setViewMode] = useState<"simple" | "full">("simple");
|
|
73
87
|
const [error, setError] = useState<string | null>(null);
|
|
@@ -274,6 +288,8 @@ export function ProxyViewerContainer(): JSX.Element {
|
|
|
274
288
|
onViewModeChange={setViewMode}
|
|
275
289
|
strip={strip}
|
|
276
290
|
slowResponseThresholdSeconds={slowResponseThresholdSeconds}
|
|
291
|
+
// Session filter is the URL's job when `initialSessionId` was given.
|
|
292
|
+
hideSessionFilter={initialSessionId !== undefined}
|
|
277
293
|
/>
|
|
278
294
|
</>
|
|
279
295
|
);
|
|
@@ -65,18 +65,11 @@ export const ConversationGroup = memo(function ({
|
|
|
65
65
|
|
|
66
66
|
// Pre-compute stop reasons for each log — used by turnIndices
|
|
67
67
|
const turnGroups = useMemo(() => buildTurnGroups(group.logs), [group.logs]);
|
|
68
|
-
const displayId =
|
|
69
|
-
group.conversationId.startsWith("PID:") || group.conversationId.includes("|")
|
|
70
|
-
? group.conversationId
|
|
71
|
-
: group.conversationId.length > 24
|
|
72
|
-
? group.conversationId.slice(0, 12) + "…" + group.conversationId.slice(-12)
|
|
73
|
-
: group.conversationId;
|
|
74
|
-
|
|
75
68
|
return (
|
|
76
69
|
<div className="mb-2">
|
|
77
70
|
{!standalone && (
|
|
78
71
|
<ConversationHeader
|
|
79
|
-
conversationId={
|
|
72
|
+
conversationId={group.conversationId}
|
|
80
73
|
startTime={startTime}
|
|
81
74
|
endTime={endTime}
|
|
82
75
|
totalCalls={group.logs.length}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { useState } from "react";
|
|
1
|
+
import { useCallback, useState } from "react";
|
|
2
2
|
import {
|
|
3
3
|
ChevronDown,
|
|
4
4
|
ChevronRight,
|
|
5
5
|
Clock,
|
|
6
|
+
ExternalLink,
|
|
6
7
|
Loader2,
|
|
7
8
|
MessageSquare,
|
|
8
9
|
Trash2,
|
|
@@ -74,6 +75,30 @@ export function ConversationHeader({
|
|
|
74
75
|
setConfirmOpen(true);
|
|
75
76
|
};
|
|
76
77
|
|
|
78
|
+
const handleOpenInNewTab = useCallback(
|
|
79
|
+
(e: React.MouseEvent | React.KeyboardEvent): void => {
|
|
80
|
+
e.stopPropagation();
|
|
81
|
+
// Base64url-encode the session id so the path contains only
|
|
82
|
+
// unreserved characters (A-Z a-z 0-9 - _) that survive Vite's
|
|
83
|
+
// URL normalisation without triggering a redirect loop.
|
|
84
|
+
// Falls back to percent-encoding when the id contains non-Latin-1
|
|
85
|
+
// characters (e.g. CJK paths in PID|folder format) that btoa()
|
|
86
|
+
// rejects.
|
|
87
|
+
let encoded: string;
|
|
88
|
+
try {
|
|
89
|
+
encoded = btoa(conversationId).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
90
|
+
} catch {
|
|
91
|
+
// Non-Latin-1 characters in the id — fall back to percent-encoding.
|
|
92
|
+
// These URLs may not survive Vite's URL normalisation but the
|
|
93
|
+
// situation is rare enough (CJK paths) to accept the edge case.
|
|
94
|
+
encoded = encodeURIComponent(conversationId);
|
|
95
|
+
}
|
|
96
|
+
const url = `/session/${encoded}`;
|
|
97
|
+
window.open(url, "_blank", "noopener,noreferrer");
|
|
98
|
+
},
|
|
99
|
+
[conversationId],
|
|
100
|
+
);
|
|
101
|
+
|
|
77
102
|
return (
|
|
78
103
|
<div
|
|
79
104
|
role="button"
|
|
@@ -110,9 +135,11 @@ export function ConversationHeader({
|
|
|
110
135
|
className="text-purple-400/90 font-mono text-xs font-semibold shrink-0"
|
|
111
136
|
title={conversationId}
|
|
112
137
|
>
|
|
113
|
-
{conversationId.
|
|
114
|
-
? conversationId
|
|
115
|
-
: conversationId
|
|
138
|
+
{conversationId.startsWith("PID:") || conversationId.includes("|")
|
|
139
|
+
? conversationId
|
|
140
|
+
: conversationId.length > 24
|
|
141
|
+
? conversationId.slice(0, 12) + "…" + conversationId.slice(-12)
|
|
142
|
+
: conversationId}
|
|
116
143
|
</span>
|
|
117
144
|
|
|
118
145
|
{/* User-Agent */}
|
|
@@ -170,6 +197,22 @@ export function ConversationHeader({
|
|
|
170
197
|
{/* Spacer */}
|
|
171
198
|
<span className="flex-1 min-w-0" />
|
|
172
199
|
|
|
200
|
+
{/* Open this session in a new tab — deep link to /session/$id */}
|
|
201
|
+
<button
|
|
202
|
+
type="button"
|
|
203
|
+
onClick={handleOpenInNewTab}
|
|
204
|
+
onKeyDown={(e) => {
|
|
205
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
206
|
+
handleOpenInNewTab(e);
|
|
207
|
+
}
|
|
208
|
+
}}
|
|
209
|
+
aria-label={`Open session ${conversationId} in a new tab`}
|
|
210
|
+
title="Open this session in a new tab"
|
|
211
|
+
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"
|
|
212
|
+
>
|
|
213
|
+
<ExternalLink className="size-3.5" />
|
|
214
|
+
</button>
|
|
215
|
+
|
|
173
216
|
{/* Per-group Clear — does not toggle the group's expand state */}
|
|
174
217
|
{onClear !== undefined && (
|
|
175
218
|
<button
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
2
|
+
import { ProxyViewerContainer } from "../../components/ProxyViewerContainer";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Base64url-decode a path segment back to the original conversation id.
|
|
6
|
+
* Base64url uses `-` instead of `+`, `_` instead of `/`, and omits padding.
|
|
7
|
+
*
|
|
8
|
+
* Falls back to `decodeURIComponent` for legacy percent-encoded URLs (e.g.
|
|
9
|
+
* plain UUIDs or "default" that survived the Vite dev-server redirect).
|
|
10
|
+
*/
|
|
11
|
+
/** Only characters that can appear in a base64url-encoded payload. */
|
|
12
|
+
const B64URL_RE = /^[A-Za-z0-9_-]+$/;
|
|
13
|
+
|
|
14
|
+
function b64urlDecode(encoded: string): string {
|
|
15
|
+
// Legacy percent-encoded URLs — may still work for simple ids.
|
|
16
|
+
if (encoded.startsWith("%")) {
|
|
17
|
+
return decodeURIComponent(encoded);
|
|
18
|
+
}
|
|
19
|
+
// Guard against non-base64url input — atob() doesn't always throw on invalid
|
|
20
|
+
// input in all browsers and can return binary garbage.
|
|
21
|
+
if (!B64URL_RE.test(encoded)) {
|
|
22
|
+
return encoded;
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
const base64 = encoded.replace(/-/g, "+").replace(/_/g, "/");
|
|
26
|
+
const decoded = atob(base64);
|
|
27
|
+
// atob() on a random alphanum string can produce binary garbage in
|
|
28
|
+
// browsers that auto-pad. Check that every character is printable
|
|
29
|
+
// (tab, newline, carriage return, and space through DEL are fine;
|
|
30
|
+
// anything else — control chars, high bytes — signals garbage).
|
|
31
|
+
for (let i = 0; i < decoded.length; i++) {
|
|
32
|
+
const c = decoded.charCodeAt(i);
|
|
33
|
+
if (c < 0x09 || c === 0x0b || c === 0x0c || (c > 0x0d && c < 0x20) || c >= 0x7f) {
|
|
34
|
+
return encoded;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return decoded;
|
|
38
|
+
} catch {
|
|
39
|
+
return encoded;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Base64url-encode a conversation id so the path survives Vite's URL
|
|
44
|
+
* normalisation (which `decodeURI`s the path and 307-redirects when the
|
|
45
|
+
* result differs — causing an infinite redirect for chars like `{` `"` `}`).
|
|
46
|
+
*/
|
|
47
|
+
function b64urlEncode(raw: string): string {
|
|
48
|
+
return btoa(raw).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Per-session deep link: opens a page that is pre-scoped to a single
|
|
53
|
+
* session id, sharing the same SSE stream and `useStripConfig` settings
|
|
54
|
+
* as the main `/` view.
|
|
55
|
+
*
|
|
56
|
+
* The session id is base64url-encoded in the URL so JSON session blobs
|
|
57
|
+
* (e.g. Claude Code's
|
|
58
|
+
* `{"device_id":"...","account_uuid":"","session_id":"..."}`) survive
|
|
59
|
+
* the Vite dev-server's URL normalisation without triggering a redirect
|
|
60
|
+
* loop.
|
|
61
|
+
*/
|
|
62
|
+
export const Route = createFileRoute("/session/$sessionId")({
|
|
63
|
+
component: SessionViewerRoute,
|
|
64
|
+
parseParams: (params) => ({
|
|
65
|
+
sessionId: b64urlDecode(params.sessionId),
|
|
66
|
+
}),
|
|
67
|
+
stringifyParams: (params) => ({
|
|
68
|
+
sessionId: b64urlEncode(params.sessionId),
|
|
69
|
+
}),
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
function SessionViewerRoute(): React.JSX.Element {
|
|
73
|
+
const { sessionId } = Route.useParams();
|
|
74
|
+
return <ProxyViewerContainer key={sessionId} initialSessionId={sessionId} />;
|
|
75
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as h,j as t}from"./main-CZJ63sQh.js";import{c as X,g as O,r as P,a as q,X as Y,b as x,B as Z,f as $,R as ee,C as te,M as _,P as J,d as M,e as B,h as re,i as ne}from"./index-B-0F9n1w.js";import{J as N}from"./json-viewer-D-z1r1Pp.js";const se=[["line",{x1:"5",x2:"19",y1:"9",y2:"9",key:"1nwqeh"}],["line",{x1:"5",x2:"19",y1:"15",y2:"15",key:"g8yjpy"}]],ae=X("equal",se),oe="";function j(e){if(e.length===0)return oe;let r="";for(let n=0;n<e.length;n++){const s=e[n];s!==void 0&&(typeof s=="number"?r+=`[${s}]`:n===0?r+=s:r+=`.${s}`)}return r}function de(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function D(e){if(typeof e=="string")try{return C(JSON.parse(e))}catch{return{kind:"primitive",value:e}}return C(e)}function C(e){if(e===null)return{kind:"primitive",value:null};if(typeof e=="string")return{kind:"primitive",value:e};if(typeof e=="number")return{kind:"primitive",value:e};if(typeof e=="boolean")return{kind:"primitive",value:e};if(Array.isArray(e))return{kind:"array",value:e.map(r=>C(r))};if(de(e)){const r={};for(const n of Object.keys(e).sort())r[n]=C(e[n]);return{kind:"object",value:r}}return{kind:"primitive",value:null}}function ie(e,r){const n=[];return R([],e,r,n),n}function R(e,r,n,s){const d=j(e);if(E(r,n)){s.push({kind:"equal",path:d,value:r});return}if(r.kind!==n.kind){s.push({kind:"changed",path:d,left:r,right:n});return}if(r.kind==="primitive"&&n.kind==="primitive"){s.push({kind:"changed",path:d,left:r,right:n});return}if(r.kind==="object"&&n.kind==="object"){const o=Object.keys(r.value),a=Object.keys(n.value),m=new Set(a);for(const i of o){const f=r.value[i];if(f!==void 0)if(!m.has(i))s.push({kind:"removed",path:j([...e,i]),value:f});else{const p=n.value[i];if(p===void 0)continue;R([...e,i],f,p,s)}}for(const i of a){if(o.includes(i))continue;const f=n.value[i];f!==void 0&&s.push({kind:"added",path:j([...e,i]),value:f})}return}if(r.kind==="array"&&n.kind==="array"){const o=Math.min(r.value.length,n.value.length);for(let a=0;a<o;a++){const m=r.value[a],i=n.value[a];m===void 0||i===void 0||R([...e,a],m,i,s)}for(let a=o;a<n.value.length;a++){const m=n.value[a];m!==void 0&&s.push({kind:"added",path:j([...e,a]),value:m})}for(let a=o;a<r.value.length;a++){const m=r.value[a];m!==void 0&&s.push({kind:"removed",path:j([...e,a]),value:m})}}}function E(e,r){if(e.kind!==r.kind)return!1;if(e.kind==="primitive"&&r.kind==="primitive")return e.value===r.value;if(e.kind==="array"&&r.kind==="array"){if(e.value.length!==r.value.length)return!1;for(let n=0;n<e.value.length;n++){const s=e.value[n],d=r.value[n];if(s===void 0||d===void 0||!E(s,d))return!1}return!0}if(e.kind==="object"&&r.kind==="object"){const n=Object.keys(e.value),s=Object.keys(r.value);if(n.length!==s.length)return!1;for(const d of n){const o=e.value[d],a=r.value[d];if(o===void 0||a===void 0||!E(o,a))return!1}return!0}return!1}function v(e,r=80){let n;switch(e.kind){case"primitive":n=e.value===null?"null":JSON.stringify(e.value);break;case"array":n=`[… ${e.value.length} items]`;break;case"object":n=`{… ${Object.keys(e.value).length} keys}`;break}return n.length>r&&(n=`${n.slice(0,r-1)}…`),n}function w(e,r=2){return JSON.stringify(S(e),null,r)}function S(e){switch(e.kind){case"primitive":return e.value;case"array":return e.value.map(S);case"object":{const r={};for(const[n,s]of Object.entries(e.value))r[n]=S(s);return r}}}function L(e){if(e==="")return"";for(let r=e.length-1;r>=0;r--){const n=e[r];if(n==="."||n==="[")return e.substring(0,r)}return""}function A(e){return e.kind==="equal"&&(e.value.kind==="object"||e.value.kind==="array")}function le(e){const r=[];let n=0;for(;n<e.length;){const s=e[n];if(s!==void 0&&A(s)){const d=L(s.path);let o=n+1;for(;o<e.length;){const a=e[o];if(a===void 0||!A(a)||L(a.path)!==d)break;o++}if(o-n>1){const a=[];for(let m=n;m<o;m++){const i=e[m];i!==void 0&&i.kind==="equal"&&a.push(i)}r.push({kind:"equal-run",ops:a}),n=o;continue}}s!==void 0&&r.push({kind:"single",op:s}),n++}return r}const V={added:{icon:J,accent:"text-emerald-600 dark:text-emerald-400",bg:"bg-emerald-500/5 hover:bg-emerald-500/10",border:"border-l-emerald-500",label:"ADDED"},removed:{icon:_,accent:"text-rose-600 dark:text-rose-400",bg:"bg-rose-500/5 hover:bg-rose-500/10",border:"border-l-rose-500",label:"REMOVED"},changed:{icon:M,accent:"text-amber-600 dark:text-amber-400",bg:"bg-amber-500/5 hover:bg-amber-500/10",border:"border-l-amber-500",label:"CHANGED"},equal:{icon:ae,accent:"text-muted-foreground/70",bg:"bg-muted/20 hover:bg-muted/30",border:"border-l-muted-foreground/20",label:"EQUAL"}};function ce({ops:e,expanded:r,onToggle:n}){const s=e[0],d=e[e.length-1];if(s===void 0||d===void 0)return t.jsx("div",{className:"text-muted-foreground/40 text-xs",children:"—"});const o=s.path,a=d.path,m=e.length===1?o:`${o} … ${a}`,i=s.value.kind==="array"?`${e.length} equal arrays`:s.value.kind==="object"?`${e.length} equal objects`:"equal",f=V.equal;return t.jsxs("div",{className:x("border-l-4 rounded-sm",f.border,f.bg),children:[t.jsxs("button",{type:"button",onClick:n,className:"w-full text-left flex items-center gap-2 px-3 py-1.5 text-xs text-muted-foreground cursor-pointer",children:[t.jsx(B,{className:x("size-3 transition-transform shrink-0",r&&"rotate-90")}),t.jsx(f.icon,{className:x("size-3 shrink-0",f.accent)}),t.jsx("span",{className:"font-mono truncate flex-1",title:`${o} … ${a}`,children:m}),t.jsx("span",{className:x("text-[10px] uppercase tracking-wider shrink-0",f.accent),children:f.label}),t.jsxs("span",{className:"text-muted-foreground/60 shrink-0",children:["(",i,")"]})]}),r&&t.jsx("div",{className:"ml-5 mt-1 mb-2 space-y-2 pr-2",children:e.map(p=>t.jsxs("div",{className:"border border-border/50 rounded p-2 bg-muted/20",children:[t.jsx("div",{className:"font-mono text-xs text-muted-foreground mb-1",children:p.path}),t.jsx(N,{text:w(p.value),defaultExpandDepth:0})]},p.path))})]})}function ue({op:e,idx:r,copiedPath:n,onCopyPath:s,expanded:d,onToggle:o}){const a=V[e.kind],m=a.icon,i=e.kind==="added"||e.kind==="removed"?e.value.kind==="object"||e.value.kind==="array":e.kind==="changed"?e.left.kind==="object"||e.left.kind==="array"||e.right.kind==="object"||e.right.kind==="array":!1,f=e.kind==="changed"?[{text:v(e.left,400),tone:"text-rose-700 dark:text-rose-300 line-through"},{text:v(e.right,400),tone:"text-emerald-700 dark:text-emerald-300"}]:e.kind==="removed"?[{text:v(e.value,400),tone:"text-rose-700 dark:text-rose-300 line-through"}]:e.kind==="added"?[{text:v(e.value,400),tone:"text-emerald-700 dark:text-emerald-300"}]:[{text:v(e.value,400),tone:"text-muted-foreground"}],p=n===e.path&&e.path!=="";return t.jsxs("div",{"data-diff-idx":r,"data-diff-kind":e.kind,className:x("border-l-4 rounded-sm px-3 py-2 my-0.5 transition-colors",a.border,a.bg),children:[t.jsxs("button",{type:"button",onClick:o,disabled:!i,className:x("w-full flex items-center gap-2 text-xs text-left rounded-sm",i?"cursor-pointer":"cursor-default"),"aria-expanded":i?d:void 0,"aria-label":i?d?`Collapse ${e.path||"root"}`:`Expand ${e.path||"root"}`:void 0,children:[i?t.jsx(B,{className:x("size-3 shrink-0 transition-transform",a.accent,d&&"rotate-90")}):t.jsx("span",{className:"size-3 shrink-0","aria-hidden":"true"}),t.jsx(m,{className:x("size-3.5 shrink-0",a.accent),strokeWidth:2.5}),t.jsx("span",{className:"font-mono truncate flex-1 min-w-0",title:e.path||"(root)",children:e.path===""?"(root)":e.path}),t.jsx("span",{className:x("text-[9px] font-bold uppercase tracking-wider shrink-0 px-1.5 py-0.5 rounded",a.accent,e.kind==="equal"?"bg-muted/40":"bg-background/60"),children:a.label}),e.path!==""&&t.jsx("span",{role:"button",tabIndex:0,onClick:b=>{b.stopPropagation(),s(e.path)},onKeyDown:b=>{(b.key==="Enter"||b.key===" ")&&(b.stopPropagation(),b.preventDefault(),s(e.path))},className:x("shrink-0 p-1 rounded transition-colors cursor-pointer inline-flex items-center justify-center",p?"text-emerald-500":"text-muted-foreground/50 hover:text-foreground hover:bg-muted"),"aria-label":p?"Copied":"Copy",title:p?"Copied!":"Copy",children:p?t.jsx(re,{className:"size-3"}):t.jsx(ne,{className:"size-3"})})]}),f.map((b,y)=>t.jsx("div",{className:x("font-mono text-xs mt-1 break-all pl-5",b.tone),children:b.text},y)),t.jsx("div",{className:"overflow-hidden transition-all duration-200",style:{maxHeight:d&&i?"2000px":"0"},"aria-hidden":!d,children:d&&i&&e.kind!=="equal"?t.jsx(me,{op:e}):null})]})}function me({op:e}){if(e.kind==="added"||e.kind==="removed")return t.jsx("div",{className:"pl-5 mt-2 border border-border/50 rounded p-2 bg-muted/20",children:t.jsx(N,{text:w(e.value),defaultExpandDepth:0})});const r=e.left.kind==="object"||e.left.kind==="array",n=e.right.kind==="object"||e.right.kind==="array";return!r&&!n?t.jsx("div",{className:"pl-5 mt-2 text-xs text-muted-foreground/70 italic",children:"Primitive values are shown inline above."}):t.jsxs("div",{className:"pl-5 mt-2 grid grid-cols-1 md:grid-cols-2 gap-2",children:[t.jsxs("div",{className:"border border-rose-500/30 rounded p-2 bg-rose-500/5",children:[t.jsx("div",{className:"text-[10px] uppercase tracking-wider text-rose-500 mb-1",children:"Old"}),t.jsx(N,{text:w(e.left),defaultExpandDepth:0})]}),t.jsxs("div",{className:"border border-emerald-500/30 rounded p-2 bg-emerald-500/5",children:[t.jsx("div",{className:"text-[10px] uppercase tracking-wider text-emerald-500 mb-1",children:"New"}),t.jsx(N,{text:w(e.right),defaultExpandDepth:0})]})]})}function xe({counts:e,onJumpTo:r}){const n=e.added+e.removed+e.changed;return t.jsxs("div",{className:"px-4 py-2 border-b border-border bg-muted/20 flex items-center gap-2 text-xs flex-wrap",children:[t.jsxs("span",{className:"text-muted-foreground font-medium",children:[n," ",n===1?"change":"changes"]}),t.jsxs("button",{type:"button",onClick:()=>r("removed"),disabled:e.removed===0,className:x("inline-flex items-center gap-1 px-2 py-0.5 rounded-full border cursor-pointer transition-colors",e.removed>0?"border-rose-500/40 text-rose-600 dark:text-rose-400 bg-rose-500/10 hover:bg-rose-500/20":"border-border text-muted-foreground/40 cursor-not-allowed"),title:e.removed>0?"Jump to first removed":"No removals",children:[t.jsx(_,{className:"size-3"}),e.removed," removed"]}),t.jsxs("button",{type:"button",onClick:()=>r("added"),disabled:e.added===0,className:x("inline-flex items-center gap-1 px-2 py-0.5 rounded-full border cursor-pointer transition-colors",e.added>0?"border-emerald-500/40 text-emerald-600 dark:text-emerald-400 bg-emerald-500/10 hover:bg-emerald-500/20":"border-border text-muted-foreground/40 cursor-not-allowed"),title:e.added>0?"Jump to first added":"No additions",children:[t.jsx(J,{className:"size-3"}),e.added," added"]}),t.jsxs("button",{type:"button",onClick:()=>r("changed"),disabled:e.changed===0,className:x("inline-flex items-center gap-1 px-2 py-0.5 rounded-full border cursor-pointer transition-colors",e.changed>0?"border-amber-500/40 text-amber-600 dark:text-amber-400 bg-amber-500/10 hover:bg-amber-500/20":"border-border text-muted-foreground/40 cursor-not-allowed"),title:e.changed>0?"Jump to first changed":"No changes",children:[t.jsx(M,{className:"size-3"}),e.changed," changed"]})]})}function fe({mode:e,onChange:r}){return t.jsxs("div",{className:"inline-flex rounded-md border border-border overflow-hidden",children:[t.jsxs("button",{type:"button",onClick:()=>r("unified"),"aria-pressed":e==="unified",className:x("flex items-center gap-1 px-2 py-1 text-xs transition-colors cursor-pointer",e==="unified"?"bg-muted text-foreground":"hover:bg-muted/50 text-muted-foreground"),title:"Unified view (single column, emphasized diffs)",children:[t.jsx(ee,{className:"size-3"}),"Unified"]}),t.jsxs("button",{type:"button",onClick:()=>r("split"),"aria-pressed":e==="split",className:x("flex items-center gap-1 px-2 py-1 text-xs transition-colors border-l border-border cursor-pointer",e==="split"?"bg-muted text-foreground":"hover:bg-muted/50 text-muted-foreground"),title:"Split view (path | left | right)",children:[t.jsx(te,{className:"size-3"}),"Split"]})]})}function K({log:e,side:r}){const n=q(e);return t.jsxs("div",{className:"flex-1 min-w-0 space-y-1 text-xs",children:[t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsx(Z,{variant:"outline",className:x("text-[10px] px-1.5 py-0 h-5 font-mono shrink-0",r==="left"?"border-rose-500/40 text-rose-400":"border-emerald-500/40 text-emerald-400"),children:r==="left"?"← Left":"Right →"}),t.jsxs("span",{className:"font-mono text-blue-400/80",children:["#",e.id]}),e.model!==null&&t.jsx("span",{className:"font-mono text-muted-foreground truncate",children:e.model})]}),t.jsxs("div",{className:"flex items-center gap-3 text-muted-foreground font-mono",children:[e.cacheCreationInputTokens!==null&&e.cacheCreationInputTokens>0&&t.jsxs("span",{className:"text-emerald-400",children:["Cache +",$(e.cacheCreationInputTokens)]}),e.cacheReadInputTokens!==null&&e.cacheReadInputTokens>0&&t.jsxs("span",{className:"text-purple-400",children:["Cache ~",$(e.cacheReadInputTokens)]}),t.jsx("span",{className:"truncate",title:e.timestamp,children:e.timestamp})]}),t.jsxs("div",{className:"text-muted-foreground/70 font-mono truncate",title:n,children:["session: ",n]})]})}function ge({left:e,right:r,onClose:n}){const s=h.useMemo(()=>{const l=O(P(e)).analyzeRequest(e.rawRequestBody),c=O(P(r)).analyzeRequest(r.rawRequestBody),u=D(l.comparisonValue),g=D(c.comparisonValue);return ie(u,g)},[e.apiFormat,e.path,e.rawRequestBody,r.apiFormat,r.path,r.rawRequestBody]),d=h.useMemo(()=>le(s),[s]),o=h.useMemo(()=>{let l=0,c=0,u=0;for(const g of d)if(g.kind==="single")switch(g.op.kind){case"added":l++;break;case"removed":c++;break;case"changed":u++;break}return{added:l,removed:c,changed:u}},[d]),[a,m]=h.useState(new Set),i=l=>{m(c=>{const u=new Set(c);return u.has(l)?u.delete(l):u.add(l),u})},[f,p]=h.useState(new Set),b=l=>{p(c=>{const u=new Set(c);return u.has(l)?u.delete(l):u.add(l),u})};h.useEffect(()=>{p(new Set)},[e.id,r.id]);const[y,F]=h.useState("unified"),T=h.useRef(null),[U,z]=h.useState(null),k=h.useRef(null),H=l=>{window.navigator.clipboard.writeText(l).then(()=>{z(l),k.current!==null&&clearTimeout(k.current),k.current=setTimeout(()=>z(null),1500)})};h.useEffect(()=>()=>{k.current!==null&&clearTimeout(k.current)},[]);const G=l=>{const c=d.findIndex(I=>I.kind==="single"&&I.op.kind===l);if(c===-1)return;const u=T.current;if(u===null)return;const g=u.querySelector(`[data-diff-idx="${c}"]`);g!==null&&g.scrollIntoView({behavior:"smooth",block:"center"})};h.useEffect(()=>{const l=u=>{u.key==="Escape"&&n()};document.addEventListener("keydown",l);const c=document.body.style.overflow;return document.body.style.overflow="hidden",()=>{document.removeEventListener("keydown",l),document.body.style.overflow=c}},[n]);const Q=q(e)===q(r),W=s.length===1&&s[0]?.kind==="equal";return t.jsxs("div",{className:"fixed inset-0 z-50 flex justify-end",role:"dialog","aria-modal":"true","aria-label":"Compare two log requests",children:[t.jsx("button",{type:"button",onClick:n,"aria-label":"Close compare drawer",className:"absolute inset-0 bg-black/40 cursor-default",tabIndex:-1}),t.jsxs("div",{className:x("relative bg-background border-l border-border shadow-xl","w-full md:w-[70vw] max-w-[1100px] flex flex-col h-full"),onClick:l=>l.stopPropagation(),onKeyDown:l=>l.stopPropagation(),children:[t.jsxs("div",{className:"flex items-start gap-4 px-4 py-3 border-b border-border",children:[t.jsxs("div",{className:"flex-1 flex gap-4 min-w-0",children:[t.jsx(K,{log:e,side:"left"}),t.jsx(K,{log:r,side:"right"})]}),t.jsxs("div",{className:"flex items-center gap-2 shrink-0",children:[t.jsx(fe,{mode:y,onChange:F}),t.jsx("button",{type:"button",onClick:n,"aria-label":"Close",className:"p-1 rounded text-muted-foreground hover:text-foreground hover:bg-muted cursor-pointer",children:t.jsx(Y,{className:"size-4"})})]})]}),!Q&&t.jsx("div",{className:"px-4 py-1.5 text-xs text-amber-400 bg-amber-500/10 border-b border-border",children:"Heads up: the two selected logs are from different sessions."}),W?t.jsx("div",{className:"flex-1 min-h-0 overflow-y-auto flex items-center justify-center text-muted-foreground text-sm",children:"The two Request payloads are identical."}):t.jsxs(t.Fragment,{children:[t.jsx(xe,{counts:o,onJumpTo:G}),t.jsx("div",{ref:T,className:"flex-1 min-h-0 overflow-y-auto",children:y==="unified"?t.jsx("div",{className:"px-3 py-2 space-y-0.5",children:d.map((l,c)=>{if(l.kind==="equal-run")return t.jsx(ce,{ops:l.ops,expanded:a.has(c),onToggle:()=>i(c)},`r${c}`);const u=l.op;return t.jsx(ue,{op:u,idx:c,copiedPath:U,onCopyPath:H,expanded:f.has(c),onToggle:()=>b(c)},`o${c}`)})}):t.jsx(pe,{grouped:d,left:e,right:r})})]})]})]})}function pe({grouped:e,left:r,right:n}){return t.jsxs("div",{className:"grid grid-cols-[200px_1fr_1fr] gap-x-2 gap-y-0.5 px-3 py-2 text-xs",children:[t.jsxs("div",{className:"grid grid-cols-[200px_1fr_1fr] gap-x-2 col-span-3 pb-2 mb-2 border-b border-border text-[10px] uppercase tracking-wider text-muted-foreground",children:[t.jsx("span",{children:"Path"}),t.jsxs("span",{children:["Left (Log #",r.id,")"]}),t.jsxs("span",{children:["Right (Log #",n.id,")"]})]}),e.map((s,d)=>{if(s.kind==="equal-run")return t.jsxs("div",{className:"col-span-3 px-2 py-1 text-xs text-muted-foreground/60",children:[s.ops.length," equal siblings collapsed — switch to Unified to expand"]},d);const o=s.op;return o.kind==="equal"?t.jsxs("div",{className:"col-span-3 grid grid-cols-[200px_1fr_1fr] gap-x-2 px-2 py-0.5 text-muted-foreground",children:[t.jsx("span",{className:"font-mono text-xs truncate",title:o.path,children:o.path}),t.jsx("span",{className:"font-mono text-xs break-all opacity-60",children:v(o.value,200)}),t.jsx("span",{className:"font-mono text-xs break-all opacity-60",children:v(o.value,200)})]},d):o.kind==="added"?t.jsxs("div",{className:"col-span-3 px-2 py-1 rounded text-xs border-l-2 border-l-emerald-400/70 bg-emerald-500/5",children:[t.jsx("div",{className:"font-mono text-xs text-muted-foreground mb-0.5",children:o.path}),t.jsxs("div",{className:"font-mono break-all text-emerald-300/90",children:["+ ",v(o.value,400)]})]},d):o.kind==="removed"?t.jsxs("div",{className:"col-span-3 px-2 py-1 rounded text-xs border-l-2 border-l-rose-400/70 bg-rose-500/5",children:[t.jsx("div",{className:"font-mono text-xs text-muted-foreground mb-0.5",children:o.path}),t.jsxs("div",{className:"font-mono break-all text-rose-300/90 line-through",children:["− ",v(o.value,400)]})]},d):t.jsxs("div",{className:"col-span-3 px-2 py-1 rounded text-xs border-l-2 border-l-amber-400/70 bg-amber-500/5",children:[t.jsx("div",{className:"font-mono text-xs text-muted-foreground mb-1",children:o.path}),t.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[t.jsx("div",{className:"font-mono text-rose-300/90 break-all line-through",children:v(o.left,400)}),t.jsx("div",{className:"font-mono text-emerald-300/90 break-all",children:v(o.right,400)})]})]},d)})]})}export{ge as CompareDrawer};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as l,j as e}from"./main-CZJ63sQh.js";import{D as S,j as C,k as q,l as D,m as F,T as i,n as u,o as n,p as t,q as B,s as E,t as I,u as O,v as V,w as z,x as v,y as d,z as R}from"./index-B-0F9n1w.js";import{ResponseView as h}from"./ResponseView-CJqxo-EN.js";import"./json-viewer-D-z1r1Pp.js";const M=z({success:v(),error:R().optional(),responseStatus:d().optional(),responseText:R().optional(),inputTokens:d().optional(),outputTokens:d().optional(),elapsedMs:d().optional(),streaming:v().optional()});function $({log:a,open:y,onOpenChange:g}){const[j,w]=l.useState(()=>a.rawRequestBody??"{}"),[s,p]=l.useState(null),[f,c]=l.useState(!1),[x,r]=l.useState(null);async function k(){c(!0),r(null),p(null);try{const N=await(await fetch(`/api/logs/${a.id}/replay`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({modifiedBody:j})})).json(),T=M.safeParse(N);if(!T.success){r("Invalid response from server"),c(!1);return}const m=T.data;p(m),m.success||r(m.error??"Replay failed")}catch(o){r(o instanceof Error?o.message:"Network error")}finally{c(!1)}}function b(){p(null),r(null),g(!1)}return e.jsx(S,{open:y,onOpenChange:b,children:e.jsxs(C,{className:"max-w-4xl max-h-[85vh] overflow-auto",children:[e.jsx(q,{children:e.jsxs(D,{className:"flex items-center gap-2",children:[e.jsx(F,{className:"size-4"}),"Replay Request #",a.id]})}),e.jsxs(i,{defaultValue:"modified",children:[e.jsxs(u,{children:[e.jsx(n,{value:"modified",children:"Modified Request"}),e.jsx(n,{value:"original",children:"Original Response"}),s&&e.jsx(n,{value:"replay",children:"Replay Response"})]}),e.jsxs(t,{value:"modified",className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"text-sm font-medium mb-2 block",children:"Request Body (JSON)"}),e.jsx(B,{children:e.jsxs(E,{children:[e.jsx(I,{asChild:!0,children:e.jsx("textarea",{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",value:j,onChange:o=>w(o.target.value),spellCheck:!1})}),e.jsx(O,{children:"Edit the request body before re-sending to the provider"})]})})]}),x!==null&&x!==""&&e.jsx("div",{className:"text-sm text-destructive bg-destructive/10 px-3 py-2 rounded-md",children:x}),e.jsx("div",{className:"flex justify-end",children:e.jsx(V,{onClick:()=>{k()},disabled:f,children:f?"Replaying...":"Replay"})}),s&&s.success&&e.jsxs(i,{defaultValue:"parsed",children:[e.jsxs(u,{children:[e.jsx(n,{value:"parsed",children:"Response"}),e.jsx(n,{value:"raw",children:"Raw Response"})]}),e.jsx(t,{value:"parsed",children:e.jsx(h,{responseText:s.responseText??null,responseStatus:s.responseStatus??null,streaming:s.streaming??!1,inputTokens:s.inputTokens??null,outputTokens:s.outputTokens??null,apiFormat:a.apiFormat})}),e.jsx(t,{value:"raw",children:e.jsx("pre",{className:"font-mono text-xs whitespace-pre-wrap bg-muted p-3 rounded-md max-h-96 overflow-auto",children:s.responseText??"No response"})})]})]}),e.jsx(t,{value:"original",children:a.responseText!==null?e.jsxs(i,{defaultValue:"parsed",children:[e.jsxs(u,{children:[e.jsx(n,{value:"parsed",children:"Response"}),e.jsx(n,{value:"raw",children:"Raw Response"})]}),e.jsx(t,{value:"parsed",children:e.jsx(h,{responseText:a.responseText,responseStatus:a.responseStatus,streaming:a.streaming,inputTokens:a.inputTokens,outputTokens:a.outputTokens,cacheCreationInputTokens:a.cacheCreationInputTokens,cacheReadInputTokens:a.cacheReadInputTokens,apiFormat:a.apiFormat})}),e.jsx(t,{value:"raw",children:e.jsx("pre",{className:"font-mono text-xs whitespace-pre-wrap bg-muted p-3 rounded-md max-h-96 overflow-auto",children:a.responseText})})]}):e.jsx("p",{className:"text-sm text-muted-foreground italic",children:"No original response"})}),s&&s.success&&e.jsx(t,{value:"replay",children:s.responseText!==null?e.jsxs(i,{defaultValue:"parsed",children:[e.jsxs(u,{children:[e.jsx(n,{value:"parsed",children:"Response"}),e.jsx(n,{value:"raw",children:"Raw Response"})]}),e.jsx(t,{value:"parsed",children:e.jsx(h,{responseText:s.responseText??null,responseStatus:s.responseStatus??null,streaming:s.streaming??!1,inputTokens:s.inputTokens??null,outputTokens:s.outputTokens??null,apiFormat:a.apiFormat})}),e.jsx(t,{value:"raw",children:e.jsx("pre",{className:"font-mono text-xs whitespace-pre-wrap bg-muted p-3 rounded-md max-h-96 overflow-auto",children:s.responseText})})]}):e.jsx("p",{className:"text-sm text-muted-foreground italic",children:"No replay response"})})]})]})})}export{$ as ReplayDialog};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as c,j as e}from"./main-CZJ63sQh.js";import{c as S,f as i,q as $,s as j,t as y,b as C,u as N}from"./index-B-0F9n1w.js";const k=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 16v-4",key:"1dtifu"}],["path",{d:"M12 8h.01",key:"e9boi3"}]],R=S("info",k),z={system:"bg-sky-500/70",user:"bg-emerald-500/70",assistant:"bg-violet-500/70",tool:"bg-amber-500/70",tools:"bg-slate-500/70"},T={system:"focus-visible:ring-sky-300",user:"focus-visible:ring-emerald-300",assistant:"focus-visible:ring-violet-300",tool:"focus-visible:ring-amber-300",tools:"focus-visible:ring-slate-300"},g=12,h=1,M=80,I=24;function O(n){return n.length<=I?n:`${n.slice(0,I-1)}…`}function A(n){const s=n.replace(/\s+/g," ").trim();return s.length<=M?s:`${s.slice(0,M)}…`}const D=c.memo(function({segments:s,totalTokens:x,onActivate:u}){const r=c.useMemo(()=>x>0?x:s.reduce((t,l)=>t+l.size,0),[s,x]),o=s.slice(0,g),d=s.slice(g),f=d.reduce((t,l)=>t+l.size,0),a=d.length,m=g,L=m+a-1,w=a>0,_=c.useMemo(()=>o.reduce((t,l)=>t+l.size,0),[o]),E=c.useMemo(()=>`Request anatomy: ~${i(r)} tokens across ${s.length} segment${s.length===1?"":"s"}`,[s.length,r]);return s.length===0||r<=0?e.jsx("div",{role:"img","aria-label":E,className:"h-6"}):e.jsx($,{delayDuration:150,children:e.jsxs("div",{role:"img","aria-label":E,className:"flex flex-col gap-1.5",children:[e.jsxs("div",{className:"relative flex h-6 w-full overflow-hidden rounded border border-border/40 bg-muted/30","data-testid":"anatomy-segment-bar",children:[o.map((t,l)=>{const b=r>0?t.size/r*100:0,v=Math.max(h,b);return e.jsxs(j,{children:[e.jsx(y,{asChild:!0,children:e.jsx("button",{type:"button",role:"button",tabIndex:0,onClick:()=>u?.(t),onKeyDown:p=>{(p.key==="Enter"||p.key===" ")&&(p.preventDefault(),u?.(t))},"data-anatomy-path":t.path,"aria-label":`${t.label}, ~${i(t.size)} tokens`,className:C("h-full border-r border-background/80 last:border-r-0","opacity-90 hover:opacity-100 focus:opacity-100","focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:ring-offset-background",z[t.role],T[t.role]),style:{width:`${v}%`}})}),e.jsxs(N,{side:"bottom",className:"max-w-sm text-xs p-2 space-y-0.5",children:[e.jsxs("div",{className:"font-semibold",children:[t.label," · ~",i(t.size)," tokens"]}),e.jsxs("div",{className:"text-muted-foreground",children:[t.characters.toLocaleString()," chars"]}),t.text.length>0&&e.jsx("div",{className:"text-muted-foreground/90 break-words whitespace-pre-wrap",children:A(t.text)})]})]},`${t.path}-${l}`)}),w&&e.jsxs(j,{children:[e.jsx(y,{asChild:!0,children:e.jsxs("div",{role:"img","aria-label":`${a} additional segments`,className:"flex h-full items-center justify-center bg-muted-foreground/30 px-1.5 text-[10px] font-mono text-background",style:{width:`${Math.max(h,f/r*100)}%`},children:["… +",a]})}),e.jsxs(N,{side:"bottom",className:"text-xs",children:[a," more segment",a===1?"":"s"," (indices"," ",m,"–",L,")"]})]})]}),e.jsxs("div",{className:"flex w-full gap-1 text-[10px] text-muted-foreground",children:[o.map((t,l)=>{const b=r>0?t.size/r*100:0,v=Math.max(h,b);return e.jsxs("div",{className:"flex flex-col gap-0.5 truncate",style:{width:`${v}%`},title:`${t.label} · ~${i(t.size)} tokens`,children:[e.jsx("span",{className:"truncate font-mono text-foreground/80",children:O(t.label)}),e.jsxs("span",{className:"truncate font-mono text-muted-foreground/70",children:["~",i(t.size)]})]},`label-${t.path}-${l}`)}),w&&e.jsxs("div",{className:"flex flex-col gap-0.5 truncate text-muted-foreground",style:{width:`${Math.max(h,f/r*100)}%`},children:[e.jsxs("span",{className:"truncate font-mono text-foreground/60",children:["… +",a]}),e.jsxs("span",{className:"truncate font-mono text-muted-foreground/60",children:["~",i(f)]})]})]}),_<r*.1&&e.jsx("div",{className:"h-0"})]})})}),P=.25;function q({parsed:n,inputTokens:s,onSegmentActivate:x,segments:u}){const r=c.useMemo(()=>u??null,[u]),o=c.useMemo(()=>(r??[]).reduce((a,m)=>a+m.size,0),[r]),d=c.useMemo(()=>r==null||s===null||o===0?!1:Math.abs(s-o)/Math.max(s,o)>=P,[s,r,o]),f=c.useMemo(()=>s===null?"text-muted-foreground":d?"text-amber-400":"text-muted-foreground",[s,d]);return r==null||r.length===0||n===null&&u===void 0?null:e.jsx($,{delayDuration:150,children:e.jsxs("div",{className:"px-4 py-3 space-y-2","data-testid":"anatomy-root",children:[e.jsxs("div",{className:"flex items-center gap-2 text-xs",children:[e.jsxs("span",{className:"font-mono tabular-nums text-foreground",children:["~",i(o)," tokens"]}),s!==null&&e.jsxs("span",{className:C("font-mono tabular-nums",f),children:["(server: ",i(s),")"]}),d&&e.jsxs(j,{children:[e.jsx(y,{asChild:!0,children:e.jsx("button",{type:"button",className:"inline-flex items-center text-amber-400 hover:text-amber-300","aria-label":"Token estimate diverges from server",children:e.jsx(R,{className:"size-3.5"})})}),e.jsx(N,{className:"max-w-xs text-xs",children:"Bar uses a token estimate heuristic (~4 ASCII chars / token, ~1 CJK / emoji char per token). The server's reported value is the source of truth for cost."})]})]}),e.jsx(D,{segments:r,totalTokens:o,onActivate:x})]})})}export{q as RequestAnatomy};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as l,j as e}from"./main-CZJ63sQh.js";import{c as ee,A as He,E as _,F as Be,G as C,H as D,I as P,J as me,K as he,L as Ve,N as R,O as We,b as X,B as E,Q as U,e as Y,S as pe,Z as te,f as w,g as Fe,U as Xe,V as Ue}from"./index-B-0F9n1w.js";import{a as xe,M as $}from"./json-viewer-D-z1r1Pp.js";const Ye=[["path",{d:"M12 18V5",key:"adv99a"}],["path",{d:"M15 13a4.17 4.17 0 0 1-3-4 4.17 4.17 0 0 1-3 4",key:"1e3is1"}],["path",{d:"M17.598 6.5A3 3 0 1 0 12 5a3 3 0 1 0-5.598 1.5",key:"1gqd8o"}],["path",{d:"M17.997 5.125a4 4 0 0 1 2.526 5.77",key:"iwvgf7"}],["path",{d:"M18 18a4 4 0 0 0 2-7.464",key:"efp6ie"}],["path",{d:"M19.967 17.483A4 4 0 1 1 12 18a4 4 0 1 1-7.967-.517",key:"1gq6am"}],["path",{d:"M6 18a4 4 0 0 1-2-7.464",key:"k1g0md"}],["path",{d:"M6.003 5.125a4 4 0 0 0-2.526 5.77",key:"q97ue3"}]],$e=ee("brain",Ye);const Ge=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["rect",{x:"9",y:"9",width:"6",height:"6",rx:"1",key:"1ssd4o"}]],fe=ee("circle-stop",Ge);const qe=[["path",{d:"M12 19h8",key:"baeox8"}],["path",{d:"m4 17 6-6-6-6",key:"1yngyt"}]],ge=ee("terminal",qe);var G="Collapsible",[Je]=he(G),[Ke,ne]=Je(G),be=l.forwardRef((t,n)=>{const{__scopeCollapsible:r,open:o,defaultOpen:s,disabled:a,onOpenChange:i,...c}=t,[d,u]=He({prop:o,defaultProp:s??!1,onChange:i,caller:G});return e.jsx(Ke,{scope:r,disabled:a,contentId:Be(),open:d,onOpenToggle:l.useCallback(()=>u(m=>!m),[u]),children:e.jsx(_.div,{"data-state":oe(d),"data-disabled":a?"":void 0,...c,ref:n})})});be.displayName=G;var ve="CollapsibleTrigger",Se=l.forwardRef((t,n)=>{const{__scopeCollapsible:r,...o}=t,s=ne(ve,r);return e.jsx(_.button,{type:"button","aria-controls":s.contentId,"aria-expanded":s.open||!1,"data-state":oe(s.open),"data-disabled":s.disabled?"":void 0,disabled:s.disabled,...o,ref:n,onClick:C(t.onClick,s.onOpenToggle)})});Se.displayName=ve;var re="CollapsibleContent",je=l.forwardRef((t,n)=>{const{forceMount:r,...o}=t,s=ne(re,t.__scopeCollapsible);return e.jsx(D,{present:r||s.open,children:({present:a})=>e.jsx(Ze,{...o,ref:n,present:a})})});je.displayName=re;var Ze=l.forwardRef((t,n)=>{const{__scopeCollapsible:r,present:o,children:s,...a}=t,i=ne(re,r),[c,d]=l.useState(o),u=l.useRef(null),m=P(n,u),p=l.useRef(0),h=p.current,x=l.useRef(0),b=x.current,y=i.open||c,A=l.useRef(y),v=l.useRef(void 0);return l.useEffect(()=>{const g=requestAnimationFrame(()=>A.current=!1);return()=>cancelAnimationFrame(g)},[]),me(()=>{const g=u.current;if(g){v.current=v.current||{transitionDuration:g.style.transitionDuration,animationName:g.style.animationName},g.style.transitionDuration="0s",g.style.animationName="none";const T=g.getBoundingClientRect();p.current=T.height,x.current=T.width,A.current||(g.style.transitionDuration=v.current.transitionDuration,g.style.animationName=v.current.animationName),d(o)}},[i.open,o]),e.jsx(_.div,{"data-state":oe(i.open),"data-disabled":i.disabled?"":void 0,id:i.contentId,hidden:!y,...a,ref:m,style:{"--radix-collapsible-content-height":h?`${h}px`:void 0,"--radix-collapsible-content-width":b?`${b}px`:void 0,...t.style},children:y&&s})});function oe(t){return t?"open":"closed"}var Qe=be;function et(t,n){return l.useReducer((r,o)=>n[r][o]??r,t)}var se="ScrollArea",[we]=he(se),[tt,S]=we(se),Ne=l.forwardRef((t,n)=>{const{__scopeScrollArea:r,type:o="hover",dir:s,scrollHideDelay:a=600,...i}=t,[c,d]=l.useState(null),[u,m]=l.useState(null),[p,h]=l.useState(null),[x,b]=l.useState(null),[y,A]=l.useState(null),[v,g]=l.useState(0),[T,I]=l.useState(0),[M,O]=l.useState(!1),[H,B]=l.useState(!1),f=P(n,k=>d(k)),j=Ve(s);return e.jsx(tt,{scope:r,type:o,dir:j,scrollHideDelay:a,scrollArea:c,viewport:u,onViewportChange:m,content:p,onContentChange:h,scrollbarX:x,onScrollbarXChange:b,scrollbarXEnabled:M,onScrollbarXEnabledChange:O,scrollbarY:y,onScrollbarYChange:A,scrollbarYEnabled:H,onScrollbarYEnabledChange:B,onCornerWidthChange:g,onCornerHeightChange:I,children:e.jsx(_.div,{dir:j,...i,ref:f,style:{position:"relative","--radix-scroll-area-corner-width":v+"px","--radix-scroll-area-corner-height":T+"px",...t.style}})})});Ne.displayName=se;var ye="ScrollAreaViewport",_e=l.forwardRef((t,n)=>{const{__scopeScrollArea:r,children:o,nonce:s,...a}=t,i=S(ye,r),c=l.useRef(null),d=P(n,c,i.onViewportChange);return e.jsxs(e.Fragment,{children:[e.jsx("style",{dangerouslySetInnerHTML:{__html:"[data-radix-scroll-area-viewport]{scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;}[data-radix-scroll-area-viewport]::-webkit-scrollbar{display:none}"},nonce:s}),e.jsx(_.div,{"data-radix-scroll-area-viewport":"",...a,ref:d,style:{overflowX:i.scrollbarXEnabled?"scroll":"hidden",overflowY:i.scrollbarYEnabled?"scroll":"hidden",...t.style},children:e.jsx("div",{ref:i.onContentChange,style:{minWidth:"100%",display:"table"},children:o})})]})});_e.displayName=ye;var N="ScrollAreaScrollbar",Ce=l.forwardRef((t,n)=>{const{forceMount:r,...o}=t,s=S(N,t.__scopeScrollArea),{onScrollbarXEnabledChange:a,onScrollbarYEnabledChange:i}=s,c=t.orientation==="horizontal";return l.useEffect(()=>(c?a(!0):i(!0),()=>{c?a(!1):i(!1)}),[c,a,i]),s.type==="hover"?e.jsx(nt,{...o,ref:n,forceMount:r}):s.type==="scroll"?e.jsx(rt,{...o,ref:n,forceMount:r}):s.type==="auto"?e.jsx(Re,{...o,ref:n,forceMount:r}):s.type==="always"?e.jsx(le,{...o,ref:n}):null});Ce.displayName=N;var nt=l.forwardRef((t,n)=>{const{forceMount:r,...o}=t,s=S(N,t.__scopeScrollArea),[a,i]=l.useState(!1);return l.useEffect(()=>{const c=s.scrollArea;let d=0;if(c){const u=()=>{window.clearTimeout(d),i(!0)},m=()=>{d=window.setTimeout(()=>i(!1),s.scrollHideDelay)};return c.addEventListener("pointerenter",u),c.addEventListener("pointerleave",m),()=>{window.clearTimeout(d),c.removeEventListener("pointerenter",u),c.removeEventListener("pointerleave",m)}}},[s.scrollArea,s.scrollHideDelay]),e.jsx(D,{present:r||a,children:e.jsx(Re,{"data-state":a?"visible":"hidden",...o,ref:n})})}),rt=l.forwardRef((t,n)=>{const{forceMount:r,...o}=t,s=S(N,t.__scopeScrollArea),a=t.orientation==="horizontal",i=J(()=>d("SCROLL_END"),100),[c,d]=et("hidden",{hidden:{SCROLL:"scrolling"},scrolling:{SCROLL_END:"idle",POINTER_ENTER:"interacting"},interacting:{SCROLL:"interacting",POINTER_LEAVE:"idle"},idle:{HIDE:"hidden",SCROLL:"scrolling",POINTER_ENTER:"interacting"}});return l.useEffect(()=>{if(c==="idle"){const u=window.setTimeout(()=>d("HIDE"),s.scrollHideDelay);return()=>window.clearTimeout(u)}},[c,s.scrollHideDelay,d]),l.useEffect(()=>{const u=s.viewport,m=a?"scrollLeft":"scrollTop";if(u){let p=u[m];const h=()=>{const x=u[m];p!==x&&(d("SCROLL"),i()),p=x};return u.addEventListener("scroll",h),()=>u.removeEventListener("scroll",h)}},[s.viewport,a,d,i]),e.jsx(D,{present:r||c!=="hidden",children:e.jsx(le,{"data-state":c==="hidden"?"hidden":"visible",...o,ref:n,onPointerEnter:C(t.onPointerEnter,()=>d("POINTER_ENTER")),onPointerLeave:C(t.onPointerLeave,()=>d("POINTER_LEAVE"))})})}),Re=l.forwardRef((t,n)=>{const r=S(N,t.__scopeScrollArea),{forceMount:o,...s}=t,[a,i]=l.useState(!1),c=t.orientation==="horizontal",d=J(()=>{if(r.viewport){const u=r.viewport.offsetWidth<r.viewport.scrollWidth,m=r.viewport.offsetHeight<r.viewport.scrollHeight;i(c?u:m)}},10);return L(r.viewport,d),L(r.content,d),e.jsx(D,{present:o||a,children:e.jsx(le,{"data-state":a?"visible":"hidden",...s,ref:n})})}),le=l.forwardRef((t,n)=>{const{orientation:r="vertical",...o}=t,s=S(N,t.__scopeScrollArea),a=l.useRef(null),i=l.useRef(0),[c,d]=l.useState({content:0,viewport:0,scrollbar:{size:0,paddingStart:0,paddingEnd:0}}),u=ke(c.viewport,c.content),m={...o,sizes:c,onSizesChange:d,hasThumb:u>0&&u<1,onThumbChange:h=>a.current=h,onThumbPointerUp:()=>i.current=0,onThumbPointerDown:h=>i.current=h};function p(h,x){return ct(h,i.current,c,x)}return r==="horizontal"?e.jsx(ot,{...m,ref:n,onThumbPositionChange:()=>{if(s.viewport&&a.current){const h=s.viewport.scrollLeft,x=ce(h,c,s.dir);a.current.style.transform=`translate3d(${x}px, 0, 0)`}},onWheelScroll:h=>{s.viewport&&(s.viewport.scrollLeft=h)},onDragScroll:h=>{s.viewport&&(s.viewport.scrollLeft=p(h,s.dir))}}):r==="vertical"?e.jsx(st,{...m,ref:n,onThumbPositionChange:()=>{if(s.viewport&&a.current){const h=s.viewport.scrollTop,x=ce(h,c);a.current.style.transform=`translate3d(0, ${x}px, 0)`}},onWheelScroll:h=>{s.viewport&&(s.viewport.scrollTop=h)},onDragScroll:h=>{s.viewport&&(s.viewport.scrollTop=p(h))}}):null}),ot=l.forwardRef((t,n)=>{const{sizes:r,onSizesChange:o,...s}=t,a=S(N,t.__scopeScrollArea),[i,c]=l.useState(),d=l.useRef(null),u=P(n,d,a.onScrollbarXChange);return l.useEffect(()=>{d.current&&c(getComputedStyle(d.current))},[d]),e.jsx(Pe,{"data-orientation":"horizontal",...s,ref:u,sizes:r,style:{bottom:0,left:a.dir==="rtl"?"var(--radix-scroll-area-corner-width)":0,right:a.dir==="ltr"?"var(--radix-scroll-area-corner-width)":0,"--radix-scroll-area-thumb-width":q(r)+"px",...t.style},onThumbPointerDown:m=>t.onThumbPointerDown(m.x),onDragScroll:m=>t.onDragScroll(m.x),onWheelScroll:(m,p)=>{if(a.viewport){const h=a.viewport.scrollLeft+m.deltaX;t.onWheelScroll(h),Oe(h,p)&&m.preventDefault()}},onResize:()=>{d.current&&a.viewport&&i&&o({content:a.viewport.scrollWidth,viewport:a.viewport.offsetWidth,scrollbar:{size:d.current.clientWidth,paddingStart:W(i.paddingLeft),paddingEnd:W(i.paddingRight)}})}})}),st=l.forwardRef((t,n)=>{const{sizes:r,onSizesChange:o,...s}=t,a=S(N,t.__scopeScrollArea),[i,c]=l.useState(),d=l.useRef(null),u=P(n,d,a.onScrollbarYChange);return l.useEffect(()=>{d.current&&c(getComputedStyle(d.current))},[d]),e.jsx(Pe,{"data-orientation":"vertical",...s,ref:u,sizes:r,style:{top:0,right:a.dir==="ltr"?0:void 0,left:a.dir==="rtl"?0:void 0,bottom:"var(--radix-scroll-area-corner-height)","--radix-scroll-area-thumb-height":q(r)+"px",...t.style},onThumbPointerDown:m=>t.onThumbPointerDown(m.y),onDragScroll:m=>t.onDragScroll(m.y),onWheelScroll:(m,p)=>{if(a.viewport){const h=a.viewport.scrollTop+m.deltaY;t.onWheelScroll(h),Oe(h,p)&&m.preventDefault()}},onResize:()=>{d.current&&a.viewport&&i&&o({content:a.viewport.scrollHeight,viewport:a.viewport.offsetHeight,scrollbar:{size:d.current.clientHeight,paddingStart:W(i.paddingTop),paddingEnd:W(i.paddingBottom)}})}})}),[lt,Ee]=we(N),Pe=l.forwardRef((t,n)=>{const{__scopeScrollArea:r,sizes:o,hasThumb:s,onThumbChange:a,onThumbPointerUp:i,onThumbPointerDown:c,onThumbPositionChange:d,onDragScroll:u,onWheelScroll:m,onResize:p,...h}=t,x=S(N,r),[b,y]=l.useState(null),A=P(n,f=>y(f)),v=l.useRef(null),g=l.useRef(""),T=x.viewport,I=o.content-o.viewport,M=R(m),O=R(d),H=J(p,10);function B(f){if(v.current){const j=f.clientX-v.current.left,k=f.clientY-v.current.top;u({x:j,y:k})}}return l.useEffect(()=>{const f=j=>{const k=j.target;b?.contains(k)&&M(j,I)};return document.addEventListener("wheel",f,{passive:!1}),()=>document.removeEventListener("wheel",f,{passive:!1})},[T,b,I,M]),l.useEffect(O,[o,O]),L(b,H),L(x.content,H),e.jsx(lt,{scope:r,scrollbar:b,hasThumb:s,onThumbChange:R(a),onThumbPointerUp:R(i),onThumbPositionChange:O,onThumbPointerDown:R(c),children:e.jsx(_.div,{...h,ref:A,style:{position:"absolute",...h.style},onPointerDown:C(t.onPointerDown,f=>{f.button===0&&(f.target.setPointerCapture(f.pointerId),v.current=b.getBoundingClientRect(),g.current=document.body.style.webkitUserSelect,document.body.style.webkitUserSelect="none",x.viewport&&(x.viewport.style.scrollBehavior="auto"),B(f))}),onPointerMove:C(t.onPointerMove,B),onPointerUp:C(t.onPointerUp,f=>{const j=f.target;j.hasPointerCapture(f.pointerId)&&j.releasePointerCapture(f.pointerId),document.body.style.webkitUserSelect=g.current,x.viewport&&(x.viewport.style.scrollBehavior=""),v.current=null})})})}),V="ScrollAreaThumb",Ae=l.forwardRef((t,n)=>{const{forceMount:r,...o}=t,s=Ee(V,t.__scopeScrollArea);return e.jsx(D,{present:r||s.hasThumb,children:e.jsx(at,{ref:n,...o})})}),at=l.forwardRef((t,n)=>{const{__scopeScrollArea:r,style:o,...s}=t,a=S(V,r),i=Ee(V,r),{onThumbPositionChange:c}=i,d=P(n,p=>i.onThumbChange(p)),u=l.useRef(void 0),m=J(()=>{u.current&&(u.current(),u.current=void 0)},100);return l.useEffect(()=>{const p=a.viewport;if(p){const h=()=>{if(m(),!u.current){const x=dt(p,c);u.current=x,c()}};return c(),p.addEventListener("scroll",h),()=>p.removeEventListener("scroll",h)}},[a.viewport,m,c]),e.jsx(_.div,{"data-state":i.hasThumb?"visible":"hidden",...s,ref:d,style:{width:"var(--radix-scroll-area-thumb-width)",height:"var(--radix-scroll-area-thumb-height)",...o},onPointerDownCapture:C(t.onPointerDownCapture,p=>{const x=p.target.getBoundingClientRect(),b=p.clientX-x.left,y=p.clientY-x.top;i.onThumbPointerDown({x:b,y})}),onPointerUp:C(t.onPointerUp,i.onThumbPointerUp)})});Ae.displayName=V;var ae="ScrollAreaCorner",Te=l.forwardRef((t,n)=>{const r=S(ae,t.__scopeScrollArea),o=!!(r.scrollbarX&&r.scrollbarY);return r.type!=="scroll"&&o?e.jsx(it,{...t,ref:n}):null});Te.displayName=ae;var it=l.forwardRef((t,n)=>{const{__scopeScrollArea:r,...o}=t,s=S(ae,r),[a,i]=l.useState(0),[c,d]=l.useState(0),u=!!(a&&c);return L(s.scrollbarX,()=>{const m=s.scrollbarX?.offsetHeight||0;s.onCornerHeightChange(m),d(m)}),L(s.scrollbarY,()=>{const m=s.scrollbarY?.offsetWidth||0;s.onCornerWidthChange(m),i(m)}),u?e.jsx(_.div,{...o,ref:n,style:{width:a,height:c,position:"absolute",right:s.dir==="ltr"?0:void 0,left:s.dir==="rtl"?0:void 0,bottom:0,...t.style}}):null});function W(t){return t?parseInt(t,10):0}function ke(t,n){const r=t/n;return isNaN(r)?0:r}function q(t){const n=ke(t.viewport,t.content),r=t.scrollbar.paddingStart+t.scrollbar.paddingEnd,o=(t.scrollbar.size-r)*n;return Math.max(o,18)}function ct(t,n,r,o="ltr"){const s=q(r),a=s/2,i=n||a,c=s-i,d=r.scrollbar.paddingStart+i,u=r.scrollbar.size-r.scrollbar.paddingEnd-c,m=r.content-r.viewport,p=o==="ltr"?[0,m]:[m*-1,0];return Le([d,u],p)(t)}function ce(t,n,r="ltr"){const o=q(n),s=n.scrollbar.paddingStart+n.scrollbar.paddingEnd,a=n.scrollbar.size-s,i=n.content-n.viewport,c=a-o,d=r==="ltr"?[0,i]:[i*-1,0],u=We(t,d);return Le([0,i],[0,c])(u)}function Le(t,n){return r=>{if(t[0]===t[1]||n[0]===n[1])return n[0];const o=(n[1]-n[0])/(t[1]-t[0]);return n[0]+o*(r-t[0])}}function Oe(t,n){return t>0&&t<n}var dt=(t,n=()=>{})=>{let r={left:t.scrollLeft,top:t.scrollTop},o=0;return(function s(){const a={left:t.scrollLeft,top:t.scrollTop},i=r.left!==a.left,c=r.top!==a.top;(i||c)&&n(),r=a,o=window.requestAnimationFrame(s)})(),()=>window.cancelAnimationFrame(o)};function J(t,n){const r=R(t),o=l.useRef(0);return l.useEffect(()=>()=>window.clearTimeout(o.current),[]),l.useCallback(()=>{window.clearTimeout(o.current),o.current=window.setTimeout(r,n)},[r,n])}function L(t,n){const r=R(n);me(()=>{let o=0;if(t){const s=new ResizeObserver(()=>{cancelAnimationFrame(o),o=window.requestAnimationFrame(r)});return s.observe(t),()=>{window.cancelAnimationFrame(o),s.unobserve(t)}}},[t,r])}var ut=Ne,mt=_e,ht=Te,pt="Separator",de="horizontal",xt=["horizontal","vertical"],ze=l.forwardRef((t,n)=>{const{decorative:r,orientation:o=de,...s}=t,a=ft(o)?o:de,c=r?{role:"none"}:{"aria-orientation":a==="vertical"?a:void 0,role:"separator"};return e.jsx(_.div,{"data-orientation":a,...c,...s,ref:n})});ze.displayName=pt;function ft(t){return xt.includes(t)}var gt=ze;function De({className:t,orientation:n="horizontal",decorative:r=!0,...o}){return e.jsx(gt,{"data-slot":"separator",decorative:r,orientation:n,className:X("bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",t),...o})}function K({...t}){return e.jsx(Qe,{"data-slot":"collapsible",...t})}function Z({...t}){return e.jsx(Se,{"data-slot":"collapsible-trigger",...t})}function Q({...t}){return e.jsx(je,{"data-slot":"collapsible-content",...t})}function ie({className:t,children:n,...r}){return e.jsxs(ut,{"data-slot":"scroll-area",className:X("relative",t),...r,children:[e.jsx(mt,{"data-slot":"scroll-area-viewport",className:"focus-visible:ring-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:outline-1",children:n}),e.jsx(bt,{}),e.jsx(ht,{})]})}function bt({className:t,orientation:n="vertical",...r}){return e.jsx(Ce,{"data-slot":"scroll-area-scrollbar",orientation:n,className:X("flex touch-none p-px transition-colors select-none",n==="vertical"&&"h-full w-2.5 border-l border-l-transparent",n==="horizontal"&&"h-2.5 flex-col border-t border-t-transparent",t),...r,children:e.jsx(Ae,{"data-slot":"scroll-area-thumb",className:"bg-border relative flex-1 rounded-full"})})}const vt=/<think>([\s\S]*?)<\/think>/gi,St=/<think>([\s\S]*?)<\/think>/i;function Ie(t){const n=St.exec(t);if(!n||n[1]===void 0)return{thinking:null,remainingText:t};const r=n[1].trim(),o=t.replace(vt,"").trim();return{thinking:r,remainingText:o}}function jt(t){return e.jsx(e.Fragment,{})}function wt({text:t}){const[n,r]=l.useState(!1);return e.jsxs(K,{open:n,onOpenChange:r,children:[e.jsxs(Z,{className:"flex items-center gap-1.5 py-0.5 cursor-pointer hover:opacity-80 transition-opacity group",children:[n?e.jsx(U,{className:"size-3 text-muted-foreground"}):e.jsx(Y,{className:"size-3 text-muted-foreground"}),e.jsx("span",{className:"text-muted-foreground text-xs italic select-none opacity-60",children:"[system-reminder]"})]}),e.jsx(Q,{children:e.jsx("div",{className:"pl-4 pt-1",children:e.jsx("div",{className:"prose prose-sm dark:prose-invert max-w-none [&_pre]:bg-muted [&_pre]:text-foreground [&_code]:text-[0.8em] [&_p]:my-1 [&_ul]:my-1 [&_ol]:my-1",children:e.jsx($,{children:t})})})})]})}const Nt=l.memo(function({text:n}){if(n.includes("<system-reminder>"))return e.jsx(wt,{text:n});const{thinking:r,remainingText:o}=Ie(n);return e.jsxs("div",{className:"space-y-2",children:[r!==null&&e.jsx(F,{thinking:r}),o.length>0&&e.jsx("div",{className:"prose prose-sm dark:prose-invert max-w-none [&_pre]:bg-muted [&_pre]:text-foreground [&_code]:text-[0.8em] [&_p]:my-1 [&_ul]:my-1 [&_ol]:my-1",children:e.jsx($,{children:o})}),r===null&&o.length===0&&e.jsx("p",{className:"text-xs text-muted-foreground italic",children:"Empty text block"})]})}),F=l.memo(function({thinking:n}){const[r,o]=l.useState(!1);return e.jsx(K,{open:r,onOpenChange:o,children:e.jsxs("div",{className:"border-l-2 border-purple-500/40 my-1",children:[e.jsxs(Z,{className:"flex items-center gap-1.5 px-3 py-1 w-full text-left cursor-pointer hover:bg-purple-500/5 transition-colors rounded-r-sm group",children:[e.jsx($e,{className:"size-3.5 text-purple-400 shrink-0"}),e.jsx("span",{className:"text-xs font-medium text-purple-400",children:"Thinking"}),e.jsxs(E,{variant:"ghost",className:"text-[10px] text-muted-foreground px-1.5 py-0 h-4 font-mono",children:[n.length.toLocaleString()," chars"]}),e.jsx("span",{className:"flex-1"}),r?e.jsx(U,{className:"size-3 text-muted-foreground"}):e.jsx(Y,{className:"size-3 text-muted-foreground"})]}),e.jsx(Q,{children:e.jsx("div",{className:"px-3 pb-2",children:e.jsx(ie,{className:"max-h-[60vh]",children:e.jsx("pre",{className:"text-xs text-muted-foreground whitespace-pre-wrap font-mono leading-relaxed",children:n})})})})]})})}),yt=l.memo(function({name:n,input:r}){const[o,s]=l.useState(!1);return e.jsx(K,{open:o,onOpenChange:s,children:e.jsxs("div",{className:"border-l-2 border-blue-500/40 my-1",children:[e.jsxs(Z,{className:"flex items-center gap-1.5 px-3 py-1 w-full text-left cursor-pointer hover:bg-blue-500/5 transition-colors rounded-r-sm group",children:[e.jsx(ge,{className:"size-3.5 text-blue-400 shrink-0"}),e.jsx(E,{variant:"outline",className:"text-[10px] font-mono px-1.5 py-0 h-4",children:n}),e.jsx("span",{className:"flex-1"}),o?e.jsx(U,{className:"size-3 text-muted-foreground"}):e.jsx(Y,{className:"size-3 text-muted-foreground"})]}),e.jsx(Q,{children:e.jsx("div",{className:"px-3 pb-2",children:e.jsx(ie,{className:"max-h-[60vh]",children:e.jsx(xe,{data:pe(r),defaultExpandDepth:0})})})})]})})}),_t=l.memo(function({block:n}){switch(n.type){case"text":return e.jsx(Nt,{text:n.text});case"thinking":case"think":return e.jsx(F,{thinking:n.thinking});case"tool_use":return e.jsx(yt,{name:n.name,input:n.input});default:return jt()}}),Ct=l.memo(function({response:n}){return e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx(E,{variant:"secondary",className:"text-[10px] px-1.5 py-0 h-5 font-mono",children:n.model}),n.stop_reason!==null&&e.jsxs(E,{variant:"outline",className:"text-[10px] px-1.5 py-0 h-5 font-mono flex items-center gap-1",children:[e.jsx(fe,{className:"size-2.5"}),n.stop_reason]}),e.jsxs("span",{className:"flex items-center gap-1 text-muted-foreground text-xs",children:[e.jsx(te,{className:"size-3"}),e.jsxs("span",{className:"font-mono tabular-nums",children:[w(n.usage.input_tokens??0)," in /"," ",w(n.usage.output_tokens??0)," out"]}),n.usage.cache_creation_input_tokens!==void 0&&n.usage.cache_creation_input_tokens!==null&&n.usage.cache_creation_input_tokens>0&&e.jsxs("span",{className:"font-mono tabular-nums text-emerald-400",children:["Cache +",w(n.usage.cache_creation_input_tokens)]}),n.usage.cache_read_input_tokens!==void 0&&n.usage.cache_read_input_tokens!==null&&n.usage.cache_read_input_tokens>0&&e.jsxs("span",{className:"font-mono tabular-nums text-purple-400",children:["Cache ~",w(n.usage.cache_read_input_tokens)]})]})]}),e.jsx(De,{className:"opacity-50"}),e.jsxs("div",{className:"space-y-2",children:[n.content.map((r,o)=>e.jsx(_t,{block:r},o)),n.content.length===0&&e.jsx("p",{className:"text-xs text-muted-foreground italic",children:"Empty response content"})]})]})});function Rt(t){if(t===void 0||t==="")return{};try{return JSON.parse(t)}catch{return null}}function Et({call:t}){const[n,r]=l.useState(!1),o=t.function.name??"(unnamed tool)",s=Rt(t.function.arguments);return e.jsx(K,{open:n,onOpenChange:r,children:e.jsxs("div",{className:"border-l-2 border-blue-500/40 my-1",children:[e.jsxs(Z,{className:"flex items-center gap-1.5 px-3 py-1 w-full text-left cursor-pointer hover:bg-blue-500/5 transition-colors rounded-r-sm group",children:[e.jsx(ge,{className:"size-3.5 text-blue-400 shrink-0"}),e.jsx(E,{variant:"outline",className:"text-[10px] font-mono px-1.5 py-0 h-4",children:o}),t.id!==void 0&&t.id!==""&&e.jsx("span",{className:"text-[10px] font-mono text-muted-foreground/60 truncate",children:t.id}),e.jsx("span",{className:"flex-1"}),n?e.jsx(U,{className:"size-3 text-muted-foreground"}):e.jsx(Y,{className:"size-3 text-muted-foreground"})]}),e.jsx(Q,{children:e.jsx("div",{className:"px-3 pb-2",children:e.jsx(ie,{className:"max-h-[60vh]",children:s===null?e.jsx("pre",{className:"font-mono text-xs whitespace-pre-wrap break-words text-rose-300/90",children:t.function.arguments}):e.jsx(xe,{data:pe(s),defaultExpandDepth:0})})})})]})})}const Pt=l.memo(function({response:n}){const r=n.choices[0],o=r?.message,s=o?.tool_calls??[];return e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx(E,{variant:"secondary",className:"text-[10px] px-1.5 py-0 h-5 font-mono",children:n.model}),r?.finish_reason!==null&&r?.finish_reason!==void 0&&e.jsxs(E,{variant:"outline",className:"text-[10px] px-1.5 py-0 h-5 font-mono flex items-center gap-1",children:[e.jsx(fe,{className:"size-2.5"}),r.finish_reason]}),e.jsxs("span",{className:"flex items-center gap-1 text-muted-foreground text-xs",children:[e.jsx(te,{className:"size-3"}),e.jsxs("span",{className:"font-mono tabular-nums",children:[w(n.usage.prompt_tokens??0)," in /"," ",w(n.usage.completion_tokens??0)," out"]})]})]}),e.jsx(De,{className:"opacity-50"}),e.jsxs("div",{className:"space-y-2",children:[o?.reasoning_content!==null&&o?.reasoning_content!==void 0&&o.reasoning_content.length>0&&e.jsx(F,{thinking:o.reasoning_content}),o?.content!==null&&o?.content!==void 0&&o.content.length>0&&(()=>{const a=o.reasoning_content!==null&&o.reasoning_content!==void 0&&o.reasoning_content.length>0,{thinking:i,remainingText:c}=Ie(o.content);return e.jsxs("div",{className:"space-y-2",children:[i!==null&&!a&&e.jsx(F,{thinking:i}),c.length>0&&e.jsx("div",{className:"prose prose-sm dark:prose-invert max-w-none [&_pre]:bg-muted [&_pre]:text-foreground [&_code]:text-[0.8em] [&_p]:my-1 [&_ul]:my-1 [&_ol]:my-1",children:e.jsx($,{children:c})})]})})(),s.map((a,i)=>e.jsx(Et,{call:a},a.id??`tc-${i}`)),o?.function_call!==null&&o?.function_call!==void 0&&e.jsxs("div",{className:"border border-blue-500/30 rounded-md p-3 bg-blue-500/5",children:[e.jsx("div",{className:"text-xs text-blue-400 font-mono mb-1",children:"function_call"}),e.jsxs("div",{className:"font-mono text-xs",children:[e.jsx("span",{className:"text-blue-300",children:o.function_call.name}),e.jsxs("span",{className:"text-muted-foreground",children:["(",o.function_call.arguments,")"]})]})]}),(o?.content===null||o?.content===void 0||o.content.length===0)&&(o?.reasoning_content===null||o?.reasoning_content===void 0||o.reasoning_content.length===0)&&(o?.function_call===null||o?.function_call===void 0)&&s.length===0&&e.jsx("p",{className:"text-xs text-muted-foreground italic",children:"Empty response content"})]})]})});function Me(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function At(t){return Me(t)&&t.object==="chat.completion"}function Tt(t){return Me(t)&&t.type==="message"&&Array.isArray(t.content)}function kt(t,n){return t==="openai"&&At(n)?e.jsx(Pt,{response:n}):t==="anthropic"&&Tt(n)?e.jsx(Ct,{response:n}):null}function Lt(t){switch(t){case"success":return"text-emerald-400";case"client_error":return"text-amber-400";case"server_error":return"text-red-400";case"pending":return"text-muted-foreground"}}function z({status:t}){const n=Ue(t),r=Lt(n);return t===null?e.jsx("span",{className:"text-xs text-muted-foreground italic",children:"pending"}):e.jsxs("span",{className:X("flex items-center gap-1 text-xs font-mono font-semibold",r),children:[n==="server_error"&&e.jsx(Xe,{className:"size-3"}),t]})}function ue({text:t}){return e.jsx("div",{className:"rounded-md border border-red-500/30 bg-red-500/5 p-3",children:e.jsx("pre",{className:"text-xs text-red-300 whitespace-pre-wrap font-mono leading-relaxed overflow-auto max-h-[60vh]",children:t})})}function Ot({text:t}){return e.jsx("div",{className:"prose prose-sm dark:prose-invert max-w-none [&_pre]:bg-muted [&_pre]:text-foreground [&_code]:text-[0.8em] [&_p]:my-1 [&_ul]:my-1 [&_ol]:my-1",children:e.jsx($,{children:t})})}const Ht=l.memo(function({responseText:n,responseStatus:r,streaming:o,inputTokens:s,outputTokens:a,cacheCreationInputTokens:i,cacheReadInputTokens:c,apiFormat:d,error:u}){const m=d??"unknown",p=l.useMemo(()=>Fe(m).analyzeResponse(n).parsed,[m,n]);return n===null&&u===void 0?e.jsxs("div",{className:"flex items-center gap-2 py-3",children:[e.jsx(z,{status:r}),e.jsx("span",{className:"text-xs text-muted-foreground italic",children:"No response"})]}):r!==null&&r>=400?e.jsxs("div",{className:"space-y-2",children:[e.jsx(z,{status:r}),e.jsx(ue,{text:n??""}),u!=null&&e.jsxs("div",{className:"rounded border border-destructive/50 bg-destructive/10 p-3 text-xs",children:[e.jsx("div",{className:"font-semibold text-destructive mb-1",children:"SSE Error"}),e.jsx("div",{className:"text-muted-foreground font-mono",children:u})]})]}):u!=null?e.jsxs("div",{className:"space-y-2",children:[e.jsx(z,{status:r}),e.jsxs("div",{className:"rounded border border-destructive/50 bg-destructive/10 p-3 text-xs",children:[e.jsx("div",{className:"font-semibold text-destructive mb-1",children:"SSE Error"}),e.jsx("div",{className:"text-muted-foreground font-mono",children:u})]}),n!==null&&e.jsx("div",{className:"mt-2",children:e.jsx(ue,{text:n})})]}):p!==null?e.jsxs("div",{className:"space-y-2",children:[e.jsx(z,{status:r}),kt(m,p)]}):e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(z,{status:r}),o&&(s!==null||a!==null)&&e.jsxs("span",{className:"flex items-center gap-1 text-muted-foreground text-xs",children:[e.jsx(te,{className:"size-3"}),e.jsxs("span",{className:"font-mono tabular-nums",children:[s!==null?w(s):"—"," in /"," ",a!==null?w(a):"—"," out"]}),i!=null&&i>0&&e.jsxs("span",{className:"font-mono tabular-nums text-emerald-400",children:["Cache +",w(i)]}),c!=null&&c>0&&e.jsxs("span",{className:"font-mono tabular-nums text-purple-400",children:["Cache ~",w(c)]})]})]}),e.jsx(Ot,{text:n??""})]})});export{Ht as ResponseView};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as a,j as e}from"./main-CZJ63sQh.js";import{q as j,s as b,t as v,Q as u,e as l,B as N,u as k,W as S}from"./index-B-0F9n1w.js";import{a as y}from"./json-viewer-D-z1r1Pp.js";const T=a.memo(function({logId:d,truncated:x}){const[o,m]=a.useState(!1),[r,i]=a.useState({status:"idle"}),[h,p]=a.useState(new Set);a.useEffect(()=>{if(!o||r.status!=="idle")return;let s=!1;return i({status:"loading"}),fetch(`/api/logs/${d}/chunks`).then(t=>t.ok?t.json():Promise.reject(new Error("Chunks not found"))).then(t=>{s||i({status:"success",chunks:t.chunks})}).catch(()=>{s||i({status:"error",message:"Chunk data unavailable"})}),()=>{s=!0}},[o,d]);const c=a.useMemo(()=>{if(r.status!=="success")return[];const s=new Map;for(const t of r.chunks){const n=s.get(t.index);n?n.push(t):s.set(t.index,[t])}return Array.from(s.entries()).map(([t,n])=>({index:t,chunks:n})).sort((t,n)=>t.index-n.index)},[r]),f=s=>{p(t=>{const n=new Set(t);return n.has(s)?n.delete(s):n.add(s),n})};function g(){return r.status==="idle"||r.status==="loading"?e.jsxs("div",{className:"flex items-center gap-2 py-2 text-xs text-muted-foreground",children:[e.jsx(S,{className:"size-3 animate-spin"}),e.jsx("span",{children:"Loading chunks..."})]}):r.status==="error"?e.jsx("div",{className:"py-2 text-xs text-muted-foreground italic",children:r.message}):e.jsxs("div",{className:"p-2 space-y-1",children:[e.jsxs("div",{className:"text-[10px] text-muted-foreground font-mono mb-2",children:[c.length," index group",c.length!==1?"s":""," available"]}),c.map(s=>{const t=h.has(s.index);return e.jsxs("div",{className:"rounded border border-border bg-background",children:[e.jsxs("button",{type:"button",className:"flex items-center gap-2 w-full px-2 py-1.5 text-left hover:bg-muted/50 transition-colors cursor-pointer",onClick:()=>f(s.index),children:[t?e.jsx(u,{className:"size-3 text-muted-foreground"}):e.jsx(l,{className:"size-3 text-muted-foreground"}),e.jsxs("span",{className:"text-[10px] text-muted-foreground font-mono",children:["[",s.index,"] ",s.chunks[0]?.type??""]}),e.jsxs("span",{className:"text-[10px] text-muted-foreground font-mono",children:[s.chunks.length," chunk",s.chunks.length!==1?"s":""]})]}),t&&e.jsx("div",{className:"px-2 pb-2 space-y-1",children:s.chunks.map(n=>e.jsxs("div",{className:"rounded border border-border bg-muted/20 p-2",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[e.jsxs("span",{className:"text-[10px] text-muted-foreground font-mono",children:["+",n.timestamp,"ms"]}),e.jsx("span",{className:"text-[10px] text-muted-foreground font-mono",children:n.type})]}),e.jsx(y,{data:n,defaultExpandDepth:0,showCopy:!0})]},n.index))})]},s.index)})]})}return e.jsxs("div",{className:"space-y-1",children:[e.jsx(j,{children:e.jsxs(b,{children:[e.jsx(v,{asChild:!0,children:e.jsxs("button",{type:"button",className:"flex items-center gap-1.5 text-xs text-muted-foreground hover:text-foreground transition-colors cursor-pointer",onClick:()=>m(s=>!s),children:[o?e.jsx(u,{className:"size-3"}):e.jsx(l,{className:"size-3"}),e.jsx("span",{children:"Raw SSE Events"}),e.jsxs(N,{variant:"outline",className:"text-[9px] px-1 py-0 h-4 font-mono ml-1",children:[d,x===!0?"+":""]})]})}),e.jsx(k,{children:"Server-Sent Events streaming chunks from the provider"})]})}),o===!0?e.jsx("div",{className:"rounded-md border border-border bg-muted/20 overflow-auto max-h-64",children:g()}):null]})});export{T as StreamingChunkSequence};
|