
Jeu d'interrogatoire policier basé sur la voix. Mistral Large 3 + Voxtral STT + ElevenLabs TTS. Conçu pour le Mistral Worldwide Hackathon 2026.

Un jeu d'interrogatoire de détective basé sur la voix. Vous êtes un détective. Mistral est un suspect qui ment. Votre travail consiste à découvrir le mensonge rien qu'en posant des questions.
Chaque affaire est générée de manière procédurale — un crime en col blanc unique, un suspect, une histoire de couverture et un mensonge caché. Le suspect est interprété par Mistral Large, doté d'une histoire complète et chargé de la défendre sous pression contradictoire. Aucune affaire n'est identique.
Construit pour le Mistral Worldwide Hackathon 2026 (Volet en ligne).
"Mistral peut raisonner. Je l'ai fait mentir. Votre travail est de le prendre sur le fait."
npm install
cp .env.example .env # Remplissez vos clés API
npm run dev # http://localhost:3000
MISTRAL_API_KEY= # Requis — génération d'affaires, interrogatoire, évaluation, STT
ELEVENLABS_API_KEY= # Requis — TTS pour la voix du suspect
ELEVENLABS_VOICE_ID= # Facultatif — ID de voix ElevenLabs spécifique
NEXT_PUBLIC_SUPABASE_URL= # Requis — URL du projet Supabase
NEXT_PUBLIC_SUPABASE_ANON_KEY= # Requis — clé anonyme Supabase (protégée par RLS)
SUPABASE_SERVICE_ROLE_KEY= # Facultatif — endpoint d'exportation admin
EXPORT_SECRET= # Facultatif — authentification d'exportation admin
Les clés API peuvent également être configurées dans la page Paramètres à l'exécution — l'application est livrée sans clé et les joueurs apportent leurs propres clés.
npm run dev # Serveur de développement
npm run build # Construction pour la production
npm run start # Serveur de production
npm run lint # ESLint
| Niveau | Indices | Minuteur | Comportement du suspect |
|---|---|---|---|
| Facile | 2 | 5 min | Mensonge évident, nerveux |
| Moyen | 3 | 7 min | Mensonge attrapable, calme |
| Difficile | 4 | 9 min | Mensonge subtil, expert en esquive |
| Expert | 5 | 10 min | Mensonge profondément enfoui, manipulateur |
Un mode minuteur illimité est également disponible — en difficulté difficile/expert, le suspect fera appel à un avocat après 4 échanges consécutifs à stress élevé.
Les indices se déverrouillent à des seuils de stress répartis de 1 à 9, conditionnés par :
Le bouton Accuser ne se déverrouille qu'après avoir collecté tous les indices requis.
score = timeScore x difficultyMultiplier x efficiencyBonus x hintPenalty x accusationPenalty
timeScore = 1000 x sqrt(max(0, 1 - elapsed / (parTime x 2)))
multiplier = easy 1.0x, medium 1.5x, hard 2.0x, expert 2.5x
efficiencyBonus = 1.0-1.5x (fewer questions than par = bonus)
hintPenalty = 0.85^hintsUsed
accusePenalty = max(0, 1 - wrongAccusations x 0.1)
Le score est calculé côté serveur à partir de statistiques figées au moment de la victoire — les valeurs du client sont ignorées.
app/
├── page.tsx # Écran titre
├── cases/ # Sélection d'affaires — lieux + difficulté
├── game/
│ ├── page.tsx # Orchestrateur principal du jeu
│ ├── hooks/ # useVoiceRecorder, useTTS, useGameTimer, useSfx, useSettings
│ ├── components/ # Dock, TopBar, CaseFile, SuspectZone, BriefingScreen, dialogs
│ ├── win/ # Écran de victoire + InitialsEntry
│ └── lose/ # Écran de défaite
├── leaderboard/ # Top 20, animation de nouvelle entrée
├── settings/ # Configuration des clés API, exportation, préférences
├── help/ # Comment jouer, score, à propos
├── about/ # Informations sur le créateur
└── api/
├── generate-case/ # GET — génération d'affaire par Mistral
├── interrogate/ # POST — question du joueur → réponse du suspect
├── accuse/ # POST — évaluation de l'accusation (juge séparé)
├── evaluate/ # POST — analyse victoire/défaite
├── hint/ # POST — indices basés sur des seuils de stress obscurcis
├── tts/ # POST — ElevenLabs TTS
├── transcribe/ # POST — Voxtral STT
├── leaderboard/ # GET/POST — classement Supabase
├── patterns/ # GET/POST — modèles d'apprentissage inter-sessions
└── export/ # GET — exportation admin JSONL
src/lib/
├── mistral/ # Client Mistral, interrogatoire, évaluation, génération d'affaires, embeddings
├── game-session.ts # Stockage de session côté serveur, jetons de victoire, exportation
├── game-state.ts # Définitions de types
├── scoring.ts # Calcul du score + classements de détective
├── sanitize.ts # Validation des entrées, détection d'injection
├── db.ts # Client Supabase
└── rate-limit.ts # Limitation de débit par IP
Le jeu confronte une IA antagoniste aux entrées du joueur — la sécurité est une fonctionnalité centrale, pas une réflexion après coup.
Assainissement des entrées : plus de 30 motifs d'injection regex, normalisation Unicode (NFKD), suppression des caractères de largeur nulle, détection de payloads base64, blocage du charabia/non-anglais.
Analyse des sorties : les réponses de l'IA sont vérifiées par rapport aux secrets de l'affaire avec correspondance floue (seuil de 40 %, filtrage des mots vides). Les réponses divulguées sont remplacées par une esquive.