fix(nvidia_nim): localize model discovery controls

This commit is contained in:
mateo-berri 2026-11-06 11:46:21 -08:00
parent c1935885c3
commit 2a81e276cb
4 changed files with 38 additions and 6 deletions

View file

@ -67,6 +67,7 @@ GET /user/spend/report
# Admin UI helper endpoints; serve UI forms and caller-scoped views, not desired state
GET /budget/settings
GET /credentials/{credential_name}/jwks
POST /credentials/nvidia_nim/models # Credential-scoped upstream discovery, not Terraform-managed state
GET /router/fields
GET /guardrails/ui/add_guardrail_settings
GET /guardrails/ui/category_yaml/{category_name}

View file

@ -7,6 +7,7 @@ import type { MountedFormValues } from "../common_components/MountedFormField";
import { apiClient } from "../networking";
import { getPlaceholder, Providers } from "../provider_info_helpers";
import NimModelNameField from "./NimModelNameField";
import i18n from "@/i18n/i18n";
vi.mock("../networking", () => ({ apiClient: { post: vi.fn() } }));
const catalogModel = "nvidia_nim/catalog-model";
@ -77,6 +78,30 @@ describe("NIM model discovery", () => {
});
});
it("translates discovery status and refresh controls in the selected language", async () => {
const previousLanguage = i18n.language;
i18n.addResourceBundle("es", "translation", {
addModel: {
nimModelDiscovery: {
loading: "Translated loading",
unavailable: "Translated unavailable",
refresh: "Translated refresh",
},
},
});
try {
await act(() => i18n.changeLanguage("es"));
vi.mocked(apiClient.post).mockResolvedValue({ status: "unavailable", models: [] });
render(<Form />);
expect(screen.getByText("Translated loading")).toBeInTheDocument();
expect(await screen.findByText("Translated unavailable")).toBeInTheDocument();
expect(screen.getByRole("button", { name: "Translated refresh" })).toBeEnabled();
} finally {
await act(() => i18n.changeLanguage(previousLanguage));
i18n.removeResourceBundle("es", "translation");
}
});
it("keeps the catalog usable when upstream discovery is unavailable", async () => {
vi.mocked(apiClient.post).mockResolvedValue({ status: "unavailable", models: [] });
render(<Form />);

View file

@ -1,5 +1,6 @@
import { useEffect, useMemo, useState, type ComponentProps } from "react";
import { useFormContext, useWatch } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { apiClient } from "../networking";
import { resolveLitellmProviderSlug } from "../provider_info_helpers";
import type { MountedFormValues } from "../common_components/MountedFormField";
@ -17,6 +18,7 @@ type Props = ComponentProps<typeof LiteLLMModelNameField> & {
};
export default function NimModelNameField({ accessToken, canDiscover, ...props }: Props) {
const { t } = useTranslation();
const { control } = useFormContext<MountedFormValues>();
const credential = useWatch({ control, name: "litellm_credential_name" });
const apiKey = useWatch({ control, name: "api_key" });
@ -86,11 +88,9 @@ export default function NimModelNameField({ accessToken, canDiscover, ...props }
{enabled && (
<div className="mb-4 text-sm text-muted-foreground">
<p role="status">
{!current && "Loading models from NVIDIA NIM"}
{current?.status === "success" &&
"Models listed by your NIM endpoint. Inference access and capabilities may vary"}
{current?.status === "unavailable" &&
"Could not refresh NIM models. Showing the built-in catalog. You can also enter a custom model"}
{!current && t("addModel.nimModelDiscovery.loading")}
{current?.status === "success" && t("addModel.nimModelDiscovery.success")}
{current?.status === "unavailable" && t("addModel.nimModelDiscovery.unavailable")}
</p>
<Button
type="button"
@ -99,7 +99,7 @@ export default function NimModelNameField({ accessToken, canDiscover, ...props }
disabled={!current}
onClick={() => setAttempt((value) => value + 1)}
>
Refresh NIM models
{t("addModel.nimModelDiscovery.refresh")}
</Button>
</div>
)}

View file

@ -18523,6 +18523,12 @@
"decisionModelSelect": {
"label": "Decision model",
"placeholder": "Select the decision model"
},
"nimModelDiscovery": {
"loading": "Loading models from NVIDIA NIM",
"success": "Models listed by your NIM endpoint. Inference access and capabilities may vary",
"unavailable": "Could not refresh NIM models. Showing the built-in catalog. You can also enter a custom model",
"refresh": "Refresh NIM models"
}
},
"modelAdd": {