@lionchat/mcp-server 1.21.0 → 1.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -422,6 +422,7 @@ Antes de escolher a ferramenta, cheque se a intenção bate com a coluna da dire
422
422
  | **Migrar conversas** de uma caixa WhatsApp pra outra (ex.: QR Code → Oficial) | `lionchat_inboxes_inbox_migration_list` (prévia) → `_execute` → acompanhar status | Admin-only e IRREVERSÍVEL: sempre mostre os números da prévia e confirme (seção 7a). Grupos não vão pro canal oficial — ficam na caixa de origem |
423
423
  | Qualquer coisa de Ligação WP (Wavoip) | **INTEGRAÇÃO REMOVIDA em 12/08/2026** — não há tool nem tela | A Wavoip saiu do produto: a aba "Ligação WP" **não existe mais**. NUNCA orientar o usuário a "Configurações da caixa → Ligação WP". Para voz em caixa QR Code, o caminho hoje é o **LionCalls**. As ligações antigas seguem no histórico (`provider: "wavoip"`); as gravações delas ficavam no servidor da Wavoip e vão sumir — ao tentar ouvir, o painel mostra "Esta gravação não está mais disponível", e isso é esperado, não é defeito. |
424
424
  | Restringir agendas que a IA oferece | `lionchat_captain_assistants_update` (`config.booking_event_type_ids: [Int]`) | binding de agenda por cenário NÃO é settable via API |
425
+ | **Programa de sessões** de um contato ("em que sessão ele está", ajustar total, encerrar/reabrir) | `lionchat_agenda_treatments_list` (por `contact_id`) / `_show` / `_update` | NÃO existe create: o programa nasce junto do agendamento (na TELA chama-se "programa"; na API segue `treatment`). Marcar TODAS de uma vez: `plano_sugerido` + `marcar_todas` de um tipo com `sessions_enabled` (`tasks_create` modo booking, `treatment: {...}` por pessoa; "marcar próxima" = `agenda_treatment_id` + `treatment_session_number`). Faltar CONSOME a sessão. Ver `lionchat://docs/agenda-multiplas-unidades` §7 |
425
426
  | Configurar o Copiloto (modelo/temperatura/prompt base) | `lionchat_copilot_settings_update` | admin-only; copiloto tem motor próprio (padrão temp 0.3) |
426
427
  | **Resetar/testar do zero a IA** numa conversa | `lionchat_conversations_captain_history_reset` (POST, sem body) | Cria pílula de marco na conversa; a partir dali TODA leitura autônoma da IA (respostas, resumo, follow-up) considera só mensagens pós-marco. Não apaga nada; o atendente segue vendo tudo. Enterprise-only |
427
428
 
@@ -441,6 +442,7 @@ Quando precisar de detalhes profundos, leia um destes documents via `resources/r
441
442
  - `lionchat://docs/api-conventions` — Auth, paginação, filtros, errors, rate limits
442
443
  - `lionchat://docs/conversation-flows` — Ciclo de vida de uma conversa (criação, auto-assignment, IA, resolução)
443
444
  - `lionchat://docs/kanban-deep-dive` — Estrutura completa do Kanban (Funnel/Stage/Item/pipeline)
445
+ - `lionchat://docs/agenda-multiplas-unidades` — **Agenda por unidade**: o que `agenda_id` nulo significa, tipos de compromisso da conta, Booking ligado a unidade, página pública (cancelar/remarcar/confirmar), Google **uma conexão por agenda** e **programa de sessões** (N sessões de um tipo; faltar consome; marcar próxima e marcar todas)
444
446
  - `lionchat://docs/best-practices` — Como economizar tokens, evitar rate limit, ordem de operações
445
447
  - `lionchat://docs/troubleshooting` — Códigos HTTP, erros comuns, debugging
446
448
  - `lionchat://docs/flowbuilder-design-guide` — **OBRIGATÓRIO** antes de criar/editar fluxo: schema de nodes, handles expostos por tipo, layout/positioning, erros comuns, checklist
