mirror of
https://github.com/melgarafael/DeskcommCRM.git
synced 2026-10-02 01:28:34 +08:00
Recorte do #714, de @betoarts (Humberto Moura Neto). A ideia e o diagnostico sao dele; o que muda em relacao ao patch original e o LUGAR onde a guarda entra, porque o arquivo alvo andou muito desde que ele escreveu. === O DEFEITO `classifyStage` e `classifyJailbreak` rodam ANTES de o agente responder e sao os dois ADVISORIOS do turno: um sugere o estagio do funil (quem confirma e o modelo do agente, via `update_lead_state`), o outro so FLAGRA a mensagem no trace e nunca vetou um inbound sozinho. A excecao de `runModelCall` subia dos dois assim mesmo. Como eles sao os dois elementos do `Promise.all` que abre `executarTurnoDoAgente`, qualquer falha deles matava o turno inteiro e o cliente ficava sem resposta. O caso dominante nao e o provedor cair: e o ponto auxiliar, em Configuracoes > Provedores de IA, apontar para um modelo que saiu do painel ou para uma credencial revogada — o modelo do agente de pe, o atendimento parado. Os dois classificadores ja degradavam saida ILEGIVEL sem bloquear (`parseStageSuggestion` devolve null, `parseJailbreakClassification` devolve `none`). A excecao era o unico caminho que fugia dessa regra, subindo. === ONDE A GUARDA ENTRA, E POR QUE NAO ONDE ELE POS O patch do #714 envolvia os dois CALL SITES em `inbound-turn.ts`, com dois `await` em serie — era a forma daquele arquivo na epoca. Hoje o turno roda os dois em `Promise.all`, e `tests/unit/classificadores-auxiliares-em-paralelo.test.ts` exige, por AST, que as duas chamadas sejam elementos DIRETOS do mesmo array. Aplicar o patch como escrito reintroduziria a latencia em serie que aquele teste existe para impedir, e reprovaria o gate. A guarda entra dentro de `classifyStage` e `classifyJailbreak`, que e o lugar certo por tres razoes: e onde a regra de degradacao dessas funcoes ja mora (a de parse), cobre todo call site futuro sem lista a manter, e deixa o turno intocado — nenhum dos dois testes de AST do `inbound-turn.ts` precisou mudar. === O QUE CONTINUA SUBINDO `LlmBudgetExceededError`, exatamente como o @betoarts escreveu. Quem a espera e `comHandoffSeOrcamentoAcabar`: os auxiliares sao os PRIMEIROS a estourar o teto do mes, e e essa escolta que passa a conversa para uma pessoa em vez de deixar o lead no vacuo. Engolir o erro de orcamento aqui trocaria o handoff por um turno que segue gastando. === O DEGRADE NAO E SILENCIOSO `runModelCall` grava a chamada falha em `llm_calls` (purposes `stage_classifier` / `jailbreak_detect`) ANTES de relancar, e o `warn` carimba o run. O laco de retorno e essa linha — "a camada auxiliar parou de rodar" tem onde ser lido, em Uso de IA. Nos campos do log vai so a mensagem do fornecedor, truncada em 200: a mensagem do lead nunca entra (regra dura 8), e ha caso medindo isso. === PROVA `tests/unit/classificador-auxiliar-nao-derruba-o-turno.test.ts`, 5 casos. Controle negativo rodado: com os dois arquivos revertidos ao estado da main, 3 dos 5 reprovam (os tres do degrade) e 2 passam — os de orcamento, que medem a propriedade que NAO podia ser quebrada pelo `catch` novo. A METADE do #714 que NAO entrou: `app/api/v1/ai/agents/[id]/versions/[vid]/test/route.ts`, onde ele trocava `status: "error"` por `"failed"`. A main ja resolveu, e melhor — o caminho de erro daquela rota ja grava `failed`, `error_message` e um `logger.error`, e o `catch` vazio que tornava a falha indiagnosticavel tambem ja foi fechado. Trazer o pedaco dele ali nao mudaria byte nenhum. Refs: #714 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FHzAhMNW4yRWfgR5Ack89m