mirror of
https://github.com/cline/cline.git
synced 2026-09-17 17:45:33 +08:00
Fix other instances of issues with the litellm model list (#11773)
* Fix other instances of issues with the litellm model list * address comment
This commit is contained in:
@@ -309,6 +309,47 @@ describe("resolveProviderConfig", () => {
|
||||
expect(resolved?.knownModels?.["gpt-5.4"]).toBeUndefined();
|
||||
});
|
||||
|
||||
it("returns an empty authoritative LiteLLM model list without auth", async () => {
|
||||
const fetchMock = vi.fn();
|
||||
vi.stubGlobal("fetch", fetchMock);
|
||||
|
||||
const resolved = await resolveProviderConfig(
|
||||
"litellm",
|
||||
{ failOnError: true, cacheTtlMs: 0 },
|
||||
{
|
||||
providerId: "litellm",
|
||||
modelId: "",
|
||||
baseUrl: "http://localhost:4000/v1/",
|
||||
},
|
||||
);
|
||||
|
||||
expect(fetchMock).not.toHaveBeenCalled();
|
||||
expect(resolved?.knownModels).toEqual({});
|
||||
expect(resolved?.knownModels?.["gpt-5.4"]).toBeUndefined();
|
||||
});
|
||||
|
||||
it("does not fall back to bundled LiteLLM models when private model fetch fails non-strictly", async () => {
|
||||
const fetchMock = vi.fn(
|
||||
async () => new Response('{"error":"unauthorized"}', { status: 401 }),
|
||||
);
|
||||
vi.stubGlobal("fetch", fetchMock);
|
||||
|
||||
const resolved = await resolveProviderConfig(
|
||||
"litellm",
|
||||
{ failOnError: false, cacheTtlMs: 0 },
|
||||
{
|
||||
providerId: "litellm",
|
||||
modelId: "",
|
||||
apiKey: "litellm-key",
|
||||
baseUrl: "http://localhost:4000",
|
||||
},
|
||||
);
|
||||
|
||||
expect(fetchMock).toHaveBeenCalled();
|
||||
expect(resolved?.knownModels).toEqual({});
|
||||
expect(resolved?.knownModels?.["gpt-5.4"]).toBeUndefined();
|
||||
});
|
||||
|
||||
it("reports attempted path, auth header, status, and body for LiteLLM model fetch failures", async () => {
|
||||
const fetchMock = vi.fn(
|
||||
async () => new Response('{"error":"unauthorized"}', { status: 401 }),
|
||||
|
||||
@@ -149,6 +149,10 @@ async function mergeKnownModels(
|
||||
publicModels: Record<string, ModelInfo> = {},
|
||||
userKnownModels: Record<string, ModelInfo> = {},
|
||||
): Promise<Record<string, ModelInfo>> {
|
||||
if (providerId === "litellm") {
|
||||
return Llms.sortModelsByReleaseDate(privateModels);
|
||||
}
|
||||
|
||||
const generatedProviderModels = await loadGeneratedProviderModels();
|
||||
const generatedKeys = Llms.resolveProviderModelCatalogKeys(providerId);
|
||||
const generated = Object.assign(
|
||||
@@ -171,16 +175,6 @@ async function mergeKnownModels(
|
||||
...userKnownModels,
|
||||
});
|
||||
}
|
||||
// LiteLLM model access is configured by the user's proxy. When the proxy
|
||||
// returns a private model list, treat it as the authoritative allowlist so
|
||||
// the picker does not show bundled OpenAI-compatible catalog entries that the
|
||||
// proxy may not actually expose.
|
||||
if (providerId === "litellm" && Object.keys(privateModels).length > 0) {
|
||||
return Llms.sortModelsByReleaseDate({
|
||||
...privateModels,
|
||||
...userKnownModels,
|
||||
});
|
||||
}
|
||||
if (providerId === "openai-codex") {
|
||||
return Llms.sortModelsByReleaseDate({
|
||||
...defaultKnownModels,
|
||||
@@ -937,6 +931,12 @@ export async function resolveProviderConfig(
|
||||
if (modelCatalog?.failOnError) {
|
||||
throw error;
|
||||
}
|
||||
if (providerId === "litellm") {
|
||||
return {
|
||||
...defaults,
|
||||
knownModels: {},
|
||||
};
|
||||
}
|
||||
return defaults;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -598,7 +598,7 @@ describe("addLocalProvider – capabilities", () => {
|
||||
expect(models[0].supportsReasoning).toBeFalsy();
|
||||
});
|
||||
|
||||
it("merges LiteLLM private models into the provider model listing when auth is configured", async () => {
|
||||
it("uses LiteLLM private models as the authoritative provider model listing when auth is configured", async () => {
|
||||
manager.saveProviderSettings(
|
||||
{
|
||||
provider: "litellm",
|
||||
@@ -632,8 +632,11 @@ describe("addLocalProvider – capabilities", () => {
|
||||
manager.getProviderConfig("litellm"),
|
||||
);
|
||||
|
||||
expect(models.map((model) => model.id)).toContain("private-proxy-model");
|
||||
expect(models.map((model) => model.id)).toContain("openai/gpt-4o-mini");
|
||||
expect(models.map((model) => model.id).sort()).toEqual([
|
||||
"openai/gpt-4o-mini",
|
||||
"private-proxy-model",
|
||||
]);
|
||||
expect(models.map((model) => model.id)).not.toContain("gpt-5.4");
|
||||
expect(
|
||||
models.find((model) => model.id === "private-proxy-model"),
|
||||
).toMatchObject({
|
||||
@@ -641,6 +644,27 @@ describe("addLocalProvider – capabilities", () => {
|
||||
supportsReasoning: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("uses an empty LiteLLM model list when no private model list is fetched", async () => {
|
||||
manager.saveProviderSettings(
|
||||
{
|
||||
provider: "litellm",
|
||||
baseUrl: "http://localhost:4010",
|
||||
model: "gpt-4o",
|
||||
},
|
||||
{ setLastUsed: false },
|
||||
);
|
||||
const fetchMock = vi.fn();
|
||||
vi.stubGlobal("fetch", fetchMock);
|
||||
|
||||
const { models } = await getLocalProviderModels(
|
||||
"litellm",
|
||||
manager.getProviderConfig("litellm"),
|
||||
);
|
||||
|
||||
expect(fetchMock).not.toHaveBeenCalled();
|
||||
expect(models).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
// ===========================================================================
|
||||
|
||||
@@ -136,6 +136,10 @@ async function resolveProviderModelMap(
|
||||
config,
|
||||
);
|
||||
|
||||
if (providerId === "litellm" && resolved?.knownModels) {
|
||||
return resolved.knownModels;
|
||||
}
|
||||
|
||||
return resolved?.knownModels
|
||||
? {
|
||||
...registeredModels,
|
||||
|
||||
Reference in New Issue
Block a user