feat(frontend): IA > Scorecards, Prompts, Configurações

Três telas novas fecham quase todo o menu IA: Scorecards (critérios
ponderados, array dinâmico como no Dialplan), Prompts (templates com
versionamento — editar = criar versão + ativar numa ação só, já que não
existe endpoint pra listar histórico), e Configurações (providers BYOK +
modelos). Chave de API nunca é reexibida em texto puro, nem uma vez — só
preview mascarado, mesmo na resposta de criação.

Novo componente Textarea em components/ui/input.tsx (mesmo estilo de
Input/Select) — primeira tela que precisa de texto longo.

Testado ponta a ponta contra a API real: scorecard, template de prompt
(v1 -> editar -> v2 ativada), provider BYOK + modelo referenciando ele.
Smoke test de regressão nas 16 telas anteriores do tenant + platform,
todas 200. Typecheck limpo no monorepo inteiro.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BFaBaBSQGhyXGEgtTYZGV8
This commit is contained in:
2026-08-29 16:30:33 -03:00
parent 4d112fcea0
commit 75212cafe6
23 changed files with 1150 additions and 3 deletions

42
TODO.md
View File

@@ -1054,6 +1054,48 @@ Troncos, Discador > Lista de Bloqueio (agente.md secao 50-51, 41-42, 71,
- [ ] Relatórios > Consumo (dashboard de quotas, secao 139) — ainda "em
breve"
## PHASE 31 — Frontend: IA > Scorecards, Prompts, Configurações
(agente.md secao 96-103, 114-118)
- [x] IA > Scorecards (`/app/ia/scorecards`): criar (nome + lista dinâmica
de critérios com peso, mesmo padrão de array dinâmico do Dialplan),
listar em cards (um por scorecard, itens com badge de peso),
remover.
- [x] IA > Prompts (`/app/ia/prompts`): criar template (finalidade
Análise/Scorecard + conteúdo v1), listar com o conteúdo da versão
ativa visível. "Editar" o conteúdo dispara `POST .../versions` +
`POST .../versions/:id/activate` numa ação só (create-então-ativa) —
não existe endpoint pra listar o histórico de versões, então a UI
não finge ter uma linha do tempo que não dá pra buscar; só o
conteúdo ativo é mostrado. Templates `Global` (da plataforma,
`tenantId=null`, RLS híbrida já resolve a união sem filtro no
client) aparecem mas sem botão de editar — só quem tem role de
plataforma pode alterar, e o backend rejeitaria com 403 mesmo que
o botão existisse.
- [x] IA > Configurações (`/app/ia/configuracoes`): providers (BYOK,
`scope: "TENANT"` sempre — a tela nem oferece GLOBAL, que já é
exclusivo de platform admin no backend) e modelos (referenciando um
provider, capacidades via checkboxes). Chave de API só aparece como
preview (`...xxxxxxxx`) mesmo na resposta de criação — nunca
reexibida em texto puro, nem uma vez (diferente do padrão "revela
uma vez" de Ramais; aqui a API nunca devolve o valor puro, ponto).
- [x] `Textarea` novo em `components/ui/input.tsx` (mesmo estilo de
`Input`/`Select`) — primeira tela que precisa de texto longo
(conteúdo de prompt).
- [x] Testado ponta a ponta contra a API real (tenant Acme): scorecard
"Atendimento" com critério "Saudação" criado e listado; template
"Análise padrão" criado (v1) → editado → v2 ativada e refletida na
tela; provider "OpenAI da Acme" (BYOK) criado com preview de chave
mascarada → modelo "GPT-4o mini" criado referenciando o provider,
com capacidade "Transcrição". Smoke test de regressão nas 16 telas
anteriores do tenant + platform, todas 200.
- [ ] Scorecards: sem edição de critérios existentes (só criar scorecard
inteiro ou remover) — mesma limitação de "só create/list/delete"
já documentada em outras telas simples
- [ ] IA > Configurações não distingue custo por modelo (`inputCost`/
`outputCost`/`audioCost` existem no backend, sem campo no form) —
decisão de escopo pra manter o formulário enxuto nesta primeira
versão
---
## Riscos conhecidos