Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
| /** | |
| * Zod schemas + types for the web app's HTTP API (browser β Next.js route | |
| * handlers). One source of truth so the client and server can't drift. | |
| */ | |
| import { z } from "zod"; | |
| export const MAX_TEXT_LENGTH = 1000; | |
| export const SESSION_TTL_SECONDS = 30 * 60; | |
| /* ββ Auth βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| export const userSchema = z.object({ | |
| id: z.number().int(), | |
| username: z.string(), | |
| hfId: z.string(), | |
| avatarUrl: z.string().nullable(), | |
| showInLeaderboard: z.boolean(), | |
| isAdmin: z.boolean(), | |
| }); | |
| export type ApiUser = z.infer<typeof userSchema>; | |
| export const meResponseSchema = z.object({ | |
| user: userSchema.nullable(), | |
| }); | |
| export type MeResponse = z.infer<typeof meResponseSchema>; | |
| /* ββ TTS generate βββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| export const ttsGenerateRequestSchema = z.object({ | |
| text: z.string().trim().min(1).max(MAX_TEXT_LENGTH), | |
| /** True when the text came from the prompt pool (the Random button), not | |
| * free-typed. Determines the vote's recorded sentenceOrigin. */ | |
| fromPool: z.boolean().optional(), | |
| /** Signed proof that this exact prompt was served by the random endpoint. */ | |
| promptToken: z.string().optional(), | |
| }); | |
| export type TTSGenerateRequest = z.infer<typeof ttsGenerateRequestSchema>; | |
| export const conversationalLineSchema = z.object({ | |
| text: z.string().trim().min(1).max(MAX_TEXT_LENGTH), | |
| speaker: z.union([z.literal(0), z.literal(1)]), | |
| }); | |
| export type ConversationalLine = z.infer<typeof conversationalLineSchema>; | |
| export const conversationalGenerateRequestSchema = z.object({ | |
| script: z.array(conversationalLineSchema).min(2), | |
| }); | |
| export type ConversationalGenerateRequest = z.infer< | |
| typeof conversationalGenerateRequestSchema | |
| >; | |
| export const generateResponseSchema = z.object({ | |
| sessionId: z.string().uuid(), | |
| audioA: z.string(), | |
| audioB: z.string(), | |
| expiresIn: z.number().int(), | |
| }); | |
| export type GenerateResponse = z.infer<typeof generateResponseSchema>; | |
| /* ββ Vote βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| export const voteRequestSchema = z.object({ | |
| sessionId: z.string().uuid(), | |
| chosen: z.union([z.literal("a"), z.literal("b")]), | |
| }); | |
| export type VoteRequest = z.infer<typeof voteRequestSchema>; | |
| export const revealedModelSchema = z.object({ | |
| id: z.string(), | |
| name: z.string(), | |
| open: z.boolean(), | |
| url: z.string(), | |
| }); | |
| export const voteResponseSchema = z.object({ | |
| chosen: revealedModelSchema, | |
| rejected: revealedModelSchema, | |
| /** Whether this vote affected the public Elo board. */ | |
| counted: z.boolean(), | |
| }); | |
| export type VoteResponse = z.infer<typeof voteResponseSchema>; | |
| /** | |
| * When a captcha is required before the vote can be recorded, the vote endpoint | |
| * returns this instead (HTTP 200) β the client solves the Cap challenge and | |
| * retries with the token. Kept separate so the normal path stays unchanged. | |
| */ | |
| export const captchaRequiredSchema = z.object({ | |
| needsCaptcha: z.literal(true), | |
| }); | |
| export type CaptchaRequired = z.infer<typeof captchaRequiredSchema>; | |
| /* ββ Leaderboard ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| export const leaderboardRowSchema = z.object({ | |
| rank: z.number().int(), | |
| id: z.string(), | |
| name: z.string(), | |
| url: z.string(), | |
| /** Optional provider logo URL. */ | |
| icon: z.string().nullable(), | |
| /** Displayed rating: Glicko-2 while preliminary, BradleyβTerry once established. */ | |
| elo: z.number().int(), | |
| /** Β± uncertainty on the rating (β2Β·RD for Glicko, half the BT CI width). */ | |
| uncertainty: z.number().int(), | |
| winRate: z.number(), // 0β100 | |
| totalVotes: z.number().int(), | |
| tier: z.enum(["S", "A", "B"]).nullable(), | |
| open: z.boolean(), | |
| /** True while the model has < ESTABLISHED_THRESHOLD counted votes. */ | |
| preliminary: z.boolean(), | |
| /** | |
| * False for retired models kept on the board for their historical rating | |
| * (no longer battled). The UI badges these "no longer active". | |
| */ | |
| active: z.boolean(), | |
| /** | |
| * True when the model was pulled for misconduct (e.g. vote manipulation). It's | |
| * delisted from the ranking (rank 0) and shown with a "Suspended" badge; its | |
| * row and votes are preserved as evidence. | |
| */ | |
| suspended: z.boolean(), | |
| /** Unix seconds when suspended (for the badge tooltip). */ | |
| suspendedAt: z.number().int().nullable(), | |
| /** Human-readable suspension reason (badge tooltip). */ | |
| suspendedReason: z.string().nullable(), | |
| }); | |
| export type LeaderboardRow = z.infer<typeof leaderboardRowSchema>; | |
| export const leaderboardResponseSchema = z.object({ | |
| rows: z.array(leaderboardRowSchema), | |
| }); | |
| export type LeaderboardResponse = z.infer<typeof leaderboardResponseSchema>; | |
| export const topVoterSchema = z.object({ | |
| rank: z.number().int(), | |
| username: z.string(), | |
| voteCount: z.number().int(), | |
| }); | |
| export type TopVoter = z.infer<typeof topVoterSchema>; | |
| /* ββ Sentences ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| export const randomSentenceResponseSchema = z.object({ | |
| sentence: z.string(), | |
| promptToken: z.string(), | |
| }); | |
| export type RandomSentenceResponse = z.infer< | |
| typeof randomSentenceResponseSchema | |
| >; | |
| export const sentenceStatsSchema = z.object({ | |
| total: z.number().int(), | |
| consumed: z.number().int(), | |
| remaining: z.number().int(), | |
| consumptionPct: z.number(), | |
| }); | |
| export type SentenceStats = z.infer<typeof sentenceStatsSchema>; | |
| /* ββ Errors βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| export const errorResponseSchema = z.object({ | |
| error: z.string(), | |
| detail: z.string().optional(), | |
| }); | |
| export type ErrorResponse = z.infer<typeof errorResponseSchema>; | |