feat(agents): agentes, tiers e pausas — call center completo
Fecha agente.md secao 45-49/52. Depois desta fase, um usuario autenticado consegue logar como agente, entrar numa fila real, se pausar e voltar, tudo refletido de verdade no FreeSWITCH. Schema (migration 20260828124245_agents): - agents (tenant-scoped, RLS): User -> Extension -> identidade de agente, state (enum AgentState de 8 valores) espelhando o estado real, so alterado via login/logout/pause/resume, nunca escrito direto pela API. - tiers: Queue<->Agent (level/position 1:1 com mod_callcenter). - agent_sessions: um ciclo login->logout por linha. - agent_state_events: historico de transicoes de estado. - pause_reasons / agent_pause_events (secao 48). Dois bugs reais corrigidos em FreeSwitchTelephonyProvider, presentes desde a fase de Event Socket original: - "queue add/del member" nao existe no mod_callcenter — membership de fila usa tier add/tier del. So foi pego agora ao confirmar de novo a sintaxe via `help callcenter_config` antes de codar esta fase. - addAgent/removeAgent nao existiam ainda (agent add/del). Mecanismo de sync: agentes e tiers nao tem representacao em XML, so comando ESL direto — diferente do padrao "regenera todos os arquivos" usado em Trunks/Queues. apps/api publica uma mensagem por acao com payload (b2bcall:agents:sync, b2bcall:tiers:sync); b2bcall-fs-config aplica o comando correspondente (agent-sync.ts). Achados confirmados manualmente contra o FreeSWITCH real antes de codar: - `agent add`/`tier add` nao sao idempotentes (erro em duplicata) — sync ignora esse erro (.catch), condicao esperada em resync. - `agent del`/`tier del` em algo inexistente nao da erro — seguro chamar sem checar existencia antes. - `agent set status` so aceita 3 valores exatos (Available/On Break/ Logged Out) — testado deliberadamente com valor invalido. - Corrida real: atribuir tier antes do primeiro login do agente falha silenciosamente do lado do FreeSWITCH (agente so existe la a partir do `agent add` no login). Login sempre re-sincroniza todos os tiers do agente depois de garantir que ele existe — auto-correcao confirmada no teste ponta a ponta. apps/api: AgentsController (CRUD), AgentsMeController (login/logout/ pause/resume — sempre resolve o agente via JWT, nunca um agentId arbitrario do client), PauseReasonsController (CRUD), QueueAgentsController (POST/DELETE de tier em /queues/:id/agents). Verificado ponta a ponta via curl + fs_cli contra o FreeSWITCH real: login -> Available, pause -> On Break, resume -> Available, logout -> Logged Out, todos batendo entre Agent.state (banco) e `agent list` (FreeSWITCH). typecheck do workspace inteiro limpo. ~350MB de memoria total (docker stats). Documentado em docs/AGENTS.md, incluindo lacuna conhecida: estados derivados de chamada (RINGING/IN_CALL/WRAP_UP/RESERVED) dependem do evento CUSTOM callcenter::info, ainda nao comprovado chegando em fs-events nesta sessao (mesma lacuna de sofia::gateway_state ja documentada em docs/TRUNKS.md) — precisa de uma chamada real passando pela fila pra investigar. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X1HxY46WGU4G1zmVDNKcWw
This commit is contained in:
36
TODO.md
36
TODO.md
@@ -200,7 +200,41 @@
|
||||
- [ ] Monitoramento em tempo real (secao 54) — depende de WebSocket
|
||||
- [ ] Quota de filas — depende de Plans/Entitlements
|
||||
|
||||
## PHASE 12+ — ver `agente.md` seções 45 em diante (Agentes, Tiers, Pausas,
|
||||
## PHASE 12 — Agentes, Tiers, Pausas (agente.md secao 45-49, 52)
|
||||
- [x] `agents`/`tiers`/`agent_sessions`/`agent_state_events`/
|
||||
`pause_reasons`/`agent_pause_events` (tenant-scoped, RLS) — separa
|
||||
User/Agent/Extension (secao 45)
|
||||
- [x] Corrigidos bugs reais em `FreeSwitchTelephonyProvider` (nunca
|
||||
testados antes): `addAgentToQueue`/`removeAgentFromQueue` usavam
|
||||
"queue add/del member", que **não existe** — comando certo é
|
||||
`tier add`/`tier del`. Adicionados `addAgent`/`removeAgent`
|
||||
(`agent add`/`agent del`), que faltavam por completo.
|
||||
- [x] Confirmado manualmente antes de codar: `agent add`/`tier add`
|
||||
duplicado dá erro ("already exist", capturado e ignorado no sync);
|
||||
`agent del`/`tier del` em algo inexistente não dá erro; `agent set
|
||||
status` só aceita `Available`/`On Break`/`Logged Out`
|
||||
- [x] Sync 100% dinâmico via ESL (sem arquivo, diferente de Trunks/Queues):
|
||||
`b2bcall:agents:sync`/`b2bcall:tiers:sync` (Redis pub/sub com payload
|
||||
por ação, não um resync geral)
|
||||
- [x] `apps/api`: `/agents` (CRUD provisionamento), `/agents/me/login|
|
||||
logout|pause|resume` (sempre sobre o agente do usuário autenticado,
|
||||
nunca um id arbitrário do client), `/pause-reasons`,
|
||||
`/queues/:id/agents` (tier assignment)
|
||||
- [x] Achado de corrida real, visto no teste ponta a ponta: atribuir tier
|
||||
antes do primeiro login falha (agente ainda não existe no
|
||||
FreeSWITCH) — login sempre re-sincroniza todos os tiers do agente,
|
||||
autocorrigindo. Confirmado acontecendo exatamente assim no teste.
|
||||
- [x] Testado ponta a ponta os 4 estados: login→Available, pause→On Break,
|
||||
resume→Available, logout→Logged Out — todos confirmados batendo
|
||||
entre `Agent.state` (banco) e `callcenter_config agent list`
|
||||
(FreeSWITCH)
|
||||
- [ ] Estados derivados de chamada (RINGING/IN_CALL/WRAP_UP/RESERVED) —
|
||||
dependem de `callcenter::info` (CUSTOM event), ainda não provado
|
||||
funcionando (mesma lacuna do `sofia::gateway_state`, ver docs/TRUNKS.md)
|
||||
- [ ] `PauseReason.maxDuration` não é aplicado automaticamente
|
||||
- [ ] Quota de agentes — depende de Plans/Entitlements
|
||||
|
||||
## PHASE 13+ — ver `agente.md` seções 54 em diante (Monitoramento em tempo real,
|
||||
Predictive Dialer, Recordings, AI, Billing, Frontend, Reports, Security, Tests)
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user