@@ -0,0 +1,185 @@
1
+ # Agenda — unidades, tipos de compromisso e Google por agenda
2
+
3
+ Guia da Agenda depois das frentes de 13/09 e 15/09/2026. Leia antes de mexer em agendas, tipos de
4
+ compromisso, Booking ligado a unidade, conexão Google ou programa de sessões.
5
+
6
+ ---
7
+
8
+ ## 1. Uma agenda é um LUGAR, nunca uma pessoa
9
+
10
+ Uma **agenda** é uma unidade: a matriz, uma filial, um consultório. Ela tem nome, fuso, cor, quem
11
+ enxerga e **conta Google próprios**. Não confunda com o calendário de uma pessoa — quem tem
12
+ calendário pessoal é o atendente, e ele aparece dentro da agenda.
13
+
14
+ **Toda conta tem UMA agenda.** Ter mais de uma exige o recurso `multiple_agendas` ligado na conta
15
+ (Super Admin), e o número de Extras Manuais define o teto — **zero ali significa ILIMITADO**, igual
16
+ a Voz, Coex e Contratos. Sem o recurso, `agendas_create` é recusado.
17
+
18
+ ### `agenda_id` NULO significa "a agenda principal"
19
+
20
+ Essa é a regra mais importante deste documento, e vale em **quatro** lugares: `account_tasks`,
21
+ `booking_event_types`, `google_calendar_connections` e nos filtros.
22
+
23
+ Nulo **não** quer dizer "sem agenda": quer dizer "a principal". É o que todo registro anterior à
24
+ funcionalidade tem, e é por isso que ligar múltiplas agendas não exige retrocarga nenhuma — nada
25
+ precisa ser migrado, nada muda de lugar.
26
+
27
+ **Ao filtrar a agenda principal, inclua os nulos.** Filtrar `agenda_id = <id da principal>` sozinho
28
+ esconde todo o histórico da conta.
29
+
30
+ ---
31
+
32
+ ## 2. Tipos de compromisso
33
+
34
+ São **7 de fábrica**, no código: `task`, `follow_up`, `call`, `meeting`, `video_call`, `deadline`,
35
+ `custom`. Não existem `consulta`, `retorno` nem `procedimento` — foram removidos em 13/09; mandar
36
+ um desses em `task_type` dá 422.
37
+
38
+ Além dos 7, a empresa **cria os dela** com o nome que usa ("Consulta", "Ondas de Choque", "Visita
39
+ ao imóvel"), em `account_task_types`.
40
+
41
+ - `key` é derivada do nome e **nunca muda**. É ela que fica gravada em `account_tasks.task_type`.
42
+ Renomear o tipo troca só o que aparece na tela; o histórico fica inteiro.
43
+ - `icon` é uma **lista fechada de 12**. Qualquer outro valor é recusado pelo servidor — nome fora da
44
+ lista produz uma classe que nunca foi gerada e o ícone **some da tela, sem erro**.
45
+ - Excluir um tipo **em uso** não apaga: **desativa** (`deactivated: true` na resposta). Os
46
+ compromissos antigos continuam com nome e ícone.
47
+
48
+ ⚠️ **O tipo que a conta cria conta como agendamento para a IA.** É o que impede o agente de IA de
49
+ concluir que ainda não agendou e marcar o cliente **duas vezes**. Não existe interruptor para
50
+ desligar isso — a chave saiu do `permit` de propósito.
51
+
52
+ ---
53
+
54
+ ## 3. Booking → agenda
55
+
56
+ Cada tipo de evento do Booking tem `agenda_id`: é a unidade em que o agendamento feito pelo cliente
57
+ vai nascer. Nulo = principal.
58
+
59
+ Sem isso (até 13/09) **todo agendamento feito por Booking caía na agenda principal**, mesmo quando o
60
+ profissional atendia na filial — e quem trocasse para a agenda da filial não via o agendamento.
61
+
62
+ `agenda_id` de outra conta é recusado pelo modelo. A FK garante que a agenda existe; ela não garante
63
+ que é sua.
64
+
65
+ ---
66
+
67
+ ## 4. Página pública (cancelar, remarcar, confirmar presença)
68
+
69
+ O tipo de evento controla o que o cliente pode fazer:
70
+
71
+ | Campo | Padrão | O que faz |
72
+ |---|---|---|
73
+ | `allow_cancel` | `true` | cliente pode cancelar |
74
+ | `allow_reschedule` | `true` | cliente pode remarcar |
75
+ | `ask_attendance_confirmation` | **`false`** | mostra "Sim, vou comparecer" |
76
+ | `cancel_min_notice_hours` | vazio | antecedência mínima para cancelar |
77
+ | `reschedule_min_notice_hours` | vazio | antecedência mínima para remarcar |
78
+ | `reschedule_max_advance_days` | vazio | até quando pode remarcar |
79
+ | `max_reschedules` | vazio | quantas vezes pode remarcar |
80
+
81
+ **Vazio ou zero = sem limite** (falha aberta, de propósito: uma regra em branco nunca deve trancar o
82
+ cliente para fora).
83
+
84
+ ### Variáveis da mensagem de abertura
85
+
86
+ `{{nome}} {{titulo}} {{tipo}} {{agente}} {{data}} {{horario}} {{dia_semana}} {{duracao}}
87
+ {{telefone}} {{email}} {{link_cancelar}} {{link_remarcar}} {{link_confirmar}}`
88
+
89
+ As chaves são **em português nos dois idiomas** — elas são o identificador, não a tradução.
90
+ Variável desconhecida **sai crua** para o cliente ("Olá {{name}}, ...").
91
+
92
+ `{{link_confirmar}}` só é útil com `ask_attendance_confirmation` ligado.
93
+
94
+ ### Presença é CARIMBO, não status
95
+
96
+ `attendance` (`attended` / `no_show`) é um campo separado de `status`. Marcar falta **não devolve o
97
+ horário** para a agenda — decisão do dono. Não use `attendance` para deduzir se o compromisso está
98
+ ativo; para isso existe `status`.
99
+
100
+ ---
101
+
102
+ ## 5. Google Calendar é UMA CONEXÃO POR AGENDA
103
+
104
+ A regra já mudou duas vezes; hoje é: **uma conta Google por agenda**. Cada unidade liga a conta
105
+ Google dela — inclusive a **mesma pessoa** com contas Google diferentes, uma por unidade.
106
+
107
+ - `google_calendar_agendas` devolve uma linha por agenda com o estado de cada uma.
108
+ - `agendas_list` / `agendas_show` trazem `google: { connected, email, state }` em cada agenda — dá para saber qual conta Google está ligada a qual unidade sem chamar o Google (o estado sai do banco). [13/09]
109
+ - Agenda **sem** Google conectado simplesmente **não sincroniza** — ela não cai no Google da matriz.
110
+ O contrário mandaria o compromisso de uma unidade para o calendário de outra.
111
+ - Os sub-calendários compartilhados com agentes pertencem à conexão daquela unidade.
112
+
113
+ ---
114
+
115
+ ## 6. Quem enxerga uma agenda
116
+
117
+ - Agenda **sem** pessoas e **sem** equipes: todo mundo da conta enxerga.
118
+ - Marcando pessoas e/ou equipes: só elas. Quem entrar na equipe ganha acesso sozinho.
119
+ - **Administrador enxerga todas**, sempre.
120
+ - `member_user_ids` e `member_team_ids` **substituem a lista inteira** (idioma do `InboxMember`).
121
+
122
+ A listagem de compromissos já vem recortada pelas agendas que o usuário enxerga, **mesmo sem mandar
123
+ `agenda_id`**. Ler ou editar compromisso de uma agenda que a pessoa não enxerga devolve 404.
124
+
125
+ ---
126
+
127
+ ## 7. Programa de sessões (15/09)
128
+
129
+ Um **programa** é um pacote de N sessões do mesmo tipo de evento para um contato ("10 sessões de ondas
130
+ de choque a cada 30 dias", "8 encontros de mentoria", "4 sessões de onboarding").
131
+
132
+ ⚠️ **Na TELA o nome é "programa"** (bloco "Programas", botão "Encerrar programa") — decisão do dono em
133
+ 15/09, porque nem sempre é saúde. No CÓDIGO e na API tudo continua `treatment`/`agenda_treatments`: as
134
+ ferramentas, os campos e a tabela não mudaram. Ao falar com o cliente, diga **programa**; ao chamar a
135
+ API, use os nomes de sempre. Cada encontro continua se chamando **sessão** nos dois lados. Só a primeira sessão nasce marcada; as outras ficam "a marcar" e a
136
+ ficha do contato mostra em que pé está: quantas foram feitas, quantos por cento, quando é a próxima
137
+ e se está atrasada.
138
+
139
+ - **Liga-se no tipo de evento**: `sessions_enabled` + `sessions_default_count` (2 a 60) +
140
+ `sessions_interval_value`/`sessions_interval_unit` (`days`/`weeks`/`months`). Tipo sem isso não
141
+ cria programa nunca.
142
+ - **O programa NASCE junto do agendamento** — não existe `create`. Todo agendamento de um tipo com
143
+ sessões (painel, link público ou IA) cria o programa do contato ou **engrossa** o que já está em
144
+ andamento como a próxima sessão livre. Um programa ativo por contato + tipo.
145
+ - **Plano por pessoa**: no `tasks_create` em modo booking, `treatment: {sessions, interval_value,
146
+ interval_unit}` vence o padrão do tipo. É validado ANTES da reserva (422 sem agendar nada).
147
+ - **"Marcar próxima"**: `tasks_create` com `agenda_treatment_id` + `treatment_session_number`. Sessão já
148
+ marcada dá 422; programa de outra ficha dá 422.
149
+ - **Sessão k = compromisso VIVO (não cancelado) de número k.** Cancelar devolve a sessão; remarcar
150
+ mantém o número; **faltar consome** (decisão do dono — a falta gasta a sessão). "Usadas" = compareceu
151
+ + faltou. Nada disso é cache: o resumo é derivado das tarefas na leitura.
152
+ - **Cheio** = todas as N marcadas e nenhuma usada ainda. Agendamento novo pelo painel/IA num
153
+ programa cheio vira **sessão extra** (N+1, até 60); pelo link público não vira nada (o
154
+ agendamento nasce solto, sem programa).
155
+ - **Concluído** = usadas ≥ N. O `status` do programa só vira `completed` na próxima reserva daquele
156
+ tipo (aí abre um ciclo novo); `closed` é encerramento pela equipe (`close_reason: manual`) ou pela
157
+ junção de contatos (`mesclagem` — o programa do perdedor que colide com um do vencedor).
158
+ - **Atrasado** = em andamento, próxima sessão com data prevista já passada e nenhuma sessão viva com
159
+ data futura. A previsão é a última data conhecida + intervalo × distância.
160
+ - **Marcar TODAS as sessões que faltam** (15/09): `lionchat_agenda_treatments_plano_sugerido` devolve o dia e a
161
+ hora sugeridos por sessão (data prevista; sem vaga, anda para a frente e marca `deslocada`), e
162
+ `lionchat_agenda_treatments_marcar_todas` marca o que for confirmado. **Não é transação única**: sucesso parcial é
163
+ 200 com `falhas` nomeadas, e o que entrou na agenda fica. Com confirmação ligada no tipo, o cliente recebe UMA
164
+ mensagem por sessão — avise isso antes de marcar em lote.
165
+ - Ferramentas: `lionchat_agenda_treatments_list` (por `contact_id`, resumo pronto por programa),
166
+ `_show`, `_update` (`planned_sessions` nunca abaixo da maior sessão já marcada; `status`
167
+ `closed`/`active`). O compromisso devolve `tratamento: {id, sessao, total, titulo}` quando pertence a
168
+ um. Compromisso de agenda que o usuário não enxerga aparece na sessão como `oculta: true`.
169
+ - O relatório de Agendamentos tem o bloco `treatments` (vale o período escolhido: programas, sessões do período e quem parou no meio — ver `reports-guide`).
170
+
171
+ ---
172
+
173
+ ## 8. Erros comuns
174
+
175
+ | Sintoma | Causa |
176
+ |---|---|
177
+ | 422 'Ha sessoes marcadas alem dessa quantidade' ao reduzir `planned_sessions` | já existe sessão marcada acima do novo total; cancele-a antes |
178
+ | 422 'Ja existe um tratamento em andamento deste tipo para este contato' (texto do servidor) ao reabrir | um programa ativo por contato + tipo; encerre o outro primeiro |
179
+ | Agendamento novo não entrou no programa | tipo sem `sessions_enabled`, ou programa CHEIO agendado pelo link público (sessão extra só pelo painel/IA) |
180
+ | 422 ao criar compromisso com `task_type: "consulta"` | os tipos clínicos saíram; use a `key` que `account_task_types_list` devolve |
181
+ | Ícone do tipo não aparece | valor fora da lista fechada de 12 |
182
+ | Agendamento do Booking caiu na unidade errada | `agenda_id` do tipo de evento não foi definido (nulo = principal) |
183
+ | Compromisso da filial no Google da matriz | não acontece mais; se aparecer, a conexão daquela agenda está com `agenda_id` errado |
184
+ | `agendas_create` recusado | recurso `multiple_agendas` desligado ou teto de Extras Manuais atingido |
185
+ | Histórico sumiu ao filtrar a principal | faltou incluir os compromissos com `agenda_id` **nulo** |
@@ -50,8 +50,10 @@ Participante: `pending` → `viewed` → `verified` (confirmou o código) → `s
50
50
  leitura de um modelo continuam abertas a qualquer membro. Cancelar contrato e apagar modelo: só administrador.
51
51
  - **Trava sagrada**: campo do modelo sem valor na ficha bloqueia o envio. Preencher a ficha primeiro.
52
52
  - **Validade** (`roles_layout.validity_days`, padrão 7) conta do ENVIO; `{{document.deadline}}` imprime a data no
53
- texto; passou = `expired` (cron de hora em hora). **Lembrete** (`reminder_days`, padrão 2, 0 = off): quem não
54
- assinou recebe o link de novo a cada N dias.
53
+ texto; passou = `expired` (cron de hora em hora). **Lembrete NÃO é mais função do sistema** (14/09): o campo
54
+ `reminder_days` e a tarefa diária das 10h foram REMOVIDOS. Quem lembra é um fluxo do cliente, com o texto e a
55
+ caixa dele — gatilho "Link de assinatura enviado para uma pessoa" (`signature_delivered`, um disparo por
56
+ pessoa), bloco Esperar em dias e a condição "Situação do contrato". Nunca sugerir `reminder_days`.
55
57
  - **Conversor de Word** é um serviço separado (docx-converter). Fora do ar = `422 conversor_indisponivel` na prévia e no envio de modelo Word — é o serviço, não o arquivo; repetir em instantes. Modelos `text` e `file` não passam por ele.
56
58
  - **Fila única de conversão do Word**: uma conversão por vez em toda a instalação (todas as contas); pela tela espera-se até 10 s, automação/macro/fluxo/formulário até 2 s.
57
59
  Passou disso o envio/prévia volta `422 fila_cheia` — é só repetir em instantes (o modelo está bom).
@@ -397,7 +397,9 @@ oficial, com WABA) sai pra Meta como evento de MENSAGEM (`action_source: busines
397
397
  Meta só aceita isso num **dataset vinculado à WABA**, nunca no pixel do site (recusa 2804132). Até
398
398
  10/09 100% desses eventos caíam no plano B (saíam como site) sem ninguém ver. Regras pro MCP:
399
399
 
400
- - **Vincular a caixa primeiro:** `lionchat_inboxes_capi_dataset_link` (POST `/inboxes/{id}/capi_dataset`).
400
+ - **Vincular a caixa primeiro:** normalmente NÃO é preciso — o vínculo é automático (na criação da caixa
401
+ e por varredura a cada 10 min). Se `capi_dataset_id` estiver vazio, `lionchat_inboxes_capi_dataset_link`
402
+ (POST `/inboxes/{id}/capi_dataset`) força na hora.
401
403
  Idempotente, vale para todos os números da mesma WABA, usa a chave da PRÓPRIA caixa (a do pixel não
402
404
  serve). O id fica em `provider_config.capi_dataset_id` (visível em `lionchat_inboxes_show` para admin).
403
405
  Sem o vínculo os eventos de anúncio saem como site com `fallback_reason: lionchat:dataset_nao_configurado`.
@@ -922,3 +924,11 @@ administrador."* — a recusa é `before_action`, então NADA do resto do update
922
924
  Ao atualizar o próprio usuário: mande times e caixas à vontade; **não mande `role` nem
923
925
  `custom_role_id`** — se mandar, a chamada inteira falha e as outras alterações se perdem também.
924
926
  Para trocar o cargo de alguém, use a conta de OUTRO administrador.
927
+
928
+ ## Cargo personalizado: descrição CURTA (16/09/2026)
929
+
930
+ Em `custom_roles_create` / `custom_roles_update`, a `description` é **uma frase de até 60 caracteres**
931
+ (ex.: *"Tudo, menos conversas das caixas em que não foi adicionado."*). **Não liste as permissões
932
+ na descrição** — a tela já as mostra na coluna "Permissões". Uma descrição de 180 caracteres
933
+ escondeu o cargo recém-criado na lista de Funções personalizadas da conta 1 (a tela foi corrigida
934
+ para cortar o texto com reticências, mas a descrição longa continua ilegível ali).
@@ -439,7 +439,7 @@ POST .../conversations/{id}/toggle_status
439
439
 
440
440
  | Ação | Tool / endpoint | Efeito |
441
441
  |---|---|---|
442
- | Marcar como **lida** | `update_last_seen` (POST `.../update_last_seen`) | Atualiza `agent_last_seen_at`; em canal WAHA dispara check azul no WhatsApp |
442
+ | Marcar como **lida** | `update_last_seen` (POST `.../update_last_seen`) | Atualiza `agent_last_seen_at` e, em canal WhatsApp (QR Code ou oficial), dispara o check azul — **só quando há mensagem do cliente ainda não lida** (12/09); sem entrante nova a chamada cai na trava de 1 h e devolve o carimbo já gravado |
443
443
  | Marcar como **não-lida** | `conversations_unread` (POST `.../unread`) | Recua o `last_seen` pra antes da última mensagem do cliente — conversa volta a aparecer como não-lida |
444
444
 
445
445
  Ambas são **ações de escrita** (POST). `unread` é o oposto de `update_last_seen`, não uma consulta.
@@ -150,8 +150,28 @@ Company
150
150
  ├── account_id (FK)
151
151
  ├── name
152
152
  └── domain
153
+
154
+ AttributeChange (histórico de alterações de atributo — 2026-09-11)
155
+ ├── id (PK)
156
+ ├── account_id (FK)
157
+ ├── contact_id (FK, opcional) / conversation_id (FK, opcional)
158
+ ├── target_type + target_id ('Contact' | 'Conversation')
159
+ ├── field (name | email | phone_number | date_of_birth | gender | cadastral.* | address.* | custom.<chave>)
160
+ ├── old_value / new_value (jsonb)
161
+ ├── actor_type + actor_id + actor_label (User | Captain::Assistant | Flow | AutomationRule | LeadForm | Integration | System)
162
+ ├── source (panel | api | mcp:npm | mcp:remote | flow | automation | ai | form | integration:<nome> | merge | system)
163
+ ├── merged_from_contact_id (linha que veio de ficha mesclada)
164
+ └── created_at
153
165
  ```
154
166
 
167
+ **Histórico de alterações (`attribute_changes`, 2026-09-11):** uma linha por campo que mudou (contato ou
168
+ conversa), com valor antes/depois, quem mudou e por onde. Mudança feita pelo MCP sai com `source`
169
+ `mcp:npm`/`mcp:remote` e o usuário do token como ator. Criação não gera linha; importação de planilha
170
+ não gera; chaves protegidas (rastreio `utm_*`/`gclid`, `waha_*`, `eclinica_*`, e toda definição
171
+ `system: true`) ficam fora. Leitura: `GET contacts/{id}/attribute_changes` e
172
+ `GET conversations/{id}/attribute_changes` (50/página; filtros `field`, `source`); telefone, e-mail,
173
+ nascimento e documentos vêm mascarados (`masked: true`) para quem não é administrador. Retenção 180 dias.
174
+
155
175
  **`additional_attributes` vs `custom_attributes` no Contato:**
156
176
  - `additional_attributes` (jsonb): campos do sistema porém **EDITÁVEIS via API** (`permitted_params` permite `additional_attributes: {}`). Guarda chaves padrão como `city`, `company`, `country_code` — que são as chaves filtráveis em `lib/filters/filter_keys.yml` (tipo `additional_attributes`). NÃO é não-editável.
157
177
  - `custom_attributes` (jsonb): dado de negócio livre, definido pelo cliente via Atributos Customizados.
@@ -384,8 +404,25 @@ AccountTask (agenda interna)
384
404
  ├── meeting_url (string, sala de reunião call/meeting)
385
405
  ├── guest_emails (jsonb array, convidados extras — máx 20)
386
406
  ├── conversation_id / contact_id / linked_kanban_item_id (FK opcionais)
407
+ ├── booked_by (polimórfico User/Contact/Captain::Assistant) / booked_by_name / booking_source
408
+ │ (painel|link|ia|sistema|fluxo) — QUEM agendou e por onde (14/09)
409
+ ├── attendance (enum attended=0 / no_show=1, NULO = nada registrado — CARIMBO, não muda status)
410
+ │ / attendance_by (polimórfico) / attendance_source — quem marcou Compareceu/Faltou (14/09)
411
+ ├── agenda_treatment_id (FK → AgendaTreatment, nullify) / treatment_session_number (1..N) — a sessão
412
+ │ que este compromisso é; índice único parcial por tratamento+número entre os NÃO cancelados (15/09)
387
413
  └── assignees (has_many → User, via account_task_assignments)
388
414
 
415
+ AgendaTreatment (tratamento em sessões — tools `agenda_treatments_*`; tabela agenda_treatments; 15/09)
416
+ ├── id (PK) / account_id (FK) / contact_id (FK) / booking_event_type_id (FK, nullify)
417
+ ├── event_type_title (cópia do nome do tipo — sobrevive à exclusão do tipo)
418
+ ├── planned_sessions (2..60) / interval_value (1..365) / interval_unit (days|weeks|months)
419
+ ├── status (active|completed|closed) / close_reason (manual|mesclagem) / closed_at
420
+ ├── source (painel|link|ia|sistema|fluxo) / created_by_id (FK → User, só quando foi gente)
421
+ ├── índice único parcial (account_id, contact_id, booking_event_type_id) WHERE status='active'
422
+ │ — UM tratamento ativo por contato + tipo
423
+ └── account_tasks (has_many, nullify) — sessão k = tarefa VIVA de número k; usadas/percentual/atrasado/
424
+ concluído são DERIVADOS na leitura (nenhuma coluna de cache)
425
+
389
426
  BookingEventType (template de agendamento — tools `booking_event_types_*`; colunas de
390
427
  db/schema.rb, tabela booking_event_types)
391
428
  ├── id (PK) / account_id (FK) / user_id (FK → agente padrão)
@@ -397,6 +434,8 @@ db/schema.rb, tabela booking_event_types)
397
434
  ├── color (hex `#RRGGBB`, opcional — cor dos compromissos desse tipo no calendário; vazio = cor do
398
435
  │ agente; 2026-08-19)
399
436
  ├── active / ask_email / ask_description
437
+ ├── sessions_enabled (bool) / sessions_default_count (2..60) / sessions_interval_value (1..365) /
438
+ │ sessions_interval_unit (days|weeks|months) — tratamento em sessões: padrão do tipo (15/09)
400
439
  ├── confirmation_* (mensagem de confirmação própria: enabled, inbox_id, channel_type,
401
440
  │ template_name, blocks). Variáveis nos textos de confirmação E de lembrete (interpolador único):
402
441
  │ {{nome}} {{email}} {{telefone}} {{data}} {{horario}} {{dia_semana}} (NOVO 24/08 — dia por
@@ -767,7 +806,7 @@ SignatureDocument (modelo) 1 ──── N SignatureEnvelope (contrato de UMA
767
806
  body ({{variáveis}}), tags, contact_id, conversation_id, status, phone/email, delivery_channel,
768
807
  roles_layout {signers, witnesses, original_sha256, sealed_sha256, conversation_id (a conversa DELE),
769
808
  sender_signs, require_id_photo, created_by (quem mandou) public_url, signed_at, viewed_at
770
- validity_days, reminder_days} │
809
+ validity_days} │
771
810
  progress (contagem por balde) └── N SignatureEvent (append-only: kind, occurred_at, ip, user_agent, detail)
772
811
  ```
773
812
  - Contrato aponta pro contato (`contact_id`, nulifica se a ficha for apagada — a prova sobrevive) e pra conversa
@@ -531,6 +531,7 @@ o botão "Usar variável" ao lado do campo alterna lista fixa ↔ variável.
531
531
  | `start_flow` | `{ flow_id }` | Inicia outro fluxo. **NÃO encerra o fluxo de origem** (desde 31/08): se houver bloco ligado depois dele, o fluxo SEGUE normalmente. Sendo o último do desenho, o fluxo termina ali como sempre. |
532
532
  | `send_conversion` (novo 2026-09-01; `event_names` 2026-09-02; `messaging_event_names` 2026-09-10) | `{ destinations: ['meta'\|'ga4'\|'google_ads'], event_names: { meta?, google_ads?, ga4? }, messaging_event_names: { meta? }, event_name (reserva), value? }` | Manda o evento de conversão pro Meta (CAPI), Google Ads e/ou GA4 — o mesmo caminho do Funil, de dentro do fluxo. Aba Sistema (só flow `conversation`). Ver bloco próprio abaixo |
533
533
  | `deactivate_flow` ou `disable_flow` | `{}` | Encerra fluxo atual |
534
+ | `set_booking_situation` (novo 2026-09-14) | `{ situation: 'cancelled' \| 'completed' \| 'attended' \| 'no_show' \| 'confirmed' }` | Muda a situação do agendamento **que disparou o fluxo** (gatilho de agendamento do bloco Início, ou fluxo ligado na configuração do tipo de agendamento). Aba **Agenda** (só flow `conversation`, só com a Agenda ligada na conta). Disparado por outra coisa: **não faz efeito e o passo fica com erro visível** (não há como adivinhar o agendamento). Já no estado pedido = passo PULADO, sem escrita (sem evento, sem laço). `cancelled` cancela o **agendamento** (desarma lembretes, invalida o link de gerenciar). Origem gravada = `fluxo`, ator = o próprio flow. Sem `rescheduled`/`snoozed`: o bloco não mexe em data |
534
535
  | `update_attribute` | `{ attr_source: 'contact'\|'conversation'\|'card', attr_key, attr_value }` | Seta custom_attribute (ver abaixo) |
535
536
  | `assign_captain` (ou `assign_captain_assistant`) | `{ assistant_id }` | Atribui IA Captain |
536
537
  | `deactivate_captain` | `{}` | Tira a IA da conversa |
@@ -843,7 +844,7 @@ tela do cliente (a tela lê só `percent`).
843
844
  ### 2.11 `update_group` — Gestão de Grupos (WAHA apenas)
844
845
 
845
846
  Bloco "Gestão de Grupos". Faz **UMA operação por bloco** (não mais um formulário-só com nome/foto/descrição
846
- juntos) — a operação vai em `data.groupOperation`. São **17 operações**, agrupadas por tema:
847
+ juntos) — a operação vai em `data.groupOperation`. São **18 operações**, agrupadas por tema:
847
848
 
848
849
  - **Grupo:** `create` (criar), `find_by_id` (buscar por id), `find_by_name` (buscar por nome), `update_subject`
849
850
  (mudar nome), `update_description` (mudar descrição), `update_picture` (mudar foto), `settings` (3
@@ -852,6 +853,10 @@ juntos) — a operação vai em `data.groupOperation`. São **17 operações**,
852
853
  - **Admins:** `promote_admin` (promover a admin), `demote_admin` (rebaixar).
853
854
  - **Convite:** `get_invite` (pegar link/código de convite), `revoke_invite` (revogar), `send_invite` (mandar
854
855
  o convite por mensagem a um telefone).
856
+ - **Mensagem no privado:** `send_private_message` (a 18ª, 16/09) — `groupPrivateTo` (obrig, telefone com código do
857
+ país, aceita `{{trigger.participant.phone}}`) + `messageItems`; manda no PRIVADO desse telefone, criando contato
858
+ e conversa para quem nunca conversou. Sem variável de resposta, sem `groupTargetId`, sem teto diário. É o jeito
859
+ de falar com quem acabou de entrar no grupo (o flow individual só roda para quem já tem conversa).
855
860
  - **Mensagem:** `send_message` (a 17ª, 08/08) — manda `messageItems` (MESMO contrato do bloco de mensagem:
856
861
  text/delay/attachment/audio/url_media; botões/template não fazem sentido em grupo) NA CONVERSA DO GRUPO
857
862
  (`groupTargetId` ou, vazio, o grupo da conversa atual; grupo inexistente = `error`). NÃO grava
@@ -1156,7 +1161,7 @@ Oferecidos no autocompletar (só quando o bloco Início tem o gatilho que os pre
1156
1161
  | `assignee_changed` | `{{trigger.assignee.name}}` (vazio = responsável removido) |
1157
1162
  | `team_changed` | `{{trigger.team.name}}` (vazio = equipe removida) |
1158
1163
  | `sla_missed` | `{{trigger.sla.policy_name}}`, `{{trigger.sla.type}}` (`frt`/`nrt`/`rt`) |
1159
- | `group_participant_joined`, `group_participant_left` | `{{trigger.group.name}}`, `{{trigger.group.id}}` |
1164
+ | `group_participant_joined`, `group_participant_left` | `{{trigger.group.name}}`, `{{trigger.group.id}}`, `{{trigger.participant.phone}}`, `{{trigger.participant.name}}` (16/09 — quem entrou/saiu; nome só se já é contato) |
1160
1165
 
1161
1166
  Resolvem mas NÃO aparecem no seletor (produtor único — só o gatilho daquela integração preenche):
1162
1167
  `{{trigger.attribute.name}}`/`current_value` (atributo do contato entrou no valor), `{{trigger.form.name}}`/
@@ -597,7 +597,8 @@ Comuns a (quase) todas:
597
597
  | `add_participants` | `groupParticipants` (obrig — ex.: `["5511999999999@c.us"]` ou lista); opcional `groupInviteOnFailure` + `groupInviteMessage` | `added`, `not_added`, `added_count`, `not_added_count`, `no_whatsapp`, `invited`, `invite_status` |
598
598
  | `send_invite` | `groupInviteTo` (obrig — telefone de destino), `groupInviteMessage` (opc) | `invite_link` |
599
599
  | `settings` | pelo menos uma de `infoAdminOnly` / `messagesAdminOnly` / `membersCanAddNewMember` (booleans) | `settings_updated` (lista do que aplicou), `settings_failed` (`[{setting, reason}]`), `settings_unsupported` |
600
- | `send_message` | `messageItems` (mesmo contrato do bloco de mensagem: text/delay/attachment/audio/url_media) + `groupTargetId` opcional — manda os balões NA CONVERSA DO GRUPO (vazio = grupo da conversa atual). É a 17ª operação (08/08) | — (única sem variável de resposta) |
600
+ | `send_message` | `messageItems` (mesmo contrato do bloco de mensagem: text/delay/attachment/audio/url_media) + `groupTargetId` opcional — manda os balões NA CONVERSA DO GRUPO (vazio = grupo da conversa atual). É a 17ª operação (08/08) | — (sem variável de resposta) |
601
+ | `send_private_message` | `groupPrivateTo` (obrig — telefone com código do país; aceita `{{trigger.participant.phone}}`) + `messageItems` — manda os balões no PRIVADO desse telefone. Quem nunca conversou ganha contato + conversa (dispara os ouvintes de conversa criada). 18ª operação (16/09), sem teto diário | — (sem variável de resposta) |
601
602
 
602
603
  Os campos `added`/`not_added`/`no_whatsapp`/`invited`/`invite_status` do `create` e `groupInviteOnFailure` são
603
604
  de 21/08/2026 (entram com o próximo deploy do app depois de 21/08/2026).
@@ -620,6 +621,13 @@ as outras duas seguem aplicadas. Não prometa essa permissão ao cliente sem con
620
621
  dígitos, aceita `1203...@g.us` ou só o número). Quando alguém entra, o `send_message` seguinte cai **no próprio
621
622
  grupo** (o grupo é a conversa do flow).
622
623
 
624
+ **Quem entrou (16/09):** o gatilho entrega `{{trigger.participant.phone}}` (telefone com `+`) e
625
+ `{{trigger.participant.name}}` (só quando a pessoa já é contato). Para falar **no privado** de quem entrou, use no
626
+ flow de grupo um `update_group` com `groupOperation: "send_private_message"` e `groupPrivateTo:
627
+ "{{trigger.participant.phone}}"`. **Não use flow individual para isso:** ele só roda para quem JÁ tem conversa
628
+ naquela caixa — quem entra pela primeira vez (link de convite) é pulado. Limite conhecido: o flow de grupo atende
629
+ uma entrada por vez; quem entrar enquanto os balões da pessoa anterior saem não recebe (prefira 1 balão).
630
+
623
631
  **Lembretes:**
624
632
  - **Teto de 20 participantes por execução** (`add_participants`/`create`) — trava ANTI-BANIMENTO, não performance.
625
633
  Adicionar em lote é o que mais rápido derruba número no WhatsApp não-oficial.
@@ -232,8 +232,10 @@ renderiza e não dá erro.
232
232
  - **Lista de recusa no servidor** (o valor é pulado de forma visível, sem erro): `name`, `email`,
233
233
  `phone_number`, `identifier`, `card` e chaves começando com `captain_`, `eclinica_`, `origin_`,
234
234
  `lt_`, `booking_`, `waha_`, `whatsapp_`, `ctwa_`, `meta_lead_`.
235
- - Contato pré-existente recebe valor **só em campo vazio** — exceto o que ESTA resposta gravou e
236
- ninguém mudou depois (correção via Voltar).
235
+ - Contato pré-existente: **dado novo vence** (regra de 11/09) — nome, e-mail, documentos e atributos
236
+ são sobrescritos por resposta nova (mesmo valor não regrava). Só o **telefone** fica protegido
237
+ (endereço da conversa): preenche vazio ou corrige o que a própria resposta gravou. O que cada
238
+ resposta gravou fica em `written_attributes` (detalhe da resposta).
237
239
 
238
240
  **`options`** (do `choice`): `[{ "id": "abc123", "label": "Sim", "image": "" }]`.
239
241
 
@@ -449,7 +449,7 @@ Campos MUTÁVEIS (atualizáveis livremente por IA/integração): `marital_status
449
449
  | **LionCalls** | Voz pelo WhatsApp em caixa **QR Code**, mas pelo **motor próprio do LionChat** (credencial global, 1 sessão por caixa; flag `lioncalls_calling`, nasce desligada e é ligada conta a conta) | **NENHUMA — sem tool no MCP** | WhatsApp QR Code |
450
450
  | **WhatsApp Calling (Cloud)** | Voz pelo WhatsApp na **API oficial** (enterprise) | `whatsapp_calls_*` + enable/disable_whatsapp_calling | WhatsApp oficial |
451
451
  | **VoIP (Zenvia)** | Telefonia COMUM com softphone no navegador (ramais, ligações) | `voip_*` | Telefone |
452
- | **VTCall** | Telefonia por **PABX click-to-call**, config por conta + ramal por atendente; **sem softphone no navegador** — o atendente fala pelo app/ramal do VTCall | `vtcall_settings_*` (show/update/test_connection), `vtcall_ramals_*` (list/create/destroy) | Telefone (PABX do cliente) |
452
+ | **VTCall** | Telefonia por **PABX click-to-call**, config por conta + ramal por atendente; **sem softphone no navegador** — o atendente fala pelo app/ramal do VTCall; desde 11/09/2026 a ligação discada direto no aparelho (ramal cadastrado) também entra no histórico | `vtcall_settings_*` (show/update/test_connection), `vtcall_ramals_*` (list/create/destroy) | Telefone (PABX do cliente) |
453
453
 
454
454
  Quando o usuário falar "ligação", descubra o canal ANTES de responder: caixa QR Code → **LionCalls**;
455
455
  caixa oficial → `whatsapp_calls`; telefone/ramal → Zenvia (softphone) ou VTCall (PABX).
@@ -503,7 +503,8 @@ cards daquele funil).
503
503
  pelo botão de WhatsApp de um anúncio (conversa com `ctwa_clid` numa caixa oficial). A Meta só
504
504
  aceita 14 nomes nele (`LeadSubmitted`, `QualifiedLead`, `ViewContent`, `AddToCart`, `InitiateCheckout`, `Purchase`, `OrderCreated`, `OrderShipped`, `OrderDelivered`, `OrderCanceled`, `OrderReturned`, `CartAbandoned`, `RatingProvided`, `ReviewProvided`) e só num dataset vinculado à WABA.
505
505
  - **Dataset da WABA** (`provider_config.capi_dataset_id` da caixa oficial): destino desses eventos,
506
- criado/recuperado pelo botão "Vincular à Meta" (`lionchat_inboxes_capi_dataset_link`) com a chave da
506
+ criado/recuperado AUTOMATICAMENTE (na criação da caixa e por varredura a cada 10 min) e, como plano B,
507
+ pelo botão "Vincular à Meta" (`lionchat_inboxes_capi_dataset_link`) com a chave da
507
508
  própria caixa. Um por conta do WhatsApp Business; vale para todos os números dela.
508
509
  - **`messaging_name` / `messaging_event_names.meta` / `messaging_event_name`**: a escolha do evento de
509
510
  WhatsApp (funil / fluxo / disparo manual). Tri-estado: ausente = automático, `''` = não enviar como
@@ -600,6 +601,17 @@ conversa). Quem atendeu voltou a aparecer nas recebidas. Se o cliente diz que o
600
601
  funciona numa ligação de hoje, o mais provável é que o arquivo permanente ainda não exista — a
