@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
|
@@ -130,16 +130,16 @@ export function buildGroupMemberRows(
|
|
|
130
130
|
function statusClassName(status: InspectorGroup["status"] | MemberStatus): string {
|
|
131
131
|
switch (status) {
|
|
132
132
|
case "completed":
|
|
133
|
-
return "border-
|
|
133
|
+
return "border-status-success/30 bg-status-success/10 text-status-success";
|
|
134
134
|
case "failed":
|
|
135
135
|
case "cancelled":
|
|
136
|
-
return "border-
|
|
136
|
+
return "border-status-danger/30 bg-status-danger/10 text-status-danger";
|
|
137
137
|
case "running":
|
|
138
|
-
return "border-
|
|
138
|
+
return "border-status-cool/30 bg-status-cool/10 text-status-cool";
|
|
139
139
|
case "created":
|
|
140
|
-
return "border-
|
|
140
|
+
return "border-border bg-muted/30 text-muted-foreground";
|
|
141
141
|
case null:
|
|
142
|
-
return "border-
|
|
142
|
+
return "border-border bg-muted/30 text-muted-foreground";
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
145
|
|
|
@@ -150,13 +150,13 @@ function statusLabel(status: InspectorGroup["status"] | MemberStatus): string {
|
|
|
150
150
|
function reportStatusClassName(status: EvidenceReport["status"]): string {
|
|
151
151
|
switch (status) {
|
|
152
152
|
case "PASS":
|
|
153
|
-
return "border-
|
|
153
|
+
return "border-status-success/30 bg-status-success/10 text-status-success";
|
|
154
154
|
case "FAIL":
|
|
155
|
-
return "border-
|
|
155
|
+
return "border-status-danger/30 bg-status-danger/10 text-status-danger";
|
|
156
156
|
case "RUNNING":
|
|
157
|
-
return "border-
|
|
157
|
+
return "border-status-cool/30 bg-status-cool/10 text-status-cool";
|
|
158
158
|
case "UNKNOWN":
|
|
159
|
-
return "border-
|
|
159
|
+
return "border-border bg-muted/30 text-muted-foreground";
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
162
|
|
|
@@ -283,7 +283,11 @@ function evidenceReportFor(
|
|
|
283
283
|
return null;
|
|
284
284
|
}
|
|
285
285
|
|
|
286
|
-
export function GroupsDialog(
|
|
286
|
+
export function GroupsDialog({
|
|
287
|
+
labelledTrigger = false,
|
|
288
|
+
}: {
|
|
289
|
+
labelledTrigger?: boolean;
|
|
290
|
+
}): JSX.Element {
|
|
287
291
|
const [open, setOpen] = useState(false);
|
|
288
292
|
const [selectedGroupId, setSelectedGroupId] = useState<string | null>(null);
|
|
289
293
|
const [exportingGroupId, setExportingGroupId] = useState<string | null>(null);
|
|
@@ -446,8 +450,11 @@ export function GroupsDialog(): JSX.Element {
|
|
|
446
450
|
<Button
|
|
447
451
|
type="button"
|
|
448
452
|
variant="ghost"
|
|
449
|
-
size="icon"
|
|
450
|
-
className={
|
|
453
|
+
size={labelledTrigger ? "default" : "icon"}
|
|
454
|
+
className={cn(
|
|
455
|
+
INSPECTOR_ICON_TRIGGER_CLASS,
|
|
456
|
+
labelledTrigger && "w-auto gap-2 px-3 text-xs max-lg:h-11 max-lg:w-auto",
|
|
457
|
+
)}
|
|
451
458
|
aria-label="Evaluation groups"
|
|
452
459
|
title="Evaluation groups"
|
|
453
460
|
>
|
|
@@ -459,7 +466,7 @@ export function GroupsDialog(): JSX.Element {
|
|
|
459
466
|
{groups.length}
|
|
460
467
|
</span>
|
|
461
468
|
) : null}
|
|
462
|
-
<span className="sr-only">
|
|
469
|
+
<span className={labelledTrigger ? "" : "sr-only"}>Groups</span>
|
|
463
470
|
</Button>
|
|
464
471
|
</DialogTrigger>
|
|
465
472
|
<DialogContent className="flex max-h-[85vh] max-w-5xl flex-col overflow-hidden">
|
|
@@ -553,7 +560,7 @@ function GroupList({
|
|
|
553
560
|
|
|
554
561
|
if (error !== undefined) {
|
|
555
562
|
return (
|
|
556
|
-
<div className="rounded-md border border-
|
|
563
|
+
<div className="rounded-md border border-status-danger/30 bg-status-danger/10 px-3 py-2 text-xs text-status-danger">
|
|
557
564
|
{error.message}
|
|
558
565
|
</div>
|
|
559
566
|
);
|
|
@@ -677,7 +684,7 @@ function GroupDetails({
|
|
|
677
684
|
type="button"
|
|
678
685
|
variant="outline"
|
|
679
686
|
size="icon"
|
|
680
|
-
className="size-8 text-
|
|
687
|
+
className="size-8 text-status-danger hover:text-status-danger/80"
|
|
681
688
|
aria-label="Delete group"
|
|
682
689
|
title="Delete group"
|
|
683
690
|
disabled={isDeleting}
|
|
@@ -751,13 +758,13 @@ function GroupDetails({
|
|
|
751
758
|
<EvidencePaths evidence={evidence} />
|
|
752
759
|
|
|
753
760
|
{exportError !== null && (
|
|
754
|
-
<div className="rounded-md border border-
|
|
761
|
+
<div className="rounded-md border border-status-danger/30 bg-status-danger/10 px-3 py-2 text-xs text-status-danger">
|
|
755
762
|
{exportError}
|
|
756
763
|
</div>
|
|
757
764
|
)}
|
|
758
765
|
|
|
759
766
|
{deleteError !== null && !isConfirmingDelete && (
|
|
760
|
-
<div className="rounded-md border border-
|
|
767
|
+
<div className="rounded-md border border-status-danger/30 bg-status-danger/10 px-3 py-2 text-xs text-status-danger">
|
|
761
768
|
{deleteError}
|
|
762
769
|
</div>
|
|
763
770
|
)}
|
|
@@ -789,14 +796,14 @@ function DeleteGroupPanel({
|
|
|
789
796
|
const evidencePath = group.evidence?.markdownPath ?? "No evidence pack exported.";
|
|
790
797
|
|
|
791
798
|
return (
|
|
792
|
-
<div className="rounded-md border border-
|
|
799
|
+
<div className="rounded-md border border-status-danger/30 bg-status-danger/10 px-3 py-3 text-status-danger">
|
|
793
800
|
<div className="flex min-w-0 flex-col gap-3 lg:flex-row lg:items-start lg:justify-between">
|
|
794
801
|
<div className="min-w-0 space-y-2">
|
|
795
802
|
<div className="flex items-center gap-2 text-sm font-semibold">
|
|
796
|
-
<Trash2 className="size-4 text-
|
|
803
|
+
<Trash2 className="size-4 text-status-danger" />
|
|
797
804
|
<span>Delete group?</span>
|
|
798
805
|
</div>
|
|
799
|
-
<p className="text-xs text-
|
|
806
|
+
<p className="text-xs text-status-danger">
|
|
800
807
|
Delete <span className="font-medium">{group.title}</span>. Session logs and run records
|
|
801
808
|
stay intact.
|
|
802
809
|
</p>
|
|
@@ -815,13 +822,13 @@ function DeleteGroupPanel({
|
|
|
815
822
|
/>
|
|
816
823
|
<span className="min-w-0">
|
|
817
824
|
<span className="block font-medium">Also delete exported evidence files</span>
|
|
818
|
-
<code className="mt-1 block truncate font-mono text-[11px] text-
|
|
825
|
+
<code className="mt-1 block truncate font-mono text-[11px] text-status-danger">
|
|
819
826
|
{evidencePath}
|
|
820
827
|
</code>
|
|
821
828
|
</span>
|
|
822
829
|
</label>
|
|
823
830
|
{error !== null && (
|
|
824
|
-
<div className="rounded-md border border-
|
|
831
|
+
<div className="rounded-md border border-status-danger/30 bg-card px-2 py-1.5 text-xs text-status-danger">
|
|
825
832
|
{error}
|
|
826
833
|
</div>
|
|
827
834
|
)}
|
|
@@ -891,7 +898,7 @@ function EvidenceReportCard({
|
|
|
891
898
|
|
|
892
899
|
if (error !== undefined && hasEvidence) {
|
|
893
900
|
return (
|
|
894
|
-
<div className="rounded-md border border-
|
|
901
|
+
<div className="rounded-md border border-status-danger/30 bg-status-danger/10 px-3 py-2 text-xs text-status-danger">
|
|
895
902
|
Failed to load evidence report: {error.message}
|
|
896
903
|
</div>
|
|
897
904
|
);
|
|
@@ -916,7 +923,11 @@ function EvidenceReportCard({
|
|
|
916
923
|
aria-label={copied ? "Copied evidence report" : "Copy evidence report"}
|
|
917
924
|
onClick={copy}
|
|
918
925
|
>
|
|
919
|
-
{copied ?
|
|
926
|
+
{copied ? (
|
|
927
|
+
<Check className="size-3.5 text-status-success" />
|
|
928
|
+
) : (
|
|
929
|
+
<Copy className="size-3.5" />
|
|
930
|
+
)}
|
|
920
931
|
</Button>
|
|
921
932
|
</div>
|
|
922
933
|
<p className="mt-1 text-xs text-muted-foreground">{report.summary}</p>
|
|
@@ -964,7 +975,11 @@ function CopyPathRow({ label, value }: { label: string; value: string }): JSX.El
|
|
|
964
975
|
aria-label={copied ? `Copied ${label} path` : `Copy ${label} path`}
|
|
965
976
|
onClick={copy}
|
|
966
977
|
>
|
|
967
|
-
{copied ?
|
|
978
|
+
{copied ? (
|
|
979
|
+
<Check className="size-3.5 text-status-success" />
|
|
980
|
+
) : (
|
|
981
|
+
<Copy className="size-3.5" />
|
|
982
|
+
)}
|
|
968
983
|
</Button>
|
|
969
984
|
</div>
|
|
970
985
|
);
|
|
@@ -1095,7 +1110,7 @@ function MemberRow({
|
|
|
1095
1110
|
<span className="min-w-0 truncate">{sessionLabel}</span>
|
|
1096
1111
|
<Badge
|
|
1097
1112
|
variant="outline"
|
|
1098
|
-
className="shrink-0 border-
|
|
1113
|
+
className="shrink-0 border-border bg-muted/30 text-muted-foreground"
|
|
1099
1114
|
>
|
|
1100
1115
|
evidence
|
|
1101
1116
|
</Badge>
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
nextInspectorPetWalkingPosition,
|
|
23
23
|
randomInspectorPetEdgePosition,
|
|
24
24
|
resolveInspectorPetStatus,
|
|
25
|
-
|
|
25
|
+
snapInspectorPetToCorner,
|
|
26
26
|
} from "./inspectorPetLogic";
|
|
27
27
|
import { InspectorPetCrab3D } from "./InspectorPetCrab3D";
|
|
28
28
|
|
|
@@ -63,11 +63,11 @@ function readViewport(): InspectorPetViewport {
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
function readStoredRoaming(): boolean {
|
|
66
|
-
if (typeof window === "undefined") return
|
|
66
|
+
if (typeof window === "undefined") return false;
|
|
67
67
|
try {
|
|
68
|
-
return window.localStorage.getItem(INSPECTOR_PET_ROAMING_STORAGE_KEY)
|
|
68
|
+
return window.localStorage.getItem(INSPECTOR_PET_ROAMING_STORAGE_KEY) === "1";
|
|
69
69
|
} catch {
|
|
70
|
-
return
|
|
70
|
+
return false;
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
|
|
@@ -126,7 +126,7 @@ export function InspectorPet({ logs }: InspectorPetProps): JSX.Element {
|
|
|
126
126
|
useEffect(() => {
|
|
127
127
|
const nextViewport = readViewport();
|
|
128
128
|
setViewport(nextViewport);
|
|
129
|
-
setPosition(randomInspectorPetEdgePosition(nextViewport,
|
|
129
|
+
setPosition(randomInspectorPetEdgePosition(nextViewport, 1));
|
|
130
130
|
}, []);
|
|
131
131
|
|
|
132
132
|
useEffect(() => {
|
|
@@ -181,7 +181,7 @@ export function InspectorPet({ logs }: InspectorPetProps): JSX.Element {
|
|
|
181
181
|
const nextViewport = readViewport();
|
|
182
182
|
setScuttling(false);
|
|
183
183
|
setViewport(nextViewport);
|
|
184
|
-
setPosition((current) =>
|
|
184
|
+
setPosition((current) => snapInspectorPetToCorner(current, nextViewport));
|
|
185
185
|
};
|
|
186
186
|
window.addEventListener("resize", handleResize);
|
|
187
187
|
return () => window.removeEventListener("resize", handleResize);
|
|
@@ -264,7 +264,7 @@ export function InspectorPet({ logs }: InspectorPetProps): JSX.Element {
|
|
|
264
264
|
dragOccurredRef.current = dragState.moved;
|
|
265
265
|
dragStateRef.current = null;
|
|
266
266
|
setDragging(false);
|
|
267
|
-
setPosition((current) =>
|
|
267
|
+
setPosition((current) => snapInspectorPetToCorner(current, viewport));
|
|
268
268
|
},
|
|
269
269
|
[viewport],
|
|
270
270
|
);
|
|
@@ -314,7 +314,7 @@ export function InspectorPet({ logs }: InspectorPetProps): JSX.Element {
|
|
|
314
314
|
<button
|
|
315
315
|
type="button"
|
|
316
316
|
className={cn(
|
|
317
|
-
"pointer-events-auto fixed left-0 top-0 z-10 flex size-28 items-center justify-center bg-transparent text-foreground outline-none transition-[filter,opacity] duration-200 hover:opacity-
|
|
317
|
+
"pointer-events-auto fixed left-0 top-0 z-10 flex size-28 items-center justify-center bg-transparent text-foreground opacity-65 outline-none transition-[filter,opacity] duration-200 hover:opacity-100 hover:drop-shadow-[0_0_28px_rgba(245,158,11,0.32)] focus-visible:opacity-100 focus-visible:drop-shadow-[0_0_14px_rgba(251,191,36,0.72)]",
|
|
318
318
|
dragging ? "cursor-grabbing" : "cursor-grab",
|
|
319
319
|
)}
|
|
320
320
|
style={petStyle}
|
|
@@ -370,7 +370,7 @@ export function InspectorPet({ logs }: InspectorPetProps): JSX.Element {
|
|
|
370
370
|
<span className="min-w-0 flex-1 truncate text-xs font-medium">{status.label}</span>
|
|
371
371
|
<button
|
|
372
372
|
type="button"
|
|
373
|
-
className="inline-flex size-
|
|
373
|
+
className="inline-flex size-7 shrink-0 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none max-lg:size-10"
|
|
374
374
|
onClick={handleToggleRoaming}
|
|
375
375
|
aria-label={roamingLabel}
|
|
376
376
|
title={roamingLabel}
|
|
@@ -103,6 +103,20 @@ export function snapInspectorPetToEdge(
|
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
export function snapInspectorPetToCorner(
|
|
107
|
+
position: InspectorPetPosition,
|
|
108
|
+
viewport: InspectorPetViewport,
|
|
109
|
+
): InspectorPetPosition {
|
|
110
|
+
const clamped = clampInspectorPetPosition(position, viewport);
|
|
111
|
+
const edgeGap = scaledMetric(INSPECTOR_PET_EDGE_GAP, viewport);
|
|
112
|
+
const maxX = maximumPetX(viewport);
|
|
113
|
+
const maxY = maximumPetY(viewport);
|
|
114
|
+
return {
|
|
115
|
+
x: clamped.x - edgeGap <= maxX - clamped.x ? edgeGap : maxX,
|
|
116
|
+
y: clamped.y - edgeGap <= maxY - clamped.y ? edgeGap : maxY,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
106
120
|
export function randomInspectorPetEdgePosition(
|
|
107
121
|
viewport: InspectorPetViewport,
|
|
108
122
|
positionSample: number,
|
|
@@ -111,7 +125,7 @@ export function randomInspectorPetEdgePosition(
|
|
|
111
125
|
const maxY = maximumPetY(viewport);
|
|
112
126
|
const edgeGap = scaledMetric(INSPECTOR_PET_EDGE_GAP, viewport);
|
|
113
127
|
return {
|
|
114
|
-
x:
|
|
128
|
+
x: clampUnit(positionSample) < 0.5 ? edgeGap : maxX,
|
|
115
129
|
y: maxY,
|
|
116
130
|
};
|
|
117
131
|
}
|
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
createEmptyPiAgentConversation,
|
|
6
6
|
getPiAgentResultLogIds,
|
|
7
7
|
normalizePiAgentResponse,
|
|
8
|
-
PI_AGENT_SCOPE_PILLS,
|
|
9
8
|
PI_AGENT_STARTERS,
|
|
10
9
|
type PiAgentConversationMessage,
|
|
11
10
|
type PiAgentEvidenceView,
|
|
@@ -30,8 +29,7 @@ export type PiAgentSearchResult = {
|
|
|
30
29
|
reportedLogCount: number;
|
|
31
30
|
};
|
|
32
31
|
|
|
33
|
-
const DEFAULT_QUESTION =
|
|
34
|
-
"Analyze the current Inspector session. What looks abnormal, slow, or likely to hang?";
|
|
32
|
+
const DEFAULT_QUESTION = "What looks abnormal, slow, or likely to hang?";
|
|
35
33
|
|
|
36
34
|
function providerSupportsPiAgent(provider: {
|
|
37
35
|
anthropicBaseUrl?: string;
|
|
@@ -209,7 +207,7 @@ export function PiAgentPanel({
|
|
|
209
207
|
currentSessionId,
|
|
210
208
|
logCount,
|
|
211
209
|
onResultChange,
|
|
212
|
-
}: PiAgentPanelProps): JSX.Element {
|
|
210
|
+
}: PiAgentPanelProps): JSX.Element | null {
|
|
213
211
|
const { providers } = useProviders();
|
|
214
212
|
const piProviders = useMemo(
|
|
215
213
|
() => sortProviderBySource(providers.filter(providerSupportsPiAgent)),
|
|
@@ -228,6 +226,8 @@ export function PiAgentPanel({
|
|
|
228
226
|
const question = conversation.question;
|
|
229
227
|
const canAsk = question.trim() !== "" && piProviders.length > 0 && !loading;
|
|
230
228
|
|
|
229
|
+
if (piProviders.length === 0) return null;
|
|
230
|
+
|
|
231
231
|
const handleQuestionChange = (event: ChangeEvent<HTMLTextAreaElement>): void => {
|
|
232
232
|
setConversation((current) => ({ ...current, question: event.currentTarget.value }));
|
|
233
233
|
};
|
|
@@ -334,9 +334,9 @@ export function PiAgentPanel({
|
|
|
334
334
|
<div className="flex items-center gap-2">
|
|
335
335
|
<BrainCircuit className="size-4 text-cyan-200" />
|
|
336
336
|
<div className="min-w-0 flex-1">
|
|
337
|
-
<div className="text-xs font-semibold text-foreground">
|
|
337
|
+
<div className="text-xs font-semibold text-foreground">Assistant</div>
|
|
338
338
|
<div className="text-[11px] text-muted-foreground">
|
|
339
|
-
{currentSessionId === null ? "
|
|
339
|
+
{currentSessionId === null ? "All evidence" : "Current session"}
|
|
340
340
|
</div>
|
|
341
341
|
</div>
|
|
342
342
|
<button
|
|
@@ -350,26 +350,9 @@ export function PiAgentPanel({
|
|
|
350
350
|
</div>
|
|
351
351
|
|
|
352
352
|
{conversation.messages.length === 0 && (
|
|
353
|
-
<
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
traffic, sessions, tools, alerts, runs, groups, and knowledge, then uses linked evidence
|
|
357
|
-
to shape the log results.
|
|
358
|
-
</p>
|
|
359
|
-
<div className="mt-2 grid gap-1.5">
|
|
360
|
-
{PI_AGENT_SCOPE_PILLS.map((pill) => (
|
|
361
|
-
<div
|
|
362
|
-
key={pill.id}
|
|
363
|
-
className="rounded-sm bg-cyan-400/[0.06] px-2 py-1.5 shadow-[inset_0_0_0_1px_rgba(103,232,249,0.08)]"
|
|
364
|
-
>
|
|
365
|
-
<div className="text-[10px] font-medium text-cyan-50">{pill.label}</div>
|
|
366
|
-
<div className="mt-0.5 text-[9px] leading-4 text-muted-foreground">
|
|
367
|
-
{pill.description}
|
|
368
|
-
</div>
|
|
369
|
-
</div>
|
|
370
|
-
))}
|
|
371
|
-
</div>
|
|
372
|
-
</div>
|
|
353
|
+
<p className="mt-3 text-[11px] leading-5 text-muted-foreground">
|
|
354
|
+
Ask about failures, latency, tokens, and tools.
|
|
355
|
+
</p>
|
|
373
356
|
)}
|
|
374
357
|
|
|
375
358
|
<div className="mt-3 grid grid-cols-2 gap-2">
|
|
@@ -437,7 +420,7 @@ export function PiAgentPanel({
|
|
|
437
420
|
value={question}
|
|
438
421
|
onChange={handleQuestionChange}
|
|
439
422
|
className="mt-3 min-h-20 w-full resize-y rounded-md bg-black/25 px-3 py-2 text-xs leading-5 text-foreground outline-none shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors placeholder:text-muted-foreground focus-visible:ring-1 focus-visible:ring-ring"
|
|
440
|
-
placeholder="
|
|
423
|
+
placeholder="Ask about this Inspector data..."
|
|
441
424
|
/>
|
|
442
425
|
|
|
443
426
|
<button
|
|
@@ -447,21 +430,15 @@ export function PiAgentPanel({
|
|
|
447
430
|
className="mt-2 inline-flex h-8 w-full items-center justify-center gap-2 rounded-md bg-cyan-400/12 px-3 text-xs font-medium text-cyan-100 shadow-[inset_0_0_0_1px_rgba(103,232,249,0.18)] transition-colors hover:bg-cyan-400/18 disabled:cursor-not-allowed disabled:opacity-50"
|
|
448
431
|
>
|
|
449
432
|
{loading ? <Loader2 className="size-3.5 animate-spin" /> : <Send className="size-3.5" />}
|
|
450
|
-
<span>{loading ? "Searching..." : "
|
|
433
|
+
<span>{loading ? "Searching..." : "Ask Assistant"}</span>
|
|
451
434
|
</button>
|
|
452
435
|
|
|
453
436
|
{conversation.error !== null && (
|
|
454
437
|
<p className="mt-2 break-words text-[11px] leading-5 text-red-200">{conversation.error}</p>
|
|
455
438
|
)}
|
|
456
|
-
{piProviders.length === 0 && (
|
|
457
|
-
<p className="mt-2 text-[11px] leading-5 text-muted-foreground">
|
|
458
|
-
Configure a Provider with Responses, Chat, or Anthropic URL to enable Inspector Assistant.
|
|
459
|
-
</p>
|
|
460
|
-
)}
|
|
461
439
|
{logCount === 0 && (
|
|
462
440
|
<p className="mt-2 text-[11px] leading-5 text-muted-foreground">
|
|
463
|
-
No logs
|
|
464
|
-
questions.
|
|
441
|
+
No logs in this scope. Setup questions still work.
|
|
465
442
|
</p>
|
|
466
443
|
)}
|
|
467
444
|
</section>
|
|
@@ -71,30 +71,6 @@ export type PiAgentStarter = {
|
|
|
71
71
|
question: string;
|
|
72
72
|
};
|
|
73
73
|
|
|
74
|
-
export type PiAgentScopePill = {
|
|
75
|
-
id: "saved-data" | "root-cause" | "evidence";
|
|
76
|
-
label: string;
|
|
77
|
-
description: string;
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
export const PI_AGENT_SCOPE_PILLS: readonly PiAgentScopePill[] = [
|
|
81
|
-
{
|
|
82
|
-
id: "saved-data",
|
|
83
|
-
label: "Saved Inspector data",
|
|
84
|
-
description: "requests, responses, sessions, tools, alerts, runs, groups, and knowledge",
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
id: "root-cause",
|
|
88
|
-
label: "Root-cause hints",
|
|
89
|
-
description: "failures, hangs, slow paths, token spikes, and provider drift",
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
id: "evidence",
|
|
93
|
-
label: "Evidence links",
|
|
94
|
-
description: "matched logs and metrics you can jump back into",
|
|
95
|
-
},
|
|
96
|
-
];
|
|
97
|
-
|
|
98
74
|
export const PI_AGENT_STARTERS: readonly PiAgentStarter[] = [
|
|
99
75
|
{
|
|
100
76
|
id: "reliability",
|
|
@@ -253,7 +253,7 @@ export function ImportWizardDialog({
|
|
|
253
253
|
)}
|
|
254
254
|
|
|
255
255
|
{importResult !== null && (
|
|
256
|
-
<div className="text-sm text-
|
|
256
|
+
<div className="border-t pt-2 text-sm text-status-success">{importResult}</div>
|
|
257
257
|
)}
|
|
258
258
|
|
|
259
259
|
{importError !== null && (
|
|
@@ -182,11 +182,11 @@ export function ProviderCard({
|
|
|
182
182
|
const isTestingValue = isTesting ?? false;
|
|
183
183
|
const providerSourceBadge =
|
|
184
184
|
provider.source === "company" ? (
|
|
185
|
-
<span className="shrink-0 rounded border border-
|
|
185
|
+
<span className="shrink-0 rounded border border-status-cool/30 bg-status-cool/10 px-1.5 py-0.5 text-xs text-status-cool">
|
|
186
186
|
Company
|
|
187
187
|
</span>
|
|
188
188
|
) : provider.source === "personal" ? (
|
|
189
|
-
<span className="shrink-0 rounded border border-
|
|
189
|
+
<span className="shrink-0 rounded border border-status-accent/30 bg-status-accent/10 px-1.5 py-0.5 text-xs text-status-accent">
|
|
190
190
|
Personal
|
|
191
191
|
</span>
|
|
192
192
|
) : null;
|
|
@@ -238,7 +238,7 @@ export function ProviderCard({
|
|
|
238
238
|
</div>
|
|
239
239
|
|
|
240
240
|
{!hasContextMetadata && (
|
|
241
|
-
<div className="flex items-center justify-between gap-2 rounded-md border border-
|
|
241
|
+
<div className="flex items-center justify-between gap-2 rounded-md border border-status-watch/30 bg-status-watch/10 px-2 py-1.5 text-xs text-status-watch">
|
|
242
242
|
<span>Context window metadata missing</span>
|
|
243
243
|
<div className="flex shrink-0 items-center gap-1">
|
|
244
244
|
<Button
|
|
@@ -270,7 +270,7 @@ export function ProviderCard({
|
|
|
270
270
|
{showDetails && (
|
|
271
271
|
<div className="space-y-3 border-t border-border/60 pt-3">
|
|
272
272
|
<div className="flex items-center gap-2 text-xs text-muted-foreground">
|
|
273
|
-
<CheckCircle className="size-3.5 text-
|
|
273
|
+
<CheckCircle className="size-3.5 text-status-success" />
|
|
274
274
|
<span>API key configured</span>
|
|
275
275
|
</div>
|
|
276
276
|
|
|
@@ -311,7 +311,7 @@ function EndpointUrlPreview({
|
|
|
311
311
|
<div
|
|
312
312
|
key={`${diagnostic.severity}:${diagnostic.message}`}
|
|
313
313
|
className={
|
|
314
|
-
diagnostic.severity === "warning" ? "text-
|
|
314
|
+
diagnostic.severity === "warning" ? "text-status-watch" : "text-muted-foreground"
|
|
315
315
|
}
|
|
316
316
|
>
|
|
317
317
|
{diagnostic.message}
|
|
@@ -809,7 +809,7 @@ export function ProviderForm({ provider, onSubmit, onCancel }: ProviderFormProps
|
|
|
809
809
|
placeholder="https://api.anthropic.com"
|
|
810
810
|
className="min-w-0 flex-1 bg-transparent px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50"
|
|
811
811
|
/>
|
|
812
|
-
<span className="shrink-0 select-none border-l border-
|
|
812
|
+
<span className="shrink-0 select-none border-l border-border bg-muted/35 px-3 py-2 font-mono text-xs text-muted-foreground">
|
|
813
813
|
{ANTHROPIC_MESSAGES_ENDPOINT}
|
|
814
814
|
</span>
|
|
815
815
|
</div>
|
|
@@ -841,7 +841,7 @@ export function ProviderForm({ provider, onSubmit, onCancel }: ProviderFormProps
|
|
|
841
841
|
placeholder="https://api.openai.com"
|
|
842
842
|
className="min-w-0 flex-1 bg-transparent px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50"
|
|
843
843
|
/>
|
|
844
|
-
<span className="shrink-0 select-none border-l border-
|
|
844
|
+
<span className="shrink-0 select-none border-l border-border bg-muted/35 px-3 py-2 font-mono text-xs text-muted-foreground">
|
|
845
845
|
{OPENAI_CHAT_COMPLETIONS_ENDPOINT}
|
|
846
846
|
</span>
|
|
847
847
|
</div>
|
|
@@ -873,7 +873,7 @@ export function ProviderForm({ provider, onSubmit, onCancel }: ProviderFormProps
|
|
|
873
873
|
placeholder="https://api.openai.com"
|
|
874
874
|
className="min-w-0 flex-1 bg-transparent px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50"
|
|
875
875
|
/>
|
|
876
|
-
<span className="shrink-0 select-none border-l border-
|
|
876
|
+
<span className="shrink-0 select-none border-l border-border bg-muted/35 px-3 py-2 font-mono text-xs text-muted-foreground">
|
|
877
877
|
{OPENAI_RESPONSES_ENDPOINT}
|
|
878
878
|
</span>
|
|
879
879
|
</div>
|
|
@@ -937,7 +937,7 @@ export function ProviderForm({ provider, onSubmit, onCancel }: ProviderFormProps
|
|
|
937
937
|
</div>
|
|
938
938
|
)}
|
|
939
939
|
{provider !== undefined && !hasContextMetadata && modelMetadataUrl.trim() === "" && (
|
|
940
|
-
<p className="text-xs text-
|
|
940
|
+
<p className="text-xs text-status-watch">
|
|
941
941
|
This provider has no matching context metadata yet.
|
|
942
942
|
</p>
|
|
943
943
|
)}
|
|
@@ -975,7 +975,11 @@ export function ProviderForm({ provider, onSubmit, onCancel }: ProviderFormProps
|
|
|
975
975
|
className="text-muted-foreground hover:text-foreground transition-colors p-1 shrink-0"
|
|
976
976
|
aria-label="Copy API key"
|
|
977
977
|
>
|
|
978
|
-
{copied ?
|
|
978
|
+
{copied ? (
|
|
979
|
+
<Check className="size-4 text-status-success" />
|
|
980
|
+
) : (
|
|
981
|
+
<Copy className="size-4" />
|
|
982
|
+
)}
|
|
979
983
|
</button>
|
|
980
984
|
</div>
|
|
981
985
|
{provider !== undefined && apiKey.trim() === "" && (
|
|
@@ -1035,7 +1039,7 @@ export function ProviderForm({ provider, onSubmit, onCancel }: ProviderFormProps
|
|
|
1035
1039
|
updateModel(i, opt);
|
|
1036
1040
|
setOpenModelDropdown(null);
|
|
1037
1041
|
}}
|
|
1038
|
-
className="w-full px-3 py-2 text-left text-sm transition-colors hover:bg-
|
|
1042
|
+
className="w-full px-3 py-2 text-left text-sm transition-colors hover:bg-muted/60"
|
|
1039
1043
|
>
|
|
1040
1044
|
{opt}
|
|
1041
1045
|
</button>
|
|
@@ -357,9 +357,9 @@ function ProviderTestResultDialog({
|
|
|
357
357
|
<DialogHeader className="border-b border-border/70 px-5 py-4 pr-12">
|
|
358
358
|
<div className="flex items-center gap-2">
|
|
359
359
|
{result.success ? (
|
|
360
|
-
<CheckCircle className="size-4 text-
|
|
360
|
+
<CheckCircle className="size-4 text-status-success" />
|
|
361
361
|
) : (
|
|
362
|
-
<AlertCircle className="size-4 text-
|
|
362
|
+
<AlertCircle className="size-4 text-status-danger" />
|
|
363
363
|
)}
|
|
364
364
|
<DialogTitle className="text-base">{probeLabel}</DialogTitle>
|
|
365
365
|
</div>
|
|
@@ -369,7 +369,7 @@ function ProviderTestResultDialog({
|
|
|
369
369
|
</DialogHeader>
|
|
370
370
|
<div className="space-y-4 overflow-y-auto p-5">
|
|
371
371
|
{!result.success && (
|
|
372
|
-
<div className="rounded-md border border-
|
|
372
|
+
<div className="rounded-md border border-status-danger/30 bg-status-danger/10 px-3 py-2 text-sm text-status-danger">
|
|
373
373
|
<div className="font-medium">{errorLabel(result.error?.type ?? "unknown")}</div>
|
|
374
374
|
<div className="mt-1 break-words text-xs text-muted-foreground">{errorMessage}</div>
|
|
375
375
|
</div>
|
|
@@ -405,8 +405,8 @@ function errorIcon(type: ErrorType): JSX.Element {
|
|
|
405
405
|
}
|
|
406
406
|
|
|
407
407
|
const PROBE_TONE_CLASSES: Record<ProbeTone, string> = {
|
|
408
|
-
success: "bg-
|
|
409
|
-
failure: "bg-
|
|
408
|
+
success: "bg-status-success/10 text-status-success hover:bg-status-success/15",
|
|
409
|
+
failure: "bg-status-danger/10 text-status-danger hover:bg-status-danger/15",
|
|
410
410
|
pending: "bg-muted/40 text-foreground/80",
|
|
411
411
|
quiet: "bg-transparent text-muted-foreground/70",
|
|
412
412
|
};
|
|
@@ -522,11 +522,9 @@ export function ProviderTestMatrix({
|
|
|
522
522
|
</div>
|
|
523
523
|
{hasAnthropic && <ProviderFormatRow label="Anthropic" results={results?.anthropic} />}
|
|
524
524
|
{hasChat && <ProviderFormatRow label="OpenAI Chat" results={results?.openaiChat} />}
|
|
525
|
-
|
|
526
|
-
label="OpenAI Responses"
|
|
527
|
-
|
|
528
|
-
configured={hasResponses}
|
|
529
|
-
/>
|
|
525
|
+
{hasResponses && (
|
|
526
|
+
<ProviderFormatRow label="OpenAI Responses" results={results?.openaiResponses} />
|
|
527
|
+
)}
|
|
530
528
|
</div>
|
|
531
529
|
</div>
|
|
532
530
|
);
|
|
@@ -554,11 +552,11 @@ function FormatSummaryBadge({
|
|
|
554
552
|
const summary = summarizeFormat(results);
|
|
555
553
|
const className =
|
|
556
554
|
summary.failed > 0
|
|
557
|
-
? "border-
|
|
555
|
+
? "border-status-danger/30 bg-status-danger/10 text-status-danger"
|
|
558
556
|
: summary.testing > 0
|
|
559
|
-
? "border-
|
|
557
|
+
? "border-status-watch/30 bg-status-watch/10 text-status-watch"
|
|
560
558
|
: summary.total > 0 && summary.passed === summary.total
|
|
561
|
-
? "border-
|
|
559
|
+
? "border-status-success/30 bg-status-success/10 text-status-success"
|
|
562
560
|
: "border-border/60 bg-transparent text-muted-foreground";
|
|
563
561
|
const value =
|
|
564
562
|
summary.failed > 0
|
|
@@ -688,7 +686,7 @@ export function ProviderTestPill({
|
|
|
688
686
|
|
|
689
687
|
if (isTesting) {
|
|
690
688
|
return (
|
|
691
|
-
<span className="inline-flex items-center gap-1 rounded border border-
|
|
689
|
+
<span className="inline-flex items-center gap-1 rounded border border-status-cool/30 bg-status-cool/10 px-2 py-1 text-xs text-status-cool">
|
|
692
690
|
<RotateCw className="size-3 animate-spin" />
|
|
693
691
|
Testing
|
|
694
692
|
</span>
|
|
@@ -710,7 +708,7 @@ export function ProviderTestPill({
|
|
|
710
708
|
}
|
|
711
709
|
if (summary.failed > 0) {
|
|
712
710
|
return (
|
|
713
|
-
<span className="inline-flex items-center gap-1 rounded border border-
|
|
711
|
+
<span className="inline-flex items-center gap-1 rounded border border-status-danger/30 bg-status-danger/10 px-2 py-1 text-xs text-status-danger">
|
|
714
712
|
<AlertCircle className="size-3" />
|
|
715
713
|
{summary.failed} failed
|
|
716
714
|
</span>
|
|
@@ -718,13 +716,13 @@ export function ProviderTestPill({
|
|
|
718
716
|
}
|
|
719
717
|
if (summary.testing > 0 || summary.passed < summary.total) {
|
|
720
718
|
return (
|
|
721
|
-
<span className="rounded border border-
|
|
719
|
+
<span className="rounded border border-status-watch/30 bg-status-watch/10 px-2 py-1 text-xs text-status-watch">
|
|
722
720
|
{summary.passed}/{summary.total}
|
|
723
721
|
</span>
|
|
724
722
|
);
|
|
725
723
|
}
|
|
726
724
|
return (
|
|
727
|
-
<span className="inline-flex items-center gap-1 rounded border border-
|
|
725
|
+
<span className="inline-flex items-center gap-1 rounded border border-status-success/30 bg-status-success/10 px-2 py-1 text-xs text-status-success">
|
|
728
726
|
<CheckCircle className="size-3" />
|
|
729
727
|
{summary.passed}/{summary.total}
|
|
730
728
|
</span>
|
|
@@ -625,7 +625,7 @@ export function ProvidersPanel({
|
|
|
625
625
|
aria-label={configPathCopied ? "Copied config file path" : "Copy config file path"}
|
|
626
626
|
>
|
|
627
627
|
{configPathCopied ? (
|
|
628
|
-
<Check className="size-3 text-
|
|
628
|
+
<Check className="size-3 text-status-success" />
|
|
629
629
|
) : (
|
|
630
630
|
<Copy className="size-3" />
|
|
631
631
|
)}
|