@tonyclaw/agent-inspector 2.0.42 → 2.0.43

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.
Files changed (32) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/{CompareDrawer-Cfqxlo-U.js → CompareDrawer-CxM1gCfL.js} +1 -1
  3. package/.output/public/assets/{ProxyViewerContainer-CE9pAX4c.js → ProxyViewerContainer-TtRG-0E7.js} +37 -37
  4. package/.output/public/assets/{ReplayDialog-daRidZo_.js → ReplayDialog-UseUkucS.js} +1 -1
  5. package/.output/public/assets/{RequestAnatomy-CJ7EPQGQ.js → RequestAnatomy-aPxgEJ2L.js} +1 -1
  6. package/.output/public/assets/{ResponseView-xBmr54hB.js → ResponseView-DA-F4F97.js} +1 -1
  7. package/.output/public/assets/{StreamingChunkSequence-nK-0LpbM.js → StreamingChunkSequence-JSQEPeNS.js} +1 -1
  8. package/.output/public/assets/_sessionId-BEXuCWq5.js +1 -0
  9. package/.output/public/assets/index-Bhsa_2xX.js +1 -0
  10. package/.output/public/assets/index-DOWlRJ0W.css +1 -0
  11. package/.output/public/assets/{main-DOy_Q96H.js → main-BpGVJcpB.js} +2 -2
  12. package/.output/server/{_sessionId-DtYRZHlM.mjs → _sessionId-DGn-TENM.mjs} +2 -2
  13. package/.output/server/_ssr/{CompareDrawer-fy1ARwtx.mjs → CompareDrawer-CFElCSYY.mjs} +2 -2
  14. package/.output/server/_ssr/{ProxyViewerContainer-9GJtCWCq.mjs → ProxyViewerContainer-B7SR9mrD.mjs} +258 -76
  15. package/.output/server/_ssr/{ReplayDialog-BrS7syOE.mjs → ReplayDialog-DfKapj0k.mjs} +3 -3
  16. package/.output/server/_ssr/{RequestAnatomy-BtWt1cWY.mjs → RequestAnatomy-CUxTCg31.mjs} +2 -2
  17. package/.output/server/_ssr/{ResponseView-CkKGYE6m.mjs → ResponseView-BXY0w197.mjs} +2 -2
  18. package/.output/server/_ssr/{StreamingChunkSequence-C7rB3osr.mjs → StreamingChunkSequence-CzMnES9H.mjs} +2 -2
  19. package/.output/server/_ssr/{index-D24WforP.mjs → index-CVlT-REW.mjs} +2 -2
  20. package/.output/server/_ssr/index.mjs +2 -2
  21. package/.output/server/_ssr/{router-CVqVjBzJ.mjs → router-B2d1LUx6.mjs} +4 -4
  22. package/.output/server/{_tanstack-start-manifest_v-DSikvwru.mjs → _tanstack-start-manifest_v-Drpi28BM.mjs} +1 -1
  23. package/.output/server/index.mjs +61 -61
  24. package/package.json +1 -1
  25. package/src/components/ProxyViewer.tsx +156 -17
  26. package/src/components/ProxyViewerContainer.tsx +66 -4
  27. package/src/components/groups/GroupsDialog.tsx +11 -10
  28. package/src/components/proxy-viewer/LogEntry.tsx +107 -56
  29. package/src/components/ui/dialog.tsx +1 -1
  30. package/.output/public/assets/_sessionId-CbWEG5ej.js +0 -1
  31. package/.output/public/assets/index-BfGJEb-2.css +0 -1
  32. package/.output/public/assets/index-D1MkoT4l.js +0 -1
@@ -1,9 +1,10 @@
1
1
  import { useState, useEffect, useCallback, useRef, useMemo, type JSX } from "react";
2
2
  import { z } from "zod";
3
3
  import { CapturedLogSchema, type CapturedLog } from "../contracts";
