mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-08-29 18:31:33 +00:00
Fix private AI custom endpoints (#1299)
This commit is contained in:
@@ -114,7 +114,11 @@ export async function probeAiModels(input: {
|
||||
baseUrl?: string | null;
|
||||
apiKey?: string | null;
|
||||
providerId?: number | null;
|
||||
}): Promise<{ models: string[]; source: "live" | "fallback" | "none" }> {
|
||||
}): Promise<{
|
||||
models: string[];
|
||||
source: "live" | "fallback" | "none";
|
||||
warning?: string;
|
||||
}> {
|
||||
try {
|
||||
return (await authApi.post("/ai/probe-models", input)).data;
|
||||
} catch (error) {
|
||||
|
||||
@@ -85,21 +85,24 @@ function AiProviderEditForm({
|
||||
const [models, setModels] = useState<string[]>([]);
|
||||
const [customModel, setCustomModel] = useState(false);
|
||||
const [detecting, setDetecting] = useState(false);
|
||||
const [detectWarning, setDetectWarning] = useState<string | null>(null);
|
||||
const [saving, setSaving] = useState(false);
|
||||
|
||||
const detectModels = useCallback(async () => {
|
||||
setDetecting(true);
|
||||
setDetectWarning(null);
|
||||
try {
|
||||
const detected = await getAiProviderModels(provider.id);
|
||||
setModels(detected);
|
||||
setCustomModel(!!defaultModel && !detected.includes(defaultModel));
|
||||
} catch {
|
||||
} catch (error) {
|
||||
setModels([]);
|
||||
setCustomModel(true);
|
||||
setDetectWarning(getErrorMessage(error, t("ai.modelDetectFailed")));
|
||||
} finally {
|
||||
setDetecting(false);
|
||||
}
|
||||
}, [provider.id, defaultModel]);
|
||||
}, [provider.id, defaultModel, t]);
|
||||
|
||||
useEffect(() => {
|
||||
void detectModels();
|
||||
@@ -203,6 +206,11 @@ function AiProviderEditForm({
|
||||
placeholder={t("ai.defaultModelPlaceholder")}
|
||||
/>
|
||||
)}
|
||||
{detectWarning && (
|
||||
<p className="text-[11px] leading-snug text-destructive">
|
||||
{detectWarning}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2">
|
||||
@@ -269,8 +277,8 @@ export function AiProviderSettings({
|
||||
apiKey: apiKey.trim() || null,
|
||||
});
|
||||
setModels(result.models);
|
||||
if (result.source === "fallback") {
|
||||
setDetectWarning(t("ai.modelDetectFailed"));
|
||||
if (result.source !== "live") {
|
||||
setDetectWarning(result.warning || t("ai.modelDetectFailed"));
|
||||
}
|
||||
// Pick the first suggestion so the field is never left empty.
|
||||
setDefaultModel((current) => current || result.models[0] || "");
|
||||
|
||||
@@ -82,4 +82,17 @@ describe("AiProviderSettings", () => {
|
||||
screen.getByRole("combobox", { name: "ai.defaultModel" }),
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it("shows the provider error when refreshing models fails", async () => {
|
||||
api.getAiProviderModels.mockRejectedValue(
|
||||
new Error("Add llm.internal to the AI endpoint allowlist"),
|
||||
);
|
||||
render(<AiProviderSettings providers={[provider]} onChanged={() => {}} />);
|
||||
|
||||
fireEvent.click(screen.getByRole("button", { name: "ai.editProvider" }));
|
||||
|
||||
expect(
|
||||
await screen.findByText("Add llm.internal to the AI endpoint allowlist"),
|
||||
).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user