@tonyclaw/agent-inspector 2.1.16 → 2.1.18
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/cli.js +57 -13
- package/.output/nitro.json +1 -1
- package/.output/public/assets/{CompareDrawer-Ccrrcx1j.js → CompareDrawer-Fqqw5Lci.js} +1 -1
- package/.output/public/assets/ProxyViewerContainer-CP_RzwW9.js +106 -0
- package/.output/public/assets/{ReplayDialog-C7axhr-l.js → ReplayDialog-hYhz_i6W.js} +1 -1
- package/.output/public/assets/{RequestAnatomy-WOptg8j_.js → RequestAnatomy-CTuWbtwC.js} +1 -1
- package/.output/public/assets/{ResponseView-CSAcxh_M.js → ResponseView-CsZ7S5Gv.js} +2 -2
- package/.output/public/assets/{StreamingChunkSequence-DJS5KhPx.js → StreamingChunkSequence-PIbJMotU.js} +1 -1
- package/.output/public/assets/_sessionId-CUGA9qU3.js +1 -0
- package/.output/public/assets/{index-DMPNh46t.js → index-F7mynwuH.js} +1 -1
- package/.output/public/assets/index-G4dTUobw.js +1 -0
- package/.output/public/assets/index-gvYkgMPF.css +1 -0
- package/.output/public/assets/{json-viewer-inX5QSa3.js → json-viewer-DCXtNmmD.js} +1 -1
- package/.output/public/assets/{main-aCAKYGSD.js → main-BJZf7_Ib.js} +2 -2
- package/.output/server/_libs/lucide-react.mjs +220 -202
- package/.output/server/{_sessionId-C0fhvQnn.mjs → _sessionId-DjSHDNh8.mjs} +2 -2
- package/.output/server/_ssr/{CompareDrawer-CO-Ti5sg.mjs → CompareDrawer-Dal52IFo.mjs} +3 -3
- package/.output/server/_ssr/{ProxyViewerContainer-N4J7uBCX.mjs → ProxyViewerContainer-CVqFZGff.mjs} +1833 -1366
- package/.output/server/_ssr/{ReplayDialog-J1VxC0In.mjs → ReplayDialog-BOEgdMes.mjs} +4 -4
- package/.output/server/_ssr/{RequestAnatomy-DBH-F3rq.mjs → RequestAnatomy-gch7_vCV.mjs} +2 -2
- package/.output/server/_ssr/{ResponseView-DLFwV7Hd.mjs → ResponseView-lEWPy-H4.mjs} +3 -3
- package/.output/server/_ssr/{StreamingChunkSequence-BywmuND0.mjs → StreamingChunkSequence-DnudbJ1O.mjs} +2 -2
- package/.output/server/_ssr/{index-CStymIc0.mjs → index-Cza8zDrW.mjs} +2 -2
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{json-viewer-DlQu0N1x.mjs → json-viewer-C2lIVEX3.mjs} +3 -3
- package/.output/server/_ssr/{router-CQ4Zxhmr.mjs → router-bF9uzd1k.mjs} +939 -113
- package/.output/server/{_tanstack-start-manifest_v-BHeJBGfo.mjs → _tanstack-start-manifest_v-ErvW-mtr.mjs} +1 -1
- package/.output/server/index.mjs +74 -74
- package/README.md +57 -2
- package/package.json +1 -1
- package/src/cli/startupOutput.ts +16 -0
- package/src/cli.ts +61 -15
- package/src/components/ProxyViewer.tsx +395 -64
- package/src/components/providers/ProviderCard.tsx +132 -31
- package/src/components/providers/ProviderForm.tsx +43 -11
- package/src/components/providers/ProvidersPanel.tsx +1 -1
- package/src/components/proxy-viewer/ConversationHeader.tsx +133 -112
- package/src/components/proxy-viewer/LogEntry.tsx +109 -26
- package/src/components/proxy-viewer/LogEntryHeader.tsx +339 -329
- package/src/components/proxy-viewer/ThreadConnector.tsx +49 -46
- package/src/components/proxy-viewer/TurnGroup.tsx +22 -62
- package/src/components/proxy-viewer/bodyHydration.ts +56 -0
- package/src/lib/providerTestContract.ts +56 -10
- package/src/lib/providerTestPrompt.ts +23 -1
- package/src/lib/upstreamUrl.ts +105 -1
- package/src/mcp/server.ts +275 -0
- package/src/mcp/toolHandlers.ts +381 -4
- package/src/proxy/logSearch.ts +3 -0
- package/src/proxy/store.ts +40 -15
- package/src/routes/api/logs.ts +8 -2
- package/src/routes/api/providers.$providerId.test.log.ts +85 -10
- package/.output/public/assets/ProxyViewerContainer-DLqClc9A.js +0 -106
- package/.output/public/assets/_sessionId-DUSalzKH.js +0 -1
- package/.output/public/assets/index-BPpA21dY.css +0 -1
- package/.output/public/assets/index-Bt0Az2I2.js +0 -1
|
@@ -218,6 +218,9 @@ export const LogEntryHeader = memo(function ({
|
|
|
218
218
|
log.clientCwd !== null && log.clientCwd !== undefined && log.clientCwd !== "";
|
|
219
219
|
const statusCue = STATUS_CUE_CLASSES[statusCategory];
|
|
220
220
|
const statusLabel = statusCueLabel(statusCategory, log.responseStatus);
|
|
221
|
+
const showStatusBadge = statusCategory !== "success" || log.responseStatus !== 200;
|
|
222
|
+
const showStandaloneStreamingIndicator =
|
|
223
|
+
log.streaming && firstChunkLabel === null && tokenRateLabel === null;
|
|
221
224
|
|
|
222
225
|
return (
|
|
223
226
|
<TooltipProvider>
|
|
@@ -228,7 +231,7 @@ export const LogEntryHeader = memo(function ({
|
|
|
228
231
|
data-nav-id={`log-${log.id}`}
|
|
229
232
|
data-nav-action={expanded ? "collapse" : "expand"}
|
|
230
233
|
className={cn(
|
|
231
|
-
"group/header relative isolate flex min-w-0
|
|
234
|
+
"group/header relative isolate flex min-w-0 cursor-pointer items-start gap-2 overflow-hidden px-3 py-2 transition-[background-color,border-color,box-shadow]",
|
|
232
235
|
expanded
|
|
233
236
|
? "bg-white/[0.035] shadow-[inset_0_1px_0_rgba(255,255,255,0.10)]"
|
|
234
237
|
: "bg-transparent hover:bg-white/[0.035]",
|
|
@@ -243,370 +246,377 @@ export const LogEntryHeader = memo(function ({
|
|
|
243
246
|
}
|
|
244
247
|
}}
|
|
245
248
|
>
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
249
|
+
<span className="flex min-w-0 flex-1 flex-wrap items-center gap-x-2 gap-y-1">
|
|
250
|
+
{/* Request ID */}
|
|
251
|
+
<span
|
|
252
|
+
className={cn(
|
|
253
|
+
"border border-border bg-muted/40 inline-flex h-8 shrink-0 items-center gap-2 rounded-md px-2 font-mono",
|
|
254
|
+
statusCue.frame,
|
|
255
|
+
)}
|
|
256
|
+
>
|
|
257
|
+
<span className={cn("size-1.5 rounded-full", statusCue.dot)} aria-hidden="true" />
|
|
258
|
+
<span className="text-xs font-semibold tabular-nums" title={`Log ID ${String(log.id)}`}>
|
|
259
|
+
#{displayNumber}
|
|
260
|
+
</span>
|
|
256
261
|
</span>
|
|
257
|
-
</span>
|
|
258
262
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
263
|
+
{/* Request start time */}
|
|
264
|
+
<span className="border border-border bg-muted/40 flex h-7 shrink-0 items-center gap-1 rounded-md px-2 text-xs text-muted-foreground">
|
|
265
|
+
<Clock className="size-3" />
|
|
266
|
+
<span className="font-mono tabular-nums" title={log.timestamp}>
|
|
267
|
+
{formatTimestamp(log.timestamp, timeDisplayFormat)}
|
|
268
|
+
</span>
|
|
264
269
|
</span>
|
|
265
|
-
</span>
|
|
266
270
|
|
|
267
|
-
|
|
271
|
+
{/* Response Status - only shown for non-200 or pending. Each category
|
|
268
272
|
carries a distinct icon in addition to color so the meaning is
|
|
269
273
|
legible without color perception. */}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
274
|
+
{showStatusBadge && (
|
|
275
|
+
<Badge
|
|
276
|
+
variant="outline"
|
|
277
|
+
className={cn(
|
|
278
|
+
"h-6 gap-1 rounded-md px-2 py-0 font-mono text-[10px] font-semibold uppercase tabular-nums shadow-[inset_0_1px_0_rgba(255,255,255,0.05)]",
|
|
279
|
+
STATUS_BADGE_CLASSES[statusCategory],
|
|
280
|
+
)}
|
|
281
|
+
>
|
|
282
|
+
{statusCategory === "success" ? (
|
|
283
|
+
<Check className="size-3" aria-label="Success" />
|
|
284
|
+
) : statusCategory === "server_error" ? (
|
|
285
|
+
<OctagonAlert className="size-3" aria-label="Server error" />
|
|
286
|
+
) : statusCategory === "client_error" ? (
|
|
287
|
+
<AlertTriangle className="size-3" aria-label="Client error" />
|
|
288
|
+
) : (
|
|
289
|
+
<Loader2 className="size-3 animate-spin" aria-label="Pending" />
|
|
290
|
+
)}
|
|
291
|
+
{statusLabel}
|
|
292
|
+
</Badge>
|
|
275
293
|
)}
|
|
276
|
-
>
|
|
277
|
-
{statusCategory === "success" ? (
|
|
278
|
-
<Check className="size-3" aria-label="Success" />
|
|
279
|
-
) : statusCategory === "server_error" ? (
|
|
280
|
-
<OctagonAlert className="size-3" aria-label="Server error" />
|
|
281
|
-
) : statusCategory === "client_error" ? (
|
|
282
|
-
<AlertTriangle className="size-3" aria-label="Client error" />
|
|
283
|
-
) : (
|
|
284
|
-
<Loader2 className="size-3 animate-spin" aria-label="Pending" />
|
|
285
|
-
)}
|
|
286
|
-
{statusLabel}
|
|
287
|
-
</Badge>
|
|
288
294
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
295
|
+
{warningCount > 0 && (
|
|
296
|
+
<Tooltip>
|
|
297
|
+
<TooltipTrigger asChild>
|
|
298
|
+
<Badge
|
|
299
|
+
variant="outline"
|
|
300
|
+
className="h-6 gap-1 rounded-md border-amber-300/30 bg-amber-300/[0.10] px-2 py-0 font-mono text-[10px] tabular-nums text-amber-100"
|
|
301
|
+
>
|
|
302
|
+
<AlertTriangle className="size-3" aria-label="Tool schema warnings" />
|
|
303
|
+
{warningCount}
|
|
304
|
+
</Badge>
|
|
305
|
+
</TooltipTrigger>
|
|
306
|
+
<TooltipContent>
|
|
307
|
+
{warningCount === 1
|
|
308
|
+
? "1 tool schema warning"
|
|
309
|
+
: `${warningCount} tool schema warnings`}
|
|
310
|
+
</TooltipContent>
|
|
311
|
+
</Tooltip>
|
|
312
|
+
)}
|
|
307
313
|
|
|
308
|
-
|
|
314
|
+
{/* Elapsed time. Tooltip is only shown when this log exceeded the slow-
|
|
309
315
|
response threshold - for normal-speed logs the elapsed value is
|
|
310
316
|
self-explanatory, so we skip the tooltip wrapper to keep the row
|
|
311
317
|
quiet. */}
|
|
312
|
-
|
|
313
|
-
|
|
318
|
+
{log.elapsedMs !== null &&
|
|
319
|
+
(isSlowResponse ? (
|
|
320
|
+
<Tooltip>
|
|
321
|
+
<TooltipTrigger asChild>
|
|
322
|
+
<span
|
|
323
|
+
className={cn(
|
|
324
|
+
TELEMETRY_CHIP_CLASS,
|
|
325
|
+
"shrink-0 border-amber-300/25 text-amber-200",
|
|
326
|
+
)}
|
|
327
|
+
>
|
|
328
|
+
<Clock className="size-3" />
|
|
329
|
+
<span className="font-mono tabular-nums">{formatElapsed(log.elapsedMs)}</span>
|
|
330
|
+
<AlertTriangle className="size-3" aria-label="Slow response" />
|
|
331
|
+
</span>
|
|
332
|
+
</TooltipTrigger>
|
|
333
|
+
<TooltipContent>
|
|
334
|
+
Slow response: {formatElapsed(log.elapsedMs)} exceeds{" "}
|
|
335
|
+
{formatElapsed(slowResponseThresholdSeconds * 1000)}
|
|
336
|
+
</TooltipContent>
|
|
337
|
+
</Tooltip>
|
|
338
|
+
) : (
|
|
339
|
+
<span className={cn(TELEMETRY_CHIP_CLASS, "shrink-0 text-muted-foreground")}>
|
|
340
|
+
<Clock className="size-3" />
|
|
341
|
+
<span className="font-mono tabular-nums">{formatElapsed(log.elapsedMs)}</span>
|
|
342
|
+
</span>
|
|
343
|
+
))}
|
|
344
|
+
|
|
345
|
+
{/* Streaming timing */}
|
|
346
|
+
{log.streaming && firstChunkLabel !== null && (
|
|
347
|
+
<Tooltip>
|
|
348
|
+
<TooltipTrigger asChild>
|
|
349
|
+
<span className={cn(TELEMETRY_CHIP_CLASS, "shrink-0 text-cyan-300")}>
|
|
350
|
+
<Radio className="size-3" />
|
|
351
|
+
<span className="font-mono tabular-nums">first {firstChunkLabel}</span>
|
|
352
|
+
</span>
|
|
353
|
+
</TooltipTrigger>
|
|
354
|
+
<TooltipContent>Time to first streaming chunk</TooltipContent>
|
|
355
|
+
</Tooltip>
|
|
356
|
+
)}
|
|
357
|
+
{log.streaming && tokenRateLabel !== null && (
|
|
314
358
|
<Tooltip>
|
|
315
359
|
<TooltipTrigger asChild>
|
|
360
|
+
<span className={cn(TELEMETRY_CHIP_CLASS, "shrink-0 text-cyan-300")}>
|
|
361
|
+
<Gauge className="size-3" />
|
|
362
|
+
<span className="font-mono tabular-nums">{tokenRateLabel}</span>
|
|
363
|
+
</span>
|
|
364
|
+
</TooltipTrigger>
|
|
365
|
+
<TooltipContent>Output token throughput after first chunk</TooltipContent>
|
|
366
|
+
</Tooltip>
|
|
367
|
+
)}
|
|
368
|
+
|
|
369
|
+
{/* Token counts */}
|
|
370
|
+
{hasTokens && (
|
|
371
|
+
<span className={cn(TELEMETRY_CHIP_CLASS, "min-w-0 sm:shrink-0")}>
|
|
372
|
+
<Zap className="size-3 text-muted-foreground" />
|
|
373
|
+
<span className="flex min-w-0 flex-wrap items-center gap-x-1 font-mono tabular-nums">
|
|
316
374
|
<span
|
|
317
375
|
className={cn(
|
|
318
|
-
|
|
319
|
-
"
|
|
376
|
+
"whitespace-nowrap",
|
|
377
|
+
log.inputTokens !== null ? "text-blue-400" : "text-muted-foreground",
|
|
320
378
|
)}
|
|
321
379
|
>
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
380
|
+
IN {log.inputTokens !== null ? formatTokens(log.inputTokens) : "n/a"}
|
|
381
|
+
</span>
|
|
382
|
+
<span className="text-muted-foreground">/</span>
|
|
383
|
+
<span
|
|
384
|
+
className={cn(
|
|
385
|
+
"whitespace-nowrap",
|
|
386
|
+
log.outputTokens !== null ? "text-amber-400" : "text-muted-foreground",
|
|
387
|
+
)}
|
|
388
|
+
>
|
|
389
|
+
OUT {log.outputTokens !== null ? formatTokens(log.outputTokens) : "n/a"}
|
|
325
390
|
</span>
|
|
326
|
-
</TooltipTrigger>
|
|
327
|
-
<TooltipContent>
|
|
328
|
-
Slow response: {formatElapsed(log.elapsedMs)} exceeds{" "}
|
|
329
|
-
{formatElapsed(slowResponseThresholdSeconds * 1000)}
|
|
330
|
-
</TooltipContent>
|
|
331
|
-
</Tooltip>
|
|
332
|
-
) : (
|
|
333
|
-
<span className={cn(TELEMETRY_CHIP_CLASS, "shrink-0 text-muted-foreground")}>
|
|
334
|
-
<Clock className="size-3" />
|
|
335
|
-
<span className="font-mono tabular-nums">{formatElapsed(log.elapsedMs)}</span>
|
|
336
|
-
</span>
|
|
337
|
-
))}
|
|
338
|
-
|
|
339
|
-
{/* Streaming timing */}
|
|
340
|
-
{log.streaming && firstChunkLabel !== null && (
|
|
341
|
-
<Tooltip>
|
|
342
|
-
<TooltipTrigger asChild>
|
|
343
|
-
<span className={cn(TELEMETRY_CHIP_CLASS, "shrink-0 text-cyan-300")}>
|
|
344
|
-
<Radio className="size-3" />
|
|
345
|
-
<span className="font-mono tabular-nums">first {firstChunkLabel}</span>
|
|
346
|
-
</span>
|
|
347
|
-
</TooltipTrigger>
|
|
348
|
-
<TooltipContent>Time to first streaming chunk</TooltipContent>
|
|
349
|
-
</Tooltip>
|
|
350
|
-
)}
|
|
351
|
-
{log.streaming && tokenRateLabel !== null && (
|
|
352
|
-
<Tooltip>
|
|
353
|
-
<TooltipTrigger asChild>
|
|
354
|
-
<span className={cn(TELEMETRY_CHIP_CLASS, "shrink-0 text-cyan-300")}>
|
|
355
|
-
<Gauge className="size-3" />
|
|
356
|
-
<span className="font-mono tabular-nums">{tokenRateLabel}</span>
|
|
357
|
-
</span>
|
|
358
|
-
</TooltipTrigger>
|
|
359
|
-
<TooltipContent>Output token throughput after first chunk</TooltipContent>
|
|
360
|
-
</Tooltip>
|
|
361
|
-
)}
|
|
362
|
-
|
|
363
|
-
{/* Token counts */}
|
|
364
|
-
{hasTokens && (
|
|
365
|
-
<span className={cn(TELEMETRY_CHIP_CLASS, "min-w-0 sm:shrink-0")}>
|
|
366
|
-
<Zap className="size-3 text-muted-foreground" />
|
|
367
|
-
<span className="flex min-w-0 flex-wrap items-center gap-x-1 font-mono tabular-nums">
|
|
368
|
-
<span
|
|
369
|
-
className={cn(
|
|
370
|
-
"whitespace-nowrap",
|
|
371
|
-
log.inputTokens !== null ? "text-blue-400" : "text-muted-foreground",
|
|
372
|
-
)}
|
|
373
|
-
>
|
|
374
|
-
IN {log.inputTokens !== null ? formatTokens(log.inputTokens) : "n/a"}
|
|
375
|
-
</span>
|
|
376
|
-
<span className="text-muted-foreground">/</span>
|
|
377
|
-
<span
|
|
378
|
-
className={cn(
|
|
379
|
-
"whitespace-nowrap",
|
|
380
|
-
log.outputTokens !== null ? "text-amber-400" : "text-muted-foreground",
|
|
381
|
-
)}
|
|
382
|
-
>
|
|
383
|
-
OUT {log.outputTokens !== null ? formatTokens(log.outputTokens) : "n/a"}
|
|
384
391
|
</span>
|
|
385
392
|
</span>
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
393
|
+
)}
|
|
394
|
+
{/* Cache tokens */}
|
|
395
|
+
{log.cacheCreationInputTokens !== null && log.cacheCreationInputTokens > 0 && (
|
|
396
|
+
<span className={cn(TELEMETRY_CHIP_CLASS, "shrink-0")}>
|
|
397
|
+
<CacheTrendIndicator trend={cacheTrend?.creation ?? null} />
|
|
398
|
+
<span className="font-mono tabular-nums text-cyan-300">
|
|
399
|
+
KV Cache +{formatTokens(log.cacheCreationInputTokens)}
|
|
400
|
+
</span>
|
|
394
401
|
</span>
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
+
)}
|
|
403
|
+
{log.cacheReadInputTokens !== null && log.cacheReadInputTokens > 0 && (
|
|
404
|
+
<span className={cn(TELEMETRY_CHIP_CLASS, "shrink-0")}>
|
|
405
|
+
<CacheTrendIndicator trend={cacheTrend?.read ?? null} />
|
|
406
|
+
<span className="font-mono tabular-nums text-purple-400">
|
|
407
|
+
KV Cache ~{formatTokens(log.cacheReadInputTokens)}
|
|
408
|
+
</span>
|
|
402
409
|
</span>
|
|
403
|
-
|
|
404
|
-
)}
|
|
405
|
-
|
|
406
|
-
{/* Message count */}
|
|
407
|
-
{messageCount !== null && (
|
|
408
|
-
<span className={cn(TELEMETRY_CHIP_CLASS, "shrink-0 text-muted-foreground")}>
|
|
409
|
-
<MessageSquare className="size-3" />
|
|
410
|
-
<span className="font-mono tabular-nums">{messageCount}</span>
|
|
411
|
-
</span>
|
|
412
|
-
)}
|
|
410
|
+
)}
|
|
413
411
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
412
|
+
{/* Message count */}
|
|
413
|
+
{messageCount !== null && (
|
|
414
|
+
<span className={cn(TELEMETRY_CHIP_CLASS, "shrink-0 text-muted-foreground")}>
|
|
415
|
+
<MessageSquare className="size-3" />
|
|
416
|
+
<span className="font-mono tabular-nums">{messageCount}</span>
|
|
417
|
+
</span>
|
|
418
|
+
)}
|
|
421
419
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
>
|
|
428
|
-
<Globe className="size-3" />
|
|
429
|
-
<span className="font-mono tabular-nums truncate max-w-[120px]" title={log.origin}>
|
|
430
|
-
{log.origin}
|
|
420
|
+
{/* Tool count */}
|
|
421
|
+
{toolCount !== null && (
|
|
422
|
+
<span className={cn(TELEMETRY_CHIP_CLASS, "shrink-0 text-muted-foreground")}>
|
|
423
|
+
<Wrench className="size-3" />
|
|
424
|
+
<span className="font-mono tabular-nums">{toolCount}</span>
|
|
431
425
|
</span>
|
|
432
|
-
|
|
433
|
-
)}
|
|
426
|
+
)}
|
|
434
427
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
<span className="font-mono tabular-nums">PID {log.clientPid}</span>
|
|
445
|
-
)}
|
|
428
|
+
{/* Origin */}
|
|
429
|
+
{log.origin !== null && (
|
|
430
|
+
<span
|
|
431
|
+
className={cn(TELEMETRY_CHIP_CLASS, "hidden shrink-0 text-muted-foreground xl:flex")}
|
|
432
|
+
title={`Origin: ${log.origin}`}
|
|
433
|
+
>
|
|
434
|
+
<Globe className="size-3" />
|
|
435
|
+
<span className="font-mono tabular-nums truncate max-w-[120px]" title={log.origin}>
|
|
436
|
+
{log.origin}
|
|
446
437
|
</span>
|
|
447
|
-
</
|
|
448
|
-
|
|
449
|
-
{hasClientCwd
|
|
450
|
-
? `PID: ${log.clientPid ?? "?"} CWD: ${log.clientCwd}`
|
|
451
|
-
: `Process ID: ${log.clientPid ?? "?"}`}
|
|
452
|
-
</TooltipContent>
|
|
453
|
-
</Tooltip>
|
|
454
|
-
)}
|
|
438
|
+
</span>
|
|
439
|
+
)}
|
|
455
440
|
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
441
|
+
{/* Client info (PID + project folder) */}
|
|
442
|
+
{showClientMetadata && (hasClientPid || hasClientProjectFolder) && (
|
|
443
|
+
<Tooltip>
|
|
444
|
+
<TooltipTrigger asChild>
|
|
445
|
+
<span
|
|
446
|
+
className={cn(TELEMETRY_CHIP_CLASS, "hidden shrink-0 text-purple-300 xl:flex")}
|
|
447
|
+
>
|
|
448
|
+
<FileTerminal className="size-3" />
|
|
449
|
+
{hasClientProjectFolder ? (
|
|
450
|
+
<span className="font-mono tabular-nums">{log.clientProjectFolder}</span>
|
|
451
|
+
) : (
|
|
452
|
+
<span className="font-mono tabular-nums">PID {log.clientPid}</span>
|
|
453
|
+
)}
|
|
454
|
+
</span>
|
|
455
|
+
</TooltipTrigger>
|
|
456
|
+
<TooltipContent>
|
|
457
|
+
{hasClientCwd
|
|
458
|
+
? `PID: ${log.clientPid ?? "?"} CWD: ${log.clientCwd}`
|
|
459
|
+
: `Process ID: ${log.clientPid ?? "?"}`}
|
|
460
|
+
</TooltipContent>
|
|
461
|
+
</Tooltip>
|
|
462
|
+
)}
|
|
465
463
|
|
|
466
|
-
|
|
467
|
-
|
|
464
|
+
{/* Streaming indicator */}
|
|
465
|
+
{showStandaloneStreamingIndicator && (
|
|
466
|
+
<Tooltip>
|
|
467
|
+
<TooltipTrigger asChild>
|
|
468
|
+
<Radio className="size-3 text-muted-foreground/60 shrink-0" />
|
|
469
|
+
</TooltipTrigger>
|
|
470
|
+
<TooltipContent>Request used SSE streaming</TooltipContent>
|
|
471
|
+
</Tooltip>
|
|
472
|
+
)}
|
|
473
|
+
</span>
|
|
468
474
|
|
|
469
|
-
|
|
475
|
+
<span className="flex shrink-0 items-start gap-1.5">
|
|
476
|
+
{/* Header actions - only when expanded, so the collapsed view stays
|
|
470
477
|
compact. Buttons stop propagation so they don't toggle the log. */}
|
|
471
|
-
|
|
478
|
+
{expanded && (
|
|
479
|
+
<span
|
|
480
|
+
className="flex items-center gap-1.5 shrink-0"
|
|
481
|
+
onClick={(e) => e.stopPropagation()}
|
|
482
|
+
onKeyDown={(e) => e.stopPropagation()}
|
|
483
|
+
>
|
|
484
|
+
{tabActions !== undefined &&
|
|
485
|
+
activeTab !== undefined &&
|
|
486
|
+
(() => {
|
|
487
|
+
const action = tabActions[activeTab];
|
|
488
|
+
if (action === undefined) return null;
|
|
489
|
+
return (
|
|
490
|
+
<>
|
|
491
|
+
{action.expansion !== null && (
|
|
492
|
+
<Tooltip>
|
|
493
|
+
<TooltipTrigger asChild>
|
|
494
|
+
<Button
|
|
495
|
+
variant="outline"
|
|
496
|
+
size="icon"
|
|
497
|
+
className={HEADER_ACTION_BUTTON_CLASS}
|
|
498
|
+
onClick={action.expansion.onToggle}
|
|
499
|
+
disabled={action.expansion.isPending}
|
|
500
|
+
aria-pressed={action.expansion.isExpanded}
|
|
501
|
+
aria-label={
|
|
502
|
+
action.expansion.isExpanded
|
|
503
|
+
? "Collapse all JSON"
|
|
504
|
+
: "Expand all JSON"
|
|
505
|
+
}
|
|
506
|
+
>
|
|
507
|
+
{action.expansion.isExpanded ? (
|
|
508
|
+
<ChevronsUp className="size-3.5" />
|
|
509
|
+
) : (
|
|
510
|
+
<ChevronsDown className="size-3.5" />
|
|
511
|
+
)}
|
|
512
|
+
</Button>
|
|
513
|
+
</TooltipTrigger>
|
|
514
|
+
<TooltipContent>
|
|
515
|
+
{action.expansion.isExpanded
|
|
516
|
+
? "Collapse all JSON nodes"
|
|
517
|
+
: "Expand all JSON nodes"}
|
|
518
|
+
</TooltipContent>
|
|
519
|
+
</Tooltip>
|
|
520
|
+
)}
|
|
521
|
+
{action.diffWithRaw !== undefined && (
|
|
522
|
+
<Tooltip>
|
|
523
|
+
<TooltipTrigger asChild>
|
|
524
|
+
<Button
|
|
525
|
+
variant="outline"
|
|
526
|
+
size="icon"
|
|
527
|
+
className={cn(
|
|
528
|
+
HEADER_ACTION_BUTTON_CLASS,
|
|
529
|
+
action.diffWithRaw.active &&
|
|
530
|
+
"border-cyan-300/35 bg-cyan-400/15 text-cyan-100",
|
|
531
|
+
)}
|
|
532
|
+
onClick={action.diffWithRaw.onToggle}
|
|
533
|
+
aria-pressed={action.diffWithRaw.active}
|
|
534
|
+
aria-label={
|
|
535
|
+
action.diffWithRaw.active ? "Hide raw diff" : "Diff with raw"
|
|
536
|
+
}
|
|
537
|
+
>
|
|
538
|
+
<FileDiff className="size-3.5" />
|
|
539
|
+
</Button>
|
|
540
|
+
</TooltipTrigger>
|
|
541
|
+
<TooltipContent>
|
|
542
|
+
{action.diffWithRaw.active
|
|
543
|
+
? "Hide diff with raw request"
|
|
544
|
+
: "Show diff between displayed and raw request body"}
|
|
545
|
+
</TooltipContent>
|
|
546
|
+
</Tooltip>
|
|
547
|
+
)}
|
|
548
|
+
{action.diffWithPrevious !== undefined && (
|
|
549
|
+
<Tooltip>
|
|
550
|
+
<TooltipTrigger asChild>
|
|
551
|
+
<Button
|
|
552
|
+
variant="outline"
|
|
553
|
+
size="icon"
|
|
554
|
+
className={HEADER_ACTION_BUTTON_CLASS}
|
|
555
|
+
onClick={action.diffWithPrevious}
|
|
556
|
+
aria-label="Diff with previous"
|
|
557
|
+
>
|
|
558
|
+
<History className="size-3.5" />
|
|
559
|
+
</Button>
|
|
560
|
+
</TooltipTrigger>
|
|
561
|
+
<TooltipContent>
|
|
562
|
+
Compare this request with the immediately preceding one
|
|
563
|
+
</TooltipContent>
|
|
564
|
+
</Tooltip>
|
|
565
|
+
)}
|
|
566
|
+
{action.copyText !== null && (
|
|
567
|
+
<Tooltip>
|
|
568
|
+
<TooltipTrigger asChild>
|
|
569
|
+
<Button
|
|
570
|
+
variant="outline"
|
|
571
|
+
size="icon"
|
|
572
|
+
className={HEADER_ACTION_BUTTON_CLASS}
|
|
573
|
+
onClick={action.onCopy}
|
|
574
|
+
aria-label={action.copyCopied ? "Copied" : action.copyLabel}
|
|
575
|
+
>
|
|
576
|
+
{action.copyCopied ? (
|
|
577
|
+
<Check className="size-3.5 text-cyan-300" />
|
|
578
|
+
) : (
|
|
579
|
+
<Copy className="size-3.5" />
|
|
580
|
+
)}
|
|
581
|
+
</Button>
|
|
582
|
+
</TooltipTrigger>
|
|
583
|
+
<TooltipContent>
|
|
584
|
+
{action.copyCopied ? "Copied to clipboard" : action.copyLabel}
|
|
585
|
+
</TooltipContent>
|
|
586
|
+
</Tooltip>
|
|
587
|
+
)}
|
|
588
|
+
</>
|
|
589
|
+
);
|
|
590
|
+
})()}
|
|
591
|
+
{onReplay !== undefined && (
|
|
592
|
+
<Tooltip>
|
|
593
|
+
<TooltipTrigger asChild>
|
|
594
|
+
<Button
|
|
595
|
+
variant="outline"
|
|
596
|
+
size="icon"
|
|
597
|
+
className={HEADER_ACTION_BUTTON_CLASS}
|
|
598
|
+
onClick={onReplay}
|
|
599
|
+
aria-label="Replay request"
|
|
600
|
+
>
|
|
601
|
+
<RotateCcw className="size-3.5" />
|
|
602
|
+
</Button>
|
|
603
|
+
</TooltipTrigger>
|
|
604
|
+
<TooltipContent>Re-send this request to the provider</TooltipContent>
|
|
605
|
+
</Tooltip>
|
|
606
|
+
)}
|
|
607
|
+
</span>
|
|
608
|
+
)}
|
|
609
|
+
|
|
472
610
|
<span
|
|
473
|
-
className="flex items-center
|
|
474
|
-
|
|
475
|
-
onKeyDown={(e) => e.stopPropagation()}
|
|
611
|
+
className="border border-input bg-background hover:bg-accent hover:text-accent-foreground inline-flex size-8 shrink-0 items-center justify-center rounded-md text-slate-200"
|
|
612
|
+
aria-hidden="true"
|
|
476
613
|
>
|
|
477
|
-
{
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
if (action === undefined) return null;
|
|
482
|
-
return (
|
|
483
|
-
<>
|
|
484
|
-
{action.expansion !== null && (
|
|
485
|
-
<Tooltip>
|
|
486
|
-
<TooltipTrigger asChild>
|
|
487
|
-
<Button
|
|
488
|
-
variant="outline"
|
|
489
|
-
size="icon"
|
|
490
|
-
className={HEADER_ACTION_BUTTON_CLASS}
|
|
491
|
-
onClick={action.expansion.onToggle}
|
|
492
|
-
disabled={action.expansion.isPending}
|
|
493
|
-
aria-pressed={action.expansion.isExpanded}
|
|
494
|
-
aria-label={
|
|
495
|
-
action.expansion.isExpanded ? "Collapse all JSON" : "Expand all JSON"
|
|
496
|
-
}
|
|
497
|
-
>
|
|
498
|
-
{action.expansion.isExpanded ? (
|
|
499
|
-
<ChevronsUp className="size-3.5" />
|
|
500
|
-
) : (
|
|
501
|
-
<ChevronsDown className="size-3.5" />
|
|
502
|
-
)}
|
|
503
|
-
</Button>
|
|
504
|
-
</TooltipTrigger>
|
|
505
|
-
<TooltipContent>
|
|
506
|
-
{action.expansion.isExpanded
|
|
507
|
-
? "Collapse all JSON nodes"
|
|
508
|
-
: "Expand all JSON nodes"}
|
|
509
|
-
</TooltipContent>
|
|
510
|
-
</Tooltip>
|
|
511
|
-
)}
|
|
512
|
-
{action.diffWithRaw !== undefined && (
|
|
513
|
-
<Tooltip>
|
|
514
|
-
<TooltipTrigger asChild>
|
|
515
|
-
<Button
|
|
516
|
-
variant="outline"
|
|
517
|
-
size="icon"
|
|
518
|
-
className={cn(
|
|
519
|
-
HEADER_ACTION_BUTTON_CLASS,
|
|
520
|
-
action.diffWithRaw.active &&
|
|
521
|
-
"border-cyan-300/35 bg-cyan-400/15 text-cyan-100",
|
|
522
|
-
)}
|
|
523
|
-
onClick={action.diffWithRaw.onToggle}
|
|
524
|
-
aria-pressed={action.diffWithRaw.active}
|
|
525
|
-
aria-label={
|
|
526
|
-
action.diffWithRaw.active ? "Hide raw diff" : "Diff with raw"
|
|
527
|
-
}
|
|
528
|
-
>
|
|
529
|
-
<FileDiff className="size-3.5" />
|
|
530
|
-
</Button>
|
|
531
|
-
</TooltipTrigger>
|
|
532
|
-
<TooltipContent>
|
|
533
|
-
{action.diffWithRaw.active
|
|
534
|
-
? "Hide diff with raw request"
|
|
535
|
-
: "Show diff between displayed and raw request body"}
|
|
536
|
-
</TooltipContent>
|
|
537
|
-
</Tooltip>
|
|
538
|
-
)}
|
|
539
|
-
{action.diffWithPrevious !== undefined && (
|
|
540
|
-
<Tooltip>
|
|
541
|
-
<TooltipTrigger asChild>
|
|
542
|
-
<Button
|
|
543
|
-
variant="outline"
|
|
544
|
-
size="icon"
|
|
545
|
-
className={HEADER_ACTION_BUTTON_CLASS}
|
|
546
|
-
onClick={action.diffWithPrevious}
|
|
547
|
-
aria-label="Diff with previous"
|
|
548
|
-
>
|
|
549
|
-
<History className="size-3.5" />
|
|
550
|
-
</Button>
|
|
551
|
-
</TooltipTrigger>
|
|
552
|
-
<TooltipContent>
|
|
553
|
-
Compare this request with the immediately preceding one
|
|
554
|
-
</TooltipContent>
|
|
555
|
-
</Tooltip>
|
|
556
|
-
)}
|
|
557
|
-
{action.copyText !== null && (
|
|
558
|
-
<Tooltip>
|
|
559
|
-
<TooltipTrigger asChild>
|
|
560
|
-
<Button
|
|
561
|
-
variant="outline"
|
|
562
|
-
size="icon"
|
|
563
|
-
className={HEADER_ACTION_BUTTON_CLASS}
|
|
564
|
-
onClick={action.onCopy}
|
|
565
|
-
aria-label={action.copyCopied ? "Copied" : action.copyLabel}
|
|
566
|
-
>
|
|
567
|
-
{action.copyCopied ? (
|
|
568
|
-
<Check className="size-3.5 text-cyan-300" />
|
|
569
|
-
) : (
|
|
570
|
-
<Copy className="size-3.5" />
|
|
571
|
-
)}
|
|
572
|
-
</Button>
|
|
573
|
-
</TooltipTrigger>
|
|
574
|
-
<TooltipContent>
|
|
575
|
-
{action.copyCopied ? "Copied to clipboard" : action.copyLabel}
|
|
576
|
-
</TooltipContent>
|
|
577
|
-
</Tooltip>
|
|
578
|
-
)}
|
|
579
|
-
</>
|
|
580
|
-
);
|
|
581
|
-
})()}
|
|
582
|
-
{onReplay !== undefined && (
|
|
583
|
-
<Tooltip>
|
|
584
|
-
<TooltipTrigger asChild>
|
|
585
|
-
<Button
|
|
586
|
-
variant="outline"
|
|
587
|
-
size="icon"
|
|
588
|
-
className={HEADER_ACTION_BUTTON_CLASS}
|
|
589
|
-
onClick={onReplay}
|
|
590
|
-
aria-label="Replay request"
|
|
591
|
-
>
|
|
592
|
-
<RotateCcw className="size-3.5" />
|
|
593
|
-
</Button>
|
|
594
|
-
</TooltipTrigger>
|
|
595
|
-
<TooltipContent>Re-send this request to the provider</TooltipContent>
|
|
596
|
-
</Tooltip>
|
|
614
|
+
{expanded ? (
|
|
615
|
+
<ChevronDown className="size-4 shrink-0" />
|
|
616
|
+
) : (
|
|
617
|
+
<ChevronRight className="size-4 shrink-0" />
|
|
597
618
|
)}
|
|
598
619
|
</span>
|
|
599
|
-
)}
|
|
600
|
-
|
|
601
|
-
<span
|
|
602
|
-
className="border border-input bg-background hover:bg-accent hover:text-accent-foreground inline-flex size-8 shrink-0 items-center justify-center rounded-md text-slate-200"
|
|
603
|
-
aria-hidden="true"
|
|
604
|
-
>
|
|
605
|
-
{expanded ? (
|
|
606
|
-
<ChevronDown className="size-4 shrink-0" />
|
|
607
|
-
) : (
|
|
608
|
-
<ChevronRight className="size-4 shrink-0" />
|
|
609
|
-
)}
|
|
610
620
|
</span>
|
|
611
621
|
</div>
|
|
612
622
|
</TooltipProvider>
|