chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
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 });
|
||||
}
|
||||
Reference in New Issue
Block a user