import { and, eq } from "drizzle-orm"; import { NextResponse } from "next/server"; import { fetchAtlasCloudModelPresets, resolveAtlasCloudDisplayName, shouldInsertMissingAtlasCloudPreset, } from "@/lib/ai/atlascloud-models"; import { db } from "@/lib/db"; import { getAiProviderById } from "@/lib/db/queries"; import { type AiModel, aiModel } from "@/lib/db/schema"; import { requireAdmin } from "@/lib/middleware/admin"; export const runtime = "nodejs"; export const maxDuration = 300; export async function GET() { try { await requireAdmin(); const result = await fetchAtlasCloudModelPresets(); return NextResponse.json({ presets: result.presets, errors: result.errors.length > 0 ? result.errors : undefined, counts: { total: result.catalogCount, available: result.presets.length, failed: result.errors.length, }, }); } catch (error) { console.error("[Atlas Cloud Models API] GET error:", error); return NextResponse.json( { error: error instanceof Error ? error.message : "Failed to fetch Atlas Cloud models", }, { status: 500 } ); } } export async function POST(request: Request) { try { await requireAdmin(); const body = await request.json(); const providerId = String(body?.providerId || "").trim(); const requestedModelIds = Array.isArray(body?.modelIds) ? new Set( body.modelIds.map((item: unknown) => String(item || "").trim()).filter(Boolean) ) : null; if (!providerId) { return NextResponse.json({ error: "Provider ID is required" }, { status: 400 }); } const provider = await getAiProviderById({ id: providerId }); if (!provider || provider.type !== "atlascloud") { return NextResponse.json( { error: "Provider must be an Atlas Cloud provider" }, { status: 400 } ); } const catalog = await fetchAtlasCloudModelPresets(); const presets = requestedModelIds ? catalog.presets.filter((preset) => requestedModelIds.has(preset.modelId)) : catalog.presets; const addedModels: AiModel[] = []; const updatedModels: AiModel[] = []; const errors = [...catalog.errors]; const providerModels = await db.query.aiModel.findMany({ where: eq(aiModel.providerId, providerId), }); const existingByModelId = new Map( providerModels.map((model) => [model.modelId, model]) ); const existingMediaKinds = new Set( providerModels.map((model) => { const capabilities = model.capabilities as Record | null; return String(capabilities?.mediaType || "image"); }) ); let preservedDeletedCount = 0; for (const preset of presets) { try { const existing = existingByModelId.get(preset.modelId); const presetCapabilities = preset.capabilities as Record; const mediaKind = String(presetCapabilities.mediaType || "image"); if ( !existing && !shouldInsertMissingAtlasCloudPreset(existingMediaKinds, mediaKind) ) { preservedDeletedCount += 1; continue; } const values = { displayName: resolveAtlasCloudDisplayName( existing?.displayName, preset.displayName, preset.modelId ), avatarUrl: preset.avatarUrl || null, description: preset.description, supportsVision: preset.supportsVision, supportsImageGen: preset.supportsImageGen, sortOrder: existing?.sortOrder ?? preset.sortOrder, capabilities: preset.capabilities, defaultParams: preset.defaultParams, imageGenConfig: preset.imageGenConfig, updatedAt: new Date(), }; if (existing) { const [updated] = await db .update(aiModel) .set(values) .where( and( eq(aiModel.providerId, providerId), eq(aiModel.modelId, preset.modelId) ) ) .returning(); if (updated) updatedModels.push(updated); } else { const [created] = await db .insert(aiModel) .values({ providerId, modelId: preset.modelId, ...values, isEnabled: true, isHidden: false, isDefault: false, isSubModel: false, parentModelId: null, }) .returning(); if (created) addedModels.push(created); } } catch (error) { console.error( `[Atlas Cloud Models API] Failed to sync ${preset.modelId}:`, error ); errors.push({ modelId: preset.modelId, error: error instanceof Error ? error.message : "Sync failed", }); } } return NextResponse.json({ success: true, addedCount: addedModels.length, updatedCount: updatedModels.length, addedModels, updatedModels, errors: errors.length > 0 ? errors : undefined, counts: { requested: presets.length, total: catalog.catalogCount, available: catalog.presets.length, skippedUnsupported: catalog.skipped.length, preservedDeleted: preservedDeletedCount, }, }); } catch (error) { console.error("[Atlas Cloud Models API] POST error:", error); return NextResponse.json( { error: error instanceof Error ? error.message : "Failed to sync Atlas Cloud models", }, { status: 500 } ); } }