39 lines
2.4 KiB
TypeScript
39 lines
2.4 KiB
TypeScript
import { and, eq } from "drizzle-orm";
|
|
import { db } from "@/lib/db";
|
|
import { aiModel, aiProvider } from "@/lib/db/schema";
|
|
import { normalizeVip98kBaseUrl } from "@/lib/ai/vip98k-models";
|
|
import { selectVip98kChatInvocation, vip98kChatSupportsVision } from "@/lib/ai/vip98k-chat-contract";
|
|
|
|
// Explicit administration command: discover the provider's published vision
|
|
// chat routes. Never re-enable a disabled model or change the user's defaults.
|
|
async function main() {
|
|
const providers = await db.select().from(aiProvider).where(and(eq(aiProvider.type, "vip98k"), eq(aiProvider.isEnabled, true)));
|
|
const added: string[] = [];
|
|
for (const provider of providers) {
|
|
const response = await fetch(`${normalizeVip98kBaseUrl(provider.baseUrl)}/api/v2/catalog/models`, {
|
|
headers: { Accept: "application/json", "User-Agent": "Mozilla/5.0" }, redirect: "error", signal: AbortSignal.timeout(15_000),
|
|
});
|
|
if (!response.ok) throw new Error(`Provider catalog unavailable (${response.status})`);
|
|
const payload = await response.json();
|
|
const entries = (payload?.data?.sections || []).flatMap((section: { models?: Record<string, any>[] }) => section.models || []);
|
|
const existing = await db.select({ modelId: aiModel.modelId }).from(aiModel).where(eq(aiModel.providerId, provider.id));
|
|
const known = new Set(existing.map(model => model.modelId));
|
|
let index = 0;
|
|
for (const entry of entries) {
|
|
const contract = selectVip98kChatInvocation(entry);
|
|
if (!contract || !vip98kChatSupportsVision(entry) || !entry.id || known.has(entry.id)) continue;
|
|
const id = String(entry.id);
|
|
// The catalog's chat contract and vision modality are both required.
|
|
// Pure generation, media-task and Anthropic-only routes are excluded.
|
|
await db.insert(aiModel).values({ providerId: provider.id, modelId: id, displayName: id,
|
|
supportsVision: true, supportsImageGen: false, isEnabled: true, isHidden: true, isDefault: false,
|
|
sortOrder: 10_000 + index++, defaultParams: { agentAutoModel: false },
|
|
capabilities: { kind: "chat", multimodalModel: true, agentFallbackOnly: true, vip98k: entry },
|
|
});
|
|
known.add(id); added.push(id);
|
|
}
|
|
}
|
|
console.log(JSON.stringify({ added, count: added.length, imageModelsUnchanged: true, defaultsUnchanged: true }));
|
|
}
|
|
main().then(() => process.exit(0)).catch(() => { console.error("Multimodal fallback catalog sync failed; no credentials were logged"); process.exit(1); });
|