601
602
  reconferência resolve sozinha dentro de 36h.
602
603
 
604
+ ## Ligação feita direto no aparelho do VTCall (11/09/2026)
605
+
606
+ Antes, só a ligação iniciada pelo botão Ligar do LionChat entrava no histórico e na coluna "Feitas" do bloco de
607
+ ligações. Agora a ligação que o atendente disca direto no aparelho ou no app do VTCall também entra, desde que o ramal
608
+ esteja cadastrado (`vtcall_ramals_*`). Ela aparece em `voip_calls_list` com `direction: "outbound"`, protocolo `LIG-...`
609
+ (o do botão continua `AAMMDD-NNN`) e sem caixa. O card na conversa sai sem autor, com o nome do atendente.
610
+
611
+ Cuidado ao ler "Feitas atendidas": pelo botão a central marca atendida sempre (é a perna em que o atendente atende o
612
+ próprio ramal); pelo aparelho, só quando o cliente atende. Não compare as duas taxas como se medissem a mesma coisa.
613
+ Ramal sem cadastro não gera registro — se o cliente diz que "liguei e não apareceu", confira os ramais primeiro.
614
+
603
615
  ## Assinatura eletrônica de contratos (04/09)
604
616
 
605
617
  ### `status` do contrato (`signature_envelopes`)
