/* * ============================================================================= * VibeQuant (vquant) — AI-Powered Financial Intelligence Platform * ----------------------------------------------------------------------------- * File: server/routes/validation.ts * * Author: Simon-Pierre Boucher * Contact: contact@spboucher.ai * Website: https://www.spboucher.ai * Demo: https://www.vquant.ai * License: MIT (see LICENSE) * * Copyright © 2026 Simon-Pierre Boucher. All rights reserved. * ============================================================================= */ import { z } from "zod"; export const ALLOWED_MODELS = [ 'claude-fable-5', 'claude-opus-4-6', 'claude-opus-4-7', 'claude-opus-4-8', 'claude-sonnet-4-6', 'claude-haiku-4-5-20251001', 'gpt-5.6-sol', 'gpt-5.6-terra', 'gpt-5.6-luna', 'gpt-5.5', 'gpt-5.4', 'gpt-5.2', 'gpt-5.1', 'gpt-5', 'gpt-5-mini', 'gpt-5-nano', 'gpt-4.1', 'gpt-4.1-mini', 'gemini-3.5-flash', 'gemini-3.1-pro-preview', 'gemini-3-flash-preview', 'gemini-3.1-flash-lite', ] as const; export const UNAVAILABLE_MODELS: readonly string[] = []; export const DEFAULT_MODEL = 'claude-fable-5'; export type AllowedModel = typeof ALLOWED_MODELS[number]; export const chatBodySchema = z.object({ query: z.string().min(1, "Query is required").max(10000), history: z.array(z.object({ question: z.string(), answer: z.string(), })).optional().default([]), sessionId: z.string().optional(), imageData: z.string().optional(), imageMimeType: z.string().optional(), model: z.enum(ALLOWED_MODELS).optional().default(DEFAULT_MODEL).transform( (m) => (UNAVAILABLE_MODELS.includes(m as typeof UNAVAILABLE_MODELS[number]) ? DEFAULT_MODEL : m) ), }); export const shareBodySchema = z.object({ question: z.string().min(1, "Question is required"), answer: z.string().min(1, "Answer is required"), toolResults: z.unknown().optional(), sources: z.unknown().optional(), customPythonFigures: z.unknown().optional(), }); export const registerBodySchema = z.object({ name: z.string().min(2, "Le nom doit contenir au moins 2 caracteres"), }); export const loginBodySchema = z.object({ token: z.string().min(1, "Le token est requis"), }); export const heartbeatBodySchema = z.object({ sessionId: z.string().min(1, "sessionId is required"), status: z.string().optional(), currentQuery: z.string().nullable().optional(), userId: z.string().nullable().optional(), });