import { type ActionFunctionArgs, type LoaderFunctionArgs, json } from "@remix-run/server-runtime"; import { z } from "zod"; import { prisma } from "~/db.server"; import { requireAdminApiRequest } from "~/services/personalAccessToken.server"; import { generateFriendlyId } from "~/v3/friendlyIdentifiers"; export async function loader({ request }: LoaderFunctionArgs) { await requireAdminApiRequest(request); const url = new URL(request.url); const page = parseInt(url.searchParams.get("page") ?? "1"); const pageSize = parseInt(url.searchParams.get("pageSize") ?? "50"); const [models, total] = await Promise.all([ prisma.llmModel.findMany({ where: { projectId: null }, include: { pricingTiers: { include: { prices: true }, orderBy: { priority: "asc" }, }, }, orderBy: { modelName: "asc" }, skip: (page - 1) * pageSize, take: pageSize, }), prisma.llmModel.count({ where: { projectId: null } }), ]); return json({ models, total, page, pageSize }); } const CreateModelSchema = z.object({ modelName: z.string().min(1), matchPattern: z.string().min(1), startDate: z.string().optional(), source: z.enum(["default", "admin"]).optional().default("admin"), provider: z.string().optional(), description: z.string().optional(), contextWindow: z.number().int().optional(), maxOutputTokens: z.number().int().optional(), capabilities: z.array(z.string()).optional(), isHidden: z.boolean().optional(), pricingUnit: z.string().optional(), pricingTiers: z.array( z.object({ name: z.string().min(1), isDefault: z.boolean().default(true), priority: z.number().int().default(0), conditions: z .array( z.object({ usageDetailPattern: z.string(), operator: z.enum(["gt", "gte", "lt", "lte", "eq", "neq"]), value: z.number(), }) ) .default([]), prices: z.record(z.string(), z.number()), }) ), }); export async function action({ request }: ActionFunctionArgs) { await requireAdminApiRequest(request); if (request.method !== "POST") { return json({ error: "Method not allowed" }, { status: 405 }); } let body: unknown; try { body = await request.json(); } catch { return json({ error: "Invalid JSON body" }, { status: 400 }); } const parsed = CreateModelSchema.safeParse(body); if (!parsed.success) { return json({ error: "Invalid request body", details: parsed.error.issues }, { status: 400 }); } const { modelName, matchPattern, startDate, source, pricingTiers, provider, description, contextWindow, maxOutputTokens, capabilities, isHidden, pricingUnit, } = parsed.data; // Validate regex pattern — strip (?i) POSIX flag since our registry handles it try { const testPattern = matchPattern.startsWith("(?i)") ? matchPattern.slice(4) : matchPattern; new RegExp(testPattern); } catch { return json({ error: "Invalid regex in matchPattern" }, { status: 400 }); } // Create model + tiers atomically const created = await prisma.$transaction(async (tx) => { const model = await tx.llmModel.create({ data: { friendlyId: generateFriendlyId("llm_model"), modelName, matchPattern, startDate: startDate ? new Date(startDate) : null, source, provider: provider ?? null, description: description ?? null, contextWindow: contextWindow ?? null, maxOutputTokens: maxOutputTokens ?? null, capabilities: capabilities ?? [], isHidden: isHidden ?? false, pricingUnit: pricingUnit ?? null, }, }); for (const tier of pricingTiers) { await tx.llmPricingTier.create({ data: { modelId: model.id, name: tier.name, isDefault: tier.isDefault, priority: tier.priority, conditions: tier.conditions, prices: { create: Object.entries(tier.prices).map(([usageType, price]) => ({ modelId: model.id, usageType, price, })), }, }, }); } return tx.llmModel.findUnique({ where: { id: model.id }, include: { pricingTiers: { include: { prices: true } }, }, }); }); return json({ model: created }, { status: 201 }); }