@tonyclaw/agent-inspector 3.0.14 → 3.0.15
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-DDfwHQUi.js → CompareDrawer-UaIxykqz.js} +1 -1
- package/.output/public/assets/ProxyViewerContainer-DlpfcX56.js +106 -0
- package/.output/public/assets/{ReplayDialog-D-26DMBt.js → ReplayDialog-BFFomU1m.js} +1 -1
- package/.output/public/assets/{RequestAnatomy-B6zNFqNX.js → RequestAnatomy-DKQJBt_c.js} +1 -1
- package/.output/public/assets/{ResponseView-Ccy95rWI.js → ResponseView-D7yotmne.js} +2 -2
- package/.output/public/assets/{StreamingChunkSequence-yIiscGuE.js → StreamingChunkSequence-Da-6WNFG.js} +1 -1
- package/.output/public/assets/{_sessionId-BnMB0zab.js → _sessionId-ByTXLS-w.js} +1 -1
- package/.output/public/assets/{index-BbtAIxbg.js → index-BrM8t5mc.js} +1 -1
- package/.output/public/assets/index-CGpPRty8.js +1 -0
- package/.output/public/assets/index-HRfrFVYw.css +1 -0
- package/.output/public/assets/{json-viewer-C838cVmD.js → json-viewer-DyjXQdVu.js} +1 -1
- package/.output/public/assets/{main-BfN4culo.js → main-Zv_gjZMb.js} +2 -2
- package/.output/server/_libs/lucide-react.mjs +215 -201
- package/.output/server/{_sessionId-DoprmwZV.mjs → _sessionId-GcFhWT0i.mjs} +2 -2
- package/.output/server/_ssr/{CompareDrawer-YMLJNxXR.mjs → CompareDrawer-BV7dw1TN.mjs} +3 -3
- package/.output/server/_ssr/{ProxyViewerContainer-C62eZnva.mjs → ProxyViewerContainer-CcgfvaS4.mjs} +725 -378
- package/.output/server/_ssr/{ReplayDialog-NmN7Ukjo.mjs → ReplayDialog-B7sBKxIO.mjs} +4 -4
- package/.output/server/_ssr/{RequestAnatomy-Dawm2qxe.mjs → RequestAnatomy-s_9Veje2.mjs} +3 -3
- package/.output/server/_ssr/{ResponseView-BHyAY83t.mjs → ResponseView-DsOFPCvF.mjs} +3 -3
- package/.output/server/_ssr/{StreamingChunkSequence-C4qgcJbg.mjs → StreamingChunkSequence-CyA1XtiF.mjs} +3 -3
- package/.output/server/_ssr/{index-B2Pf6W_T.mjs → index-CDDRt201.mjs} +2 -2
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{json-viewer-u67BASf8.mjs → json-viewer-BFV-xtRM.mjs} +3 -3
- package/.output/server/_ssr/{router-CZhFVMGN.mjs → router-B2Q7vHPM.mjs} +58 -14
- package/.output/server/{_tanstack-start-manifest_v-Dk2HfOoe.mjs → _tanstack-start-manifest_v-Dm_GmuRz.mjs} +1 -1
- package/.output/server/index.mjs +73 -73
- package/package.json +1 -1
- package/src/components/ProxyViewer.tsx +470 -197
- package/src/components/ProxyViewerContainer.tsx +145 -17
- package/src/components/proxy-viewer/ToolTraceEvents.tsx +36 -10
- package/src/components/proxy-viewer/TurnGroup.tsx +4 -1
- package/src/proxy/formats/openai/codexMetadata.ts +61 -0
- package/src/proxy/formats/openai/handler.ts +8 -2
- package/styles/globals.css +54 -0
- package/.output/public/assets/ProxyViewerContainer-CbNsaoQw.js +0 -106
- package/.output/public/assets/index-49RC4dlD.js +0 -1
- package/.output/public/assets/index-DXKupW0r.css +0 -1
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type ChangeEvent,
|
|
3
|
+
type CSSProperties,
|
|
3
4
|
type JSX,
|
|
5
|
+
type PointerEvent as ReactPointerEvent,
|
|
4
6
|
type ReactNode,
|
|
5
7
|
useCallback,
|
|
6
8
|
useEffect,
|
|
@@ -26,6 +28,8 @@ import {
|
|
|
26
28
|
FileJson,
|
|
27
29
|
Gauge,
|
|
28
30
|
Flag,
|
|
31
|
+
PanelRightClose,
|
|
32
|
+
PanelRightOpen,
|
|
29
33
|
Plus,
|
|
30
34
|
RefreshCw,
|
|
31
35
|
Search,
|
|
@@ -1381,6 +1385,291 @@ function BrandHeader({
|
|
|
1381
1385
|
);
|
|
1382
1386
|
}
|
|
1383
1387
|
|
|
1388
|
+
type FloatingLogoPosition = {
|
|
1389
|
+
x: number;
|
|
1390
|
+
y: number;
|
|
1391
|
+
};
|
|
1392
|
+
|
|
1393
|
+
type FloatingLogoDragState = {
|
|
1394
|
+
pointerId: number;
|
|
1395
|
+
offsetX: number;
|
|
1396
|
+
offsetY: number;
|
|
1397
|
+
};
|
|
1398
|
+
|
|
1399
|
+
type FloatingLogoEdge = "left" | "right" | "top" | "bottom";
|
|
1400
|
+
|
|
1401
|
+
const FLOATING_LOGO_SIZE = 56;
|
|
1402
|
+
const FLOATING_LOGO_MARGIN = 14;
|
|
1403
|
+
const FLOATING_LOGO_MIN_DRIFT_MS = 5200;
|
|
1404
|
+
const FLOATING_LOGO_DRIFT_WINDOW_MS = 2400;
|
|
1405
|
+
const FLOATING_LOGO_MIN_STEP = 72;
|
|
1406
|
+
const FLOATING_LOGO_MAX_STEP = 156;
|
|
1407
|
+
const DETAILS_PANEL_COLLAPSED_STORAGE_KEY = "agent-inspector.detailsPanelCollapsed";
|
|
1408
|
+
|
|
1409
|
+
function readStoredDetailsPanelCollapsed(): boolean {
|
|
1410
|
+
if (typeof window === "undefined") return true;
|
|
1411
|
+
const stored = window.localStorage.getItem(DETAILS_PANEL_COLLAPSED_STORAGE_KEY);
|
|
1412
|
+
return stored === null || stored === "1";
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
function clampFloatingLogoPosition(position: FloatingLogoPosition): FloatingLogoPosition {
|
|
1416
|
+
const maxX = Math.max(
|
|
1417
|
+
FLOATING_LOGO_MARGIN,
|
|
1418
|
+
window.innerWidth - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN,
|
|
1419
|
+
);
|
|
1420
|
+
const maxY = Math.max(
|
|
1421
|
+
FLOATING_LOGO_MARGIN,
|
|
1422
|
+
window.innerHeight - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN,
|
|
1423
|
+
);
|
|
1424
|
+
return {
|
|
1425
|
+
x: Math.min(Math.max(position.x, FLOATING_LOGO_MARGIN), maxX),
|
|
1426
|
+
y: Math.min(Math.max(position.y, FLOATING_LOGO_MARGIN), maxY),
|
|
1427
|
+
};
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1430
|
+
function snapFloatingLogoToEdge(position: FloatingLogoPosition): FloatingLogoPosition {
|
|
1431
|
+
const clamped = clampFloatingLogoPosition(position);
|
|
1432
|
+
const maxX = Math.max(
|
|
1433
|
+
FLOATING_LOGO_MARGIN,
|
|
1434
|
+
window.innerWidth - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN,
|
|
1435
|
+
);
|
|
1436
|
+
const maxY = Math.max(
|
|
1437
|
+
FLOATING_LOGO_MARGIN,
|
|
1438
|
+
window.innerHeight - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN,
|
|
1439
|
+
);
|
|
1440
|
+
const leftDistance = clamped.x - FLOATING_LOGO_MARGIN;
|
|
1441
|
+
const rightDistance = maxX - clamped.x;
|
|
1442
|
+
const topDistance = clamped.y - FLOATING_LOGO_MARGIN;
|
|
1443
|
+
const bottomDistance = maxY - clamped.y;
|
|
1444
|
+
const nearestDistance = Math.min(leftDistance, rightDistance, topDistance, bottomDistance);
|
|
1445
|
+
|
|
1446
|
+
if (nearestDistance === leftDistance) return { x: FLOATING_LOGO_MARGIN, y: clamped.y };
|
|
1447
|
+
if (nearestDistance === rightDistance) return { x: maxX, y: clamped.y };
|
|
1448
|
+
if (nearestDistance === topDistance) return { x: clamped.x, y: FLOATING_LOGO_MARGIN };
|
|
1449
|
+
return { x: clamped.x, y: maxY };
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
function randomFloatingLogoEdgePosition(): FloatingLogoPosition {
|
|
1453
|
+
const maxX = Math.max(
|
|
1454
|
+
FLOATING_LOGO_MARGIN,
|
|
1455
|
+
window.innerWidth - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN,
|
|
1456
|
+
);
|
|
1457
|
+
const maxY = Math.max(
|
|
1458
|
+
FLOATING_LOGO_MARGIN,
|
|
1459
|
+
window.innerHeight - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN,
|
|
1460
|
+
);
|
|
1461
|
+
const randomX = FLOATING_LOGO_MARGIN + Math.random() * (maxX - FLOATING_LOGO_MARGIN);
|
|
1462
|
+
const randomY = FLOATING_LOGO_MARGIN + Math.random() * (maxY - FLOATING_LOGO_MARGIN);
|
|
1463
|
+
const edgeIndex = Math.floor(Math.random() * 4);
|
|
1464
|
+
|
|
1465
|
+
switch (edgeIndex) {
|
|
1466
|
+
case 0:
|
|
1467
|
+
return { x: FLOATING_LOGO_MARGIN, y: randomY };
|
|
1468
|
+
case 1:
|
|
1469
|
+
return { x: maxX, y: randomY };
|
|
1470
|
+
case 2:
|
|
1471
|
+
return { x: randomX, y: FLOATING_LOGO_MARGIN };
|
|
1472
|
+
case 3:
|
|
1473
|
+
return { x: randomX, y: maxY };
|
|
1474
|
+
default:
|
|
1475
|
+
return { x: maxX, y: FLOATING_LOGO_MARGIN };
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
function nearestFloatingLogoEdge(position: FloatingLogoPosition): FloatingLogoEdge {
|
|
1480
|
+
const clamped = clampFloatingLogoPosition(position);
|
|
1481
|
+
const maxX = Math.max(
|
|
1482
|
+
FLOATING_LOGO_MARGIN,
|
|
1483
|
+
window.innerWidth - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN,
|
|
1484
|
+
);
|
|
1485
|
+
const maxY = Math.max(
|
|
1486
|
+
FLOATING_LOGO_MARGIN,
|
|
1487
|
+
window.innerHeight - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN,
|
|
1488
|
+
);
|
|
1489
|
+
const distances: { edge: FloatingLogoEdge; distance: number }[] = [
|
|
1490
|
+
{ edge: "left", distance: clamped.x - FLOATING_LOGO_MARGIN },
|
|
1491
|
+
{ edge: "right", distance: maxX - clamped.x },
|
|
1492
|
+
{ edge: "top", distance: clamped.y - FLOATING_LOGO_MARGIN },
|
|
1493
|
+
{ edge: "bottom", distance: maxY - clamped.y },
|
|
1494
|
+
];
|
|
1495
|
+
return distances.reduce((best, current) => (current.distance < best.distance ? current : best))
|
|
1496
|
+
.edge;
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
function nextFloatingLogoWalkingPosition(position: FloatingLogoPosition): FloatingLogoPosition {
|
|
1500
|
+
const clamped = snapFloatingLogoToEdge(position);
|
|
1501
|
+
const maxX = Math.max(
|
|
1502
|
+
FLOATING_LOGO_MARGIN,
|
|
1503
|
+
window.innerWidth - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN,
|
|
1504
|
+
);
|
|
1505
|
+
const maxY = Math.max(
|
|
1506
|
+
FLOATING_LOGO_MARGIN,
|
|
1507
|
+
window.innerHeight - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN,
|
|
1508
|
+
);
|
|
1509
|
+
const step =
|
|
1510
|
+
FLOATING_LOGO_MIN_STEP + Math.random() * (FLOATING_LOGO_MAX_STEP - FLOATING_LOGO_MIN_STEP);
|
|
1511
|
+
const direction = Math.random() > 0.5 ? 1 : -1;
|
|
1512
|
+
const edge = nearestFloatingLogoEdge(clamped);
|
|
1513
|
+
|
|
1514
|
+
switch (edge) {
|
|
1515
|
+
case "left": {
|
|
1516
|
+
const nextY = clamped.y + step * direction;
|
|
1517
|
+
if (nextY <= FLOATING_LOGO_MARGIN)
|
|
1518
|
+
return { x: FLOATING_LOGO_MARGIN, y: FLOATING_LOGO_MARGIN };
|
|
1519
|
+
if (nextY >= maxY) return { x: FLOATING_LOGO_MARGIN, y: maxY };
|
|
1520
|
+
return { x: FLOATING_LOGO_MARGIN, y: nextY };
|
|
1521
|
+
}
|
|
1522
|
+
case "right": {
|
|
1523
|
+
const nextY = clamped.y + step * direction;
|
|
1524
|
+
if (nextY <= FLOATING_LOGO_MARGIN) return { x: maxX, y: FLOATING_LOGO_MARGIN };
|
|
1525
|
+
if (nextY >= maxY) return { x: maxX, y: maxY };
|
|
1526
|
+
return { x: maxX, y: nextY };
|
|
1527
|
+
}
|
|
1528
|
+
case "top": {
|
|
1529
|
+
const nextX = clamped.x + step * direction;
|
|
1530
|
+
if (nextX <= FLOATING_LOGO_MARGIN)
|
|
1531
|
+
return { x: FLOATING_LOGO_MARGIN, y: FLOATING_LOGO_MARGIN };
|
|
1532
|
+
if (nextX >= maxX) return { x: maxX, y: FLOATING_LOGO_MARGIN };
|
|
1533
|
+
return { x: nextX, y: FLOATING_LOGO_MARGIN };
|
|
1534
|
+
}
|
|
1535
|
+
case "bottom": {
|
|
1536
|
+
const nextX = clamped.x + step * direction;
|
|
1537
|
+
if (nextX <= FLOATING_LOGO_MARGIN) return { x: FLOATING_LOGO_MARGIN, y: maxY };
|
|
1538
|
+
if (nextX >= maxX) return { x: maxX, y: maxY };
|
|
1539
|
+
return { x: nextX, y: maxY };
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
function FloatingInspectorLogo(): JSX.Element {
|
|
1545
|
+
const [position, setPosition] = useState<FloatingLogoPosition>({
|
|
1546
|
+
x: FLOATING_LOGO_MARGIN,
|
|
1547
|
+
y: FLOATING_LOGO_MARGIN,
|
|
1548
|
+
});
|
|
1549
|
+
const [motionTick, setMotionTick] = useState(0);
|
|
1550
|
+
const [dragging, setDragging] = useState(false);
|
|
1551
|
+
const dragStateRef = useRef<FloatingLogoDragState | null>(null);
|
|
1552
|
+
|
|
1553
|
+
useEffect(() => {
|
|
1554
|
+
setPosition(randomFloatingLogoEdgePosition());
|
|
1555
|
+
}, []);
|
|
1556
|
+
|
|
1557
|
+
useEffect(() => {
|
|
1558
|
+
if (dragging) return undefined;
|
|
1559
|
+
let timeoutId: number | null = null;
|
|
1560
|
+
|
|
1561
|
+
const scheduleDrift = () => {
|
|
1562
|
+
const delay = FLOATING_LOGO_MIN_DRIFT_MS + Math.random() * FLOATING_LOGO_DRIFT_WINDOW_MS;
|
|
1563
|
+
timeoutId = window.setTimeout(() => {
|
|
1564
|
+
setMotionTick((current) => current + 1);
|
|
1565
|
+
setPosition((current) => nextFloatingLogoWalkingPosition(current));
|
|
1566
|
+
scheduleDrift();
|
|
1567
|
+
}, delay);
|
|
1568
|
+
};
|
|
1569
|
+
|
|
1570
|
+
scheduleDrift();
|
|
1571
|
+
return () => {
|
|
1572
|
+
if (timeoutId !== null) {
|
|
1573
|
+
window.clearTimeout(timeoutId);
|
|
1574
|
+
}
|
|
1575
|
+
};
|
|
1576
|
+
}, [dragging]);
|
|
1577
|
+
|
|
1578
|
+
useEffect(() => {
|
|
1579
|
+
const handleResize = () => {
|
|
1580
|
+
setPosition((current) => snapFloatingLogoToEdge(current));
|
|
1581
|
+
};
|
|
1582
|
+
window.addEventListener("resize", handleResize);
|
|
1583
|
+
return () => window.removeEventListener("resize", handleResize);
|
|
1584
|
+
}, []);
|
|
1585
|
+
|
|
1586
|
+
const handlePointerDown = useCallback((event: ReactPointerEvent<HTMLButtonElement>) => {
|
|
1587
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
1588
|
+
dragStateRef.current = {
|
|
1589
|
+
pointerId: event.pointerId,
|
|
1590
|
+
offsetX: event.clientX - rect.left,
|
|
1591
|
+
offsetY: event.clientY - rect.top,
|
|
1592
|
+
};
|
|
1593
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
1594
|
+
setDragging(true);
|
|
1595
|
+
}, []);
|
|
1596
|
+
|
|
1597
|
+
const handlePointerMove = useCallback((event: ReactPointerEvent<HTMLButtonElement>) => {
|
|
1598
|
+
const dragState = dragStateRef.current;
|
|
1599
|
+
if (dragState === null || dragState.pointerId !== event.pointerId) return;
|
|
1600
|
+
setPosition(
|
|
1601
|
+
clampFloatingLogoPosition({
|
|
1602
|
+
x: event.clientX - dragState.offsetX,
|
|
1603
|
+
y: event.clientY - dragState.offsetY,
|
|
1604
|
+
}),
|
|
1605
|
+
);
|
|
1606
|
+
}, []);
|
|
1607
|
+
|
|
1608
|
+
const handlePointerUp = useCallback((event: ReactPointerEvent<HTMLButtonElement>) => {
|
|
1609
|
+
const dragState = dragStateRef.current;
|
|
1610
|
+
if (dragState === null || dragState.pointerId !== event.pointerId) return;
|
|
1611
|
+
if (event.currentTarget.hasPointerCapture(event.pointerId)) {
|
|
1612
|
+
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
1613
|
+
}
|
|
1614
|
+
dragStateRef.current = null;
|
|
1615
|
+
setDragging(false);
|
|
1616
|
+
setPosition((current) => snapFloatingLogoToEdge(current));
|
|
1617
|
+
}, []);
|
|
1618
|
+
|
|
1619
|
+
const style = useMemo<CSSProperties>(
|
|
1620
|
+
() => ({
|
|
1621
|
+
transform: `translate3d(${position.x}px, ${position.y}px, 0) rotate(${
|
|
1622
|
+
motionTick % 2 === 0 ? "-4deg" : "5deg"
|
|
1623
|
+
}) scale(${dragging ? "1.08" : "1"})`,
|
|
1624
|
+
transition: dragging ? "none" : "transform 4800ms cubic-bezier(0.33, 1, 0.68, 1)",
|
|
1625
|
+
touchAction: "none",
|
|
1626
|
+
}),
|
|
1627
|
+
[dragging, motionTick, position.x, position.y],
|
|
1628
|
+
);
|
|
1629
|
+
|
|
1630
|
+
return (
|
|
1631
|
+
<button
|
|
1632
|
+
type="button"
|
|
1633
|
+
className={cn(
|
|
1634
|
+
"fixed left-0 top-0 z-40 flex size-14 items-center justify-center rounded-full bg-transparent text-foreground outline-none transition-[filter,opacity] duration-200 hover:opacity-95 hover:drop-shadow-[0_0_24px_rgba(245,158,11,0.36)] focus-visible:ring-1 focus-visible:ring-amber-300/55",
|
|
1635
|
+
dragging ? "cursor-grabbing" : "cursor-grab",
|
|
1636
|
+
)}
|
|
1637
|
+
style={style}
|
|
1638
|
+
onPointerDown={handlePointerDown}
|
|
1639
|
+
onPointerMove={handlePointerMove}
|
|
1640
|
+
onPointerUp={handlePointerUp}
|
|
1641
|
+
onPointerCancel={handlePointerUp}
|
|
1642
|
+
aria-label="Floating Inspector logo"
|
|
1643
|
+
title="Drag Inspector logo"
|
|
1644
|
+
>
|
|
1645
|
+
<span
|
|
1646
|
+
className={cn(
|
|
1647
|
+
"relative flex size-12 items-center justify-center",
|
|
1648
|
+
!dragging && "floating-crab-body",
|
|
1649
|
+
)}
|
|
1650
|
+
aria-hidden="true"
|
|
1651
|
+
>
|
|
1652
|
+
<CrabLogo className="relative z-10 size-11 text-amber-500 drop-shadow-[0_0_15px_rgba(245,158,11,0.30)]" />
|
|
1653
|
+
<span className="pointer-events-none absolute inset-x-0 bottom-0 z-0 flex items-end justify-center gap-1 text-amber-400/80">
|
|
1654
|
+
{[0, 1, 2, 3, 4, 5].map((leg) => (
|
|
1655
|
+
<span
|
|
1656
|
+
key={leg}
|
|
1657
|
+
className={cn(
|
|
1658
|
+
"floating-crab-leg h-2 w-0.5 rounded-full bg-current shadow-[0_0_7px_rgba(245,158,11,0.24)]",
|
|
1659
|
+
leg < 3 ? "floating-crab-leg-left" : "floating-crab-leg-right",
|
|
1660
|
+
dragging && "animate-none",
|
|
1661
|
+
)}
|
|
1662
|
+
style={{
|
|
1663
|
+
animationDelay: `${leg % 2 === 0 ? 0 : 180}ms`,
|
|
1664
|
+
}}
|
|
1665
|
+
/>
|
|
1666
|
+
))}
|
|
1667
|
+
</span>
|
|
1668
|
+
</span>
|
|
1669
|
+
</button>
|
|
1670
|
+
);
|
|
1671
|
+
}
|
|
1672
|
+
|
|
1384
1673
|
function SessionContextLogButton({ label, logId }: { label: string; logId: number }): JSX.Element {
|
|
1385
1674
|
return (
|
|
1386
1675
|
<button
|
|
@@ -1697,8 +1986,8 @@ export type ProxyViewerProps = {
|
|
|
1697
1986
|
onSessionChange: (session: string) => void;
|
|
1698
1987
|
onModelChange: (model: string) => void;
|
|
1699
1988
|
onClearAll: () => void;
|
|
1700
|
-
/** Delete
|
|
1701
|
-
onDeleteCurrentView?: (
|
|
1989
|
+
/** Delete persisted storage for the selected session, or all storage from the all-sessions view. */
|
|
1990
|
+
onDeleteCurrentView?: () => Promise<void>;
|
|
1702
1991
|
/** Reload the selected/pinned session from stored logs without requiring a page refresh. */
|
|
1703
1992
|
onReloadSession?: () => void;
|
|
1704
1993
|
/** Clear only the logs whose ids are passed. Called by the per-group
|
|
@@ -1765,8 +2054,10 @@ export function ProxyViewer({
|
|
|
1765
2054
|
const [importStatus, setImportStatus] = useState<string | null>(null);
|
|
1766
2055
|
const [importError, setImportError] = useState<string | null>(null);
|
|
1767
2056
|
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
|
1768
|
-
const [deleteStoredData, setDeleteStoredData] = useState(false);
|
|
1769
2057
|
const [deletingCurrentView, setDeletingCurrentView] = useState(false);
|
|
2058
|
+
const [detailsPanelCollapsed, setDetailsPanelCollapsed] = useState(
|
|
2059
|
+
readStoredDetailsPanelCollapsed,
|
|
2060
|
+
);
|
|
1770
2061
|
const [comparePair, setComparePair] = useState<[CapturedLog, CapturedLog] | null>(null);
|
|
1771
2062
|
const [crabEntrancePhase, setCrabEntrancePhase] = useState<"hidden" | "playing" | "done">(
|
|
1772
2063
|
"hidden",
|
|
@@ -1807,6 +2098,13 @@ export function ProxyViewer({
|
|
|
1807
2098
|
};
|
|
1808
2099
|
}, []);
|
|
1809
2100
|
|
|
2101
|
+
useEffect(() => {
|
|
2102
|
+
window.localStorage.setItem(
|
|
2103
|
+
DETAILS_PANEL_COLLAPSED_STORAGE_KEY,
|
|
2104
|
+
detailsPanelCollapsed ? "1" : "0",
|
|
2105
|
+
);
|
|
2106
|
+
}, [detailsPanelCollapsed]);
|
|
2107
|
+
|
|
1810
2108
|
useEffect(() => {
|
|
1811
2109
|
if (pinnedSessionId === undefined) {
|
|
1812
2110
|
document.title = "Agent Inspector";
|
|
@@ -1898,7 +2196,6 @@ export function ProxyViewer({
|
|
|
1898
2196
|
}, [cancelTransientTasks, onClearAll]);
|
|
1899
2197
|
|
|
1900
2198
|
const handleRequestDeleteCurrentView = useCallback(() => {
|
|
1901
|
-
setDeleteStoredData(false);
|
|
1902
2199
|
setDeleteDialogOpen(true);
|
|
1903
2200
|
}, []);
|
|
1904
2201
|
|
|
@@ -1908,14 +2205,10 @@ export function ProxyViewer({
|
|
|
1908
2205
|
setImportError(null);
|
|
1909
2206
|
setComparePair(null);
|
|
1910
2207
|
|
|
1911
|
-
if (
|
|
1912
|
-
setDeleteDialogOpen(false);
|
|
1913
|
-
onClearAll();
|
|
1914
|
-
return;
|
|
1915
|
-
}
|
|
2208
|
+
if (onDeleteCurrentView === undefined) return;
|
|
1916
2209
|
|
|
1917
2210
|
setDeletingCurrentView(true);
|
|
1918
|
-
void onDeleteCurrentView(
|
|
2211
|
+
void onDeleteCurrentView()
|
|
1919
2212
|
.then(() => {
|
|
1920
2213
|
setDeleteDialogOpen(false);
|
|
1921
2214
|
})
|
|
@@ -1930,7 +2223,7 @@ export function ProxyViewer({
|
|
|
1930
2223
|
.finally(() => {
|
|
1931
2224
|
setDeletingCurrentView(false);
|
|
1932
2225
|
});
|
|
1933
|
-
}, [cancelTransientTasks,
|
|
2226
|
+
}, [cancelTransientTasks, onDeleteCurrentView, onNotify]);
|
|
1934
2227
|
|
|
1935
2228
|
const handleReloadCurrentSession = useCallback(() => {
|
|
1936
2229
|
if (onReloadSession === undefined) return;
|
|
@@ -1945,6 +2238,10 @@ export function ProxyViewer({
|
|
|
1945
2238
|
setComparePair(null);
|
|
1946
2239
|
}, []);
|
|
1947
2240
|
|
|
2241
|
+
const toggleDetailsPanelCollapsed = useCallback(() => {
|
|
2242
|
+
setDetailsPanelCollapsed((value) => !value);
|
|
2243
|
+
}, []);
|
|
2244
|
+
|
|
1948
2245
|
const groups = useMemo(() => groupLogsByConversation(logs), [logs]);
|
|
1949
2246
|
const displayNumberByLogId = useMemo(() => buildDisplayNumberByLogId(groups), [groups]);
|
|
1950
2247
|
const sessionContextScope = useMemo(
|
|
@@ -1966,6 +2263,13 @@ export function ProxyViewer({
|
|
|
1966
2263
|
const exportActionVisibility = getExportActionVisibility(captureMode, logs.length);
|
|
1967
2264
|
const isPinnedSessionPage = pinnedSessionId !== undefined;
|
|
1968
2265
|
const canClearCurrentView = logs.length > 0;
|
|
2266
|
+
const canDeleteCurrentView =
|
|
2267
|
+
onDeleteCurrentView !== undefined && (logs.length > 0 || selectedSession !== "__all__");
|
|
2268
|
+
const deleteTargetLabel = selectedSession === "__all__" ? "all sessions" : "this session";
|
|
2269
|
+
const deleteTargetDescription =
|
|
2270
|
+
selectedSession === "__all__"
|
|
2271
|
+
? "Deletes every stored log, streaming chunk, and session archive entry across all sessions."
|
|
2272
|
+
: "Deletes every stored log, streaming chunk, and session archive entry for this session, including history that is not currently loaded.";
|
|
1969
2273
|
const reloadSessionLabel = logs.length === 0 ? "Load" : "Reload";
|
|
1970
2274
|
const sessionInputValue = selectedSession === "__all__" ? "" : selectedSession;
|
|
1971
2275
|
const sessionSelectValue =
|
|
@@ -2019,173 +2323,159 @@ export function ProxyViewer({
|
|
|
2019
2323
|
|
|
2020
2324
|
return (
|
|
2021
2325
|
<div className="bg-background min-h-screen w-full text-foreground">
|
|
2022
|
-
<
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2326
|
+
<button
|
|
2327
|
+
type="button"
|
|
2328
|
+
onClick={toggleDetailsPanelCollapsed}
|
|
2329
|
+
className={cn(
|
|
2330
|
+
"group fixed top-1/2 right-3 z-40 inline-flex h-14 w-7 -translate-y-1/2 items-center justify-center rounded-l-md border border-white/[0.08] bg-background/90 text-muted-foreground shadow-[0_12px_34px_rgba(0,0,0,0.26),inset_0_1px_0_rgba(255,255,255,0.06)] backdrop-blur transition-[right,background-color,color,border-color] duration-200 hover:border-white/[0.16] hover:bg-white/[0.07] hover:text-foreground focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none",
|
|
2331
|
+
detailsPanelCollapsed ? "right-3" : "lg:right-[326px] xl:right-[346px]",
|
|
2332
|
+
)}
|
|
2333
|
+
aria-label={detailsPanelCollapsed ? "Show details panel" : "Hide details panel"}
|
|
2334
|
+
title={detailsPanelCollapsed ? "Show details panel" : "Hide details panel"}
|
|
2335
|
+
>
|
|
2336
|
+
<span className="absolute left-1 top-2 bottom-2 w-px rounded-full bg-white/[0.16] transition-colors group-hover:bg-white/[0.28]" />
|
|
2337
|
+
{detailsPanelCollapsed ? (
|
|
2338
|
+
<PanelRightOpen className="size-3.5" />
|
|
2339
|
+
) : (
|
|
2340
|
+
<PanelRightClose className="size-3.5" />
|
|
2341
|
+
)}
|
|
2342
|
+
</button>
|
|
2343
|
+
{detailsPanelCollapsed && <FloatingInspectorLogo />}
|
|
2344
|
+
<div
|
|
2345
|
+
className={cn(
|
|
2346
|
+
"grid min-h-screen w-full grid-cols-1",
|
|
2347
|
+
detailsPanelCollapsed
|
|
2348
|
+
? "lg:grid-cols-[minmax(0,1fr)]"
|
|
2349
|
+
: "lg:grid-cols-[minmax(0,1fr)_340px] xl:grid-cols-[minmax(0,1fr)_360px]",
|
|
2350
|
+
)}
|
|
2351
|
+
>
|
|
2352
|
+
{!detailsPanelCollapsed && (
|
|
2353
|
+
<aside className="bg-background/95 order-1 border-b border-white/[0.045] lg:sticky lg:top-0 lg:order-2 lg:h-screen lg:overflow-y-auto lg:border-b-0 lg:border-l lg:border-white/[0.055]">
|
|
2354
|
+
<div className="space-y-4 p-4">
|
|
2355
|
+
<BrandHeader
|
|
2356
|
+
compact={true}
|
|
2357
|
+
crabEntrancePhase={crabEntrancePhase}
|
|
2358
|
+
currentSessionId={labSessionId}
|
|
2359
|
+
logCount={logs.length}
|
|
2360
|
+
/>
|
|
2031
2361
|
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
onClick={handleReloadCurrentSession}
|
|
2050
|
-
disabled={isLoading}
|
|
2051
|
-
className="bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 min-w-0 items-center justify-center gap-1.5 rounded-md px-2 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50"
|
|
2052
|
-
title="Load stored logs for this session"
|
|
2053
|
-
>
|
|
2054
|
-
<RefreshCw className={cn("size-3.5", isLoading && "animate-spin")} />
|
|
2055
|
-
<span>{reloadSessionLabel}</span>
|
|
2056
|
-
</button>
|
|
2362
|
+
<SidebarPanel label="Session">
|
|
2363
|
+
<div className="grid grid-cols-2 gap-2">
|
|
2364
|
+
<SidebarMetric label="Requests" value={logs.length} />
|
|
2365
|
+
<SidebarMetric label="Sessions" value={sessions.length} />
|
|
2366
|
+
<SidebarMetric
|
|
2367
|
+
label="Input"
|
|
2368
|
+
value={formatTokens(hasSessionContext ? sessionContextTotalIn : totalIn)}
|
|
2369
|
+
/>
|
|
2370
|
+
<SidebarMetric
|
|
2371
|
+
label="Output"
|
|
2372
|
+
value={formatTokens(hasSessionContext ? sessionContextTotalOut : totalOut)}
|
|
2373
|
+
/>
|
|
2374
|
+
</div>
|
|
2375
|
+
{sessionLoadProgress !== undefined && (
|
|
2376
|
+
<div className="mt-2 rounded-md bg-black/20 px-2 py-2 shadow-[inset_0_0_0_1px_rgba(255,255,255,0.045)]">
|
|
2377
|
+
<SessionLoadProgressBar progress={sessionLoadProgress} />
|
|
2378
|
+
</div>
|
|
2057
2379
|
)}
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
"
|
|
2064
|
-
|
|
2065
|
-
onDeleteCurrentView === undefined &&
|
|
2066
|
-
"col-span-2",
|
|
2067
|
-
)}
|
|
2068
|
-
title="Clear the current view. Stored logs remain reloadable."
|
|
2069
|
-
>
|
|
2070
|
-
<Trash2 className="size-3.5" />
|
|
2071
|
-
<span>Clear</span>
|
|
2072
|
-
</button>
|
|
2073
|
-
{onDeleteCurrentView !== undefined && (
|
|
2074
|
-
<button
|
|
2075
|
-
type="button"
|
|
2076
|
-
onClick={handleRequestDeleteCurrentView}
|
|
2077
|
-
disabled={!canClearCurrentView || deletingCurrentView}
|
|
2078
|
-
className="bg-red-500/[0.07] hover:bg-red-500/[0.12] inline-flex h-8 min-w-0 items-center justify-center gap-1.5 rounded-md px-2 text-xs text-red-200 shadow-[inset_0_0_0_1px_rgba(248,113,113,0.14)] transition-colors hover:text-red-100 disabled:cursor-not-allowed disabled:opacity-50"
|
|
2079
|
-
title="Choose whether to delete stored data for the current view."
|
|
2380
|
+
</SidebarPanel>
|
|
2381
|
+
|
|
2382
|
+
<SidebarPanel label="Workspace">
|
|
2383
|
+
<div className="bg-black/20 rounded-md px-3 py-2 shadow-[inset_0_1px_0_rgba(255,255,255,0.035)]">
|
|
2384
|
+
<div
|
|
2385
|
+
className="truncate font-mono text-xs font-semibold text-cyan-100"
|
|
2386
|
+
title={activeScopeLabel}
|
|
2080
2387
|
>
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
{sessionLoadProgress !== undefined && (
|
|
2087
|
-
<div className="mt-2 rounded-md bg-black/20 px-2 py-2 shadow-[inset_0_0_0_1px_rgba(255,255,255,0.045)]">
|
|
2088
|
-
<SessionLoadProgressBar progress={sessionLoadProgress} />
|
|
2388
|
+
{activeScopeLabel}
|
|
2389
|
+
</div>
|
|
2390
|
+
<div className="mt-1 text-[11px] text-muted-foreground">
|
|
2391
|
+
{isPinnedSessionPage ? "Session workspace" : "Live workspace"}
|
|
2392
|
+
</div>
|
|
2089
2393
|
</div>
|
|
2394
|
+
</SidebarPanel>
|
|
2395
|
+
|
|
2396
|
+
{hasSessionContext && sessionContextScope !== null && (
|
|
2397
|
+
<SessionContextBar
|
|
2398
|
+
label={sessionContextScope.label}
|
|
2399
|
+
logs={sessionContextLogs}
|
|
2400
|
+
totalIn={sessionContextTotalIn}
|
|
2401
|
+
totalOut={sessionContextTotalOut}
|
|
2402
|
+
timeDisplayFormat={timeDisplayFormat}
|
|
2403
|
+
contextSummary={sessionContextSummary}
|
|
2404
|
+
showBackLink={sessionContextScope.showBackLink}
|
|
2405
|
+
/>
|
|
2090
2406
|
)}
|
|
2091
|
-
</SidebarPanel>
|
|
2092
2407
|
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
>
|
|
2099
|
-
{activeScopeLabel}
|
|
2100
|
-
</div>
|
|
2101
|
-
<div className="mt-1 text-[11px] text-muted-foreground">
|
|
2102
|
-
{isPinnedSessionPage ? "Session workspace" : "Live workspace"}
|
|
2103
|
-
</div>
|
|
2104
|
-
</div>
|
|
2105
|
-
</SidebarPanel>
|
|
2106
|
-
|
|
2107
|
-
{hasSessionContext && sessionContextScope !== null && (
|
|
2108
|
-
<SessionContextBar
|
|
2109
|
-
label={sessionContextScope.label}
|
|
2110
|
-
logs={sessionContextLogs}
|
|
2111
|
-
totalIn={sessionContextTotalIn}
|
|
2112
|
-
totalOut={sessionContextTotalOut}
|
|
2113
|
-
timeDisplayFormat={timeDisplayFormat}
|
|
2114
|
-
contextSummary={sessionContextSummary}
|
|
2115
|
-
showBackLink={sessionContextScope.showBackLink}
|
|
2116
|
-
/>
|
|
2117
|
-
)}
|
|
2118
|
-
|
|
2119
|
-
{hasSessionContext &&
|
|
2120
|
-
pinnedSessionId !== undefined &&
|
|
2121
|
-
sessionMemberships.length > 0 && (
|
|
2122
|
-
<SessionMembershipPanel memberships={sessionMemberships} />
|
|
2123
|
-
)}
|
|
2408
|
+
{hasSessionContext &&
|
|
2409
|
+
pinnedSessionId !== undefined &&
|
|
2410
|
+
sessionMemberships.length > 0 && (
|
|
2411
|
+
<SessionMembershipPanel memberships={sessionMemberships} />
|
|
2412
|
+
)}
|
|
2124
2413
|
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
)}
|
|
2151
|
-
</div>
|
|
2152
|
-
<Select value={sessionSelectValue} onValueChange={handleSessionSelectChange}>
|
|
2153
|
-
<SelectTrigger className="bg-black/25 hover:bg-white/[0.045] h-9 w-full border-0 text-xs text-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)]">
|
|
2154
|
-
<SelectValue placeholder="All sessions" />
|
|
2155
|
-
</SelectTrigger>
|
|
2156
|
-
<SelectContent>
|
|
2157
|
-
<SelectItem value="__all__">All sessions</SelectItem>
|
|
2158
|
-
{sessionSelectValue === "__typed__" && (
|
|
2159
|
-
<SelectItem value="__typed__">
|
|
2160
|
-
Typed: {truncateSessionId(selectedSession)}
|
|
2161
|
-
</SelectItem>
|
|
2414
|
+
<SidebarPanel label="Filters">
|
|
2415
|
+
<div className="space-y-2">
|
|
2416
|
+
{!hideSessionFilter && (
|
|
2417
|
+
<>
|
|
2418
|
+
<div className="relative">
|
|
2419
|
+
<Search className="pointer-events-none absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground" />
|
|
2420
|
+
<input
|
|
2421
|
+
type="search"
|
|
2422
|
+
value={sessionInputValue}
|
|
2423
|
+
onChange={handleSessionInputChange}
|
|
2424
|
+
placeholder="Paste session ID"
|
|
2425
|
+
className="bg-black/25 hover:bg-white/[0.045] focus-visible:ring-ring h-9 w-full rounded-md px-8 font-mono text-xs text-foreground outline-none shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors placeholder:font-sans placeholder:text-muted-foreground focus-visible:ring-1"
|
|
2426
|
+
aria-label="Filter by session ID"
|
|
2427
|
+
title="Filter by exact session ID"
|
|
2428
|
+
/>
|
|
2429
|
+
{sessionInputValue !== "" && (
|
|
2430
|
+
<button
|
|
2431
|
+
type="button"
|
|
2432
|
+
onClick={() => onSessionChange("__all__")}
|
|
2433
|
+
className="absolute right-1.5 top-1/2 inline-flex size-6 -translate-y-1/2 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-white/[0.06] hover:text-foreground"
|
|
2434
|
+
aria-label="Clear session filter"
|
|
2435
|
+
title="Clear session filter"
|
|
2436
|
+
>
|
|
2437
|
+
<X className="size-3.5" />
|
|
2438
|
+
</button>
|
|
2162
2439
|
)}
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
</
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2440
|
+
</div>
|
|
2441
|
+
<Select value={sessionSelectValue} onValueChange={handleSessionSelectChange}>
|
|
2442
|
+
<SelectTrigger className="bg-black/25 hover:bg-white/[0.045] h-9 w-full border-0 text-xs text-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)]">
|
|
2443
|
+
<SelectValue placeholder="All sessions" />
|
|
2444
|
+
</SelectTrigger>
|
|
2445
|
+
<SelectContent>
|
|
2446
|
+
<SelectItem value="__all__">All sessions</SelectItem>
|
|
2447
|
+
{sessionSelectValue === "__typed__" && (
|
|
2448
|
+
<SelectItem value="__typed__">
|
|
2449
|
+
Typed: {truncateSessionId(selectedSession)}
|
|
2450
|
+
</SelectItem>
|
|
2451
|
+
)}
|
|
2452
|
+
{sessions.map((s) => (
|
|
2453
|
+
<SelectItem key={s} value={s}>
|
|
2454
|
+
{truncateSessionId(s)}
|
|
2455
|
+
</SelectItem>
|
|
2456
|
+
))}
|
|
2457
|
+
</SelectContent>
|
|
2458
|
+
</Select>
|
|
2459
|
+
</>
|
|
2460
|
+
)}
|
|
2461
|
+
<Select value={selectedModel} onValueChange={onModelChange}>
|
|
2462
|
+
<SelectTrigger className="bg-black/25 hover:bg-white/[0.045] h-9 w-full border-0 text-xs text-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)]">
|
|
2463
|
+
<SelectValue placeholder="All models" />
|
|
2464
|
+
</SelectTrigger>
|
|
2465
|
+
<SelectContent>
|
|
2466
|
+
<SelectItem value="__all__">All models</SelectItem>
|
|
2467
|
+
{models.map((m) => (
|
|
2468
|
+
<SelectItem key={m} value={m}>
|
|
2469
|
+
{m}
|
|
2470
|
+
</SelectItem>
|
|
2471
|
+
))}
|
|
2472
|
+
</SelectContent>
|
|
2473
|
+
</Select>
|
|
2474
|
+
</div>
|
|
2475
|
+
</SidebarPanel>
|
|
2476
|
+
</div>
|
|
2477
|
+
</aside>
|
|
2478
|
+
)}
|
|
2189
2479
|
|
|
2190
2480
|
<main className="order-2 min-w-0 lg:order-1">
|
|
2191
2481
|
<div className="bg-background/95 shadow-[0_12px_36px_rgba(0,0,0,0.18),inset_0_-1px_0_rgba(255,255,255,0.045)] sticky top-0 z-30 px-4 py-3 lg:px-5">
|
|
@@ -2289,9 +2579,9 @@ export function ProxyViewer({
|
|
|
2289
2579
|
<button
|
|
2290
2580
|
type="button"
|
|
2291
2581
|
onClick={handleRequestDeleteCurrentView}
|
|
2292
|
-
disabled={!
|
|
2582
|
+
disabled={!canDeleteCurrentView || deletingCurrentView}
|
|
2293
2583
|
className="bg-red-500/[0.07] hover:bg-red-500/[0.12] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-red-200 shadow-[inset_0_0_0_1px_rgba(248,113,113,0.14)] transition-colors hover:text-red-100 disabled:cursor-not-allowed disabled:opacity-50"
|
|
2294
|
-
title="
|
|
2584
|
+
title="Delete persisted history for the selected session."
|
|
2295
2585
|
>
|
|
2296
2586
|
<Trash2 className="size-3.5" />
|
|
2297
2587
|
<span>Delete</span>
|
|
@@ -2431,28 +2721,15 @@ export function ProxyViewer({
|
|
|
2431
2721
|
<Dialog open={deleteDialogOpen} onOpenChange={setDeleteDialogOpen}>
|
|
2432
2722
|
<DialogContent className="border-red-500/20 bg-zinc-950 text-zinc-100 sm:max-w-md">
|
|
2433
2723
|
<DialogHeader>
|
|
2434
|
-
<DialogTitle>Delete
|
|
2724
|
+
<DialogTitle>Delete {deleteTargetLabel} history?</DialogTitle>
|
|
2435
2725
|
<DialogDescription>
|
|
2436
|
-
|
|
2437
|
-
current view.
|
|
2726
|
+
Clear only hides logs from the UI. Delete removes stored history from disk.
|
|
2438
2727
|
</DialogDescription>
|
|
2439
2728
|
</DialogHeader>
|
|
2440
|
-
<
|
|
2441
|
-
<
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
checked={deleteStoredData}
|
|
2445
|
-
disabled={deletingCurrentView}
|
|
2446
|
-
onChange={(event) => setDeleteStoredData(event.currentTarget.checked)}
|
|
2447
|
-
/>
|
|
2448
|
-
<span className="min-w-0">
|
|
2449
|
-
<span className="block font-medium">Also delete stored data</span>
|
|
2450
|
-
<span className="mt-1 block text-xs text-red-200/80">
|
|
2451
|
-
Removes persisted log rows, streaming chunks, and session archive entries for these{" "}
|
|
2452
|
-
{logs.length.toString()} visible request{logs.length === 1 ? "" : "s"}.
|
|
2453
|
-
</span>
|
|
2454
|
-
</span>
|
|
2455
|
-
</label>
|
|
2729
|
+
<div className="rounded-md bg-red-500/[0.08] px-3 py-3 text-sm text-red-100 shadow-[inset_0_0_0_1px_rgba(248,113,113,0.16)]">
|
|
2730
|
+
<span className="block font-medium">This is a full history delete.</span>
|
|
2731
|
+
<span className="mt-1 block text-xs text-red-200/80">{deleteTargetDescription}</span>
|
|
2732
|
+
</div>
|
|
2456
2733
|
<div className="flex justify-end gap-2">
|
|
2457
2734
|
<Button
|
|
2458
2735
|
type="button"
|
|
@@ -2465,16 +2742,12 @@ export function ProxyViewer({
|
|
|
2465
2742
|
</Button>
|
|
2466
2743
|
<Button
|
|
2467
2744
|
type="button"
|
|
2468
|
-
variant=
|
|
2745
|
+
variant="destructive"
|
|
2469
2746
|
size="sm"
|
|
2470
2747
|
disabled={deletingCurrentView}
|
|
2471
2748
|
onClick={handleConfirmDeleteCurrentView}
|
|
2472
2749
|
>
|
|
2473
|
-
{deletingCurrentView
|
|
2474
|
-
? "Deleting..."
|
|
2475
|
-
: deleteStoredData
|
|
2476
|
-
? "Delete data"
|
|
2477
|
-
: "Clear only"}
|
|
2750
|
+
{deletingCurrentView ? "Deleting..." : "Delete history"}
|
|
2478
2751
|
</Button>
|
|
2479
2752
|
</div>
|
|
2480
2753
|
</DialogContent>
|