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
83 lines
3.6 KiB
Markdown
83 lines
3.6 KiB
Markdown
# Filas (mod_callcenter)
|
|
|
|
Agente.md secao 37 (mod_callcenter como ACD) e 50-51 (Filas/Estratégias).
|
|
Primeira peça do Call Center — Agentes/Tiers/Pausas ficam pra próxima fase
|
|
(dependem do fluxo de login do agente, seção 45-49, escopo maior).
|
|
|
|
## Descoberta real sobre `callcenter_config`
|
|
|
|
Antes de escrever qualquer código, rodei `help callcenter_config` no
|
|
FreeSWITCH real pra ver a sintaxe exata — e ela é bem diferente do que os
|
|
Trunks fizeram supor:
|
|
|
|
- **Filas**: só `queue load`/`unload`/`reload`/`list` — **não existe**
|
|
`queue add` nem `queue set param`. Filas só podem vir de XML estático,
|
|
carregado/recarregado por nome.
|
|
- **Agentes**: `agent add`/`del`/`set status`/`set state`/... — 100%
|
|
dinâmico via comando ESL, sem XML.
|
|
- **Tiers**: `tier add`/`del`/`set state`/`set level`/`set position` — também
|
|
100% dinâmico.
|
|
|
|
Ou seja, filas usam o mesmo padrão "arquivo + reload" dos Trunks; agentes e
|
|
tiers (próxima fase) vão usar comandos ESL diretos, sem arquivo nenhum.
|
|
|
|
## Mecanismo
|
|
|
|
Mesmo padrão dos gateways Sofia: um arquivo XML por fila
|
|
(`autoload_configs/callcenter_queues.conf.d/<queue_id>.xml`, volume Docker
|
|
compartilhado), incluído via `X-PRE-PROCESS` no nosso
|
|
`callcenter.conf.xml` próprio (agente.md secao 15 — "carregar somente o
|
|
necessário": zeramos os `<agents>`/`<tiers>` estáticos da vanilla, já que
|
|
essas partes vão ser 100% dinâmicas).
|
|
|
|
**Sequência de comandos confirmada manualmente contra o FreeSWITCH real**
|
|
(testei cada passo antes de escrever o código):
|
|
|
|
1. `queue load <nome>` **falha** ("Invalid Queue not found!") se o arquivo
|
|
foi adicionado depois do boot — a árvore XML em memória não sabe do
|
|
arquivo novo ainda.
|
|
2. `reloadxml` primeiro repopula essa árvore a partir do disco.
|
|
3. Depois disso, **`queue reload <nome>` sozinho** já serve tanto pra criar
|
|
quanto atualizar — não precisa distinguir `load` de `reload`.
|
|
4. Fila removida: apagar o arquivo, `reloadxml`, `queue unload <nome>`.
|
|
|
|
`b2bcall-fs-config` (`queue-sync.ts`) reescreve todos os arquivos de fila
|
|
habilitada (todos os tenants) a cada sync, remove os obsoletos, roda
|
|
`reloadxml` uma vez, depois `queue reload` por fila desejada e
|
|
`queue unload` por fila removida. Disparado por Redis pub/sub
|
|
(`b2bcall:queues:sync`, mesmo mecanismo dos Trunks) a cada create/delete via
|
|
API, e uma vez no boot do serviço.
|
|
|
|
## Nome da fila no FreeSWITCH
|
|
|
|
`<queue.id>@<tenant.telephonyDomain>` — mesma convenção UUID dos gateways.
|
|
Como o `telephonyDomain` hoje é compartilhado entre tenants (limitação já
|
|
documentada em docs/EXTENSIONS.md), o unload de uma fila apagada usa o
|
|
domain de "qualquer tenant ativo" como aproximação, já que o registro no
|
|
banco já não existe mais nesse ponto pra sabermos o domain exato.
|
|
|
|
## Verificado ponta a ponta
|
|
|
|
```
|
|
POST /queues {"name":"Suporte","strategy":"ROUND_ROBIN","maxWaitTime":120,"discardAbandonedAfter":90}
|
|
→ fs-config sincroniza (desired:1) → reloadxml + queue reload
|
|
|
|
callcenter_config queue list
|
|
→ <id>@b2bcall.local|round-robin|...|90|false|120|... (parâmetros batem)
|
|
|
|
DELETE /queues/:id
|
|
→ fs-config sincroniza (removed:1) → reloadxml + queue unload
|
|
→ callcenter_config queue list volta vazia
|
|
```
|
|
|
|
## O que falta
|
|
|
|
- Agentes, Tiers, Pausas (secao 45-49) — implementados na fase seguinte, ver
|
|
docs/AGENTS.md.
|
|
- Monitoramento em tempo real das filas (secao 54) — depende de WebSocket
|
|
multi-tenant, que ainda não existe.
|
|
- `tier-rule-wait-multiply-level` e `tier-rule-no-agent-no-wait` (vistos no
|
|
`queue list` da config vanilla) não são expostos como campos próprios
|
|
ainda — ficaram de fora do escopo desta fase.
|
|
- Quota de filas (`max_queues`) — depende de Plans/Entitlements.
|