@@ -721,6 +721,9 @@ Colunas: Ligações · Atendidas · Não atendidas · **Não concluídas** · Te
721
721
  - **Ligação sem atendente tem linha própria** e pode ser boa parte do volume (23% numa conta real).
722
722
  Não a esconda ao resumir por pessoa.
723
723
  - A tabela lista só quem teve ligação no período — atendente ausente da tabela fez zero.
724
+ - **VTCall (11/09/2026):** "Feitas" conta também a ligação discada direto no aparelho de ramal cadastrado. No botão a
725
+ central marca "atendida" sempre; no aparelho, só quando o cliente atende — não compare a taxa de atendidas de quem
726
+ liga pelo botão com a de quem liga pelo aparelho.
724
727
 
725
728
  ### Agendamentos (`lionchat_booking_reports`) — 2026-08-19
726
729
 
@@ -728,11 +731,36 @@ Colunas: Ligações · Atendidas · Não atendidas · **Não concluídas** · Te
728
731
  AGENDAMENTO (Booking). Params: `since`/`until` (datas; padrão 30 dias pra trás E 30 pra frente,
729
732
  porque agenda tem futuro), `event_type_id`, `user_id` (responsável da tarefa), `status`
730
733
  (`pending` | `completed` | `cancelled` | `snoozed`), `group_by` (`day` | `week` | `month`).
