
Jogo de interrogatório detetivesco baseado em voz. Mistral Large 3 + Voxtral STT + ElevenLabs TTS. Criado para o Mistral Worldwide Hackathon 2026.

Um jogo de interrogatório detetivesco baseado em voz. Você é um detetive. Mistral é um suspeito que está mentindo. Seu trabalho é descobrir a mentira apenas fazendo perguntas.
Cada caso é gerado proceduralmente — um crime financeiro único, um suspeito, uma história de fachada e uma mentira oculta. O suspeito é interpretado pelo Mistral Large, com uma história completa e instruído a defendê-la sob pressão adversarial. Dois casos nunca são iguais.
Construído para o Mistral Worldwide Hackathon 2026 (Trilha Online).
"Mistral consegue raciocinar. Eu a fiz mentir. Seu trabalho é pegá-la."
A IA é instruída a nunca confessar, mesmo sob estresse máximo. Você vence fazendo uma acusação específica e precisa — não fazendo o suspeito quebrar.
npm install
cp .env.example .env # Fill in your API keys
npm run dev # http://localhost:3000
MISTRAL_API_KEY= # Required — case gen, interrogation, evaluation, STT
ELEVENLABS_API_KEY= # Required — TTS for suspect voice
ELEVENLABS_VOICE_ID= # Optional — specific ElevenLabs voice ID
NEXT_PUBLIC_SUPABASE_URL= # Required — Supabase project URL
NEXT_PUBLIC_SUPABASE_ANON_KEY= # Required — Supabase anon key (RLS-protected)
SUPABASE_SERVICE_ROLE_KEY= # Optional — admin export endpoint
EXPORT_SECRET= # Optional — admin export auth
As chaves de API também podem ser configuradas na página de Configurações em tempo de execução — o aplicativo vem sem chaves e os jogadores trazem as suas próprias.
npm run dev # Dev server
npm run build # Production build
npm run start # Production server
npm run lint # ESLint
| Nível | Pistas | Tempo | Comportamento do Suspeito |
|---|---|---|---|
| Fácil | 2 | 5 min | Mentira óbvia, nervoso |
| Médio | 3 | 7 min | Mentira detectável, controlado |
| Difícil | 4 | 9 min | Mentira sutil, desviador habilidoso |
| Expert | 5 | 10 min | Mentira profundamente enterrada, manipulador |
Um modo ilimitado de tempo também está disponível — no difícil/expert, o suspeito chamará um advogado após 4 trocas consecutivas de alto estresse.
As pistas são desbloqueadas em patamares de estresse distribuídos entre 1 e 9, condicionadas por:
O botão de Acusar só é desbloqueado depois que todas as pistas necessárias são coletadas.
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)
A pontuação é calculada no servidor a partir de estatísticas congeladas no momento da vitória — os valores do cliente são ignorados.
app/
├── page.tsx # Tela de título
├── cases/ # Seleção de casos — locais + dificuldade
├── game/
│ ├── page.tsx # Orquestrador principal do jogo
│ ├── hooks/ # useVoiceRecorder, useTTS, useGameTimer, useSfx, useSettings
│ ├── components/ # Dock, TopBar, CaseFile, SuspectZone, BriefingScreen, dialogs
│ ├── win/ # Tela de vitória + InitialsEntry
│ └── lose/ # Tela de derrota
├── leaderboard/ # Top 20, animação de nova entrada
├── settings/ # Configuração de chaves API, exportação, preferências
├── help/ # Como jogar, pontuação, sobre
├── about/ # Informações do construtor
└── api/
├── generate-case/ # GET — geração de caso Mistral
├── interrogate/ # POST — pergunta do jogador → resposta do suspeito
├── accuse/ # POST — avaliação da acusação (juiz separado)
├── evaluate/ # POST — análise de vitória/derrota
├── hint/ # POST — dicas ofuscadas de gatilhos de estresse
├── tts/ # POST — ElevenLabs TTS
├── transcribe/ # POST — Voxtral STT
├── leaderboard/ # GET/POST — placar Supabase
├── patterns/ # GET/POST — padrões de aprendizado entre sessões
└── export/ # GET — exportação JSONL para administrador
src/lib/
├── mistral/ # Cliente Mistral, interrogatório, avaliação, geração de caso, embeddings
├── game-session.ts # Armazenamento de sessão no servidor, tokens de vitória, exportação
├── game-state.ts # Definições de tipo
├── scoring.ts # Cálculo de pontuação + classificações de detetive
├── sanitize.ts # Validação de entrada, detecção de injeção
├── db.ts # Cliente Supabase
└── rate-limit.ts # Limitação de taxa por IP
O jogo executa IA adversarial contra a entrada do jogador — a segurança é um recurso central, não um complemento.
Sanitização de entrada: Mais de 30 padrões de injeção regex, normalização Unicode (NFKD), remoção de caracteres de largura zero, detecção de payload base64, bloqueio de jargão/não inglês.
Varredura de saída: Respostas da IA verificadas contra segredos do caso com correspondência fuzzy (limiar de 40%, filtragem de stop words). Respostas vazadas substituídas por desvio.
Isolamento do juiz: A avaliação da acusação usa uma chamada Mistral separada com prompt de sistema dedicado, tokens de limite aleatórios, marcadores de injeção removidos. O juiz nunca usa chaves de API fornecidas pelo jogador.
Aplicação de estresse: Travamento monotônico no servidor — o estresse só aumenta, no máximo +1 por turno. Os limiares de pista são aplicados pelo servidor. A IA não pode aumentar ou diminuir o estresse para contornar as portas do jogo.