TypeScript 97.4%
SQL 1%
JavaScript 0.9%
CSS 0.6%
1import { z } from "zod";23export const reasoningEffortSchema = z.enum(["none", "minimal", "low", "medium", "high", "xhigh", "max"]);45export const generationSettingsSchema = z6 .object({7 temperature: z.number().min(0).max(2).optional(),8 topP: z.number().min(0).max(1).optional(),9 topK: z.number().int().min(1).max(500).optional(),10 maxTokens: z.number().int().min(1).max(400_000).optional(),11 stop: z.array(z.string().min(1).max(64)).max(4).optional(),12 seed: z.number().int().min(0).max(2_147_483_647).optional(),13 frequencyPenalty: z.number().min(-2).max(2).optional(),14 presencePenalty: z.number().min(-2).max(2).optional(),15 reasoningEffort: reasoningEffortSchema.optional(),16 thinkingBudget: z.number().int().min(0).max(200_000).optional(),17 includeReasoning: z.boolean().optional(),18 verbosity: z.enum(["low", "medium", "high"]).optional(),19 responseFormat: z20 .object({21 type: z.enum(["text", "json", "json_schema"]),22 schema: z.record(z.string(), z.unknown()).optional(),23 schemaName: z.string().max(64).optional(),24 strict: z.boolean().optional(),25 })26 .optional(),27 toolChoice: z.union([z.enum(["auto", "none", "required"]), z.object({ type: z.literal("tool"), name: z.string() })]).optional(),28 webSearch: z.boolean().optional(),29 codeExecution: z.boolean().optional(),30 /** Built-in tool ids (calculator, clock, random). */31 tools: z.array(z.string()).max(10).optional(),32 })33 .strict();3435export type GenerationSettingsInput = z.infer<typeof generationSettingsSchema>;3637/** Prior turns replayed by the client for temporary (ephemeral) chats, which have no server-side history. */38export const ephemeralHistorySchema = z39 .array(40 z.object({41 role: z.enum(["user", "assistant"]),42 content: z.string().max(200_000),43 }),44 )45 .max(200);4647export const chatRequestSchema = z.object({48 conversationId: z.string().max(64).optional(),49 modelKey: z.string().min(3).max(120),50 action: z.enum(["send", "regenerate", "edit", "continue", "retry"]).default("send"),51 message: z52 .object({53 text: z.string().max(200_000),54 attachmentIds: z.array(z.string().max(64)).max(10).optional(),55 })56 .optional(),57 /** For regenerate/edit/continue/retry. */58 targetMessageId: z.string().max(64).optional(),59 systemPrompt: z.string().max(50_000).nullable().optional(),60 settings: generationSettingsSchema.optional(),61 /** Client-side id echo so the UI can reconcile optimistic messages. */62 clientId: z.string().max(64).optional(),63 /**64 * Temporary chat: stream the answer without creating a conversation or message rows.65 * Usage is still recorded (with a null conversation) so cost tracking stays exact.66 * Only `action: "send"` without `conversationId` is allowed; prior turns come from `history`.67 */68 ephemeral: z.boolean().optional(),69 history: ephemeralHistorySchema.optional(),70 /** Project (workspace) the new conversation belongs to. Ignored for existing conversations. */71 projectId: z.string().max(64).nullable().optional(),72});73export type ChatRequestInput = z.infer<typeof chatRequestSchema>;7475/**76 * POST /api/chat/adopt — insert an assistant message that was generated elsewhere (inline77 * Compare / Arena) into a conversation, switching the conversation to that model. When no78 * `conversationId` is given, a new conversation is created with `userText` as the first turn.79 * Content/metrics are copied server-side from `arenaResponseId` when provided.80 */81export const chatAdoptSchema = z82 .object({83 conversationId: z.string().max(64).optional(),84 modelKey: z.string().min(3).max(120),85 arenaResponseId: z.string().max(64).optional(),86 content: z.string().max(400_000).optional(),87 userText: z.string().max(200_000).optional(),88 systemPrompt: z.string().max(50_000).nullable().optional(),89 settings: generationSettingsSchema.optional(),90 projectId: z.string().max(64).nullable().optional(),91 })92 .refine((v) => Boolean(v.arenaResponseId || (v.content && v.content.trim())), { message: "content or arenaResponseId is required" })93 .refine((v) => Boolean(v.conversationId || (v.userText && v.userText.trim())), { message: "userText is required when creating a conversation" });94export type ChatAdoptInput = z.infer<typeof chatAdoptSchema>;9596export const arenaRunSchema = z.object({97 prompt: z.string().min(1).max(100_000),98 systemPrompt: z.string().max(20_000).optional(),99 modelKeys: z.array(z.string().min(3).max(120)).min(1).max(4),100 settings: generationSettingsSchema.optional(),101 attachmentIds: z.array(z.string().max(64)).max(6).optional(),102 /** Blind Arena: identities hidden (Model A/B/C/D, shuffled) until the user votes or reveals. */103 blind: z.boolean().optional(),104});105106export const arenaStreamSchema = z.object({107 sessionId: z.string().max(64),108 modelKey: z.string().min(3).max(120),109});110111/** Criterion ids: built-ins or `custom:<slug>`. */112export const arenaCriterionSchema = z.string().regex(/^(best|accurate|writing|coding|value|fastest|custom:[a-z0-9][a-z0-9-]{0,31})$/, "Invalid criterion");113114export const arenaCategorySchema = z.enum(["coding", "research", "writing", "reasoning", "general"]);115116export const arenaVoteSchema = z.object({117 sessionId: z.string().max(64),118 responseId: z.string().max(64),119 criterion: arenaCriterionSchema,120 category: arenaCategorySchema.optional(),121});122123export const arenaRetractVoteSchema = z.object({124 sessionId: z.string().max(64),125 criterion: arenaCriterionSchema,126});127