731
- Resposta: `totals` (`total`, `pending`, `completed`, `cancelled`, `snoozed`, `attendance_rate`),
732
- `timeline`, `by_event_type`, `by_agent`, `by_origin`.
733
-
734
- - **`attendance_rate` = concluídos / (concluídos + cancelados)**, em %. Pendentes ficam FORA do
735
- denominador (ainda não aconteceram). Não recalcule com o total.
734
+ Resposta: `totals` (`total`, `pending`, `completed`, `cancelled`, `snoozed`, `attended`, `no_show`,
735
+ `attendance_rate`, `attendance_basis`), `timeline`, `by_event_type`, `by_agent`, `by_origin` e
736
+ `treatments`.
737
+
738
+ - **`attended` / `no_show`** (15/09) são as marcas Compareceu/Faltou do compromisso
739
+ (`account_tasks.attendance`), um eixo próprio: **não mudam a situação** — compromisso "faltou"
740
+ continua `pending` até alguém concluir ou cancelar, igual a Agenda mostra.
741
+ - **`attendance_rate` (regra de 15/09) = compareceram / (compareceram + faltaram)**, em %. Período em
742
+ que NINGUÉM marcou presença (dado anterior a 14/09, equipe que só conclui/cancela) cai na regra
743
+ antiga — concluídos / (concluídos + cancelados), pendentes FORA — e `attendance_basis` diz qual
744
+ valeu: `attendance` ou `status`. Não recalcule com o total; diga qual base valeu.
745
+ - **`treatments`** (refeito em 15/09 à noite) é o bloco "Programas" da tela. **O período
746
+ (`since`/`until`) VALE** — decisão do dono; `event_type_id` recorta; `user_id` e `status` NÃO recortam
747
+ (são da tarefa, não do programa). Três andares:
748
+ 1. **Programas**: `em_andamento` (não tinha terminado no FIM do período), `atrasados` (medido no fim do
749
+ período, nunca em "hoje"), `comecaram`, `concluidos` e `encerrados` — esses três só contam se a data
750
+ cair DENTRO do período ("concluído" não tem data no banco: vale a data da última sessão usada).
751
+ `sessoes_planejadas`, `sessoes_usadas` e `percentual` são **só dos em andamento** (somar os concluídos
752
+ puxaria para 100).
753
+ 2. **Sessões do período**: `previstas` = `marcadas` + `nao_marcadas`; `aconteceram`, `faltaram` e `taxa`
754
+ = aconteceram / (aconteceram + faltaram), em %. `nao_marcadas` é a sessão que o plano previa e
755
+ ninguém agendou — é PREVISÃO, não existe no banco.
756
+ 3. **`parados`** `{programas, sessoes_restantes}`: em andamento sem nenhuma sessão futura marcada.
757
+ Vêm também `duracao` `{programas, dias_reais, dias_previstos}` (médias dos que concluíram no período;
758
+ `null` sem dado), `linha[]` e `por_tipo[]` (mesmos campos por `tipo`, ordenado pelos em andamento).
759
+ Cada ponto de `linha[]` traz `period`, `previstas`, `aconteceram`, `faltaram`, `aguardando` (marcada e
760
+ ainda sem Compareceu/Faltou — campo de 16/09) e `nao_marcadas`; as quatro últimas somam `previstas`. O
761
+ período inteiro vira ponto, com zero nos dias vazios; lista vazia = nenhum programa no período.
762
+ "Usada" = compareceu OU faltou (a falta consome). **Não há valor em reais** (o programa não guarda
763
+ preço). Ver `lionchat://docs/agenda-multiplas-unidades` §7.
736
764
  - A SITUAÇÃO vem da tarefa da Agenda (`account_tasks.status`), não de `bookings.status` — quem