4
+ import { InspectorGroupsListResponseSchema, type InspectorGroup } from "../lib/groupContract";
4
5
  import { useStripConfig } from "../lib/useStripConfig";
5
6
  import { OnboardingBanner } from "./OnboardingBanner";
6
- import { ProxyViewer } from "./ProxyViewer";
7
+ import { ProxyViewer, type SessionMembershipEvidence } from "./ProxyViewer";
7
8
  import { dispatchLogFocusRequest } from "./proxy-viewer/logFocus";
8
9
 
9
10
  type SSEUpdate =
@@ -27,6 +28,29 @@ const SSEUpdateSchema = z.union([
27
28
  }),
28
29
  ]);
29
30
 
31
+ function buildSessionMembershipEvidence(
32
+ groups: readonly InspectorGroup[],
33
+ sessionId: string,
34
+ ): SessionMembershipEvidence[] {
35
+ const memberships: SessionMembershipEvidence[] = [];
36
+ for (const group of groups) {
37
+ for (const member of group.members) {
38
+ if (member.sessionId !== sessionId) continue;
39
+ memberships.push({
40
+ groupId: group.id,
41
+ groupTitle: group.title,
42
+ groupKind: group.kind,
43
+ groupStatus: group.status,
44
+ groupTask: group.task,
45
+ groupProject: group.project,
46
+ groupEvidence: group.evidence,
47
+ member,
48
+ });
49
+ }
50
+ }
51
+ return memberships;
52
+ }
53
+
30
54
  function extractSessions(logs: CapturedLog[]): string[] {
31
55
  const set = new Set<string>();
32
56
  for (const l of logs) {
@@ -67,9 +91,13 @@ const HASH_HIGHLIGHT_MS = 1800;
67
91
  const MAX_CLIENT_LOGS = 500;
68
92
 
69
93
  function buildLogsStreamUrl(sessionId: string | undefined): string {
70
- if (sessionId === undefined) return "/api/logs/stream";
71
- const params = new URLSearchParams({ sessionId });
72
- return `/api/logs/stream?${params.toString()}`;
94
+ const params = new URLSearchParams();
95
+ if (sessionId !== undefined) {
96
+ params.set("sessionId", sessionId);
97
+ params.set("compact", "1");
98
+ }
99
+ const query = params.toString();
100
+ return query.length > 0 ? `/api/logs/stream?${query}` : "/api/logs/stream";
73
101
  }
74
102
 
75
103
  function buildLogIndex(logs: readonly CapturedLog[]): Map<number, number> {
@@ -109,6 +137,8 @@ export function ProxyViewerContainer({
109
137
  const [selectedModel, setSelectedModel] = useState("__all__");
110
138
  const [viewMode, setViewMode] = useState<"simple" | "full">("simple");
111
139
  const [error, setError] = useState<string | null>(null);
140
+ const [streamInitialized, setStreamInitialized] = useState(initialSessionId === undefined);
141
+ const [sessionMemberships, setSessionMemberships] = useState<SessionMembershipEvidence[]>([]);
112
142
  const eventSourceRef = useRef<EventSource | null>(null);
113
143
  const reconnectTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
114
144
  const handledHashRef = useRef<string | null>(null);
@@ -169,6 +199,7 @@ export function ProxyViewerContainer({
169
199
  eventSourceRef.current.close();
170
200
  }
171
201
 
202
+ setStreamInitialized(false);
172
203
  const es = new EventSource(buildLogsStreamUrl(initialSessionId));
173
204
  eventSourceRef.current = es;
174
205
 
@@ -193,6 +224,7 @@ export function ProxyViewerContainer({
193
224
  const nextLogs = trimClientLogs(update.logs);
194
225
  logIndexRef.current = buildLogIndex(nextLogs);
195
226
  setAllLogs(nextLogs);
227
+ setStreamInitialized(true);
196
228
  setError(null);
197
229
  } else if (update.type === "update") {
198
230
  scheduleUpdate(update.log);
@@ -204,6 +236,7 @@ export function ProxyViewerContainer({
204
236
 
205
237
  es.onerror = () => {
206
238
  setError("SSE connection lost, reconnecting...");
239
+ setStreamInitialized(true);
207
240
  es.close();
208
241
  if (reconnectTimeoutRef.current !== null) {
209
242
  clearTimeout(reconnectTimeoutRef.current);
@@ -212,6 +245,33 @@ export function ProxyViewerContainer({
212
245
  };
213
246
  }, [initialSessionId, scheduleUpdate]);
214
247
 
248
+ useEffect(() => {
249
+ if (initialSessionId === undefined) {
250
+ setSessionMemberships([]);
251
+ return;
252
+ }
253
+
254
+ let cancelled = false;
255
+ void fetch("/api/groups")
256
+ .then(async (response) => {
257
+ if (!response.ok) return null;
258
+ const raw: unknown = await response.json();
259
+ const parsed = InspectorGroupsListResponseSchema.safeParse(raw);
260
+ return parsed.success ? parsed.data.groups : null;
261
+ })
262
+ .then((groups) => {
263
+ if (cancelled || groups === null) return;
264
+ setSessionMemberships(buildSessionMembershipEvidence(groups, initialSessionId));
265
+ })
266
+ .catch(() => {
267
+ if (!cancelled) setSessionMemberships([]);
268
+ });
269
+
270
+ return () => {
271
+ cancelled = true;
272
+ };
273
+ }, [initialSessionId]);
274
+
215
275
  useEffect(() => {
216
276
  connectSSE();
217
277
  return () => {
@@ -361,6 +421,8 @@ export function ProxyViewerContainer({
361
421
  onModelChange={setSelectedModel}
362
422
  onClearAll={handleClearAll}
363
423
  onClearGroup={handleClearGroup}
424
+ isLoading={initialSessionId !== undefined && !streamInitialized}
425
+ sessionMemberships={sessionMemberships}
364
426
  viewMode={viewMode}
365
427
  onViewModeChange={setViewMode}
366
428
  captureMode={captureMode}
@@ -920,21 +920,22 @@ function MemberRow({ row }: { row: GroupMemberRow }): JSX.Element {
920
920
  const errors = session?.errorCount ?? null;
921
921
  const tokens = session?.tokenUsage.total ?? null;
922
922
  const firstChunkMs = log?.firstChunkMs ?? null;
923
+ const sessionLabel = firstNonEmpty(member.label, member.sessionId);
923
924
 
924
925
  return (
925
926
  <tr className="border-b border-border last:border-0">
926
927
  <td className="max-w-56 px-3 py-2">
927
- <div className="flex min-w-0 items-center gap-2">
928
- <a
929
- href={sessionPath}
930
- target="_blank"
931
- rel="noreferrer"
932
- className="min-w-0 truncate font-mono text-xs text-primary hover:underline"
933
- >
934
- {firstNonEmpty(member.label, member.sessionId)}
935
- </a>
928
+ <a
929
+ href={sessionPath}
930
+ target="_blank"
931
+ rel="noreferrer"
932
+ className="inline-flex max-w-full min-w-0 items-center gap-2 rounded-sm font-mono text-xs text-primary outline-none hover:underline focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
933
+ aria-label={`Open session ${sessionLabel}`}
934
+ title={`Open session ${sessionLabel}`}
935
+ >
936
+ <span className="min-w-0 truncate">{sessionLabel}</span>
936
937
  <ExternalLink className="size-3 shrink-0 text-muted-foreground" />
937
- </div>
938
+ </a>
938
939
  <div className="mt-0.5 truncate text-[11px] text-muted-foreground">
939
940
  {displayText(member.agent)}
940
941
  </div>
@@ -1,7 +1,8 @@
1
1
  import { AlertTriangle, GitCompareArrows } from "lucide-react";
2
2
  import { Suspense, type JSX } from "react";
3
3
  import { useCallback, useEffect, useMemo, useRef, useState, memo } from "react";
4
- import type { CapturedLog } from "../../contracts";
4
+ import { CapturedLogSchema, type CapturedLog } from "../../contracts";
5
+ import { fetchJson } from "../../lib/apiClient";
5
6
  import type { TimeDisplayFormat } from "../../lib/runtimeConfig";
6
7
  import { stripClaudeCodeBillingHeader } from "../../proxy/claudeCodeStrip";
7
8
  import { Button } from "../ui/button";
@@ -50,6 +51,12 @@ function resolveFocusedTab(tab: LogFocusTab, anatomySegments: AnatomySegment[] |
50
51
  }
51
52
  }
52
53
 
54
+ type BodyHydrationState = "idle" | "loading" | "failed";
55
+
56
+ function shouldHydrateLogBody(log: CapturedLog): boolean {
57
+ return log.bodyContentMode === "compact" || log.bodyContentMode === "truncated";
58
+ }
59
+
53
60
  export type LogEntryProps = {
54
61
  log: CapturedLog;
55
62
  viewMode?: "simple" | "full";
@@ -144,53 +151,56 @@ export const LogEntry = memo(function ({
144
151
  const [requestDiff, setRequestDiff] = useState<boolean>(false);
145
152
  const [activeTab, setActiveTab] = useState("request");
146
153
  const [expandToPath, setExpandToPath] = useState<string | null>(null);
154
+ const [hydratedLog, setHydratedLog] = useState<CapturedLog | null>(null);
155
+ const [bodyHydrationState, setBodyHydrationState] = useState<BodyHydrationState>("idle");
147
156
  const requestJsonRef = useRef<HTMLDivElement | null>(null);
148
- const resolvedFormat = resolveLogFormat(log);
157
+ const displayLog = hydratedLog ?? log;
158
+ const resolvedFormat = resolveLogFormat(displayLog);
149
159
  const adapter = getLogFormatAdapter(resolvedFormat);
150
160
  const requestAnalysis = useMemo(
151
- () => adapter.analyzeRequest(log.rawRequestBody),
152
- [adapter, log.rawRequestBody],
161
+ () => adapter.analyzeRequest(displayLog.rawRequestBody),
162
+ [adapter, displayLog.rawRequestBody],
153
163
  );
154
164
  const responseAnalysis = useMemo(
155
- () => adapter.analyzeResponse(log.responseText),
156
- [adapter, log.responseText],
165
+ () => adapter.analyzeResponse(displayLog.responseText),
166
+ [adapter, displayLog.responseText],
157
167
  );
158
168
  const strippedRequestBody = useMemo(() => {
159
- if (!strip || resolvedFormat !== "anthropic" || log.rawRequestBody === null) {
169
+ if (!strip || resolvedFormat !== "anthropic" || displayLog.rawRequestBody === null) {
160
170
  return null;
161
171
  }
162
- return stripClaudeCodeBillingHeader(log.rawRequestBody).body;
163
- }, [log.rawRequestBody, resolvedFormat, strip]);
164
- const displayedRequestBody = strippedRequestBody ?? log.rawRequestBody;
172
+ return stripClaudeCodeBillingHeader(displayLog.rawRequestBody).body;
173
+ }, [displayLog.rawRequestBody, resolvedFormat, strip]);
174
+ const displayedRequestBody = strippedRequestBody ?? displayLog.rawRequestBody;
165
175
  const requestExpansion = useJsonBulkExpansion(displayedRequestBody);
166
- const rawRequestExpansion = useJsonBulkExpansion(log.rawRequestBody);
167
- const responseExpansion = useJsonBulkExpansion(log.responseText);
176
+ const rawRequestExpansion = useJsonBulkExpansion(displayLog.rawRequestBody);
177
+ const responseExpansion = useJsonBulkExpansion(displayLog.responseText);
168
178
 
169
179
  // Headers are rendered as a flat list, so we copy them as pretty-printed JSON.
170
180
  // Only build the string when there's at least one entry — empty headers would
171
181
  // otherwise copy "{}", which is misleading.
172
182
  const headersText = useMemo(
173
183
  () =>
174
- log.headers && Object.keys(log.headers).length > 0
175
- ? JSON.stringify(log.headers, null, 2)
184
+ displayLog.headers && Object.keys(displayLog.headers).length > 0
185
+ ? JSON.stringify(displayLog.headers, null, 2)
176
186
  : null,
177
- [log.headers],
187
+ [displayLog.headers],
178
188
  );
179
189
  const rawHeadersText = useMemo(
180
190
  () =>
181
- log.rawHeaders && Object.keys(log.rawHeaders).length > 0
182
- ? JSON.stringify(log.rawHeaders, null, 2)
191
+ displayLog.rawHeaders && Object.keys(displayLog.rawHeaders).length > 0
192
+ ? JSON.stringify(displayLog.rawHeaders, null, 2)
183
193
  : null,
184
- [log.rawHeaders],
194
+ [displayLog.rawHeaders],
185
195
  );
186
196
 
187
197
  // One copy-feedback hook per JSON-bearing tab, so each tab can surface its
188
198
  // own Copy button in the header with independent "Copied!" feedback.
189
199
  const requestCopy = useCopyFeedback(displayedRequestBody);
190
- const rawRequestCopy = useCopyFeedback(log.rawRequestBody);
200
+ const rawRequestCopy = useCopyFeedback(displayLog.rawRequestBody);
191
201
  const headersCopy = useCopyFeedback(headersText);
192
202
  const rawHeadersCopy = useCopyFeedback(rawHeadersText);
193
- const responseCopy = useCopyFeedback(log.responseText);
203
+ const responseCopy = useCopyFeedback(displayLog.responseText);
194
204
 
195
205
  // Per-tab action bundles consumed by the header. The header renders the
196
206
  // entry whose key matches `activeTab`. Tabs without an entry (Context,
@@ -214,7 +224,7 @@ export const LogEntry = memo(function ({
214
224
  resolvedFormat,
215
225
  viewMode,
216
226
  strip,
217
- log.rawRequestBody !== null,
227
+ displayLog.rawRequestBody !== null,
218
228
  )
219
229
  ? { active: requestDiff, onToggle: () => setRequestDiff(!requestDiff) }
220
230
  : undefined,
@@ -222,12 +232,12 @@ export const LogEntry = memo(function ({
222
232
  onCompareWithPrevious === undefined
223
233
  ? undefined
224
234
  : () => {
225
- onCompareWithPrevious(log);
235
+ onCompareWithPrevious(displayLog);
226
236
  },
227
237
  },
228
238
  "raw-request": {
229
239
  copyLabel: "Copy raw request",
230
- copyText: log.rawRequestBody,
240
+ copyText: displayLog.rawRequestBody,
231
241
  copyCopied: rawRequestCopy.copied,
232
242
  onCopy: rawRequestCopy.copy,
233
243
  expansion: {
@@ -253,7 +263,7 @@ export const LogEntry = memo(function ({
253
263
  },
254
264
  raw: {
255
265
  copyLabel: "Copy response",
256
- copyText: log.responseText,
266
+ copyText: displayLog.responseText,
257
267
  copyCopied: responseCopy.copied,
258
268
  onCopy: responseCopy.copy,
259
269
  expansion: {
@@ -268,14 +278,15 @@ export const LogEntry = memo(function ({
268
278
  requestCopy,
269
279
  requestExpansion,
270
280
  requestDiff,
271
- log.rawRequestBody,
281
+ displayLog,
282
+ displayLog.rawRequestBody,
272
283
  rawRequestCopy,
273
284
  rawRequestExpansion,
274
285
  headersText,
275
286
  headersCopy,
276
287
  rawHeadersText,
277
288
  rawHeadersCopy,
278
- log.responseText,
289
+ displayLog.responseText,
279
290
  responseCopy,
280
291
  responseExpansion,
281
292
  resolvedFormat,
@@ -295,7 +306,7 @@ export const LogEntry = memo(function ({
295
306
  () => parseRequestTools(requestExpansion.parsedData),
296
307
  [requestExpansion.parsedData],
297
308
  );
298
- const warnings = log.warnings ?? [];
309
+ const warnings = displayLog.warnings ?? [];
299
310
  const anatomyPaths = useMemo(() => {
300
311
  if (anatomySegments === null) return undefined;
301
312
  return new Set(anatomySegments.map((s) => s.path));
@@ -316,6 +327,34 @@ export const LogEntry = memo(function ({
316
327
  setExpanded(nextExpanded);
317
328
  }, [anatomySegments, expanded]);
318
329
 
330
+ useEffect(() => {
331
+ setHydratedLog(null);
332
+ setBodyHydrationState("idle");
333
+ }, [log.id]);
334
+
335
+ useEffect(() => {
336
+ if (!expanded) return;
337
+ if (!shouldHydrateLogBody(log)) return;
338
+ if (hydratedLog !== null || bodyHydrationState !== "idle") return;
339
+
340
+ let cancelled = false;
341
+ setBodyHydrationState("loading");
342
+ void fetchJson(`/api/logs/${String(log.id)}`, CapturedLogSchema)
343
+ .then((fullLog) => {
344
+ if (cancelled) return;
345
+ setHydratedLog(fullLog);
346
+ setBodyHydrationState("idle");
347
+ })
348
+ .catch(() => {
349
+ if (cancelled) return;
350
+ setBodyHydrationState("failed");
351
+ });
352
+
353
+ return () => {
354
+ cancelled = true;
355
+ };
356
+ }, [bodyHydrationState, expanded, hydratedLog, log.bodyContentMode, log.id]);
357
+
319
358
  useEffect(() => {
320
359
  const handleLogFocusRequest = (event: Event): void => {
321
360
  const request = readLogFocusRequest(event);
@@ -335,7 +374,7 @@ export const LogEntry = memo(function ({
335
374
  <TooltipProvider>
336
375
  <div className="border border-border rounded-lg mb-1 overflow-hidden">
337
376
  <LogEntryHeader
338
- log={log}
377
+ log={displayLog}
339
378
  messageCount={requestAnalysis.messageCount}
340
379
  toolCount={requestAnalysis.toolCount}
341
380
  expanded={expanded}
@@ -373,7 +412,7 @@ export const LogEntry = memo(function ({
373
412
  <TabsContent value="raw-request">
374
413
  {activeTab === "raw-request" && (
375
414
  <div className="px-4 pt-1 pb-3">
376
- {log.rawRequestBody === null ? (
415
+ {displayLog.rawRequestBody === null ? (
377
416
  <p className="text-xs text-muted-foreground italic">No request body</p>
378
417
  ) : rawRequestExpansion.parsedData !== null ? (
379
418
  <Suspense fallback={<TabFallback />}>
@@ -385,7 +424,7 @@ export const LogEntry = memo(function ({
385
424
  </Suspense>
386
425
  ) : (
387
426
  <pre className="font-mono text-xs whitespace-pre-wrap break-words">
388
- {log.rawRequestBody}
427
+ {displayLog.rawRequestBody}
389
428
  </pre>
390
429
  )}
391
430
  </div>
@@ -396,6 +435,17 @@ export const LogEntry = memo(function ({
396
435
  <TabsContent value="request">
397
436
  {activeTab === "request" && (
398
437
  <div className="px-4 pt-1 pb-3">
438
+ {bodyHydrationState === "loading" && (
439
+ <div className="mb-3 rounded border border-border bg-muted/30 p-3 text-xs text-muted-foreground">
440
+ Loading full request and response bodies...
441
+ </div>
442
+ )}
443
+ {bodyHydrationState === "failed" && (
444
+ <div className="mb-3 rounded border border-amber-500/30 bg-amber-500/10 p-3 text-xs text-amber-200">
445
+ Full request and response bodies could not be loaded. Compact metadata is
446
+ still available.
447
+ </div>
448
+ )}
399
449
  {warnings.length > 0 && (
400
450
  <div className="mb-3 rounded border border-amber-500/30 bg-amber-500/10 p-3 text-xs">
401
451
  <div className="flex items-center gap-2 font-semibold text-amber-300">
@@ -418,7 +468,7 @@ export const LogEntry = memo(function ({
418
468
  the diff or JSON view, depending on toggle state. */}
419
469
  {requestDiff ? (
420
470
  <RequestDiffContent
421
- rawBody={log.rawRequestBody}
471
+ rawBody={displayLog.rawRequestBody}
422
472
  displayedBody={displayedRequestBody}
423
473
  emptyLabel="No transformation applied; raw and sent request bodies are identical."
424
474
  />
@@ -453,8 +503,8 @@ export const LogEntry = memo(function ({
453
503
  <Suspense fallback={<TabFallback />}>
454
504
  <LazyRequestAnatomy
455
505
  parsed={requestExpansion.parsedData}
456
- inputTokens={log.inputTokens ?? null}
457
- model={log.model}
506
+ inputTokens={displayLog.inputTokens ?? null}
507
+ model={displayLog.model}
458
508
  segments={anatomySegments}
459
509
  onSegmentActivate={jumpToAnatomySegment}
460
510
  />
@@ -471,7 +521,8 @@ export const LogEntry = memo(function ({
471
521
  <div className="flex justify-end gap-2 mb-2">
472
522
  {shouldShowHeadersDiffButton(
473
523
  viewMode,
474
- log.rawHeaders !== undefined && Object.keys(log.rawHeaders).length > 0,
524
+ displayLog.rawHeaders !== undefined &&
525
+ Object.keys(displayLog.rawHeaders).length > 0,
475
526
  ) && (
476
527
  <DiffToggleButton
477
528
  active={headersDiff}
@@ -484,13 +535,13 @@ export const LogEntry = memo(function ({
484
535
  </div>
485
536
  {headersDiff ? (
486
537
  <HeadersDiffContent
487
- rawHeaders={log.rawHeaders}
488
- headers={log.headers}
538
+ rawHeaders={displayLog.rawHeaders}
539
+ headers={displayLog.headers}
489
540
  emptyLabel="No transformation applied; raw and processed headers are identical."
490
541
  />
491
- ) : log.headers && Object.keys(log.headers).length > 0 ? (
542
+ ) : displayLog.headers && Object.keys(displayLog.headers).length > 0 ? (
492
543
  <div className="space-y-1 font-mono text-xs">
493
- {Object.entries(log.headers)
544
+ {Object.entries(displayLog.headers)
494
545
  .sort(([a], [b]) => a.localeCompare(b))
495
546
  .map(([key, value]) => (
496
547
  <div key={key} className="flex gap-2">
@@ -516,9 +567,9 @@ export const LogEntry = memo(function ({
516
567
  {activeTab === "raw-headers" && (
517
568
  <div className="px-4 pt-1 pb-3">
518
569
  {/* Copy lives in the log header. */}
519
- {log.rawHeaders && Object.keys(log.rawHeaders).length > 0 ? (
570
+ {displayLog.rawHeaders && Object.keys(displayLog.rawHeaders).length > 0 ? (
520
571
  <div className="space-y-1 font-mono text-xs">
521
- {Object.entries(log.rawHeaders)
572
+ {Object.entries(displayLog.rawHeaders)
522
573
  .sort(([a], [b]) => a.localeCompare(b))
523
574
  .map(([key, value]) => (
524
575
  <div key={key} className="flex gap-2">
@@ -544,16 +595,16 @@ export const LogEntry = memo(function ({
544
595
  <TabsContent value="raw">
545
596
  {activeTab === "raw" && (
546
597
  <div className="px-4 pt-1 pb-3 space-y-3">
547
- {log.error !== undefined && log.error !== null && (
598
+ {displayLog.error !== undefined && displayLog.error !== null && (
548
599
  <div className="rounded border border-destructive/50 bg-destructive/10 p-3 text-xs">
549
600
  <div className="font-semibold text-destructive mb-1">SSE Error</div>
550
- <div className="text-muted-foreground font-mono">{log.error}</div>
601
+ <div className="text-muted-foreground font-mono">{displayLog.error}</div>
551
602
  </div>
552
603
  )}
553
- {log.responseText !== null ? (
604
+ {displayLog.responseText !== null ? (
554
605
  <Suspense fallback={<TabFallback />}>
555
606
  <LazyJsonViewerFromString
556
- text={log.responseText}
607
+ text={displayLog.responseText}
557
608
  defaultExpandDepth={0}
558
609
  bulkDepth={responseExpansion.bulkDepth}
559
610
  bulkRevision={responseExpansion.bulkRevision}
@@ -562,11 +613,11 @@ export const LogEntry = memo(function ({
562
613
  ) : (
563
614
  <p className="text-xs text-muted-foreground italic">No response</p>
564
615
  )}
565
- {log.streaming === true && (
616
+ {displayLog.streaming === true && (
566
617
  <Suspense fallback={<TabFallback />}>
567
618
  <LazyStreamingChunkSequence
568
- logId={log.id}
569
- truncated={log.streamingChunksPath !== null}
619
+ logId={displayLog.id}
620
+ truncated={displayLog.streamingChunksPath !== null}
570
621
  />
571
622
  </Suspense>
572
623
  )}
@@ -579,15 +630,15 @@ export const LogEntry = memo(function ({
579
630
  <div className="px-4 pt-1 pb-3">
580
631
  <Suspense fallback={<TabFallback />}>
581
632
  <LazyResponseView
582
- responseText={log.responseText}
583
- responseStatus={log.responseStatus}
584
- streaming={log.streaming}
585
- inputTokens={log.inputTokens}
586
- outputTokens={log.outputTokens}
587
- cacheCreationInputTokens={log.cacheCreationInputTokens}
588
- cacheReadInputTokens={log.cacheReadInputTokens}
633
+ responseText={displayLog.responseText}
634
+ responseStatus={displayLog.responseStatus}
635
+ streaming={displayLog.streaming}
636
+ inputTokens={displayLog.inputTokens}
637
+ outputTokens={displayLog.outputTokens}
638
+ cacheCreationInputTokens={displayLog.cacheCreationInputTokens}
639
+ cacheReadInputTokens={displayLog.cacheReadInputTokens}
589
640
  apiFormat={resolvedFormat}
590
- error={log.error}
641
+ error={displayLog.error}
591
642
  />
592
643
  </Suspense>
593
644
  </div>
@@ -598,7 +649,7 @@ export const LogEntry = memo(function ({
598
649
  )}
599
650
  </div>
600
651
  <Suspense fallback={null}>
601
- <LazyReplayDialog log={log} open={replayOpen} onOpenChange={setReplayOpen} />
652
+ <LazyReplayDialog log={displayLog} open={replayOpen} onOpenChange={setReplayOpen} />
602
653
  </Suspense>
603
654
  </TooltipProvider>
604
655
  );
@@ -38,7 +38,7 @@ function DialogOverlay({
38
38
  <DialogPrimitive.Overlay
39
39
  data-slot="dialog-overlay"
40
40
  className={cn(
41
- "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
41
+ "fixed inset-0 z-40 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
42
42
  className,
43
43
  )}
44
44
  {...props}
@@ -1 +0,0 @@
1
- import{R as s,j as e}from"./main-DOy_Q96H.js";import{P as i}from"./ProxyViewerContainer-CE9pAX4c.js";function t(){const{sessionId:o}=s.useParams();return e.jsx(i,{initialSessionId:o},o)}export{t as component};