Fix model list not showing

This commit is contained in:
yuneng-jiang 2026-01-13 18:16:26 -08:00
parent 7c57138398
commit 851006790c
2 changed files with 309 additions and 8 deletions

View file

@ -0,0 +1,301 @@
import { afterEach, describe, expect, it, vi } from "vitest";
import {
Providers,
getPlaceholder,
getProviderLogoAndName,
getProviderModels,
providerLogoMap,
provider_map,
} from "./provider_info_helpers";
describe("provider_info_helpers", () => {
describe("getProviderLogoAndName", () => {
it("should return empty logo and dash display name when providerValue is empty", () => {
const result = getProviderLogoAndName("");
expect(result).toEqual({ logo: "", displayName: "-" });
});
it("should return empty logo and dash display name when providerValue is undefined", () => {
const result = getProviderLogoAndName(undefined as any);
expect(result).toEqual({ logo: "", displayName: "-" });
});
it("should handle gemini provider value case-insensitively", () => {
const result = getProviderLogoAndName("gemini");
expect(result.displayName).toBe(Providers.Google_AI_Studio);
expect(result.logo).toBe(providerLogoMap[Providers.Google_AI_Studio]);
});
it("should handle GEMINI provider value in uppercase", () => {
const result = getProviderLogoAndName("GEMINI");
expect(result.displayName).toBe(Providers.Google_AI_Studio);
expect(result.logo).toBe(providerLogoMap[Providers.Google_AI_Studio]);
});
it("should map openai provider value to OpenAI display name and logo", () => {
const result = getProviderLogoAndName("openai");
expect(result.displayName).toBe(Providers.OpenAI);
expect(result.logo).toBe(providerLogoMap[Providers.OpenAI]);
});
it("should map anthropic provider value to Anthropic display name and logo", () => {
const result = getProviderLogoAndName("anthropic");
expect(result.displayName).toBe(Providers.Anthropic);
expect(result.logo).toBe(providerLogoMap[Providers.Anthropic]);
});
it("should map azure provider value to Azure display name and logo", () => {
const result = getProviderLogoAndName("azure");
expect(result.displayName).toBe(Providers.Azure);
expect(result.logo).toBe(providerLogoMap[Providers.Azure]);
});
it("should map bedrock provider value to Bedrock display name and logo", () => {
const result = getProviderLogoAndName("bedrock");
expect(result.displayName).toBe(Providers.Bedrock);
expect(result.logo).toBe(providerLogoMap[Providers.Bedrock]);
});
it("should map groq provider value to Groq display name and logo", () => {
const result = getProviderLogoAndName("groq");
expect(result.displayName).toBe(Providers.Groq);
expect(result.logo).toBe(providerLogoMap[Providers.Groq]);
});
it("should handle provider values case-insensitively", () => {
const result = getProviderLogoAndName("OPENAI");
expect(result.displayName).toBe(Providers.OpenAI);
expect(result.logo).toBe(providerLogoMap[Providers.OpenAI]);
});
it("should return provider value as display name when no mapping exists", () => {
const unknownProvider = "unknown_provider";
const result = getProviderLogoAndName(unknownProvider);
expect(result.displayName).toBe(unknownProvider);
expect(result.logo).toBe("");
});
it("should map provider_map values to valid display names", () => {
const uniqueProviderValues = new Set(Object.values(provider_map));
uniqueProviderValues.forEach((providerValue) => {
if (providerValue.toLowerCase() !== "gemini") {
const result = getProviderLogoAndName(providerValue);
expect(result.displayName).not.toBe("-");
expect(result.displayName).toBeTruthy();
}
});
});
});
describe("getPlaceholder", () => {
it("should return aiml placeholder for AIML provider", () => {
expect(getPlaceholder(Providers.AIML)).toBe("aiml/flux-pro/v1.1");
});
it("should return gemini-pro placeholder for Vertex_AI provider", () => {
expect(getPlaceholder(Providers.Vertex_AI)).toBe("gemini-pro");
});
it("should return claude-3-opus placeholder for Anthropic provider", () => {
expect(getPlaceholder(Providers.Anthropic)).toBe("claude-3-opus");
});
it("should return claude-3-opus placeholder for Bedrock provider", () => {
expect(getPlaceholder(Providers.Bedrock)).toBe("claude-3-opus");
});
it("should return sagemaker placeholder for SageMaker provider", () => {
expect(getPlaceholder(Providers.SageMaker)).toBe("sagemaker/jumpstart-dft-meta-textgeneration-llama-2-7b");
});
it("should return gemini-pro placeholder for Google_AI_Studio provider", () => {
expect(getPlaceholder(Providers.Google_AI_Studio)).toBe("gemini-pro");
});
it("should return azure_ai placeholder for Azure_AI_Studio provider", () => {
expect(getPlaceholder(Providers.Azure_AI_Studio)).toBe("azure_ai/command-r-plus");
});
it("should return my-deployment placeholder for Azure provider", () => {
expect(getPlaceholder(Providers.Azure)).toBe("my-deployment");
});
it("should return oci placeholder for Oracle provider", () => {
expect(getPlaceholder(Providers.Oracle)).toBe("oci/xai.grok-4");
});
it("should return snowflake placeholder for Snowflake provider", () => {
expect(getPlaceholder(Providers.Snowflake)).toBe("snowflake/mistral-7b");
});
it("should return voyage placeholder for Voyage provider", () => {
expect(getPlaceholder(Providers.Voyage)).toBe("voyage/");
});
it("should return jina_ai placeholder for JinaAI provider", () => {
expect(getPlaceholder(Providers.JinaAI)).toBe("jina_ai/");
});
it("should return volcengine placeholder for VolcEngine provider", () => {
expect(getPlaceholder(Providers.VolcEngine)).toBe("volcengine/<any-model-on-volcengine>");
});
it("should return deepinfra placeholder for DeepInfra provider", () => {
expect(getPlaceholder(Providers.DeepInfra)).toBe("deepinfra/<any-model-on-deepinfra>");
});
it("should return fal_ai placeholder for FalAI provider", () => {
expect(getPlaceholder(Providers.FalAI)).toBe("fal_ai/fal-ai/flux-pro/v1.1-ultra");
});
it("should return runwayml placeholder for RunwayML provider", () => {
expect(getPlaceholder(Providers.RunwayML)).toBe("runwayml/gen4_turbo");
});
it("should return watsonx placeholder for Watsonx provider", () => {
expect(getPlaceholder(Providers.Watsonx)).toBe("watsonx/ibm/granite-3-3-8b-instruct");
});
it("should return default gpt-3.5-turbo placeholder for unknown provider", () => {
expect(getPlaceholder("UnknownProvider" as any)).toBe("gpt-3.5-turbo");
});
it("should return default gpt-3.5-turbo placeholder for OpenAI provider", () => {
expect(getPlaceholder(Providers.OpenAI)).toBe("gpt-3.5-turbo");
});
});
describe("getProviderModels", () => {
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => {});
afterEach(() => {
consoleSpy.mockClear();
});
it("should return empty array when provider is not provided", () => {
const modelMap = {};
const result = getProviderModels(undefined as any, modelMap);
expect(result).toEqual([]);
});
it("should return empty array when modelMap is not an object type", () => {
const result = getProviderModels(Providers.OpenAI, "not-an-object" as any);
expect(result).toEqual([]);
});
it("should return empty array when modelMap is undefined", () => {
const result = getProviderModels(Providers.OpenAI, undefined as any);
expect(result).toEqual([]);
});
it("should return empty array when modelMap is empty", () => {
const modelMap = {};
const result = getProviderModels(Providers.OpenAI, modelMap);
expect(result).toEqual([]);
});
it("should return models matching the provider from modelMap", () => {
const modelMap = {
"gpt-3.5-turbo": { litellm_provider: "openai" },
"gpt-4": { litellm_provider: "openai" },
"claude-3-opus": { litellm_provider: "anthropic" },
};
const result = getProviderModels(Providers.OpenAI, modelMap);
expect(result).toEqual(["gpt-3.5-turbo", "gpt-4"]);
});
it("should return models when litellm_provider includes the provider string", () => {
const modelMap = {
"custom-openai-model": { litellm_provider: "custom_openai_endpoint" },
"another-model": { litellm_provider: "openai" },
};
const result = getProviderModels(Providers.OpenAI, modelMap);
expect(result).toContain("custom-openai-model");
expect(result).toContain("another-model");
});
it("should filter out models with null values", () => {
const modelMap = {
"gpt-3.5-turbo": { litellm_provider: "openai" },
"null-model": null,
"gpt-4": { litellm_provider: "openai" },
};
const result = getProviderModels(Providers.OpenAI, modelMap);
expect(result).toEqual(["gpt-3.5-turbo", "gpt-4"]);
});
it("should filter out models without litellm_provider property", () => {
const modelMap = {
"gpt-3.5-turbo": { litellm_provider: "openai" },
"no-provider-model": { someOtherProperty: "value" },
};
const result = getProviderModels(Providers.OpenAI, modelMap);
expect(result).toEqual(["gpt-3.5-turbo"]);
});
it("should include both cohere and cohere_chat models for Cohere provider", () => {
const modelMap = {
"cohere-model-1": { litellm_provider: "cohere" },
"cohere-model-2": { litellm_provider: "cohere_chat" },
"other-model": { litellm_provider: "openai" },
};
const result = getProviderModels(Providers.Cohere, modelMap);
expect(result).toContain("cohere-model-1");
expect(result).toContain("cohere-model-2");
expect(result).not.toContain("other-model");
expect(result.length).toBeGreaterThanOrEqual(2);
});
it("should include sagemaker_chat models for SageMaker provider", () => {
const modelMap = {
"sagemaker-model-1": { litellm_provider: "sagemaker_chat" },
"sagemaker-model-2": { litellm_provider: "sagemaker" },
"other-model": { litellm_provider: "openai" },
};
const result = getProviderModels(Providers.SageMaker, modelMap);
expect(result).toContain("sagemaker-model-1");
expect(result).not.toContain("other-model");
});
it("should handle modelMap with non-object values", () => {
const modelMap = {
"string-model": "not-an-object",
"number-model": 123,
"valid-model": { litellm_provider: "openai" },
};
const result = getProviderModels(Providers.OpenAI, modelMap);
expect(result).toEqual(["valid-model"]);
});
it("should log provider key and mapped provider when called", () => {
const modelMap = { "gpt-3.5-turbo": { litellm_provider: "openai" } };
getProviderModels(Providers.OpenAI, modelMap);
expect(consoleSpy).toHaveBeenCalledWith(`Provider key: ${Providers.OpenAI}`);
expect(consoleSpy).toHaveBeenCalledWith(`Provider mapped to: ${provider_map[Providers.OpenAI]}`);
});
it("should return empty array for provider with no matching models", () => {
const modelMap = {
"gpt-3.5-turbo": { litellm_provider: "openai" },
"claude-3-opus": { litellm_provider: "anthropic" },
};
const result = getProviderModels(Providers.Bedrock, modelMap);
expect(result).toEqual([]);
});
it("should handle multiple providers correctly", () => {
const modelMap = {
"gpt-3.5-turbo": { litellm_provider: "openai" },
"claude-3-opus": { litellm_provider: "anthropic" },
"groq-model": { litellm_provider: "groq" },
};
const openaiResult = getProviderModels(Providers.OpenAI, modelMap);
const anthropicResult = getProviderModels(Providers.Anthropic, modelMap);
const groqResult = getProviderModels(Providers.Groq, modelMap);
expect(openaiResult).toEqual(["gpt-3.5-turbo"]);
expect(anthropicResult).toEqual(["claude-3-opus"]);
expect(groqResult).toContain("groq-model");
});
});
});

View file

@ -221,14 +221,14 @@ export const getProviderModels = (provider: Providers, modelMap: any): Array<str
if (providerKey && typeof modelMap === "object") {
Object.entries(modelMap).forEach(([key, value]) => {
if (
value !== null &&
typeof value === "object" &&
"litellm_provider" in (value as object) &&
((value as any)["litellm_provider"] === custom_llm_provider ||
(value as any)["litellm_provider"].includes(custom_llm_provider))
) {
providerModels.push(key);
if (value !== null && typeof value === "object" && "litellm_provider" in (value as object)) {
const litellmProvider = (value as any)["litellm_provider"];
if (
litellmProvider === custom_llm_provider ||
(typeof litellmProvider === "string" && litellmProvider.includes(custom_llm_provider))
) {
providerModels.push(key);
}
}
});
// Special case for cohere