737
765
  conclui/cancela pela Agenda deixa o booking parado em "confirmado". Ler `bookings_*` direto pra
738
766
  contar "concluídos" dá zero.
@@ -292,6 +292,20 @@ Desde 2026-09-02 há uma rede a mais: quando o WhatsApp recusa o endereço grava
292
292
  chegaram e guarda a correção. Interruptor `WAHA_SEND_PROVEN_ADDRESS` (Super Admin > App Config >
293
293
  WAHA). Não cobre campanha de WhatsApp QR nem convivência, que montam o endereço por conta própria.
294
294
 
295
+ ### "Balao vermelho no WhatsApp oficial com `(#131000) Something went wrong`"
296
+ Erro GENERICO da Meta: sem subcodigo e sem motivo. **Nao e bloqueio, nao e pagamento, nao e limite e
297
+ nao e defeito nosso** — a mensagem saiu daqui e a Meta recusou. Costuma ser uma janela de alguns
298
+ minutos: medido em producao, a mesma mensagem para o mesmo contato foi entregue 15 minutos depois.
299
+
300
+ Desde 2026-09-16 o sistema **tenta de novo sozinho** 4 vezes (1, 4, 10 e 20 minutos depois da
301
+ recusa). O balao fica vermelho o tempo todo e so vira verde quando a Meta aceitar de verdade. A
302
+ escada desiste se o atendente ja mandou por outra via (painel ou celular), se a janela de 24 h
303
+ fechar, ou se as 4 tentativas acabarem. Interruptor `WHATSAPP_AUTO_RETRY_TRANSIENT` (Super Admin >
304
+ App Config > WhatsApp oficial). Campanha fica de fora.
305
+
306
+ Se o cliente perguntar: pedir para **esperar uns 10 a 15 minutos antes de clicar Reenviar** —
307
+ reenviar na hora cai na mesma janela e falha de novo.
308
+
295
309
  ### "Cliente mandou um contato (vCard) e não apareceu nada"
