Fetch provider names only for failed runs, through a shared helper

Every run page asked for the provider catalog, though only a failed or
dead run's banner uses it. useProviders takes an enabled flag, and the
id-to-display-name map settings-models built by hand is now
providerNamesById, shared with the run page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Scott Werner 2026-10-27 14:01:35 -04:00
parent 7a769525c4
commit 758ddc532b
4 changed files with 17 additions and 10 deletions

View file

@ -1,4 +1,4 @@
import type { Model } from "@qltysh/fabro-api-client";
import type { Model, Provider } from "@qltysh/fabro-api-client";
type ModelOfferingIdentity = Pick<Model, "provider" | "id">;
@ -6,6 +6,13 @@ export function modelOfferingKey(model: ModelOfferingIdentity): string {
return `${model.provider}\u0000${model.id}`;
}
/** Provider ids to the names the catalog displays, falling back to the id. */
export function providerNamesById(
providers: readonly Pick<Provider, "id" | "display_name">[],
): Map<string, string> {
return new Map(providers.map((p) => [p.id, p.display_name || p.id]));
}
export function modelOfferingTestArgs(
model: ModelOfferingIdentity,
): [id: string, provider: string] {

View file

@ -534,9 +534,10 @@ export function useServerSettings() {
);
}
export function useProviders() {
/** The provider catalog; `enabled: false` skips the request. */
export function useProviders({ enabled = true }: { enabled?: boolean } = {}) {
return useSWR<ProviderList>(
queryKeys.providers.list(),
enabled ? queryKeys.providers.list() : null,
() => apiData(() => modelsApi.listProviders()),
immutableOptions,
);

View file

@ -36,6 +36,7 @@ import {
import { useRunEvents } from "../lib/run-events";
import { useRunToasts } from "../hooks/use-run-toasts";
import { useProviders, useRun, useRunQuestions, useRunState } from "../lib/queries";
import { providerNamesById } from "../lib/model-offerings";
import {
canApprove,
deleteErrorMessage,
@ -151,9 +152,10 @@ export default function RunDetail({ params }: { params: { id: string } }) {
useRunEvents(params.id);
useRunToasts(params.id);
const providersQuery = useProviders();
// Provider names only matter to a failed run's banner.
const providersQuery = useProviders({ enabled: statusKind === "failed" || statusKind === "dead" });
const providerNames = useMemo(
() => new Map((providersQuery.data?.data ?? []).map((p) => [p.id, p.display_name || p.id])),
() => providerNamesById(providersQuery.data?.data ?? []),
[providersQuery.data],
);
const failure = buildRunFailureView(runStateQuery.data, {

View file

@ -31,6 +31,7 @@ import { formatContextWindow, formatTokensPerSecond } from "../lib/format";
import {
modelOfferingKey,
modelOfferingTestArgs,
providerNamesById,
} from "../lib/model-offerings";
import { useDebouncedValue } from "../hooks/effects";
@ -244,11 +245,7 @@ function ModelsSection({ providers }: { providers: Provider[] }) {
const { data, isLoading } = useModels(providerFilter, debouncedSearch);
const providerNameById = useMemo(() => {
const map = new Map<string, string>();
for (const p of providers) map.set(p.id, p.display_name || p.id);
return map;
}, [providers]);
const providerNameById = useMemo(() => providerNamesById(providers), [providers]);
const rows = useMemo(() => {
const all = (data?.data ?? []).filter((m) => m.configured);