# Refactor Log Este arquivo registra o que mudou a cada etapa do refactor incremental. Nota: - as entradas `000` a `010` foram escritas antes da consolidacao da estrutura atual do repositorio - por isso, varias delas ainda referenciam caminhos antigos sem o prefixo `src/` - a partir da entrada `011`, os caminhos refletem o layout atual da raiz + `src/` ## Como preencher Para cada mudanca relevante, registrar: - data - objetivo - arquivos alterados - comportamento preservado - comportamento alterado - risco conhecido - validacao executada - proximo passo ## Entrada 000 - Baseline documental - Data: 2026-03-27 - Objetivo: criar uma base de documentacao viva para acompanhar o refactor incremental - Arquivos alterados: - `README.md` - `docs/README.md` - `docs/refactor-plan.md` - `docs/refactor-log.md` - `docs/api-overview.md` - Comportamento preservado: nenhum codigo de execucao foi alterado - Comportamento alterado: nenhum - Risco conhecido: a documentacao precisa ser mantida junto das mudancas, senao perde valor - Validacao executada: revisao manual do conteudo criado - Proximo passo: iniciar Fase 1 com extracao dos adapters de pipeline, speech, bridge e export ## Entrada 001 - Fase 1 / adapters extraidos - Data: 2026-03-27 - Objetivo: extrair boundaries de pipeline, speech, bridge e export sem mudar o comportamento publico da API - Arquivos alterados: - `app/livekit/main.py` - `app/livekit/adapters/pipeline_adapter.py` - `app/livekit/adapters/speech_service.py` - `app/livekit/adapters/bridge_gateway.py` - `app/livekit/adapters/export_service.py` - `docs/refactor-log.md` - Comportamento preservado: - contrato do websocket do bridge - fluxo STT -> pipeline -> TTS - notificacao `DONE` para o bridge - exportacao final de sessao - Comportamento alterado: - nenhum comportamento publico planejado - `app/livekit/main.py` passa a delegar responsabilidades para adapters - Risco conhecido: - como a extracao preserva a logica inline, ainda existe acoplamento forte no runtime - faltam testes automatizados de regressao para interrupcao, idle nudge e finalizacao - Validacao executada: - revisao manual do diff - validacao sintatica prevista apos a extracao - Proximo passo: - reduzir `nonlocal` no runtime com um `CallRuntime` explicito - preparar o terreno para policies e scheduler unificados ## Entrada 002 - Fase 2 / runtime explicito - Data: 2026-03-27 - Objetivo: encapsular o fluxo da chamada em um `CallRuntime` com `CallState` explicito, reduzindo estado implícito e `nonlocal` em `app/livekit/main.py` - Arquivos alterados: - `app/livekit/main.py` - `app/livekit/runtime/state.py` - `app/livekit/runtime/call_runtime.py` - `docs/refactor-log.md` - `docs/api-overview.md` - Comportamento preservado: - contrato do websocket do bridge - fluxo STT -> pipeline -> TTS - idle nudge, interrupcao e finalizacao continuam com a mesma logica operacional - exportacao e notificacao `DONE` continuam sendo disparadas pelo agent - Comportamento alterado: - `app/livekit/main.py` passa a ser majoritariamente wiring do session e construcao do runtime - o estado mutavel da chamada fica concentrado em `CallState` - Risco conhecido: - as regras ainda nao foram transformadas em policies puras; a logica segue acoplada ao runtime, apenas mais organizada - ainda faltam testes automatizados para cenarios concorrentes de fala, interrupcao e fechamento - Validacao executada: - revisao manual do diff - `PYTHONDONTWRITEBYTECODE=1 python3 -m py_compile app/livekit/main.py app/livekit/adapters/bridge_gateway.py app/livekit/adapters/export_service.py app/livekit/adapters/pipeline_adapter.py app/livekit/adapters/speech_service.py app/livekit/runtime/state.py app/livekit/runtime/call_runtime.py` - Proximo passo: - introduzir command/execution boundaries no runtime - preparar a migracao de interrupcao, idle e finalize para policies + scheduler ## Entrada 003 - Fase 3 / commands e executor - Data: 2026-03-29 - Objetivo: separar efeitos colaterais do `CallRuntime` por meio de comandos tipados e um executor dedicado - Arquivos alterados: - `app/livekit/main.py` - `app/livekit/runtime/commands.py` - `app/livekit/runtime/command_executor.py` - `app/livekit/runtime/call_runtime.py` - `docs/refactor-log.md` - `docs/api-overview.md` - Comportamento preservado: - contrato do websocket do bridge - fluxo STT -> pipeline -> TTS - sequencia de idle nudge, interrupcao e finalizacao - integracao com LiveKit, pipeline e export sem troca de contrato - Comportamento alterado: - `CallRuntime` deixa de chamar diretamente bridge/export/speech/pipeline para os principais side effects - side effects passam a trafegar por comandos (`commands.py`) executados por `RuntimeCommandExecutor` - Risco conhecido: - ainda existe conhecimento de regras dentro de `CallRuntime`; a extracao atual isola efeitos, mas nao transforma as regras em policies puras - `agent._ready`, `agent._run_lock` e coordenacao de fila ainda pertencem ao runtime - Validacao executada: - revisao manual do diff - validacao sintatica com `python3 -c 'from pathlib import Path; paths = [...]; [compile(Path(p).read_text(), p, "exec") for p in paths]'` - Proximo passo: - extrair policies de interrupcao, idle e finalizacao - introduzir scheduler unico para timers e reduzir logica condicional no runtime ## Entrada 004 - Fase 4 / policies e scheduler - Data: 2026-03-29 - Objetivo: mover regras de interrupcao, idle e finalize-once para policies dedicadas e centralizar timers em um scheduler unico - Arquivos alterados: - `app/livekit/main.py` - `app/livekit/policies/interrupt_policy.py` - `app/livekit/policies/idle_policy.py` - `app/livekit/policies/finalization_policy.py` - `app/livekit/runtime/scheduler.py` - `app/livekit/runtime/state.py` - `app/livekit/runtime/call_runtime.py` - `docs/refactor-log.md` - `docs/api-overview.md` - Comportamento preservado: - contrato do websocket do bridge - fluxo STT -> pipeline -> TTS - timers de idle nudge e idle close continuam ativos - finalizacao por `DONE`, `room_empty`, `shutdown_callback` e `no_user_response` continua existindo - Comportamento alterado: - `InterruptPolicy` passa a decidir interrupcao por stage e filtro de backchannel - `IdlePolicy` passa a concentrar regras de nudge/close - `FinalizationPolicy` passa a concentrar regras de finalize-once e room-empty - `TimerScheduler` passa a concentrar arm/cancel/token dos timers - `CallState` deixa de carregar estado interno de timers - Risco conhecido: - o `CallRuntime` ainda conhece a ordem operacional completa da chamada; as policies reduzem acoplamento, mas ainda nao existe reducer/event engine - `RuntimeConfig` ainda carrega campos hoje parcialmente sobrepostos pelas policies; isso pode ser simplificado em um corte futuro - Validacao executada: - revisao manual do diff - validacao sintatica com `python3 -c 'from pathlib import Path; paths = [...]; [compile(Path(p).read_text(), p, "exec") for p in paths]'` - Proximo passo: - avaliar se vale introduzir eventos/comandos mais declarativos no runtime ou parar aqui e estabilizar - se seguir, o proximo salto natural e um reducer/event engine ou a evolucao da integracao de IA (`llm_node` ou agente remoto) ## Entrada 005 - Estabilizacao / testes unitarios do runtime - Data: 2026-03-29 - Objetivo: adicionar cobertura automatizada para os cenarios mais criticos do runtime sem depender de LiveKit real - Arquivos alterados: - `tests/__init__.py` - `tests/livekit/__init__.py` - `tests/livekit/test_runtime.py` - `docs/refactor-log.md` - Comportamento preservado: - nenhum contrato publico da API foi alterado - nenhum fluxo de audio ou websocket foi modificado - Comportamento alterado: - o repositorio passa a ter uma suite unitária para policies, scheduler, command executor e cenarios críticos do `CallRuntime` - Risco conhecido: - os testes ainda usam doubles/fakes e nao substituem validacao integrada com LiveKit real - ainda faltam cenarios mais completos de timer real, callback de room e speech handle real - Validacao executada: - `python3 -m unittest tests.livekit.test_runtime -v` - `python3 -m unittest discover -s tests -v` - Proximo passo: - ampliar cobertura para speech handle real e integracao de callbacks com objetos LiveKit reais, se isso passar a ser area de regressao - ou encerrar a fase de estabilizacao e voltar a discutir a evolucao da camada de IA ## Entrada 006 - Backend remoto via websocket - Data: 2026-03-29 - Objetivo: permitir trocar a pipeline local por um agent remoto via websocket, preservando o fluxo STT -> IA -> TTS e o runtime atual - Arquivos alterados: - `app/livekit/main.py` - `app/livekit/adapters/agent_backend.py` - `app/livekit/adapters/backend_factory.py` - `app/livekit/adapters/pipeline_adapter.py` - `app/livekit/adapters/remote_agent_ws_adapter.py` - `app/livekit/runtime/command_executor.py` - `requirements.txt` - `tests/livekit/test_remote_agent_ws_adapter.py` - `docs/refactor-log.md` - `docs/api-overview.md` - Comportamento preservado: - contrato do websocket do bridge - fluxo de audio com LiveKit e TTS no agent local - runtime de interrupcao, idle nudge e finalizacao - backend `langgraph` segue como default - Comportamento alterado: - o backend da camada de IA passa a ser selecionavel por `AGENT_BACKEND` - quando `AGENT_BACKEND=remote_ws`, o agent envia cada turno transcrito para um websocket remoto e vocaliza a resposta retornada - a finalizacao pode opcionalmente buscar um `result` remoto via mensagem `type=end` - o bridge agora repassa `agent`, `RouterCallKeyDay`, `RouterCallKey`, `ANI`, `GSM` e `ID_FATURA` para o agent quando esses campos vierem no metadata do cliente - o adapter remoto roteia a chamada para endpoints diferentes de acordo com `agent` (`conta`, `oferta`, `cobranca`) - o agent `conta` passou a usar contrato proprio em websocket com `action/payload` na entrada e `result.content` na resposta - Risco conhecido: - o contrato do websocket remoto ainda e interno e precisa ser homologado com o agent externo real - o adapter atual usa conexao websocket por turno, nao uma sessao persistente - se o agent remoto nao devolver `stage`, a politica local dependera do ultimo stage conhecido ou do default configurado - o campo `timestamp` e gerado localmente no momento de cada turno; se o integrador exigir outro formato, isso ainda precisa ser alinhado - Validacao executada: - testes unitarios do adapter remoto e factory - execucao da suite `unittest` - Proximo passo: - homologar o contrato do websocket remoto com payload/resposta reais - decidir se a conexao remota deve continuar por turno ou evoluir para sessao persistente ## Entrada 007 - Cliente web de voz e call_config por chamada - Data: 2026-03-30 - Objetivo: disponibilizar um cliente web para testar o fluxo de voz pelo navegador e permitir overrides de `STT`, `TTS` e `AGENT` por chamada - Arquivos alterados: - `app/ws_gateway/main.py` - `app/ws_gateway/voice_client.html` - `app/ws_gateway/call_config.py` - `app/livekit/main.py` - `app/livekit/call_config.py` - `app/livekit/adapters/backend_factory.py` - `tests/config/test_call_config.py` - `docs/api-overview.md` - `docs/refactor-log.md` - Comportamento preservado: - fluxo principal de audio via `/ws/agent` - bridge continua recebendo `start`, audio binario e encerrando com `stop` - defaults de `STT`, `TTS` e backend continuam vindo de env quando nao houver override - Comportamento alterado: - `/voice-client` agora serve um cliente web para capturar microfone e ouvir o audio retornado - o `start` pode carregar `call_config` com overrides por chamada - o agent agora aplica overrides de backend, STT e TTS para a sessao corrente - Risco conhecido: - o cliente web usa `ScriptProcessorNode`, que e suficiente para homologacao mas nao e a opcao mais moderna da Web Audio API - os providers dinamicos suportados ainda sao os que ja existem no projeto (`internal_http` e `elevenlabs`) - Validacao executada: - testes puros de `call_config` - execucao da suite `unittest` - Proximo passo: - se o cliente web passar a ser usado em rotina de homologacao, vale migrar a captura/playback para `AudioWorklet` - se surgirem novos providers de STT/TTS, plugar nas factories por chamada ## Entrada 008 - Timeline estruturada por chamada - Data: 2026-03-30 - Objetivo: criar observabilidade ponta a ponta para entender o caminho `bridge -> livekit -> stt -> backend -> tts -> stop` por chamada - Arquivos alterados: - `app/utils/call_timeline.py` - `app/ws_gateway/main.py` - `app/livekit/main.py` - `app/livekit/runtime/call_runtime.py` - `app/livekit/adapters/backend_factory.py` - `app/livekit/adapters/pipeline_adapter.py` - `app/livekit/adapters/remote_agent_ws_adapter.py` - `app/livekit/adapters/bridge_gateway.py` - `app/providers/stt_internal_livekit.py` - `tests/utils/test_call_timeline.py` - `docs/api-overview.md` - `docs/refactor-log.md` - Comportamento preservado: - contrato publico de `WS /ws/agent` - fluxo de audio ja existente entre cliente, bridge, LiveKit e agent - backends de IA, STT e TTS seguem com a mesma responsabilidade funcional - Comportamento alterado: - bridge e agent agora escrevem uma timeline estruturada em `jsonl` compartilhada por chamada - a timeline usa o mesmo `timeline_id` e o mesmo `origin_unix_ms` entre os dois processos para manter a ordem relativa dos eventos - o bridge passou a registrar eventos como `ready_sent`, `dispatch_started`, `agent_join`, `client_audio_enabled`, `done_packet_received` e `call_end` - o agent passou a registrar eventos como `user_transcript_final`, `pipeline_run_started`, `pipeline_run_completed`, `tts_stage_started`, `interrupt_marked`, `finalize_started` e `finalize_completed` - o provider de STT agora registra etapas de reconhecimento (`stt_recognize_started`, `stt_vosk_completed`, `stt_http_completed`) - o backend remoto por websocket agora registra `remote_agent_request` e `remote_agent_response` - Risco conhecido: - a timeline registra payloads de request do backend remoto, o que aumenta a verbosidade e pode expor dados sensiveis em ambiente de debug - o arquivo `jsonl` e compartilhado entre dois processos locais; o uso atual com `flock` e suficiente para dev/homologacao, mas nao substitui observabilidade centralizada - Validacao executada: - `py_compile` dos arquivos alterados - teste unitario novo de timeline - execucao completa da suite `unittest` - Proximo passo: - decidir se a timeline deve continuar sempre habilitada em dev ou ficar atras de flag por ambiente - se a homologacao exigir, adicionar visualizador simples da timeline no cliente web ## Entrada 009 - Fake remoto para homologacao via UI - Data: 2026-03-30 - Objetivo: permitir testar o fluxo `STT -> remote_ws -> TTS` pela UI mesmo sem o agent remoto real estar de pe - Arquivos alterados: - `app/ws_gateway/fake_remote_agent.py` - `app/ws_gateway/main.py` - `app/ws_gateway/voice_client.html` - `app/livekit/adapters/backend_factory.py` - `tests/ws_gateway/test_fake_remote_agent.py` - `tests/livekit/test_remote_agent_ws_adapter.py` - `docs/api-overview.md` - `docs/refactor-log.md` - Comportamento preservado: - backend `remote_ws` continua exigindo URL real quando selecionado - o contrato do adapter remoto segue o mesmo - Comportamento alterado: - o `bridge` agora expoe `WS /fake-agent/ws` - a UI ganhou a opcao `remote_ws_fake` - quando `remote_ws_fake` e selecionado, o agent local aponta para `REMOTE_AGENT_WS_FAKE_URL` ou usa por padrao `ws://127.0.0.1:8000/fake-agent/ws` - o fake responde nos contratos `conta` e generico, com progressao simples de stages e encerramento por palavras-chave como `encerrar`, `obrigado` e `tchau` - Risco conhecido: - o fake nao simula comportamento de negocio real; ele serve apenas para homologacao tecnica do fluxo de voz - o fake e stateless por conexao, entao a progressao depende do `stage` enviado pelo agent local - Validacao executada: - testes unitarios do fake remoto - testes do backend fake no adapter remoto - execucao completa da suite `unittest` - Proximo passo: - se a homologacao pedir cenarios mais realistas, adicionar scripts por agent (`conta`, `oferta`, `cobranca`) com respostas configuraveis ## Template de nova entrada - Data: - Objetivo: - Arquivos alterados: - Comportamento preservado: - Comportamento alterado: - Risco conhecido: - Validacao executada: - Proximo passo: ## Entrada 010 - Correcao do roteamento `remote_ws_fake` - Data: 2026-03-30 - Objetivo: garantir que a selecao `remote_ws_fake` na UI nao seja sobrescrita pela URL real configurada em `REMOTE_AGENT_WS_URL` - Arquivos alterados: - `app/livekit/adapters/backend_factory.py` - `app/livekit/adapters/remote_agent_ws_adapter.py` - `tests/livekit/test_remote_agent_ws_adapter.py` - `docs/api-overview.md` - `docs/refactor-log.md` - Comportamento preservado: - `remote_ws` continua usando `REMOTE_AGENT_WS_URL` - o adapter remoto continua sendo o mesmo para backend real e fake - Comportamento alterado: - `remote_ws_fake` agora prioriza sempre `REMOTE_AGENT_WS_FAKE_URL`, mesmo quando `REMOTE_AGENT_WS_URL` existe no ambiente - a timeline do adapter remoto agora diferencia `backend=remote_ws_fake` de `backend=remote_ws` - Risco conhecido: - aliases como `fake_remote_ws` e `ws_fake` continuam sendo tratados como `remote_ws_fake`, mas o label emitido na timeline fica canonico como `remote_ws_fake` - Validacao executada: - `python3 -m unittest tests.livekit.test_remote_agent_ws_adapter -v` - `python3 -m py_compile app/livekit/adapters/backend_factory.py app/livekit/adapters/remote_agent_ws_adapter.py tests/livekit/test_remote_agent_ws_adapter.py` - Proximo passo: - validar na chamada real da UI que o timeline e o request usam `ws://127.0.0.1:8000/fake-agent/ws` ## Entrada 011 - Reorganizacao da raiz e remocao de boilerplate - Data: 2026-04-06 - Objetivo: consolidar a estrutura real do projeto na raiz do repositorio, mantendo `src/app` e `src/agent` como codigo-fonte canonico - Arquivos alterados: - `README.md` - `makefile` - `Dockerfile` - `pytest.ini` - `.env.example` - `.gitignore` - `.dockerignore` - `requirements.txt` - `livekit.yaml` - `docs/*` - `tests/*` - `k8s/deployment.yaml` - remocao de `pyproject.toml`, `uv.lock`, `README copy.md`, `configs/config.example.yaml` e scripts herdados do boilerplate - Comportamento preservado: - `src/app` e `src/agent` permanecem como raiz do codigo de execucao - o bridge FastAPI continua em `src/app/ws_gateway/main.py` - o projeto continua usando `PYTHONPATH=src` - Comportamento alterado: - a raiz do repositorio passa a refletir o projeto real, e nao mais o boilerplate original - `requirements.txt` passa a ser a fonte principal de dependencias - artefatos de runtime (`logs`, `timeline`, `__pycache__`) deixam de ser versionados - Risco conhecido: - arquivos de infra legados fora do fluxo principal ainda poderiam carregar suposicoes antigas do boilerplate - a migracao para `requirements.txt` simplifica a operacao, mas remove o lockfile anterior - Validacao executada: - `python3 -m compileall src tests` - `python3 -m pytest tests/utils/test_call_timeline.py -q` - Proximo passo: - revisar a infra auxiliar restante e reduzir ruido operacional na raiz ## Entrada 012 - Simplificacao do compose local de observabilidade - Data: 2026-04-06 - Objetivo: transformar o `docker-compose.yml` em uma stack minima e coerente para Langfuse local - Arquivos alterados: - `docker-compose.yml` - Comportamento preservado: - a stack opcional de Langfuse continua disponivel para uso local - a aplicacao principal segue fora do compose, operada via `make` - Comportamento alterado: - remocao do servico `mongo` - consolidacao apenas de `langfuse-web`, `langfuse-worker`, `postgres`, `redis`, `clickhouse` e `minio` - reducao de duplicacao com anchors para configuracoes compartilhadas - Risco conhecido: - o compose continua sendo opcional e depende de configuracao explicita do projeto para apontar para Langfuse self-hosted - Validacao executada: - validacao sintatica do YAML com parser local - Proximo passo: - se a equipe mantiver uso frequente, considerar alvos dedicados no `makefile` para subir e derrubar a stack ## Entrada 013 - Provider TTS opcional desacoplado do import global - Data: 2026-04-06 - Objetivo: impedir que a falta do SDK do ElevenLabs quebrasse o import do modulo inteiro de TTS - Arquivos alterados: - `src/app/providers/tts.py` - `tests/providers/test_tts.py` - Comportamento preservado: - selecao de provider TTS por configuracao - suporte aos providers ja existentes - Comportamento alterado: - o SDK do ElevenLabs deixa de ser carregado no topo do modulo e passa a ser resolvido sob demanda - ausencia do SDK passa a gerar `missing_elevenlabs_sdk`, em vez de falha de import que derruba testes e providers nao relacionados - Risco conhecido: - o provider continua opcional, mas a disciplina de dependencias ainda segue concentrada em `requirements.txt` - Validacao executada: - `python3 -m pytest tests/providers/test_tts.py -q` - `python3 -m pytest tests/adapters/test_azure_tts.py -q` - Proximo passo: - continuar removendo acoplamentos desnecessarios entre providers e entrypoints ## Entrada 014 - Remocao de mocks e hardcodes dos pipelines de texto - Data: 2026-04-06 - Objetivo: tirar codigo de demonstracao do caminho produtivo dos endpoints de texto - Arquivos alterados: - `src/app/services/session_context.py` - `src/app/services/text_pipeline.py` - `src/app/services/text_pipeline_stream.py` - `src/app/ws_gateway/main.py` - `tests/services/test_session_context.py` - Comportamento preservado: - os endpoints `/ws/text` e `/ws/text_stream` continuam aceitando a mesma sessao de entrada - os pipelines continuam recebendo `mailing` e `intro` - Comportamento alterado: - remocao do uso de `app.models.mock` - remocao de protocolo e dados fixos hardcoded nos pipelines - introducao de extracao explicita de protocolo via `session_context` - Risco conhecido: - se existiam fluxos de dev que dependiam dos mocks antigos, eles passam a precisar de payloads reais - Validacao executada: - `python3 -m pytest -q` - resultado observado na etapa: `36 passed` - Proximo passo: - consolidar contratos duplicados entre gateway e runtime ## Entrada 015 - Unificacao de `call_config` - Data: 2026-04-06 - Objetivo: eliminar duplicacao entre as implementacoes de `call_config` do gateway e do runtime LiveKit - Arquivos alterados: - `src/app/common/call_config.py` - `src/app/ws_gateway/call_config.py` - `src/app/livekit/call_config.py` - `tests/config/test_call_config.py` - Comportamento preservado: - API publica de `build_call_config(...)` - API publica de `normalize_call_config(...)` e resolucao dos campos auxiliares - Comportamento alterado: - a normalizacao passa a ter um nucleo compartilhado em `src/app/common/call_config.py` - `ws_gateway` e `livekit` viram wrappers leves para o mesmo contrato - Risco conhecido: - qualquer evolucao futura de `call_config` passa a ter impacto compartilhado entre bridge e agent, o que e desejado, mas exige disciplina de compatibilidade - Validacao executada: - `python3 -m pytest tests/config/test_call_config.py -q` - `python3 -m pytest -q` - resultado observado na etapa: `36 passed` - Proximo passo: - iniciar a quebra incremental do monolito em `src/app/ws_gateway/main.py` ## Entrada 016 - Extracao do parsing inicial da sessao no bridge - Data: 2026-04-06 - Objetivo: remover do `ws_gateway/main.py` a logica de parsing da mensagem `start`, resolucao de mailing e montagem de `intro`/`nudge` - Arquivos alterados: - `src/app/ws_gateway/session_start.py` - `src/app/ws_gateway/main.py` - `tests/ws_gateway/test_session_start.py` - Comportamento preservado: - contrato de primeira mensagem `type=start` - geracao de `mailing`, `intro` e `nudge` - construcao do contexto do agente remoto a partir de metadata + mailing - Comportamento alterado: - criacao da dataclass `StartSessionContext` - centralizacao de `parse_start_payload`, `recv_start_message` e `build_remote_agent_context` em modulo proprio - `/ws/agent`, `/ws/text` e `/ws/text_stream` passam a consumir um contexto estruturado, e nao uma tuple solta - Risco conhecido: - o contrato de entrada continua dependente do payload do cliente; a extracao melhora testabilidade, mas nao redefine o protocolo - Validacao executada: - `python3 -m compileall src/app/ws_gateway src/app/services tests/ws_gateway` - `python3 -m pytest tests/ws_gateway/test_session_start.py -q` - `python3 -m pytest -q` - resultado observado na etapa: `39 passed` - Proximo passo: - extrair o bootstrap da chamada para reduzir ainda mais a responsabilidade do endpoint ## Entrada 017 - Extracao do bootstrap da chamada do bridge - Data: 2026-04-06 - Objetivo: separar a preparacao da chamada do runtime do endpoint `/ws/agent` - Arquivos alterados: - `src/app/ws_gateway/session_bootstrap.py` - `src/app/ws_gateway/main.py` - `tests/ws_gateway/test_session_bootstrap.py` - Comportamento preservado: - geracao de token de acesso ao LiveKit - montagem de `call_config`, `remote_agent_context`, `timeline` e `dispatch_metadata` - fallbacks de protocolo e telefone - Comportamento alterado: - introducao da dataclass `BridgeSessionBootstrap` - centralizacao de `room_name`, `identity`, `token`, `protocol`, `phone_number` e `dispatch_metadata` em um builder dedicado - `main.py` passa a consumir um pacote pronto de bootstrap - Risco conhecido: - o bootstrap ainda depende de envs e factories externas; a extracao organiza responsabilidade, mas nao muda a politica de configuracao - Validacao executada: - `python3 -m compileall src/app/ws_gateway tests/ws_gateway` - `python3 -m pytest tests/ws_gateway/test_session_bootstrap.py -q` - `python3 -m pytest -q` - resultado observado na etapa: `41 passed` - Proximo passo: - extrair o ciclo de vida da sessao LiveKit do endpoint ## Entrada 018 - Extracao do lifecycle da sessao LiveKit no bridge - Data: 2026-04-06 - Objetivo: remover do endpoint os handlers de participante, o processamento do pacote `DONE` e o watcher de encerramento - Arquivos alterados: - `src/app/ws_gateway/session_lifecycle.py` - `src/app/ws_gateway/main.py` - `tests/ws_gateway/test_session_lifecycle.py` - Comportamento preservado: - deteccao de entrada e saida do agente remoto - processamento do pacote `agent.stage` com `DONE` - envio de `stop` para o cliente ao final da chamada - Comportamento alterado: - criacao de `RoomLifecycleState` para concentrar `agent_participant` e `done_payload` - extracao de `register_room_lifecycle_handlers(...)` - extracao de `watch_call_done(...)` - Risco conhecido: - o fluxo ainda depende de coordenacao concorrente entre tasks do bridge; a extracao reduz tamanho do endpoint, mas nao muda o modelo de concorrencia - Validacao executada: - `python3 -m compileall src/app/ws_gateway tests/ws_gateway` - `python3 -m pytest tests/ws_gateway/test_session_lifecycle.py -q` - `python3 -m pytest -q` - resultado observado na etapa: `43 passed` - Proximo passo: - extrair a camada de intro/sinalizacao do bridge ## Entrada 019 - Extracao da intro TTS e da sinalizacao de audio no bridge - Data: 2026-04-07 - Objetivo: isolar do endpoint o trecho responsavel por intro TTS, liberacao do audio do cliente, sinalizacao `client_audio_enabled` e bootstrap do streaming do agente - Arquivos alterados: - `src/app/ws_gateway/session_audio.py` - `src/app/ws_gateway/main.py` - `tests/ws_gateway/test_session_audio.py` - Comportamento preservado: - intro sintetizada antes da liberacao do audio do cliente - emissao do controle `client_audio_enabled` para o agente - inicializacao do worker que consome audio do agente quando ele fica pronto - Comportamento alterado: - extracao de `play_intro_to_client(...)` - extracao de `notify_client_audio_enabled(...)` - extracao de `stream_agent_audio_when_ready(...)` - `main.py` passa a gerenciar explicitamente a task `t_control`, em vez de disparar a notificacao como fire-and-forget - ajuste de typing para evitar import-time acidental de `audioop` em testes unitarios do modulo novo - Risco conhecido: - o caminho quente de audio continua centralizado em `main.py`; ainda faltam as primitivas de transporte para o arquivo deixar de ser monolitico - Validacao executada: - `python3 -m compileall src/app/ws_gateway tests/ws_gateway` - `python3 -m pytest tests/ws_gateway/test_session_audio.py -q` - `python3 -m pytest -q` - resultado observado na etapa: `46 passed` - Proximo passo: - extrair as primitivas de transporte de audio e LiveKit (`ws_audio_receiver`, `publish_queue_to_livekit`, `connect_publish_livekit`, `stream_agent_audio_to_queue`) ## Entrada 020 - Validacao do Dockerfile para CI/CD - Data: 2026-04-07 - Objetivo: revisar o `Dockerfile` frente ao layout atual do projeto e corrigir o principal risco de compatibilidade para pipeline - Arquivos alterados: - `Dockerfile` - Comportamento preservado: - execucao do bridge via `uvicorn app.ws_gateway.main:app` - exposicao da porta `8000` - `PYTHONPATH=/app/src` - healthcheck em `/health` - Comportamento alterado: - troca da base de `python:3.13-slim` para `python:3.12-slim` - o ajuste foi necessario porque o projeto ainda depende de `audioop` em `src/app/ws_gateway/main.py` e `src/app/utils/background.py` - Risco conhecido: - o build real da imagem nao conseguiu ser concluido nesta maquina porque nem o daemon Docker nem a conexao efetiva do Podman estavam operacionais no momento da validacao - portanto, a validacao foi estrutural e de coerencia do arquivo, nao um smoke test completo de container - Validacao executada: - revisao manual de `Dockerfile`, `.dockerignore`, `requirements.txt`, `makefile` e `k8s/deployment.yaml` - tentativa de `docker build`, bloqueada por daemon indisponivel - tentativa de `podman build`, bloqueada por conexao local com a VM do Podman - Proximo passo: - executar um build real da imagem assim que houver runtime de containers disponivel no host ou direto no pipeline