296
310
  Corrigido em 2026-06-09: vCard agora vira anexo `file_type: "contact"` na mensagem (nome +
297
311
  telefone extraídos). Em versões antigas a mensagem era descartada.
package/dist/resources.js CHANGED
@@ -41,6 +41,12 @@ export const RESOURCES = [
41
41
  description: 'Ciclo de vida de uma conversa: criacao, greeting, auto-assignment, Captain IA, resolucao, snooze. Use pra diagnosticar comportamento de conversas.',
42
42
  filename: 'conversation-flows.md',
43
43
  },
44
+ {
45
+ name: 'Agenda — Unidades, Tipos e Google',
46
+ uri: 'lionchat://docs/agenda-multiplas-unidades',
47
+ description: 'Agenda por UNIDADE (matriz, filial, consultorio): o que agenda_id NULO significa, tipos de compromisso criados pela conta, Booking ligado a unidade, regras da pagina publica (cancelar/remarcar/confirmar presenca) e conexao Google UMA POR AGENDA. Leia antes de mexer em agenda, tipo de compromisso ou Booking.',
48
+ filename: 'agenda-multiplas-unidades.md',
49
+ },
44
50
  {
45
51
  name: 'Kanban Detalhado',
46
52
  uri: 'lionchat://docs/kanban-deep-dive',
@@ -1 +1 @@
1
- {"version":3,"file":"resources.js","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resources.js","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"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"}