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

View File

@@ -0,0 +1,40 @@
export interface AIProviderConfig {
id: string;
scope: "GLOBAL" | "TENANT";
tenantId: string | null;
providerType: string;
name: string;
baseUrl: string | null;
organization: string | null;
project: string | null;
apiKeyPreview: string;
enabled: boolean;
createdAt: string;
}
export const PROVIDER_TYPES = ["openai", "anthropic"] as const;
export interface AIModelConfig {
id: string;
tenantId: string | null;
providerId: string;
externalModelId: string;
displayName: string;
capabilities: string[];
inputCost: number | null;
outputCost: number | null;
audioCost: number | null;
enabled: boolean;
createdAt: string;
}
export const AI_CAPABILITIES = ["TRANSCRIPTION", "DIARIZATION", "TEXT_ANALYSIS", "STRUCTURED_OUTPUT", "EMBEDDINGS", "REALTIME_AUDIO"] as const;
export const AI_CAPABILITY_LABELS: Record<string, string> = {
TRANSCRIPTION: "Transcrição",
DIARIZATION: "Diarização",
TEXT_ANALYSIS: "Análise de texto",
STRUCTURED_OUTPUT: "Saída estruturada",
EMBEDDINGS: "Embeddings",
REALTIME_AUDIO: "Áudio em tempo real",
};

View File

@@ -0,0 +1,21 @@
export interface AIPromptVersion {
id: string;
templateId: string;
version: number;
content: string;
createdAt: string;
}
export interface AIPromptTemplate {
id: string;
tenantId: string | null;
purpose: "ANALYSIS" | "SCORECARD";
name: string;
activeVersionId: string | null;
activeVersion: AIPromptVersion | null;
}
export const PROMPT_PURPOSE_LABELS: Record<string, string> = {
ANALYSIS: "Análise de chamada",
SCORECARD: "Avaliação de scorecard",
};

View File

@@ -0,0 +1,14 @@
export interface QualityScorecardItem {
id: string;
name: string;
weight: number;
description: string | null;
evaluationPrompt: string | null;
}
export interface QualityScorecard {
id: string;
name: string;
enabled: boolean;
items: QualityScorecardItem[];
}