SPB Git forge

spb/polyllm

Public
15commits 1branches 0releases
2.2 MBsize
maindefault branch
13 days agolast push
TypeScript 97.4% SQL 1% JavaScript 0.9% CSS 0.6%
5.4 KB · 127 lines typescript
Raw Blame History
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