b763ea48cf
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6.7 KiB
6.7 KiB
newwhats.clube67.com — Contrato de integração Motor ↔ Satélite
O motor (newwhats) expõe a plataforma WhatsApp + Secretária IA; cada satélite (ex.: mercado.clube67.com / "Alemão Conveniências", plugin
newwhatsv2.1.0) consome o motor e fornece dados do seu negócio. Fonte da verdade do contrato (auditado em 28/jun/2026).
⚠️ Regra de registro bidirecional
- Cada plugin satélite é ÚNICO do projeto onde está instalado — o
newwhatsdomercado.clube67.compode divergir do de outro projeto. Não copiar cego. - Toda mudança no plugin que toque o contrato deve ser registrada no motor
e nesta doc; toda mudança no motor que afete o contrato deve ser refletida no
doc do plugin (
INTEGRACAO-MOTOR.md, dentro de cada plugin). - O plugin é um braço inteligente do motor: consome, alimenta e configura — não duplica lógica do motor.
Satélites conhecidos
- mercado.clube67.com ("Alemão Conveniências") — plugin CommonJS no PluginManager. Domínio: clubes/planos/sorteio/vagas/promoções.
- scoreodonto.com (28/jun/2026) — clonado e adaptado ao odonto. Módulo
ESM em
backend/newwhats/(sem PluginManager;registerNewwhats(app, pool)noserver.js), config por ENV./nw/*esync-knowledgeusam clínica/especialidades/dentistas/procedimentos/planos (multi-tenant porclinica_id). Removidos os recursos só-mercado e omedia-transcribe. Em branchfeat/newwhats-satelite(sem deploy); falta parear com o motor (apiKey + agente) e preencher as ENV. Verbackend/newwhats/INTEGRACAO-MOTOR.md.
Docs relacionadas
- tarefas.md — checklist mestre de pendências.
- wasabi-midias.md — storage, index e delete em lote.
- ativacao-whatsapp.md — trajeto inteligente de ativação.
INTEGRACAO-MOTOR.md— dentro de cada plugin satélite (lado do satélite).
Config do satélite (plugin_configs, manifest newwhats)
newwhats_url (URL do motor) · integration_key (x-nw-key, rotas /nw/*) ·
api_token (Bearer, envio de mensagens) · webhook_secret (HMAC do webhook).
Contrato A — Satélite → Motor (ext-api /api/ext/v1/*)
| Satélite chama | Motor (ext-api) | Status |
|---|---|---|
inbox, inbox/:chatId/messages, inbox/:chatId/send |
idem | ✅ |
media/:messageId |
media/:messageId |
✅ |
stream (WS) |
stream |
✅ |
secretaria/ask |
secretaria/ask (routes.ts) |
✅ |
secretaria/numbers |
alias adicionado → sec_numbers |
✅ (corrigido) |
secretaria/* interno (sync-knowledge) |
/api/secretaria/* (plugin) |
✅ |
Demais dados da Secretária no ext-api ficam sob
/sec/*(sec/agent,sec/nodes,sec/slots,sec/conversations,sec/keys,sec/handoff).
Contrato B — Motor → Satélite
| Mecanismo | Satélite | Auth |
|---|---|---|
Webhook POST /api/webhook/newwhats (message.new, session.status) |
webhook-receiver.js |
HMAC webhook_secret |
Secretária consulta /nw/* (/cliente, /clube, /parceiros, /promocoes, /sorteio, /vagas, /ping) |
routes.js |
integration_key (timingSafeEqual) |
O que o satélite já faz (e poderia migrar ao motor)
media-transcribe.js: transcrição de áudio + descrição de imagem via Gemini (cache Redis, fallback Whisper). Hoje só no satélite → candidato a ir ao motor.sync-knowledge.js: monta o nó de conhecimento com dados reais e envia ao motor.smart-router.js(roteamento sem LLM),personas.js,follow-up-detector.js,context-builder.js(contexto local do negócio).
Estado da sincronização (faseado)
- ✅ Contrato documentado (este arquivo).
- ✅ Compatibilidade de API: alias
GET /secretaria/numbersno ext-api do motor (retrocompatível) — fecha o gap dowebhook-receiver. (commit motor) - ✅ Config/conexão (auditado 28/jun/2026, satélite
mercado@VPS3 ↔ motor devnewwhats_dev). Resultado:- Satélite → Motor (ext-api/proxy/WS) ✅ —
proxy.jsenviax-nw-key=integration_keydo satélite; o ext-api valida contra a tabelaapiKey. A chave do satélite (nw_t…_001, len 34) é igual àapiKeyativa do motor. Teste vivo:GET /api/ext/v1/sessionscom a chave → 200; sem chave / chave inválida → 401 (correto). - Webhook Motor → Satélite (HMAC) ✅ —
ext_webhooksdo motor: urlhttp://127.0.0.1:4001/api/webhook/newwhats, eventos[message.new, session.status], ativo,secret(len 64) igual aowebhook_secretdo satélite. Assinaturax-nw-signature: sha256=HMAC(webhook-dispatcher.ts). - Topologia co-locada (
127.0.0.1): satélite espera motor em:8008; motor espera satélite em:4001. Para teste vivo ponta-a-ponta o satélite precisa rodar co-locado com o motor dev (hoje não está rodando na VPS4). - ⚠️
/nw/*(Motor → Satélite, Secretária): o satélite valida ox-nw-keyentrante contraplugin_configs.integration_key(nw_t…_001); oPluginPairdo motor usa outra chave (nwk_…1039,lastSeenAt=null). Se esse sentido for usado, reconciliar a chave (não afeta a Fase 4, que é Satélite → Motor). - ⚠️
api_tokennão existe emplugin_configsdo satélite — não é necessário: o ext-api autentica porx-nw-key(=integration_key), não por Bearer separado.
- Satélite → Motor (ext-api/proxy/WS) ✅ —
- ✅ Conhecimento:
sync-knowledgerodado end-to-end (28/jun/2026). Driver executou obuildKnowledgeTextreal do satélite (DBmercado@VPS3: 2 clubes, 4 planos, 6 promoções → 1895 chars) e publicou no motor dev via/api/secretaria(nginx-dev :8022 → backend, rotas internas sem auth). Nóknowledgeatualizado. RAG indexou:sec_knowledge_chunks= 4 chunks do nó, todos com embedding Gemini (768d). ✅ pipeline ok.- ⚠️ A geração final do LLM (
gemini-2.0-flash:generateContent) retorna 429 quota (free tier) — billing da chave Gemini, não defeito do pipeline. - Corrigido de quebra:
/secretaria/askfiltravaprisma.chatporremoteJid(inexistente) → 500; agora usajid.
- ⚠️ A geração final do LLM (
- Mover recursos para o motor (genéricos a todos os satélites):
- ✅ Transcrição (áudio→texto, imagem→descrição) já no motor via Gemini
(
messages.transcription). Omedia-transcribe.jsdo satélite vira redundante. - ⏳ memória (a secretária já tem memória por contato no motor; falta o satélite deixar de duplicar). Satélite passa a só enviar contexto.
- ✅ Transcrição (áudio→texto, imagem→descrição) já no motor via Gemini
(
Inconsistência anotada
A transcrição no satélite usa process.env.GEMINI_API_KEY; o RAG/memória do motor
usa cfg.gemini_key (config do plugin). Unificar a fonte da chave ao migrar.