fix(ui): add Z.AI provider to Add Model

This commit is contained in:
ExDevilLee 2026-08-19 12:09:16 +08:00
parent 5290150a05
commit 0d1eaef4e4
4 changed files with 80 additions and 0 deletions

View file

@ -3240,6 +3240,34 @@
],
"default_model_placeholder": "gpt-3.5-turbo"
},
{
"provider": "ZAI",
"provider_display_name": "Z.AI",
"litellm_provider": "zai",
"credential_fields": [
{
"key": "api_key",
"label": "API Key",
"placeholder": "your-zai-api-key",
"tooltip": "Z.AI API Key from https://z.ai/manage-apikey/apikey-list",
"required": true,
"field_type": "password",
"options": null,
"default_value": null
},
{
"key": "api_base",
"label": "API Base",
"placeholder": "https://api.z.ai/api/paas/v4",
"tooltip": "General: https://api.z.ai/api/paas/v4. GLM Coding Plan: https://api.z.ai/api/coding/paas/v4. Override for self-hosted endpoints.",
"required": false,
"field_type": "text",
"options": null,
"default_value": "https://api.z.ai/api/paas/v4"
}
],
"default_model_placeholder": "zai/glm-4.6"
},
{
"provider": "CURSOR",
"provider_display_name": "Cursor",

View file

@ -63,6 +63,28 @@ def test_get_provider_create_fields():
), "Expected at least one provider to have detailed credential fields"
def test_zai_provider_fields():
app_instance = FastAPI()
app_instance.include_router(router)
client = TestClient(app_instance)
response = client.get("/public/providers/fields")
assert response.status_code == 200
providers = response.json()
zai = next((provider for provider in providers if provider["provider"] == "ZAI"), None)
assert zai is not None
assert zai["provider_display_name"] == "Z.AI"
assert zai["litellm_provider"] == "zai"
assert zai["default_model_placeholder"] == "zai/glm-4.6"
credential_fields = {field["key"]: field for field in zai["credential_fields"]}
assert credential_fields["api_key"]["required"] is True
assert credential_fields["api_key"]["field_type"] == "password"
assert credential_fields["api_base"]["default_value"] == "https://api.z.ai/api/paas/v4"
def test_get_litellm_model_cost_map_returns_cost_map():
app = FastAPI()
app.include_router(router)

View file

@ -340,6 +340,35 @@ describe("AddModelForm", () => {
});
});
it("should allow searching providers by their LiteLLM provider slug", async () => {
const mockUseAuthorized = vi.mocked(await import("@/app/(dashboard)/hooks/useAuthorized"));
const mockUseProviderFields = vi.mocked(await import("@/app/(dashboard)/hooks/providers/useProviderFields"));
mockUseAuthorized.default.mockReturnValue(mockAuthorizedUser("proxy_admin", "user-1", true));
mockUseProviderFields.useProviderFields.mockReturnValue({
data: [
{
provider: "ZAI",
provider_display_name: "Z.AI",
litellm_provider: "zai",
default_model_placeholder: "zai/glm-4.6",
credential_fields: [],
},
],
isLoading: false,
error: null,
});
const props = createTestProps();
const user = userEvent.setup({ pointerEventsCheck: PointerEventsCheckLevel.Never });
renderWithProviders(<AddModelForm {...props} />);
const providerSelect = await screen.findByRole("combobox", { name: /provider/i });
await user.click(providerSelect);
await user.type(providerSelect, "zai");
expect(await screen.findByText("Z.AI")).toBeInTheDocument();
});
describe("cache control bindings reach the parent form store", () => {
const renderWithForm = async () => {
const mockUseAuthorized = vi.mocked(await import("@/app/(dashboard)/hooks/useAuthorized"));

View file

@ -123,6 +123,7 @@ const AddModelForm: React.FC<AddModelFormProps> = ({
() =>
sortedProviderMetadata.map((providerInfo) => ({
label: providerInfo.provider_display_name,
sublabel: providerInfo.litellm_provider,
value: providerInfo.provider,
icon: <ProviderLogo provider={providerInfo.provider} className="w-5 h-5" />,
})),