@tonyclaw/agent-inspector 3.0.42 → 3.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.
- package/.output/nitro.json +1 -1
- package/.output/public/assets/{CompareDrawer-7Gr3T28l.js → CompareDrawer-BAXxwTwT.js} +1 -1
- package/.output/public/assets/{InspectorPet-BYY_Sa_k.js → InspectorPet-xYuGV4Qz.js} +167 -167
- package/.output/public/assets/ProxyViewerContainer-B6GZnUWi.js +126 -0
- package/.output/public/assets/{ReplayDialog-By1tvcuO.js → ReplayDialog-D73pyIg3.js} +1 -1
- package/.output/public/assets/{RequestAnatomy-AbVJG4VA.js → RequestAnatomy-CSDta_nu.js} +1 -1
- package/.output/public/assets/{ResponseView-BqfnTwq-.js → ResponseView-C4aIUPby.js} +1 -1
- package/.output/public/assets/{StreamingChunkSequence-BK_GhL1n.js → StreamingChunkSequence-D4xxosLx.js} +1 -1
- package/.output/public/assets/{_sessionId-BsoVln_N.js → _sessionId-CZHbJyWO.js} +1 -1
- package/.output/public/assets/{_sessionId-BEVn_RD0.js → _sessionId-DvuNLzSE.js} +1 -1
- package/.output/public/assets/{index-BmKouSES.js → index-B17u7JMC.js} +16 -22
- package/.output/public/assets/index-BWjeqxbk.css +1 -0
- package/.output/public/assets/{index-DPsfwdop.js → index-C0g79BAs.js} +1 -1
- package/.output/public/assets/{index-DavUo6mY.js → index-CmEO8ykj.js} +1 -1
- package/.output/public/assets/{index-D1Ar_Dtb.js → index-DZ_wpqQM.js} +1 -1
- package/.output/public/assets/{json-viewer-vkLlnvyf.js → json-viewer-CuWU-H6K.js} +1 -1
- package/.output/public/assets/{jszip.min-CMLonFfU.js → jszip.min-DPJI_UKW.js} +1 -1
- package/.output/server/{_sessionId-DYkPEoJd.mjs → _sessionId-CoFyeOti.mjs} +2 -2
- package/.output/server/{_sessionId-BH52f7aR.mjs → _sessionId-Cun21KZF.mjs} +1 -1
- package/.output/server/_ssr/{CompareDrawer-Bt3LIoPy.mjs → CompareDrawer-Bgc2TZh_.mjs} +2 -2
- package/.output/server/_ssr/{InspectorPet-CikVNW8S.mjs → InspectorPet-DyK2ojeh.mjs} +20 -10
- package/.output/server/_ssr/{ProxyViewerContainer-BS6MZd0t.mjs → ProxyViewerContainer-hvn6oVWD.mjs} +326 -235
- package/.output/server/_ssr/{ReplayDialog-DxFLoYlZ.mjs → ReplayDialog-KpnrGtZ-.mjs} +3 -3
- package/.output/server/_ssr/{RequestAnatomy-CbLJjhKb.mjs → RequestAnatomy-uCsfucn8.mjs} +2 -2
- package/.output/server/_ssr/{ResponseView-Bs1sYg_8.mjs → ResponseView-C8UPqoPO.mjs} +2 -2
- package/.output/server/_ssr/{StreamingChunkSequence-D0dBru3U.mjs → StreamingChunkSequence-BP28I9sh.mjs} +2 -2
- package/.output/server/_ssr/{index-DIHmtfFU.mjs → index-BVwVoQlZ.mjs} +1 -1
- package/.output/server/_ssr/{index-hK95DE4-.mjs → index-Du3YNDKx.mjs} +2 -2
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{json-viewer-BfRCUg1t.mjs → json-viewer-DrE0vtlB.mjs} +2 -2
- package/.output/server/_ssr/{router-NjASMtmk.mjs → router-C6nWUZHK.mjs} +18 -24
- package/.output/server/{_tanstack-start-manifest_v-BNqjyvHx.mjs → _tanstack-start-manifest_v-rshlRaiN.mjs} +1 -1
- package/.output/server/index.mjs +98 -98
- package/package.json +5 -1
- package/scripts/generate-theme-scales.mjs +22 -0
- package/src/components/ProxyViewer.tsx +217 -103
- package/src/components/alerts/AlertsDialog.tsx +17 -17
- package/src/components/ecosystem/AgentLabDialog.tsx +11 -4
- package/src/components/groups/GroupsDialog.tsx +41 -26
- package/src/components/inspector-pet/InspectorPet.tsx +9 -9
- package/src/components/inspector-pet/inspectorPetLogic.ts +15 -1
- package/src/components/pi-agent/PiAgentPanel.tsx +12 -35
- package/src/components/pi-agent/piAgentChatLogic.ts +0 -24
- package/src/components/providers/ImportWizardDialog.tsx +1 -1
- package/src/components/providers/ProviderCard.tsx +4 -4
- package/src/components/providers/ProviderForm.tsx +11 -7
- package/src/components/providers/ProviderTestResultsView.tsx +15 -17
- package/src/components/providers/ProvidersPanel.tsx +1 -1
- package/src/components/providers/SettingsDialog.tsx +11 -7
- package/src/components/proxy-viewer/LogEntryHeader.tsx +2 -2
- package/src/components/proxy-viewer/TurnGroup.tsx +1 -1
- package/src/components/ui/icon-trigger.ts +1 -1
- package/src/lib/themeMode.ts +1 -5
- package/src/lib/uiScale.ts +8 -3
- package/src/routes/__root.tsx +5 -10
- package/styles/globals.css +35 -143
- package/styles/theme-scales.css +50 -0
- package/styles/themes.css +157 -0
- package/.output/public/assets/ProxyViewerContainer-CCtygisW.js +0 -126
- package/.output/public/assets/index-DKwrwHsI.css +0 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type ChangeEvent,
|
|
3
3
|
type JSX,
|
|
4
|
+
type PointerEvent as ReactPointerEvent,
|
|
4
5
|
type ReactNode,
|
|
5
6
|
useCallback,
|
|
6
7
|
useEffect,
|
|
@@ -189,16 +190,29 @@ function formatTimeRange(logs: CapturedLog[], timeDisplayFormat: TimeDisplayForm
|
|
|
189
190
|
function slateMetricToneClass(tone: SessionSlateMetricTone): string {
|
|
190
191
|
switch (tone) {
|
|
191
192
|
case "cool":
|
|
192
|
-
return "text-
|
|
193
|
+
return "text-status-cool";
|
|
193
194
|
case "danger":
|
|
194
|
-
return "text-
|
|
195
|
+
return "text-status-danger";
|
|
195
196
|
case "watch":
|
|
196
|
-
return "text-
|
|
197
|
+
return "text-status-watch";
|
|
197
198
|
case "neutral":
|
|
198
199
|
return "text-foreground";
|
|
199
200
|
}
|
|
200
201
|
}
|
|
201
202
|
|
|
203
|
+
function statusMetricIcon(status: SessionSlateStatus): ReactNode {
|
|
204
|
+
switch (status) {
|
|
205
|
+
case "rolling":
|
|
206
|
+
return <RefreshCw className="size-3 text-status-cool" />;
|
|
207
|
+
case "failed":
|
|
208
|
+
return <Siren className="size-3 text-status-danger" />;
|
|
209
|
+
case "watch":
|
|
210
|
+
return <Timer className="size-3 text-status-watch" />;
|
|
211
|
+
case "clear":
|
|
212
|
+
return <Check className="size-3 text-status-success" />;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
202
216
|
function statusMetricTone(status: SessionSlateStatus): SessionSlateMetricTone {
|
|
203
217
|
switch (status) {
|
|
204
218
|
case "rolling":
|
|
@@ -232,7 +246,7 @@ function SessionSlateMetric({
|
|
|
232
246
|
tone?: SessionSlateMetricTone;
|
|
233
247
|
}): JSX.Element {
|
|
234
248
|
return (
|
|
235
|
-
<div className="min-w-0 border-t border-
|
|
249
|
+
<div className="min-w-0 border-t border-border/60 px-4 py-3">
|
|
236
250
|
<div className="flex items-center gap-1 text-[10px] uppercase text-muted-foreground">
|
|
237
251
|
{icon}
|
|
238
252
|
{label}
|
|
@@ -249,7 +263,7 @@ function SessionOpeningSlate({ stats }: { stats: SessionSlateStats }): JSX.Eleme
|
|
|
249
263
|
if (stats.requests === 0) return null;
|
|
250
264
|
|
|
251
265
|
return (
|
|
252
|
-
<div className="
|
|
266
|
+
<div className="mb-4 overflow-hidden rounded-[8px] border border-border bg-card">
|
|
253
267
|
<div className="px-4 py-3">
|
|
254
268
|
<div className="flex flex-wrap items-end justify-between gap-3">
|
|
255
269
|
<div className="min-w-0">
|
|
@@ -267,11 +281,12 @@ function SessionOpeningSlate({ stats }: { stats: SessionSlateStats }): JSX.Eleme
|
|
|
267
281
|
</div>
|
|
268
282
|
</div>
|
|
269
283
|
</div>
|
|
270
|
-
<div className="grid grid-cols-2 border-t border-
|
|
284
|
+
<div className="grid grid-cols-2 border-t border-border/60 md:grid-cols-3 2xl:grid-cols-6">
|
|
271
285
|
<SessionSlateMetric
|
|
272
286
|
label="Status"
|
|
273
287
|
value={stats.statusLabel}
|
|
274
288
|
detail={requestHealthDetail(stats)}
|
|
289
|
+
icon={statusMetricIcon(stats.status)}
|
|
275
290
|
tone={statusMetricTone(stats.status)}
|
|
276
291
|
/>
|
|
277
292
|
<SessionSlateMetric
|
|
@@ -770,14 +785,9 @@ function SidebarPanel({
|
|
|
770
785
|
className?: string;
|
|
771
786
|
}): JSX.Element {
|
|
772
787
|
return (
|
|
773
|
-
<section
|
|
774
|
-
className={cn(
|
|
775
|
-
"bg-white/[0.028] shadow-[inset_0_1px_0_rgba(255,255,255,0.035)] rounded-[8px]",
|
|
776
|
-
className,
|
|
777
|
-
)}
|
|
778
|
-
>
|
|
788
|
+
<section className={cn("rounded-[8px] border border-border/60 bg-card/55", className)}>
|
|
779
789
|
<div className="px-3 pt-3">
|
|
780
|
-
<div className="font-mono text-[10px] font-semibold uppercase tracking-[0.14em] text-
|
|
790
|
+
<div className="font-mono text-[10px] font-semibold uppercase tracking-[0.14em] text-text-subtle">
|
|
781
791
|
{label}
|
|
782
792
|
</div>
|
|
783
793
|
</div>
|
|
@@ -788,11 +798,11 @@ function SidebarPanel({
|
|
|
788
798
|
|
|
789
799
|
function SidebarMetric({ label, value }: { label: string; value: string | number }): JSX.Element {
|
|
790
800
|
return (
|
|
791
|
-
<div className="
|
|
792
|
-
<div className="truncate font-mono text-lg font-semibold leading-6 text-
|
|
801
|
+
<div className="min-w-0 rounded-md border border-border/50 bg-muted/30 px-2 py-2">
|
|
802
|
+
<div className="truncate font-mono text-lg font-semibold leading-6 text-text-strong">
|
|
793
803
|
{value}
|
|
794
804
|
</div>
|
|
795
|
-
<div className="mt-0.5 truncate font-mono text-[10px] uppercase tracking-[0.12em] text-
|
|
805
|
+
<div className="mt-0.5 truncate font-mono text-[10px] uppercase tracking-[0.12em] text-text-subtle">
|
|
796
806
|
{label}
|
|
797
807
|
</div>
|
|
798
808
|
</div>
|
|
@@ -804,7 +814,7 @@ function ThemeModeToggle(): JSX.Element {
|
|
|
804
814
|
|
|
805
815
|
return (
|
|
806
816
|
<div
|
|
807
|
-
className="
|
|
817
|
+
className="inline-flex h-9 items-center rounded-md border border-border/70 bg-muted/70 p-0.5"
|
|
808
818
|
aria-label="Theme mode"
|
|
809
819
|
role="group"
|
|
810
820
|
>
|
|
@@ -812,7 +822,7 @@ function ThemeModeToggle(): JSX.Element {
|
|
|
812
822
|
type="button"
|
|
813
823
|
onClick={() => setThemeMode("light")}
|
|
814
824
|
className={cn(
|
|
815
|
-
"inline-flex size-
|
|
825
|
+
"inline-flex size-8 items-center justify-center rounded-[6px] text-muted-foreground transition-colors hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none max-lg:size-11",
|
|
816
826
|
themeMode === "light" && "bg-background text-foreground shadow-sm",
|
|
817
827
|
)}
|
|
818
828
|
aria-label="Use light mode"
|
|
@@ -825,7 +835,7 @@ function ThemeModeToggle(): JSX.Element {
|
|
|
825
835
|
type="button"
|
|
826
836
|
onClick={() => setThemeMode("eye-care")}
|
|
827
837
|
className={cn(
|
|
828
|
-
"inline-flex size-
|
|
838
|
+
"inline-flex size-8 items-center justify-center rounded-[6px] text-muted-foreground transition-colors hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none max-lg:size-11",
|
|
829
839
|
themeMode === "eye-care" && "bg-background text-foreground shadow-sm",
|
|
830
840
|
)}
|
|
831
841
|
aria-label="Use eye care mode"
|
|
@@ -838,7 +848,7 @@ function ThemeModeToggle(): JSX.Element {
|
|
|
838
848
|
type="button"
|
|
839
849
|
onClick={() => setThemeMode("dark")}
|
|
840
850
|
className={cn(
|
|
841
|
-
"inline-flex size-
|
|
851
|
+
"inline-flex size-8 items-center justify-center rounded-[6px] text-muted-foreground transition-colors hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none max-lg:size-11",
|
|
842
852
|
themeMode === "dark" && "bg-background text-foreground shadow-sm",
|
|
843
853
|
)}
|
|
844
854
|
aria-label="Use dark mode"
|
|
@@ -896,7 +906,7 @@ function UiScaleControl({
|
|
|
896
906
|
>
|
|
897
907
|
<SelectTrigger
|
|
898
908
|
size="sm"
|
|
899
|
-
className="
|
|
909
|
+
className="h-9 min-w-[4.5rem] justify-center gap-1 border-border/70 bg-muted/70 px-2 py-0 text-muted-foreground hover:bg-muted max-lg:h-11 [&>svg:last-child]:hidden"
|
|
900
910
|
aria-label={`Interface size: ${currentLabel}`}
|
|
901
911
|
>
|
|
902
912
|
<ALargeSmall className="size-3.5" />
|
|
@@ -913,12 +923,42 @@ function UiScaleControl({
|
|
|
913
923
|
}
|
|
914
924
|
|
|
915
925
|
const DETAILS_PANEL_COLLAPSED_STORAGE_KEY = "agent-inspector.detailsPanelCollapsed";
|
|
926
|
+
const DETAILS_PANEL_WIDTH_STORAGE_KEY = "agent-inspector.detailsPanelWidth";
|
|
916
927
|
const INSPECTOR_PET_VISIBLE_STORAGE_KEY = "agent-inspector.pet.visible";
|
|
928
|
+
const DETAILS_PANEL_DEFAULT_WIDTH = 360;
|
|
929
|
+
const DETAILS_PANEL_MIN_WIDTH = 288;
|
|
930
|
+
const DETAILS_PANEL_MAX_WIDTH = 520;
|
|
931
|
+
|
|
932
|
+
type DetailsPanelResizeState = {
|
|
933
|
+
startX: number;
|
|
934
|
+
startWidth: number;
|
|
935
|
+
pointerId: number;
|
|
936
|
+
};
|
|
937
|
+
|
|
938
|
+
function clampDetailsPanelWidth(width: number): number {
|
|
939
|
+
return Math.min(Math.max(width, DETAILS_PANEL_MIN_WIDTH), DETAILS_PANEL_MAX_WIDTH);
|
|
940
|
+
}
|
|
917
941
|
|
|
918
942
|
function readStoredDetailsPanelCollapsed(): boolean {
|
|
919
943
|
if (typeof window === "undefined") return true;
|
|
920
|
-
|
|
921
|
-
|
|
944
|
+
try {
|
|
945
|
+
const stored = window.localStorage.getItem(DETAILS_PANEL_COLLAPSED_STORAGE_KEY);
|
|
946
|
+
return stored === null || stored === "1";
|
|
947
|
+
} catch {
|
|
948
|
+
return true;
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
function readStoredDetailsPanelWidth(): number {
|
|
953
|
+
if (typeof window === "undefined") return DETAILS_PANEL_DEFAULT_WIDTH;
|
|
954
|
+
try {
|
|
955
|
+
const stored = window.localStorage.getItem(DETAILS_PANEL_WIDTH_STORAGE_KEY);
|
|
956
|
+
if (stored === null) return DETAILS_PANEL_DEFAULT_WIDTH;
|
|
957
|
+
const parsed = Number.parseInt(stored, 10);
|
|
958
|
+
return Number.isFinite(parsed) ? clampDetailsPanelWidth(parsed) : DETAILS_PANEL_DEFAULT_WIDTH;
|
|
959
|
+
} catch {
|
|
960
|
+
return DETAILS_PANEL_DEFAULT_WIDTH;
|
|
961
|
+
}
|
|
922
962
|
}
|
|
923
963
|
|
|
924
964
|
function readStoredInspectorPetVisible(): boolean {
|
|
@@ -1013,7 +1053,7 @@ function SessionModelContextRow({ summary }: { summary: SessionModelContextSumma
|
|
|
1013
1053
|
<button
|
|
1014
1054
|
type="button"
|
|
1015
1055
|
onClick={openLatestContext}
|
|
1016
|
-
className="min-w-0 truncate rounded-sm text-left font-mono font-semibold text-foreground transition-colors hover:text-
|
|
1056
|
+
className="min-w-0 truncate rounded-sm text-left font-mono font-semibold text-foreground transition-colors hover:text-text-link focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1"
|
|
1017
1057
|
title={`Open latest Context for ${summary.model}`}
|
|
1018
1058
|
>
|
|
1019
1059
|
{summary.model}
|
|
@@ -1328,6 +1368,8 @@ export function ProxyViewer({
|
|
|
1328
1368
|
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
|
1329
1369
|
const [deletingCurrentView, setDeletingCurrentView] = useState(false);
|
|
1330
1370
|
const [detailsPanelCollapsed, setDetailsPanelCollapsed] = useState(true);
|
|
1371
|
+
const [detailsPanelWidth, setDetailsPanelWidth] = useState(DETAILS_PANEL_DEFAULT_WIDTH);
|
|
1372
|
+
const [detailsPanelResizing, setDetailsPanelResizing] = useState(false);
|
|
1331
1373
|
const [detailsPanelStorageLoaded, setDetailsPanelStorageLoaded] = useState(false);
|
|
1332
1374
|
const [petVisible, setPetVisible] = useState(true);
|
|
1333
1375
|
const [petVisibilityStorageLoaded, setPetVisibilityStorageLoaded] = useState(false);
|
|
@@ -1340,6 +1382,7 @@ export function ProxyViewer({
|
|
|
1340
1382
|
const importInputRef = useRef<HTMLInputElement>(null);
|
|
1341
1383
|
const exportAbortRef = useRef<AbortController | null>(null);
|
|
1342
1384
|
const exportRequestIdRef = useRef(0);
|
|
1385
|
+
const detailsPanelResizeRef = useRef<DetailsPanelResizeState | null>(null);
|
|
1343
1386
|
useKeyboardNavigation(logListRef, logListWrapperRef, { pageWide: true });
|
|
1344
1387
|
const proxyEndpoint = useMemo(() => {
|
|
1345
1388
|
const origin = typeof window === "undefined" ? "http://localhost:9527" : window.location.origin;
|
|
@@ -1365,6 +1408,7 @@ export function ProxyViewer({
|
|
|
1365
1408
|
|
|
1366
1409
|
useEffect(() => {
|
|
1367
1410
|
setDetailsPanelCollapsed(readStoredDetailsPanelCollapsed());
|
|
1411
|
+
setDetailsPanelWidth(readStoredDetailsPanelWidth());
|
|
1368
1412
|
setDetailsPanelStorageLoaded(true);
|
|
1369
1413
|
}, []);
|
|
1370
1414
|
|
|
@@ -1376,6 +1420,15 @@ export function ProxyViewer({
|
|
|
1376
1420
|
);
|
|
1377
1421
|
}, [detailsPanelCollapsed, detailsPanelStorageLoaded]);
|
|
1378
1422
|
|
|
1423
|
+
useEffect(() => {
|
|
1424
|
+
if (!detailsPanelStorageLoaded) return;
|
|
1425
|
+
try {
|
|
1426
|
+
window.localStorage.setItem(DETAILS_PANEL_WIDTH_STORAGE_KEY, String(detailsPanelWidth));
|
|
1427
|
+
} catch {
|
|
1428
|
+
// Local storage can be unavailable in hardened browser profiles.
|
|
1429
|
+
}
|
|
1430
|
+
}, [detailsPanelStorageLoaded, detailsPanelWidth]);
|
|
1431
|
+
|
|
1379
1432
|
useEffect(() => {
|
|
1380
1433
|
setPetVisible(readStoredInspectorPetVisible());
|
|
1381
1434
|
setPetVisibilityStorageLoaded(true);
|
|
@@ -1545,6 +1598,40 @@ export function ProxyViewer({
|
|
|
1545
1598
|
const toggleDetailsPanelCollapsed = useCallback(() => {
|
|
1546
1599
|
setDetailsPanelCollapsed((value) => !value);
|
|
1547
1600
|
}, []);
|
|
1601
|
+
const handleDetailsPanelResizeStart = useCallback(
|
|
1602
|
+
(event: ReactPointerEvent<HTMLButtonElement>) => {
|
|
1603
|
+
detailsPanelResizeRef.current = {
|
|
1604
|
+
startX: event.clientX,
|
|
1605
|
+
startWidth: detailsPanelWidth,
|
|
1606
|
+
pointerId: event.pointerId,
|
|
1607
|
+
};
|
|
1608
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
1609
|
+
setDetailsPanelResizing(true);
|
|
1610
|
+
},
|
|
1611
|
+
[detailsPanelWidth],
|
|
1612
|
+
);
|
|
1613
|
+
const handleDetailsPanelResizeMove = useCallback(
|
|
1614
|
+
(event: ReactPointerEvent<HTMLButtonElement>) => {
|
|
1615
|
+
const resize = detailsPanelResizeRef.current;
|
|
1616
|
+
if (resize === null || resize.pointerId !== event.pointerId) return;
|
|
1617
|
+
setDetailsPanelWidth(
|
|
1618
|
+
clampDetailsPanelWidth(resize.startWidth + resize.startX - event.clientX),
|
|
1619
|
+
);
|
|
1620
|
+
},
|
|
1621
|
+
[],
|
|
1622
|
+
);
|
|
1623
|
+
const handleDetailsPanelResizeEnd = useCallback((event: ReactPointerEvent<HTMLButtonElement>) => {
|
|
1624
|
+
const resize = detailsPanelResizeRef.current;
|
|
1625
|
+
if (resize === null || resize.pointerId !== event.pointerId) return;
|
|
1626
|
+
if (event.currentTarget.hasPointerCapture(event.pointerId)) {
|
|
1627
|
+
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
1628
|
+
}
|
|
1629
|
+
detailsPanelResizeRef.current = null;
|
|
1630
|
+
setDetailsPanelResizing(false);
|
|
1631
|
+
}, []);
|
|
1632
|
+
const resetDetailsPanelWidth = useCallback(() => {
|
|
1633
|
+
setDetailsPanelWidth(DETAILS_PANEL_DEFAULT_WIDTH);
|
|
1634
|
+
}, []);
|
|
1548
1635
|
const togglePetVisibility = useCallback(() => {
|
|
1549
1636
|
setPetVisible((value) => !value);
|
|
1550
1637
|
}, []);
|
|
@@ -1633,15 +1720,12 @@ export function ProxyViewer({
|
|
|
1633
1720
|
type="button"
|
|
1634
1721
|
onClick={toggleDetailsPanelCollapsed}
|
|
1635
1722
|
className={cn(
|
|
1636
|
-
"group fixed top-1/2 right-3 z-
|
|
1637
|
-
detailsPanelCollapsed
|
|
1638
|
-
? "right-3"
|
|
1639
|
-
: "lg:right-[calc(21.25rem-0.875rem)] xl:right-[calc(22.5rem-0.875rem)]",
|
|
1723
|
+
"group fixed top-1/2 right-3 z-50 inline-flex h-14 w-8 -translate-y-1/2 items-center justify-center rounded-l-md border border-border/70 bg-background/90 text-muted-foreground shadow-lg backdrop-blur transition-colors motion-reduce:transition-none hover:bg-muted hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none",
|
|
1640
1724
|
)}
|
|
1641
1725
|
aria-label={detailsPanelCollapsed ? "Show details panel" : "Hide details panel"}
|
|
1642
1726
|
title={detailsPanelCollapsed ? "Show details panel" : "Hide details panel"}
|
|
1643
1727
|
>
|
|
1644
|
-
<span className="absolute left-1 top-2
|
|
1728
|
+
<span className="absolute bottom-2 left-1 top-2 w-px rounded-full bg-border transition-colors group-hover:bg-foreground/35" />
|
|
1645
1729
|
{detailsPanelCollapsed ? (
|
|
1646
1730
|
<PanelRightOpen className="size-3.5" />
|
|
1647
1731
|
) : (
|
|
@@ -1657,94 +1741,124 @@ export function ProxyViewer({
|
|
|
1657
1741
|
)}
|
|
1658
1742
|
<div
|
|
1659
1743
|
className={cn(
|
|
1660
|
-
"
|
|
1661
|
-
|
|
1662
|
-
? "lg:grid-cols-[minmax(0,1fr)]"
|
|
1663
|
-
: "lg:grid-cols-[minmax(0,1fr)_21.25rem] xl:grid-cols-[minmax(0,1fr)_22.5rem]",
|
|
1744
|
+
"flex w-full min-w-0 flex-col lg:min-h-0 lg:flex-1 lg:flex-row lg:overflow-hidden",
|
|
1745
|
+
detailsPanelResizing && "cursor-col-resize select-none",
|
|
1664
1746
|
)}
|
|
1665
1747
|
>
|
|
1666
1748
|
{!detailsPanelCollapsed && (
|
|
1667
|
-
|
|
1668
|
-
<
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1749
|
+
<>
|
|
1750
|
+
<button
|
|
1751
|
+
type="button"
|
|
1752
|
+
className="fixed inset-0 z-30 bg-background/70 backdrop-blur-sm lg:hidden"
|
|
1753
|
+
onClick={toggleDetailsPanelCollapsed}
|
|
1754
|
+
aria-label="Close details panel"
|
|
1755
|
+
/>
|
|
1756
|
+
<aside
|
|
1757
|
+
className="inspector-scrollbar fixed inset-x-3 bottom-3 top-24 z-40 order-1 overflow-y-auto rounded-lg border border-border bg-background/98 shadow-2xl max-lg:!w-auto lg:relative lg:inset-auto lg:order-2 lg:h-full lg:shrink-0 lg:rounded-none lg:border-y-0 lg:border-r-0 lg:shadow-none"
|
|
1758
|
+
style={{ width: detailsPanelWidth }}
|
|
1759
|
+
>
|
|
1760
|
+
<button
|
|
1761
|
+
type="button"
|
|
1762
|
+
className="absolute bottom-0 left-0 top-0 z-30 hidden w-2 -translate-x-1/2 cursor-col-resize touch-none items-center justify-center lg:flex"
|
|
1763
|
+
onPointerDown={handleDetailsPanelResizeStart}
|
|
1764
|
+
onPointerMove={handleDetailsPanelResizeMove}
|
|
1765
|
+
onPointerUp={handleDetailsPanelResizeEnd}
|
|
1766
|
+
onPointerCancel={handleDetailsPanelResizeEnd}
|
|
1767
|
+
onDoubleClick={resetDetailsPanelWidth}
|
|
1768
|
+
aria-label="Resize details panel"
|
|
1769
|
+
title="Drag to resize; double-click to reset"
|
|
1770
|
+
>
|
|
1771
|
+
<span className="h-12 w-1 rounded-full bg-border transition-colors hover:bg-primary" />
|
|
1772
|
+
</button>
|
|
1773
|
+
<div className="flex min-h-full flex-col gap-4 p-4">
|
|
1774
|
+
<div className="sticky top-0 z-20 -mx-4 -mt-4 grid gap-2 border-b border-border/60 bg-background/95 px-4 pb-3 pt-4 backdrop-blur">
|
|
1775
|
+
<SidebarPanel label="View">
|
|
1776
|
+
<div className="flex flex-wrap items-center gap-1.5">
|
|
1777
|
+
<ThemeModeToggle />
|
|
1778
|
+
<UiScaleControl
|
|
1779
|
+
preference={uiScalePreference}
|
|
1780
|
+
resolvedScale={resolvedUiScale}
|
|
1781
|
+
onChange={setUiScalePreference}
|
|
1782
|
+
/>
|
|
1783
|
+
</div>
|
|
1784
|
+
</SidebarPanel>
|
|
1785
|
+
<SidebarPanel label="Workspace">
|
|
1786
|
+
<div className="flex flex-wrap items-center gap-2">
|
|
1787
|
+
<GroupsDialog labelledTrigger />
|
|
1788
|
+
<AgentLabDialog
|
|
1789
|
+
currentSessionId={labSessionId}
|
|
1790
|
+
logCount={logs.length}
|
|
1791
|
+
labelledTrigger
|
|
1792
|
+
/>
|
|
1793
|
+
</div>
|
|
1794
|
+
</SidebarPanel>
|
|
1795
|
+
</div>
|
|
1796
|
+
|
|
1797
|
+
<SidebarPanel label="Current scope">
|
|
1798
|
+
<div className="mb-2 rounded-md border border-border/50 bg-muted/25 px-3 py-2">
|
|
1799
|
+
<div
|
|
1800
|
+
className="truncate font-mono text-xs font-semibold text-text-link"
|
|
1801
|
+
title={activeScopeLabel}
|
|
1802
|
+
>
|
|
1803
|
+
{activeScopeLabel}
|
|
1804
|
+
</div>
|
|
1805
|
+
<div className="mt-1 text-[11px] text-muted-foreground">
|
|
1806
|
+
{isPinnedSessionPage ? "Pinned session" : "Live Inspector data"}
|
|
1807
|
+
</div>
|
|
1808
|
+
</div>
|
|
1809
|
+
<div className="grid grid-cols-2 gap-2">
|
|
1810
|
+
<SidebarMetric
|
|
1811
|
+
label={assistantSearchResult === null ? "Requests" : "Results"}
|
|
1812
|
+
value={displayedLogs.length}
|
|
1813
|
+
/>
|
|
1814
|
+
<SidebarMetric label="Sessions" value={sessions.length} />
|
|
1815
|
+
<SidebarMetric
|
|
1816
|
+
label="Input"
|
|
1817
|
+
value={formatTokens(hasSessionContext ? sessionContextTotalIn : totalIn)}
|
|
1818
|
+
/>
|
|
1819
|
+
<SidebarMetric
|
|
1820
|
+
label="Output"
|
|
1821
|
+
value={formatTokens(hasSessionContext ? sessionContextTotalOut : totalOut)}
|
|
1677
1822
|
/>
|
|
1678
|
-
<GroupsDialog />
|
|
1679
|
-
<AgentLabDialog currentSessionId={labSessionId} logCount={logs.length} />
|
|
1680
1823
|
</div>
|
|
1824
|
+
{sessionLoadProgress !== undefined && (
|
|
1825
|
+
<div className="mt-2 rounded-md border border-border/50 bg-muted/25 px-2 py-2">
|
|
1826
|
+
<SessionLoadProgressBar progress={sessionLoadProgress} />
|
|
1827
|
+
</div>
|
|
1828
|
+
)}
|
|
1681
1829
|
</SidebarPanel>
|
|
1682
|
-
</div>
|
|
1683
1830
|
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
{
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
{isPinnedSessionPage ? "Pinned session" : "Live Inspector data"}
|
|
1694
|
-
</div>
|
|
1695
|
-
</div>
|
|
1696
|
-
<div className="grid grid-cols-2 gap-2">
|
|
1697
|
-
<SidebarMetric
|
|
1698
|
-
label={assistantSearchResult === null ? "Requests" : "Results"}
|
|
1699
|
-
value={displayedLogs.length}
|
|
1700
|
-
/>
|
|
1701
|
-
<SidebarMetric label="Sessions" value={sessions.length} />
|
|
1702
|
-
<SidebarMetric
|
|
1703
|
-
label="Input"
|
|
1704
|
-
value={formatTokens(hasSessionContext ? sessionContextTotalIn : totalIn)}
|
|
1705
|
-
/>
|
|
1706
|
-
<SidebarMetric
|
|
1707
|
-
label="Output"
|
|
1708
|
-
value={formatTokens(hasSessionContext ? sessionContextTotalOut : totalOut)}
|
|
1831
|
+
{hasSessionContext && sessionContextScope !== null && (
|
|
1832
|
+
<SessionContextBar
|
|
1833
|
+
label={sessionContextScope.label}
|
|
1834
|
+
logs={sessionContextLogs}
|
|
1835
|
+
totalIn={sessionContextTotalIn}
|
|
1836
|
+
totalOut={sessionContextTotalOut}
|
|
1837
|
+
timeDisplayFormat={timeDisplayFormat}
|
|
1838
|
+
contextSummary={sessionContextSummary}
|
|
1839
|
+
showBackLink={sessionContextScope.showBackLink}
|
|
1709
1840
|
/>
|
|
1710
|
-
</div>
|
|
1711
|
-
{sessionLoadProgress !== undefined && (
|
|
1712
|
-
<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)]">
|
|
1713
|
-
<SessionLoadProgressBar progress={sessionLoadProgress} />
|
|
1714
|
-
</div>
|
|
1715
1841
|
)}
|
|
1716
|
-
</SidebarPanel>
|
|
1717
|
-
|
|
1718
|
-
{hasSessionContext && sessionContextScope !== null && (
|
|
1719
|
-
<SessionContextBar
|
|
1720
|
-
label={sessionContextScope.label}
|
|
1721
|
-
logs={sessionContextLogs}
|
|
1722
|
-
totalIn={sessionContextTotalIn}
|
|
1723
|
-
totalOut={sessionContextTotalOut}
|
|
1724
|
-
timeDisplayFormat={timeDisplayFormat}
|
|
1725
|
-
contextSummary={sessionContextSummary}
|
|
1726
|
-
showBackLink={sessionContextScope.showBackLink}
|
|
1727
|
-
/>
|
|
1728
|
-
)}
|
|
1729
1842
|
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1843
|
+
{hasSessionContext &&
|
|
1844
|
+
pinnedSessionId !== undefined &&
|
|
1845
|
+
sessionMemberships.length > 0 && (
|
|
1846
|
+
<SessionMembershipPanel memberships={sessionMemberships} />
|
|
1847
|
+
)}
|
|
1735
1848
|
|
|
1736
|
-
|
|
1849
|
+
<div className="flex-1" />
|
|
1737
1850
|
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1851
|
+
<PiAgentPanel
|
|
1852
|
+
currentSessionId={labSessionId}
|
|
1853
|
+
logCount={logs.length}
|
|
1854
|
+
onResultChange={setAssistantSearchResult}
|
|
1855
|
+
/>
|
|
1856
|
+
</div>
|
|
1857
|
+
</aside>
|
|
1858
|
+
</>
|
|
1745
1859
|
)}
|
|
1746
1860
|
|
|
1747
|
-
<main className="order-2 min-w-0 lg:order-1 lg:h-full lg:overflow-y-auto
|
|
1861
|
+
<main className="inspector-scrollbar order-2 min-w-0 lg:order-1 lg:h-full lg:flex-1 lg:overflow-y-auto">
|
|
1748
1862
|
<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">
|
|
1749
1863
|
<div className="flex flex-wrap items-center gap-2">
|
|
1750
1864
|
<div className="min-w-[180px] flex-1">
|
|
@@ -74,33 +74,33 @@ function categoryLabel(category: AlertCategory): string {
|
|
|
74
74
|
function severityAccent(severity: AlertSeverity): string {
|
|
75
75
|
switch (severity) {
|
|
76
76
|
case "critical":
|
|
77
|
-
return "border-
|
|
77
|
+
return "border-status-danger/40 bg-status-danger/10 text-status-danger";
|
|
78
78
|
case "warning":
|
|
79
|
-
return "border-
|
|
79
|
+
return "border-status-watch/40 bg-status-watch/10 text-status-watch";
|
|
80
80
|
case "notice":
|
|
81
|
-
return "border-
|
|
81
|
+
return "border-status-cool/40 bg-status-cool/10 text-status-cool";
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
function severityDot(severity: AlertSeverity): string {
|
|
86
86
|
switch (severity) {
|
|
87
87
|
case "critical":
|
|
88
|
-
return "bg-
|
|
88
|
+
return "bg-status-danger";
|
|
89
89
|
case "warning":
|
|
90
|
-
return "bg-
|
|
90
|
+
return "bg-status-watch";
|
|
91
91
|
case "notice":
|
|
92
|
-
return "bg-
|
|
92
|
+
return "bg-status-cool";
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
function severityText(severity: AlertSeverity): string {
|
|
97
97
|
switch (severity) {
|
|
98
98
|
case "critical":
|
|
99
|
-
return "text-
|
|
99
|
+
return "text-status-danger";
|
|
100
100
|
case "warning":
|
|
101
|
-
return "text-
|
|
101
|
+
return "text-status-watch";
|
|
102
102
|
case "notice":
|
|
103
|
-
return "text-
|
|
103
|
+
return "text-status-cool";
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
106
|
|
|
@@ -169,11 +169,11 @@ function AlertSummaryPill({
|
|
|
169
169
|
}): JSX.Element {
|
|
170
170
|
const toneClass =
|
|
171
171
|
tone === "critical"
|
|
172
|
-
? "border-
|
|
172
|
+
? "border-status-danger/30 bg-status-danger/10 text-status-danger"
|
|
173
173
|
: tone === "warning"
|
|
174
|
-
? "border-
|
|
174
|
+
? "border-status-watch/30 bg-status-watch/10 text-status-watch"
|
|
175
175
|
: tone === "notice"
|
|
176
|
-
? "border-
|
|
176
|
+
? "border-status-cool/30 bg-status-cool/10 text-status-cool"
|
|
177
177
|
: "border-border bg-muted/40 text-foreground";
|
|
178
178
|
|
|
179
179
|
return (
|
|
@@ -263,7 +263,7 @@ function AlertList({
|
|
|
263
263
|
|
|
264
264
|
if (error !== undefined) {
|
|
265
265
|
return (
|
|
266
|
-
<div className="rounded-md border border-
|
|
266
|
+
<div className="rounded-md border border-status-danger/30 bg-status-danger/10 px-3 py-2 text-xs text-status-danger">
|
|
267
267
|
{error.message}
|
|
268
268
|
</div>
|
|
269
269
|
);
|
|
@@ -470,10 +470,10 @@ export function AlertsDialog(): JSX.Element {
|
|
|
470
470
|
const noticeCount = summary?.notice ?? 0;
|
|
471
471
|
const triggerTone =
|
|
472
472
|
criticalCount > 0
|
|
473
|
-
? "bg-
|
|
473
|
+
? "bg-status-danger text-primary-foreground"
|
|
474
474
|
: warningCount > 0
|
|
475
|
-
? "bg-
|
|
476
|
-
: "bg-
|
|
475
|
+
? "bg-status-watch text-primary-foreground"
|
|
476
|
+
: "bg-status-cool text-primary-foreground";
|
|
477
477
|
|
|
478
478
|
return (
|
|
479
479
|
<Dialog open={open} onOpenChange={setOpen}>
|
|
@@ -505,7 +505,7 @@ export function AlertsDialog(): JSX.Element {
|
|
|
505
505
|
<DialogContent className="flex max-h-[86vh] max-w-6xl flex-col overflow-hidden">
|
|
506
506
|
<DialogHeader>
|
|
507
507
|
<DialogTitle className="flex items-center gap-2 pr-8">
|
|
508
|
-
<Siren className="size-5 text-
|
|
508
|
+
<Siren className="size-5 text-status-danger" />
|
|
509
509
|
<span>Alerts</span>
|
|
510
510
|
<Badge variant="outline">{formatCount(totalCount)}</Badge>
|
|
511
511
|
</DialogTitle>
|
|
@@ -621,7 +621,11 @@ function ExecutionConfirmationDialog({
|
|
|
621
621
|
);
|
|
622
622
|
}
|
|
623
623
|
|
|
624
|
-
export function AgentLabDialog({
|
|
624
|
+
export function AgentLabDialog({
|
|
625
|
+
currentSessionId,
|
|
626
|
+
logCount,
|
|
627
|
+
labelledTrigger = false,
|
|
628
|
+
}: AgentLabDialogProps & { labelledTrigger?: boolean }): JSX.Element {
|
|
625
629
|
const [open, setOpen] = useState(false);
|
|
626
630
|
const [copied, setCopied] = useState(false);
|
|
627
631
|
const [copiedPresets, setCopiedPresets] = useState(false);
|
|
@@ -737,13 +741,16 @@ export function AgentLabDialog({ currentSessionId, logCount }: AgentLabDialogPro
|
|
|
737
741
|
<DialogTrigger asChild>
|
|
738
742
|
<Button
|
|
739
743
|
variant="ghost"
|
|
740
|
-
size="icon"
|
|
741
|
-
className={
|
|
744
|
+
size={labelledTrigger ? "default" : "icon"}
|
|
745
|
+
className={cn(
|
|
746
|
+
INSPECTOR_ICON_TRIGGER_CLASS,
|
|
747
|
+
labelledTrigger && "w-auto gap-2 px-3 text-xs max-lg:h-11 max-lg:w-auto",
|
|
748
|
+
)}
|
|
742
749
|
aria-label="TonyClaw Lab"
|
|
743
750
|
title="TonyClaw Lab"
|
|
744
751
|
>
|
|
745
752
|
<FlaskConical className="size-4" />
|
|
746
|
-
<span className="sr-only">
|
|
753
|
+
<span className={labelledTrigger ? "" : "sr-only"}>Lab</span>
|
|
747
754
|
</Button>
|
|
748
755
|
</DialogTrigger>
|
|
749
756
|
<DialogContent className="flex max-h-[84vh] max-w-5xl flex-col overflow-hidden">
|