import type { Prisma, PrismaClient } from "./client.js"; type ModelTierScope = { userId: string; spaceId: string }; // The composite (credentialId, userId) foreign key keeps every mapped credential the user's own. function withCredential(scope: ModelTierScope) { return { credential: { include: { preferences: { where: { spaceId: scope.spaceId, userId: scope.userId }, select: { isDefault: true, modelId: true }, }, }, }, } as const; } type ModelTierRow = Prisma.SpaceModelTierGetPayload<{ include: ReturnType; }>; /** * Shape the credential like findModelCredential does. defaultModel stays the space's saved * model, not the tier's, so capabilities kept for that saved model never spread to tier models. */ function toModelTier(row: ModelTierRow) { const { preferences, ...credential } = row.credential; return { tier: row.tier, credentialId: row.credentialId, modelId: row.modelId, credential: { ...credential, isDefault: preferences[0]?.isDefault ?? false, defaultModel: preferences[0]?.modelId ?? null, }, }; } export async function listSpaceModelTiers( prisma: Pick, scope: ModelTierScope, ) { const rows = await prisma.spaceModelTier.findMany({ where: { spaceId: scope.spaceId, userId: scope.userId }, include: withCredential(scope), orderBy: { createdAt: "asc" }, }); return rows.map(toModelTier); } /** The connected model a space maps this tier to, or null when the tier is not mapped. */ export async function findSpaceModelTier( prisma: Pick, scope: ModelTierScope, tier: string, ) { const row = await prisma.spaceModelTier.findUnique({ where: { spaceId_userId_tier: { spaceId: scope.spaceId, userId: scope.userId, tier } }, include: withCredential(scope), }); return row ? toModelTier(row) : null; } export async function setSpaceModelTier( prisma: Pick, scope: ModelTierScope, tier: string, model: { credentialId: string; modelId: string } | null, ) { if (!model) { await prisma.spaceModelTier.deleteMany({ where: { spaceId: scope.spaceId, userId: scope.userId, tier }, }); return; } await prisma.spaceModelTier.upsert({ where: { spaceId_userId_tier: { spaceId: scope.spaceId, userId: scope.userId, tier } }, create: { spaceId: scope.spaceId, userId: scope.userId, tier, ...model }, update: model, }); }