fix(agent): hide unrelated models for alias fallback

This commit is contained in:
ginnoir
2026-07-08 19:07:57 -05:00
parent bb679d02be
commit 4dc04b21d6
2 changed files with 26 additions and 7 deletions
+10 -5
View File
@@ -75,14 +75,19 @@ export async function listLlmModels(options?: {
} }
const models = normalizeLlmModelsPayload(await response.json()); const models = normalizeLlmModelsPayload(await response.json());
const merged = new Map<string, LlmModelOption>();
merged.set(fallbackModel, fallbackOption); if (models.length === 0) {
for (const model of models) merged.set(model.id, model); return { models: [fallbackOption], fallbackModel, degraded: true };
}
if (!models.some((model) => model.id === fallbackModel)) {
return { models: [fallbackOption], fallbackModel, degraded: false };
}
return { return {
models: [...merged.values()].sort((a, b) => a.id.localeCompare(b.id)), models,
fallbackModel, fallbackModel,
degraded: models.length === 0, degraded: false,
}; };
} catch { } catch {
return { models: [fallbackOption], fallbackModel, degraded: true }; return { models: [fallbackOption], fallbackModel, degraded: true };
+16 -2
View File
@@ -57,13 +57,13 @@ describe("isValidLlmModelId", () => {
}); });
describe("listLlmModels", () => { describe("listLlmModels", () => {
it("fetches provider models with API key auth and includes the fallback model", async () => { it("fetches provider models with API key auth when the fallback is advertised", async () => {
const requests: Request[] = []; const requests: Request[] = [];
const result = await listLlmModels({ const result = await listLlmModels({
config: openAiConfig, config: openAiConfig,
fetchImpl: async (input, init) => { fetchImpl: async (input, init) => {
requests.push(new Request(input, init)); requests.push(new Request(input, init));
return Response.json({ data: [{ id: "qwen2.5-coder" }] }); return Response.json({ data: [{ id: "qwen2.5-coder" }, { id: "llama3.2" }] });
}, },
}); });
@@ -88,6 +88,20 @@ describe("listLlmModels", () => {
assert.equal(result.degraded, true); assert.equal(result.degraded, true);
}); });
it("uses an unadvertised fallback alias instead of unrelated provider models", async () => {
const result = await listLlmModels({
config: { ...openAiConfig, model: "uncensored" },
fetchImpl: async () =>
Response.json({
data: [{ id: "auto" }, { id: "qwen3:8b" }, { id: "qwen3-coder:30b" }],
}),
});
assert.deepEqual(result.models, [{ id: "uncensored", label: "uncensored" }]);
assert.equal(result.fallbackModel, "uncensored");
assert.equal(result.degraded, false);
});
it("uses fallback only for mock provider config", async () => { it("uses fallback only for mock provider config", async () => {
const result = await listLlmModels({ const result = await listLlmModels({
config: { provider: "mock", baseUrl: null, apiKey: null, model: "llama3.2" }, config: { provider: "mock", baseUrl: null, apiKey: null, model: "llama3.2" },