@tonyclaw/llm-inspector 1.18.2 → 1.19.0
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 +776 -139
- package/.output/nitro.json +1 -1
- package/.output/public/assets/{CompareDrawer-C-4ypEWs.js → CompareDrawer-DwayZPPO.js} +1 -1
- package/.output/public/assets/ProxyViewerContainer-iv3LVMEW.js +101 -0
- package/.output/public/assets/{ReplayDialog-CyBKOgba.js → ReplayDialog-CaV1elYO.js} +1 -1
- package/.output/public/assets/{RequestAnatomy-C0IrVQ3q.js → RequestAnatomy-CSfnjK7j.js} +1 -1
- package/.output/public/assets/{ResponseView-MogToC4i.js → ResponseView-YkOL__xm.js} +1 -1
- package/.output/public/assets/{StreamingChunkSequence-ClhUhT-s.js → StreamingChunkSequence-D_p6L-oB.js} +1 -1
- package/.output/public/assets/_sessionId-BgCVUC6R.js +1 -0
- package/.output/public/assets/index-CWA4S0FO.js +1 -0
- package/.output/public/assets/index-DeJyypsp.css +1 -0
- package/.output/public/assets/{json-viewer-BicGakI5.js → json-viewer-BB-9bqnP.js} +2 -2
- package/.output/public/assets/{main-Be2qqUUW.js → main-COVN451W.js} +2 -2
- package/.output/server/_libs/lucide-react.mjs +93 -72
- package/.output/server/{_sessionId-DhKJIdQC.mjs → _sessionId-BJT5qIib.mjs} +2 -2
- package/.output/server/_ssr/{CompareDrawer-BGUgukJ8.mjs → CompareDrawer-DNGYdUXs.mjs} +4 -4
- package/.output/server/_ssr/{ProxyViewerContainer--3K3o3Sm.mjs → ProxyViewerContainer-B-zDOLYE.mjs} +354 -343
- package/.output/server/_ssr/{ReplayDialog-Bo86xZI4.mjs → ReplayDialog-DWeqMA4y.mjs} +4 -4
- package/.output/server/_ssr/{RequestAnatomy-jRU5qgwB.mjs → RequestAnatomy-TOsrMu9-.mjs} +3 -3
- package/.output/server/_ssr/{ResponseView-DdO_-79a.mjs → ResponseView-BuqdPrzm.mjs} +4 -4
- package/.output/server/_ssr/{StreamingChunkSequence-BigLwhh4.mjs → StreamingChunkSequence-DuzNZkqL.mjs} +3 -3
- package/.output/server/_ssr/{index-BHG6vOnr.mjs → index-1nCQUt3y.mjs} +2 -2
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{json-viewer-B4c_WjXD.mjs → json-viewer-BL8xhHbi.mjs} +9 -5
- package/.output/server/_ssr/{router-DVixpJO-.mjs → router-aCaUgVTW.mjs} +3 -3
- package/.output/server/{_tanstack-start-manifest_v-BbvWUF4v.mjs → _tanstack-start-manifest_v-cBRxvCjb.mjs} +1 -1
- package/.output/server/index.mjs +61 -61
- package/package.json +2 -1
- package/src/cli/detect-tools.ts +146 -0
- package/src/cli/onboard.ts +229 -0
- package/src/cli/templates/command-onboard.ts +17 -0
- package/src/cli/templates/skill-onboard.ts +325 -0
- package/src/cli.ts +185 -163
- package/src/components/ProxyViewer.tsx +153 -142
- package/src/components/proxy-viewer/LogEntry.tsx +136 -157
- package/src/components/proxy-viewer/LogEntryHeader.tsx +147 -66
- package/src/components/proxy-viewer/useCopyFeedback.ts +36 -0
- package/src/components/ui/json-viewer.tsx +12 -0
- package/.output/public/assets/ProxyViewerContainer-WRenRpeh.js +0 -101
- package/.output/public/assets/_sessionId-BO47oA3Z.js +0 -1
- package/.output/public/assets/index-BRvz6-L6.css +0 -1
- package/.output/public/assets/index-Btw8ec7-.js +0 -1
|
@@ -303,165 +303,176 @@ export function ProxyViewer({
|
|
|
303
303
|
|
|
304
304
|
return (
|
|
305
305
|
<div className="max-w-[1400px] xl:max-w-[1600px] 2xl:max-w-[1800px] mx-auto px-6 pb-6">
|
|
306
|
-
{/*
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
306
|
+
{/* Sticky chrome — brand row, optional pinned-session context, and the
|
|
307
|
+
filter/control bar stay visible while the user scrolls through the
|
|
308
|
+
log list. `z-30` sits above the per-conversation sticky header
|
|
309
|
+
(`z-10`) but below modal-level overlays (dialogs, dropdowns,
|
|
310
|
+
tooltips — `z-50`). Background is fully opaque so logs don't bleed
|
|
311
|
+
through. */}
|
|
312
|
+
<div className="sticky top-0 z-30 bg-background pt-6">
|
|
313
|
+
{/* Brand row */}
|
|
314
|
+
<div className="grid grid-cols-[1fr_auto_1fr] items-start gap-3 pb-8">
|
|
315
|
+
<div />
|
|
316
|
+
<h1 className="flex min-w-0 flex-col items-center gap-2 text-center">
|
|
317
|
+
<span className="flex max-w-[calc(100vw-7rem)] items-end gap-2 whitespace-nowrap">
|
|
318
|
+
{/* Crab family — hover to animate together */}
|
|
319
|
+
<span
|
|
320
|
+
className="flex shrink-0 items-end gap-1 group cursor-default"
|
|
321
|
+
aria-hidden="true"
|
|
322
|
+
>
|
|
323
|
+
<CrabLogo className="size-10 text-amber-500 transition-all duration-300 group-hover:scale-125 group-hover:-translate-y-1.5" />
|
|
324
|
+
<span className="hidden items-end gap-0.5 sm:flex">
|
|
325
|
+
{crabVariants.map((Crab, i) => {
|
|
326
|
+
const color = [
|
|
327
|
+
"text-amber-500",
|
|
328
|
+
"text-rose-500",
|
|
329
|
+
"text-sky-500",
|
|
330
|
+
"text-emerald-500",
|
|
331
|
+
"text-violet-500",
|
|
332
|
+
"text-orange-500",
|
|
333
|
+
"text-cyan-500",
|
|
334
|
+
"text-pink-500",
|
|
335
|
+
"text-lime-500",
|
|
336
|
+
"text-blue-500",
|
|
337
|
+
"text-yellow-500",
|
|
338
|
+
"text-fuchsia-500",
|
|
339
|
+
][i];
|
|
340
|
+
const entranceClass =
|
|
341
|
+
crabEntrancePhase === "hidden"
|
|
342
|
+
? "opacity-0 scale-0"
|
|
343
|
+
: crabEntrancePhase === "playing"
|
|
344
|
+
? "animate-crab-piano-pop"
|
|
345
|
+
: "";
|
|
346
|
+
return (
|
|
347
|
+
<Crab
|
|
348
|
+
key={i}
|
|
349
|
+
className={`size-5 ${color} transition-all duration-300 ease-out group-hover:scale-125 group-hover:-translate-y-1 ${entranceClass}`}
|
|
350
|
+
style={{
|
|
351
|
+
transitionDelay: `${i * 50}ms`,
|
|
352
|
+
...(crabEntrancePhase === "playing"
|
|
353
|
+
? { animationDelay: `${i * 400}ms` }
|
|
354
|
+
: {}),
|
|
355
|
+
}}
|
|
356
|
+
/>
|
|
357
|
+
);
|
|
358
|
+
})}
|
|
359
|
+
</span>
|
|
349
360
|
</span>
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
361
|
+
<span className="flex min-w-0 items-baseline gap-2 pl-1">
|
|
362
|
+
<span className="truncate text-lg font-bold">LLM Inspector</span>
|
|
363
|
+
<span className="shrink-0 font-mono text-xs font-semibold text-muted-foreground">
|
|
364
|
+
v{packageJson.version}
|
|
365
|
+
</span>
|
|
355
366
|
</span>
|
|
367
|
+
<Plus className="size-4 shrink-0 text-muted-foreground/70" aria-hidden="true" />
|
|
368
|
+
<McpLogo className="size-10 shrink-0" />
|
|
356
369
|
</span>
|
|
357
|
-
<
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
<div className="justify-self-end">
|
|
363
|
-
<SettingsDialog />
|
|
370
|
+
<McpReadyBadge />
|
|
371
|
+
</h1>
|
|
372
|
+
<div className="justify-self-end">
|
|
373
|
+
<SettingsDialog />
|
|
374
|
+
</div>
|
|
364
375
|
</div>
|
|
365
|
-
</div>
|
|
366
376
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
377
|
+
{pinnedSessionId !== undefined && (
|
|
378
|
+
<SessionContextBar
|
|
379
|
+
sessionId={pinnedSessionId}
|
|
380
|
+
logs={logs}
|
|
381
|
+
totalIn={totalIn}
|
|
382
|
+
totalOut={totalOut}
|
|
383
|
+
/>
|
|
384
|
+
)}
|
|
375
385
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
386
|
+
{/* Controls + Filters */}
|
|
387
|
+
<div className="flex items-center gap-3 mb-4">
|
|
388
|
+
{!hideSessionFilter && (
|
|
389
|
+
<Select value={selectedSession} onValueChange={onSessionChange}>
|
|
390
|
+
<SelectTrigger className="flex-1 max-w-[350px] text-xs">
|
|
391
|
+
<SelectValue placeholder="All sessions" />
|
|
392
|
+
</SelectTrigger>
|
|
393
|
+
<SelectContent>
|
|
394
|
+
<SelectItem value="__all__">All sessions</SelectItem>
|
|
395
|
+
{sessions.map((s) => (
|
|
396
|
+
<SelectItem key={s} value={s}>
|
|
397
|
+
{truncateSessionId(s)}
|
|
398
|
+
</SelectItem>
|
|
399
|
+
))}
|
|
400
|
+
</SelectContent>
|
|
401
|
+
</Select>
|
|
402
|
+
)}
|
|
403
|
+
<Select value={selectedModel} onValueChange={onModelChange}>
|
|
404
|
+
<SelectTrigger className="flex-1 max-w-[250px] text-xs">
|
|
405
|
+
<SelectValue placeholder="All models" />
|
|
382
406
|
</SelectTrigger>
|
|
383
407
|
<SelectContent>
|
|
384
|
-
<SelectItem value="__all__">All
|
|
385
|
-
{
|
|
386
|
-
<SelectItem key={
|
|
387
|
-
{
|
|
408
|
+
<SelectItem value="__all__">All models</SelectItem>
|
|
409
|
+
{models.map((m) => (
|
|
410
|
+
<SelectItem key={m} value={m}>
|
|
411
|
+
{m}
|
|
388
412
|
</SelectItem>
|
|
389
413
|
))}
|
|
390
414
|
</SelectContent>
|
|
391
415
|
</Select>
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
>
|
|
416
|
-
|
|
417
|
-
|
|
416
|
+
<div className="flex items-center border border-border rounded-md overflow-hidden">
|
|
417
|
+
<button
|
|
418
|
+
type="button"
|
|
419
|
+
onClick={() => onViewModeChange("simple")}
|
|
420
|
+
className={`h-8 px-3 cursor-pointer transition-colors text-xs ${
|
|
421
|
+
viewMode === "simple"
|
|
422
|
+
? "bg-muted text-foreground"
|
|
423
|
+
: "text-muted-foreground hover:bg-muted/50"
|
|
424
|
+
}`}
|
|
425
|
+
>
|
|
426
|
+
Simple
|
|
427
|
+
</button>
|
|
428
|
+
<button
|
|
429
|
+
type="button"
|
|
430
|
+
onClick={() => onViewModeChange("full")}
|
|
431
|
+
className={`h-8 px-3 cursor-pointer transition-colors text-xs ${
|
|
432
|
+
viewMode === "full"
|
|
433
|
+
? "bg-muted text-foreground"
|
|
434
|
+
: "text-muted-foreground hover:bg-muted/50"
|
|
435
|
+
}`}
|
|
436
|
+
>
|
|
437
|
+
Full
|
|
438
|
+
</button>
|
|
439
|
+
</div>
|
|
440
|
+
<div className="flex-1" />
|
|
441
|
+
<span className="text-muted-foreground text-xs font-mono">
|
|
442
|
+
{logs.length} request{logs.length !== 1 ? "s" : ""}
|
|
443
|
+
{totalIn > 0 || totalOut > 0
|
|
444
|
+
? ` · ${formatTokens(totalIn)} in / ${formatTokens(totalOut)} out`
|
|
445
|
+
: ""}
|
|
446
|
+
</span>
|
|
447
|
+
{logs.length > 0 && (
|
|
448
|
+
<button
|
|
449
|
+
type="button"
|
|
450
|
+
onClick={() => {
|
|
451
|
+
void handleExport();
|
|
452
|
+
}}
|
|
453
|
+
disabled={exporting}
|
|
454
|
+
className="h-8 px-3 text-xs text-muted-foreground hover:text-foreground transition-colors cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed inline-flex items-center gap-1.5 rounded-md hover:bg-muted"
|
|
455
|
+
title="Export all logs as JSON ZIP"
|
|
456
|
+
>
|
|
457
|
+
{exporting ? (
|
|
458
|
+
<span>Exporting...</span>
|
|
459
|
+
) : (
|
|
460
|
+
<>
|
|
461
|
+
<Download className="size-3.5" />
|
|
462
|
+
<span>Export</span>
|
|
463
|
+
</>
|
|
464
|
+
)}
|
|
465
|
+
</button>
|
|
466
|
+
)}
|
|
418
467
|
<button
|
|
419
468
|
type="button"
|
|
420
|
-
onClick={
|
|
421
|
-
className=
|
|
422
|
-
|
|
423
|
-
? "bg-muted text-foreground"
|
|
424
|
-
: "text-muted-foreground hover:bg-muted/50"
|
|
425
|
-
}`}
|
|
469
|
+
onClick={onClearAll}
|
|
470
|
+
className="h-8 px-3 text-xs text-muted-foreground hover:text-foreground transition-colors cursor-pointer rounded-md hover:bg-muted"
|
|
471
|
+
title="Clear all logs"
|
|
426
472
|
>
|
|
427
|
-
|
|
473
|
+
Clear
|
|
428
474
|
</button>
|
|
429
475
|
</div>
|
|
430
|
-
<div className="flex-1" />
|
|
431
|
-
<span className="text-muted-foreground text-xs font-mono">
|
|
432
|
-
{logs.length} request{logs.length !== 1 ? "s" : ""}
|
|
433
|
-
{totalIn > 0 || totalOut > 0
|
|
434
|
-
? ` · ${formatTokens(totalIn)} in / ${formatTokens(totalOut)} out`
|
|
435
|
-
: ""}
|
|
436
|
-
</span>
|
|
437
|
-
{logs.length > 0 && (
|
|
438
|
-
<button
|
|
439
|
-
type="button"
|
|
440
|
-
onClick={() => {
|
|
441
|
-
void handleExport();
|
|
442
|
-
}}
|
|
443
|
-
disabled={exporting}
|
|
444
|
-
className="h-8 px-3 text-xs text-muted-foreground hover:text-foreground transition-colors cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed inline-flex items-center gap-1.5 rounded-md hover:bg-muted"
|
|
445
|
-
title="Export all logs as JSON ZIP"
|
|
446
|
-
>
|
|
447
|
-
{exporting ? (
|
|
448
|
-
<span>Exporting...</span>
|
|
449
|
-
) : (
|
|
450
|
-
<>
|
|
451
|
-
<Download className="size-3.5" />
|
|
452
|
-
<span>Export</span>
|
|
453
|
-
</>
|
|
454
|
-
)}
|
|
455
|
-
</button>
|
|
456
|
-
)}
|
|
457
|
-
<button
|
|
458
|
-
type="button"
|
|
459
|
-
onClick={onClearAll}
|
|
460
|
-
className="h-8 px-3 text-xs text-muted-foreground hover:text-foreground transition-colors cursor-pointer rounded-md hover:bg-muted"
|
|
461
|
-
title="Clear all logs"
|
|
462
|
-
>
|
|
463
|
-
Clear
|
|
464
|
-
</button>
|
|
465
476
|
</div>
|
|
466
477
|
|
|
467
478
|
{/* Log list */}
|