fiemwl / src /app /api /models /route.ts
automindy's picture
Upload 1980 files
6111b2b verified
Raw
History Blame Contribute Delete
5.22 kB
import { NextResponse } from "next/server";
import { getModelAliases, setModelAlias, getProviderConnections } from "@/models";
import { AI_MODELS, PROVIDER_ID_TO_ALIAS } from "@/shared/constants/models";
import { updateModelAliasSchema } from "@/shared/validation/schemas";
import { isValidationFailure, validateBody } from "@/shared/validation/helpers";
import { hasEligibleConnectionForModel } from "@/domain/connectionModelRules";
// GET /api/models - Get models with aliases (only from active providers by default)
export async function GET(request: Request) {
try {
const { searchParams } = new URL(request.url);
const showAll = searchParams.get("all") === "true";
const modelAliases = await getModelAliases();
// Get active provider connections to filter available models
let activeProviders: Set<string> | null = null;
if (!showAll) {
try {
const connections = await getProviderConnections();
const active = connections.filter((c: any) => c.isActive !== false);
// Include both provider IDs and their aliases in the active set.
// PROVIDER_MODELS keys are aliases (e.g. 'cc' for 'claude', 'gh' for 'github').
// DB connections are stored under provider IDs ('claude', 'github').
// Without this, models for aliased providers always appear unconfigured.
activeProviders = new Set<string>();
for (const c of active) {
const pId = String((c as Record<string, unknown>).provider);
activeProviders.add(pId);
const alias = PROVIDER_ID_TO_ALIAS[pId];
if (alias) activeProviders.add(alias);
}
const connectionsByProvider = new Map<string, typeof active>();
const registerConnectionKey = (
key: string | null | undefined,
connection: (typeof active)[number]
) => {
if (!key) return;
const existing = connectionsByProvider.get(key) || [];
existing.push(connection);
connectionsByProvider.set(key, existing);
};
for (const connection of active) {
registerConnectionKey(connection.provider, connection);
registerConnectionKey(PROVIDER_ID_TO_ALIAS[connection.provider], connection);
}
const getConnectionsForProvider = (...keys: Array<string | null | undefined>) => {
const seen = new Set<string>();
const collected: typeof active = [];
for (const key of keys) {
if (!key) continue;
for (const connection of connectionsByProvider.get(key) || []) {
if (!connection?.id || seen.has(connection.id)) continue;
seen.add(connection.id);
collected.push(connection);
}
}
return collected;
};
activeProviders = new Set(
AI_MODELS.flatMap((model: any) => {
const providerKeys = [model.provider, PROVIDER_ID_TO_ALIAS[model.provider]];
return hasEligibleConnectionForModel(
getConnectionsForProvider(...providerKeys),
model.model
)
? providerKeys.filter(Boolean)
: [];
})
);
} catch {
// If DB unavailable, show all models
}
}
const models = AI_MODELS.map((m: any) => {
const fullModel = `${m.provider}/${m.model}`;
const available = !activeProviders || activeProviders.has(m.provider);
return {
...m,
fullModel,
alias: modelAliases[fullModel] || m.model,
available,
};
}).filter((m: any) => showAll || m.available);
return NextResponse.json({ models });
} catch (error) {
console.log("Error fetching models:", error);
return NextResponse.json({ error: "Failed to fetch models" }, { status: 500 });
}
}
// PUT /api/models - Update model alias
export async function PUT(request) {
let rawBody;
try {
rawBody = await request.json();
} catch {
return NextResponse.json(
{
error: {
message: "Invalid request",
details: [{ field: "body", message: "Invalid JSON body" }],
},
},
{ status: 400 }
);
}
try {
const validation = validateBody(updateModelAliasSchema, rawBody);
if (isValidationFailure(validation)) {
return NextResponse.json({ error: validation.error }, { status: 400 });
}
const { model, alias } = validation.data;
const modelAliases = await getModelAliases();
// Check if alias already exists for different model
const existingModel = Object.entries(modelAliases).find(
([key, val]) => val === alias && key !== model
);
if (existingModel) {
return NextResponse.json({ error: "Alias already in use" }, { status: 400 });
}
// Update alias
await setModelAlias(model, alias);
return NextResponse.json({ success: true, model, alias });
} catch (error) {
console.log("Error updating alias:", error);
return NextResponse.json({ error: "Failed to update alias" }, { status: 500 });
}
}