mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-31 04:12:10 +03:00
fix(providers): use synced models as fallback for all providers (#3148)
Use synced models as authoritative local catalog for all providers (+regression test). Integrated into release/v3.8.10.
This commit is contained in:
committed by
GitHub
parent
44b9d0e5f7
commit
d3c753ecbe
@@ -76,6 +76,7 @@ import {
|
||||
isAutoFetchModelsEnabled,
|
||||
persistDiscoveredModels,
|
||||
} from "@/lib/providerModels/modelDiscovery";
|
||||
import { getSyncedAvailableModels } from "@/lib/db/models";
|
||||
import { fetchCursorAgentModels } from "@/lib/providerModels/cursorAgent";
|
||||
|
||||
type JsonRecord = Record<string, unknown>;
|
||||
@@ -794,8 +795,32 @@ export async function GET(
|
||||
const accessToken = typeof connection.accessToken === "string" ? connection.accessToken : "";
|
||||
const autoFetchModels = isAutoFetchModelsEnabled(connection.providerSpecificData);
|
||||
const cachedDiscoveryModels = await getCachedDiscoveredModels(provider, connectionId);
|
||||
const registryCatalogModels = getModelsByProviderId(provider) || [];
|
||||
const specialtyCatalogModels = getStaticModelsForProvider(provider) || [];
|
||||
|
||||
// Check for synced models from ANY connection of this provider.
|
||||
// When sync has been performed (even on a different connection),
|
||||
// use the synced list as the authoritative source instead of static models.
|
||||
let providerSyncedModels: Array<{
|
||||
id: string;
|
||||
name: string;
|
||||
apiFormat?: string;
|
||||
supportedEndpoints?: string[];
|
||||
}> | null = null;
|
||||
try {
|
||||
const allSynced = await getSyncedAvailableModels(provider);
|
||||
if (Array.isArray(allSynced) && allSynced.length > 0) {
|
||||
providerSyncedModels = allSynced.map((m) => ({
|
||||
id: m.id,
|
||||
name: m.name || m.id,
|
||||
...(m.apiFormat ? { apiFormat: m.apiFormat } : {}),
|
||||
...(m.supportedEndpoints ? { supportedEndpoints: m.supportedEndpoints } : {}),
|
||||
}));
|
||||
}
|
||||
} catch {
|
||||
// DB unavailable — fall through to static catalog
|
||||
}
|
||||
|
||||
const registryCatalogModels = providerSyncedModels ?? (getModelsByProviderId(provider) || []);
|
||||
const specialtyCatalogModels = providerSyncedModels ? [] : (getStaticModelsForProvider(provider) || []);
|
||||
|
||||
const toLocalCatalogModels = () => {
|
||||
const localCatalog = mergeLocalCatalogModels(registryCatalogModels, specialtyCatalogModels);
|
||||
|
||||
@@ -640,6 +640,47 @@ test("provider models route honors autoFetchModels=false and skips remote discov
|
||||
assert.ok(body.models.some((model) => model.id === "glm-5"));
|
||||
});
|
||||
|
||||
test("provider models route uses synced models as the authoritative local catalog (#3148)", async () => {
|
||||
// A connection that resolves to the local catalog (auto-fetch off, no remote
|
||||
// discovery). Once a sync has populated the synced-models table for this
|
||||
// provider, the route must surface the synced list — even on a connection
|
||||
// that never ran the sync itself — instead of the static catalog.
|
||||
const connection = await seedConnection("opencode-go", {
|
||||
apiKey: "opencode-go-key",
|
||||
providerSpecificData: {
|
||||
autoFetchModels: false,
|
||||
},
|
||||
});
|
||||
|
||||
await modelsDb.replaceSyncedAvailableModelsForConnection("opencode-go", "synced-conn", [
|
||||
{ id: "synced-only-model", name: "Synced Only Model" },
|
||||
]);
|
||||
|
||||
let called = false;
|
||||
globalThis.fetch = async () => {
|
||||
called = true;
|
||||
return Response.json({ data: [] });
|
||||
};
|
||||
|
||||
const response = await callRoute(connection.id);
|
||||
const body = (await response.json()) as any;
|
||||
|
||||
assert.equal(response.status, 200);
|
||||
assert.equal(body.source, "local_catalog");
|
||||
assert.equal(called, false);
|
||||
// Synced models become the catalog…
|
||||
assert.ok(
|
||||
body.models.some((model) => model.id === "synced-only-model"),
|
||||
"synced model should be present in the local catalog"
|
||||
);
|
||||
// …and the static catalog entries are no longer surfaced for this provider.
|
||||
assert.equal(
|
||||
body.models.some((model) => model.id === "glm-5"),
|
||||
false,
|
||||
"static catalog should be superseded by the synced list"
|
||||
);
|
||||
});
|
||||
|
||||
test("provider models route validates Gemini CLI credentials before fetching quota buckets", async () => {
|
||||
const missingToken = await seedConnection("gemini-cli", {
|
||||
authType: "oauth",
|
||||
|
||||
Reference in New Issue
Block a user