
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
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.
Tokens de vitória: 128 bits aleatórios, comparação segura de tempo, uso único, TTL de 30 minutos. Pontuação calculada a partir de snapshot de estatísticas do servidor — valores relatados pelo cliente ignorados.
Segurança de sessão: IDs aleatórios de 192 bits, locks mutex, TTL de 1 hora, máximo de 5000 sessões com evicção LRU. Modo de timer fixado na criação.
Validação TTS: Requer sessão ativa. O texto deve corresponder a uma mensagem recente do assistente. Previne abuso de proxy TTS gratuito.
Defesa contra envenenamento RAG: Táticas aprendidas entre sessões são filtradas por meio de detecção de injeção e sanitização antes da inclusão no prompt.
Os jogos concluídos são persistidos no Supabase para análise e melhoria do modelo:
GET /api/export?limit=100&offset=0&outcome=win&difficulty=hard com cabeçalho Authorization: Bearer <EXPORT_SECRET>EXPORT_SECRET=xxx npx tsx scripts/export-data.ts --output=data/export.jsonlEstética noir de detetive. Escuro, minimalista, tipográfico. JetBrains Mono. Fundos pixel art e retratos de suspeitos. Sem balões de bate-papo — o diálogo aparece como texto estilizado na cena.
Crie uma tabela leaderboard:
CREATE TABLE leaderboard (
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
player_name text NOT NULL,
case_number text,
case_setting text,
suspect_name text,
time_remaining int,
stress_level int,
clues_found int,
hints_used int,
accusations_used int,
detective_rating text,
score int NOT NULL,
created_at timestamptz DEFAULT now()
);
ALTER TABLE leaderboard ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Public read" ON leaderboard FOR SELECT USING (true);
CREATE POLICY "Public insert" ON leaderboard FOR INSERT WITH CHECK (true);
Tabela opcional game_exports para dados de treinamento:
CREATE TABLE game_exports (
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
session_id text UNIQUE NOT NULL,
case_data jsonb NOT NULL,
conversation jsonb NOT NULL,
outcome text NOT NULL,
difficulty text NOT NULL,
setting text,
stats jsonb NOT NULL,
accusation_text text,
accusation_correct boolean,
created_at timestamptz DEFAULT now()
);
ALTER TABLE game_exports ENABLE ROW LEVEL SECURITY;
CREATE POLICY "anon_insert" ON game_exports FOR INSERT TO anon WITH CHECK (true);
CREATE POLICY "no_public_read" ON game_exports FOR SELECT TO anon USING (false);
Tabela opcional interrogation_patterns para aprendizado entre sessões:
CREATE TABLE interrogation_patterns (
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
session_id text UNIQUE NOT NULL,
setting text,
difficulty text NOT NULL,
outcome text NOT NULL,
questions jsonb,
effective_questions jsonb,
max_stress int,
clues_found int,
time_elapsed int,
embedding vector(1024),
created_at timestamptz DEFAULT now()
);
ALTER TABLE interrogation_patterns ENABLE ROW LEVEL SECURITY;
CREATE POLICY "anon_insert" ON interrogation_patterns FOR INSERT TO anon WITH CHECK (true);
CREATE POLICY "anon_read" ON interrogation_patterns FOR SELECT TO anon USING (true);
Mistral Worldwide Hackathon 2026 — Trilha Online, categoria "Vale Tudo".
Critérios de avaliação: Criatividade/originalidade (mais importante), potencial futuro, implementação técnica, qualidade da apresentação.
Prêmios especiais: Melhor Vibe Mistral (AirPods), Melhor Voz AI (assinatura ElevenLabs 6 meses).
Patrocinadores: Mistral, ElevenLabs, NVIDIA, AWS, Hugging Face, Jump Trading, Weights & Biases, Giant, Raise, Tilde Research, White Circle.
A maioria dos projetos de IA em hackathons são assistentes ou chatbots. Este inverte o roteiro — a IA não está ajudando você, está mentindo para você. O jogador é adversarial ao modelo, não colaborativo. Isso cria uma interação fundamentalmente diferente: você está sondando inconsistências, aplicando pressão e lendo sinais comportamentais, em vez de pedir ajuda.
O jogo também gera dados de treinamento. Cada sessão concluída — perguntas feitas, progressão do estresse, quais táticas funcionaram, quais não funcionaram — é exportável como JSONL. Isso cria um ciclo de feedback: jogue o jogo, exporte os dados, ajuste o modelo, torne-o mais difícil de ser pego.
Jason Poindexter — Inscrição solo, trilha online a partir de Barcelona.
| 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 |