fix(frontend): show session catalog in pi management

This commit is contained in:
User
2026-09-08 14:58:18 +02:00
parent e68e80a33d
commit 8fe526dd6e
2 changed files with 60 additions and 1 deletions
+20 -1
View File
@@ -23,7 +23,10 @@ function renderManagement() {
}
beforeEach(() => {
server.use(http.get("/api/pi-management/status", () => HttpResponse.json(readyStatus)));
server.use(
http.get("/api/pi-management/status", () => HttpResponse.json(readyStatus)),
http.get("/api/models", () => HttpResponse.json({ models: [] })),
);
});
test("shows the catalog default as read-only installation state", async () => {
@@ -49,6 +52,22 @@ test("shows the catalog default as read-only installation state", async () => {
expect(document.querySelector('input[type="password"]')).toBeNull();
});
test("shows every session model exposed by Core", async () => {
server.use(http.get("/api/models", () => HttpResponse.json({ models: [
{ provider: "zai", id: "glm-5.3", name: "GLM 5.3", reasoning: true },
{ provider: "deepseek", id: "deepseek-v4-pro", name: "DeepSeek V4 Pro", reasoning: true },
{ provider: "deepseek", id: "deepseek-v4-flash", name: "DeepSeek V4 Flash", reasoning: true },
{ provider: "local-qwen", id: "qwen3.6-35b-a3b", name: "Local Qwen 3.6 35B A3B", reasoning: false },
] })));
renderManagement();
const catalog = await screen.findByRole("region", { name: "Session models" });
expect(catalog).toHaveTextContent("GLM 5.3");
expect(catalog).toHaveTextContent("DeepSeek V4 Pro");
expect(catalog).toHaveTextContent("DeepSeek V4 Flash");
expect(catalog).toHaveTextContent("Local Qwen 3.6 35B A3B");
});
test("tests the catalog default without mutating credential presence", async () => {
const user = userEvent.setup();
let tests = 0;
+40
View File
@@ -7,6 +7,7 @@ import {
getPiManagementStatus,
runPiManagementTest,
} from "../api/pi-management";
import { listModels } from "../api/models";
import { Button } from "../components/ui/button";
import { WorkAreaPanel } from "./WorkAreaPanel";
@@ -280,6 +281,7 @@ export function PiManagement({ open, onClose }: { open: boolean; onClose: () =>
const [smokeState, setSmokeState] = useState<SmokeState>();
const [logsRequested, setLogsRequested] = useState(false);
const statusQuery = useQuery({ queryKey: ["pi-management", "status"], queryFn: getPiManagementStatus, enabled: open });
const modelsQuery = useQuery({ queryKey: ["models"], queryFn: listModels, enabled: open });
const logsQuery = useQuery({ queryKey: ["pi-management", "logs"], queryFn: getPiManagementLogs, enabled: open && logsRequested });
const catalogReady = Boolean(
statusQuery.data?.config.provider
@@ -402,6 +404,44 @@ export function PiManagement({ open, onClose }: { open: boolean; onClose: () =>
)}
</section>
<section aria-label="Session models" className="border-t border-border/70 pt-5">
<div className="flex flex-wrap items-baseline justify-between gap-2">
<div>
<h3 className="font-heading text-sm font-semibold">Session models</h3>
<p className="mt-1 text-sm text-muted-foreground">Models currently available for interactive sessions in this installation.</p>
</div>
{modelsQuery.data && (
<span className="font-mono text-xs tabular-nums text-muted-foreground">{modelsQuery.data.models.length} available</span>
)}
</div>
{modelsQuery.isLoading ? (
<p className="mt-4 text-sm text-muted-foreground">Loading session models…</p>
) : modelsQuery.isError ? (
<div className="mt-4 flex flex-wrap items-center justify-between gap-3" role="alert">
<p className="text-sm text-destructive">Could not load the session model catalog.</p>
<Button size="sm" variant="ghost" onClick={() => { void modelsQuery.refetch(); }}>Retry models</Button>
</div>
) : modelsQuery.data?.models.length ? (
<ul className="mt-4 divide-y divide-border/70 border-y border-border/70">
{modelsQuery.data.models.map((model) => {
const isDefault = statusQuery.data.config.provider === model.provider
&& statusQuery.data.config.model === model.id;
return (
<li key={model.provider + "/" + model.id} className="flex min-w-0 items-center justify-between gap-4 py-3">
<div className="min-w-0">
<p className="truncate text-sm font-semibold" title={model.name}>{model.name}</p>
<p className="mt-0.5 truncate font-mono text-xs text-muted-foreground" title={model.provider + "/" + model.id}>{model.provider}/{model.id}</p>
</div>
{isDefault && <span className="shrink-0 rounded-md bg-muted px-2 py-1 text-xs font-semibold text-foreground">Default</span>}
</li>
);
})}
</ul>
) : (
<p className="mt-4 text-sm text-muted-foreground">No session models are configured for this installation.</p>
)}
</section>
<section aria-label="Sanitized diagnostics" className="border-t border-border/70 pt-5">
<div className="flex flex-wrap items-center justify-between gap-3">
<div><h3 className="font-heading text-sm font-semibold">Sanitized diagnostics</h3><p className="mt-1 text-sm text-muted-foreground">Shows at most 200 recent lines with declared secret values removed.</p></div>