mirror of
https://github.com/decolua/9router.git
synced 2026-05-08 12:01:28 +00:00
fix(v1/models): include alias-backed models in listing (#730)
Ensure /v1/models includes provider models added through alias mappings so compatible provider entries like huoshan/kimi-k2.6 are discoverable by clients. Made-with: Cursor Co-authored-by: Ken Lin <kenlin1988@foxmail.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { PROVIDER_MODELS, PROVIDER_ID_TO_ALIAS } from "@/shared/constants/models";
|
||||
import { getProviderAlias, isAnthropicCompatibleProvider, isOpenAICompatibleProvider } from "@/shared/constants/providers";
|
||||
import { getProviderConnections, getCombos } from "@/lib/localDb";
|
||||
import { getProviderConnections, getCombos, getCustomModels, getModelAliases } from "@/lib/localDb";
|
||||
|
||||
const parseOpenAIStyleModels = (data) => {
|
||||
if (Array.isArray(data)) return data;
|
||||
@@ -105,6 +105,20 @@ export async function GET() {
|
||||
console.log("Could not fetch combos");
|
||||
}
|
||||
|
||||
let customModels = [];
|
||||
try {
|
||||
customModels = await getCustomModels();
|
||||
} catch (e) {
|
||||
console.log("Could not fetch custom models");
|
||||
}
|
||||
|
||||
let modelAliases = {};
|
||||
try {
|
||||
modelAliases = await getModelAliases();
|
||||
} catch (e) {
|
||||
console.log("Could not fetch model aliases");
|
||||
}
|
||||
|
||||
// Build first active connection per provider (connections already sorted by priority)
|
||||
const activeConnectionByProvider = new Map();
|
||||
for (const conn of connections) {
|
||||
@@ -146,6 +160,26 @@ export async function GET() {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Also include custom LLM models when no active connections are available.
|
||||
for (const customModel of customModels) {
|
||||
if (!customModel?.id || (customModel.type && customModel.type !== "llm")) continue;
|
||||
const providerAlias = customModel.providerAlias;
|
||||
if (!providerAlias) continue;
|
||||
|
||||
const modelId = String(customModel.id).trim();
|
||||
if (!modelId) continue;
|
||||
|
||||
models.push({
|
||||
id: `${providerAlias}/${modelId}`,
|
||||
object: "model",
|
||||
created: timestamp,
|
||||
owned_by: providerAlias,
|
||||
permission: [],
|
||||
root: modelId,
|
||||
parent: null,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
for (const [providerId, conn] of activeConnectionByProvider.entries()) {
|
||||
const staticAlias = PROVIDER_ID_TO_ALIAS[providerId] || providerId;
|
||||
@@ -193,7 +227,41 @@ export async function GET() {
|
||||
})
|
||||
.filter((modelId) => typeof modelId === "string" && modelId.trim() !== "");
|
||||
|
||||
for (const modelId of modelIds) {
|
||||
const customModelIds = customModels
|
||||
.filter((m) => {
|
||||
if (!m?.id || (m.type && m.type !== "llm")) return false;
|
||||
const alias = m.providerAlias;
|
||||
return alias === staticAlias || alias === outputAlias || alias === providerId;
|
||||
})
|
||||
.map((m) => String(m.id).trim())
|
||||
.filter((modelId) => modelId !== "");
|
||||
|
||||
const aliasModelIds = Object.values(modelAliases || {})
|
||||
.filter((fullModel) => {
|
||||
if (typeof fullModel !== "string" || !fullModel.includes("/")) return false;
|
||||
return (
|
||||
fullModel.startsWith(`${outputAlias}/`) ||
|
||||
fullModel.startsWith(`${staticAlias}/`) ||
|
||||
fullModel.startsWith(`${providerId}/`)
|
||||
);
|
||||
})
|
||||
.map((fullModel) => {
|
||||
if (fullModel.startsWith(`${outputAlias}/`)) {
|
||||
return fullModel.slice(outputAlias.length + 1);
|
||||
}
|
||||
if (fullModel.startsWith(`${staticAlias}/`)) {
|
||||
return fullModel.slice(staticAlias.length + 1);
|
||||
}
|
||||
if (fullModel.startsWith(`${providerId}/`)) {
|
||||
return fullModel.slice(providerId.length + 1);
|
||||
}
|
||||
return fullModel;
|
||||
})
|
||||
.filter((modelId) => typeof modelId === "string" && modelId.trim() !== "");
|
||||
|
||||
const mergedModelIds = Array.from(new Set([...modelIds, ...customModelIds, ...aliasModelIds]));
|
||||
|
||||
for (const modelId of mergedModelIds) {
|
||||
models.push({
|
||||
id: `${outputAlias}/${modelId}`,
|
||||
object: "model",
|
||||
@@ -207,9 +275,17 @@ export async function GET() {
|
||||
}
|
||||
}
|
||||
|
||||
const dedupedModels = [];
|
||||
const seenModelIds = new Set();
|
||||
for (const model of models) {
|
||||
if (!model?.id || seenModelIds.has(model.id)) continue;
|
||||
seenModelIds.add(model.id);
|
||||
dedupedModels.push(model);
|
||||
}
|
||||
|
||||
return Response.json({
|
||||
object: "list",
|
||||
data: models,
|
||||
data: dedupedModels,
|
||||
}, {
|
||||
headers: {
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
|
||||
Reference in New Issue
Block a user