Adicionado4
O "Novo Lead" do funil passa a escolher o contato
Pelo funil, o "Novo Lead" pedia título, etapa, valor e tags, mas não tinha onde pôr a pessoa: o negócio nascia sem contato, sem telefone e sem ligação com a base de contatos. Quem cadastrava pelo quadro ficava com um card que o WhatsApp não consegue responder e que as automações não conseguem casar com ninguém. A importação de planilha já fazia o certo — procura o contato pelo telefone, reaproveita e cria quando falta —, e as duas telas davam resultados diferentes para a mesma coisa.
Agora o diálogo abre com um campo Contato no topo: procure pelo nome ou pelo telefone, escolha da base ou crie na hora, sem sair da tela. Escolher alguém com o título ainda vazio preenche o título com o nome do contato.
O contato continua opcional: quem abre o card no meio da ligação e completa depois segue conseguindo. Sem contato escolhido, a tela diz o que o lead perde — não recebe WhatsApp nem entra nas automações. Aberto pelo Inbox, que já sabe de quem é a conversa, nada muda.
Leads sem contato criados antes desta versão continuam como estão; vinculá-los pela tela é a próxima fatia da #852. Crédito: @rafaelbatistazz.
A tela de Contatos passa a filtrar quem veio de anúncio
A lista de Contatos oferecia filtrar por Manual, WhatsApp, Nuvemshop e Importado (CSV). Quem chegou por um clique em anúncio — do Meta ou do Google — ficava gravado com essa origem no sistema e não aparecia em filtro nenhum: para encontrá-lo era preciso abrir contato por contato. Agora as duas origens de anúncio estão na mesma lista de filtros, em português e em espanhol.
Dá para digitar o identificador do modelo quando o provedor não tem catálogo
Na tela do agente, o campo Modelo só oferecia uma lista. Quando o provedor escolhido não devolve catálogo — é o caso de quem usa um serviço compatível, um gateway próprio ou um modelo que acabou de sair —, a lista aparecia vazia e não havia como seguir: o agente ficava sem modelo, mesmo com a chave certa cadastrada. Agora, quando não há catálogo para aquele provedor, o campo vira um campo de digitação e aceita o identificador do modelo exatamente como o serviço o nomeia. Com catálogo, nada muda: a lista continua sendo a lista.
Áudio pode ser transcrito em outro serviço compatível, sem trocar a chave da conversa
Quem quiser transcrever áudio num serviço diferente do padrão — Groq, um Whisper próprio, qualquer endereço com o mesmo formato de transcrição da OpenAI — agora preenche TRANSCRIPTION_API_KEY no .env, e opcionalmente TRANSCRIPTION_BASE_URL (o endereço do serviço) e TRANSCRIPTION_MODEL (o modelo de transcrição). A chave vale só para a transcrição: a conversa com o cliente e a leitura de imagem continuam usando o provedor que já está configurado. Sem essas variáveis, nada muda — a transcrição segue usando a chave da OpenAI, e se ela também não existir, o comportamento é o de hoje, com o aviso na Central e a orientação para cadastrar a chave.
Corrigido12
Um aviso de atualização antiga que falhou não trava mais o botão de atualizar
Quando uma atualização feita pela tela falhava e o sistema voltava sozinho para a versão anterior, a tela de Atualização passava a mostrar "A atualização para a versão … não deu certo", sem o botão de atualizar. Se depois alguém atualizasse por outro caminho (o update.sh no terminal, por exemplo), o sistema subia normalmente, mas o aviso antigo continuava ali. Quando saía uma versão nova, a tela mostrava de novo a falha de dias atrás e não oferecia o botão, e o único jeito de sair desse aviso era justamente clicar nele. Isso foi medido numa instalação real: uma falha de 13/09 impedia atualizar para a 1.27.2 pela tela em 15/09, com a 1.23.0 já no ar desde 14/09.
Agora, quando o servidor informa uma versão diferente das duas envolvidas na tentativa que falhou, a tela entende que a falha foi superada e volta a oferecer a atualização normalmente. Uma falha que ainda é o estado atual do servidor continua sendo mostrada como antes, com o comando para voltar.
Automação com condição de tag passa a funcionar quando a caixa difere
Numa automação, a condição sobre tags só disparava quando o texto digitado era idêntico à tag, maiúsculas incluídas: a regra escrita para "Google" não rodava para a tag "google", que é exatamente como o Inbox grava toda tag de contato. A regra existia, aparecia ativa na tela e nunca acontecia. Agora a condição compara a tag inteira sem diferenciar maiúsculas — "Google" pega "google" e continua não pegando "Google Ads", que é outra tag. Nada que funcionava antes deixa de funcionar, e nenhuma regra passa a alcançar quem não alcançava. Na tela de regras, o operador desses campos passa a se chamar "tem a tag", que é o que ele faz.
Automação por tag do contato deixa de criar lead repetido
Uma regra com gatilho "quando um contato ganhar uma tag" e ação "criar/mover lead no funil" criava um negócio novo toda vez que rodava, mesmo quando o contato já tinha um negócio aberto naquele funil — o contato acabava com vários leads iguais. E as ações seguintes da mesma regra, como "atribuir a um atendente", ficavam sem lead para agir, então a execução aparecia como "Parcial" na aba Atividade. Agora a automação move o negócio que o contato já tem no funil de destino, cria só quando não existe nenhum, e as ações seguintes passam a agir sobre esse lead. Leads criados em duplicidade antes desta versão continuam onde estão. Uma consequência que vale saber: numa regra assim, a ação "adicionar tag" que vier depois passa a etiquetar o NEGÓCIO, não mais o contato — é o efeito de as ações seguintes enxergarem o lead. Crédito: @rafaelbatistazz.
Contato que veio de anúncio da Meta pelo número oficial passa a ter a origem do anúncio
Quem clicava num anúncio "Clique para o WhatsApp" e caía num número conectado pela API oficial da Meta ficava com a origem "whatsapp", como se tivesse escrito por conta própria. O anúncio de onde a pessoa veio não era gravado, e a venda desse contato não podia ser devolvida à Meta como conversão. Agora a origem passa a ser o anúncio da Meta, com o clique e o título do anúncio, como o canal intermediado já fazia. Vale para os cliques a partir desta versão: a Meta só envia esses dados na primeira mensagem, então os contatos que já entraram continuam como estão. Crédito: @rafaelbatistazz.
O CI volta a medir a instalação em PostgreSQL 17, além do 15
Nada muda na sua VPS: nenhuma variável nova, nenhuma migration, nenhuma imagem. O que muda é o que o pipeline mede antes de a release sair — o gate de banco do CI voltou a rodar nas duas majors do PostgreSQL (15 e 17) e passou a exercitar também o update.sh sobre um banco COM DADOS, que é o caso da sua instalação e não o de um banco vazio. Crédito: @webtecnica.
A spec do inbox em tempo real volta a medir o que conserta o canal, e não só a tela
Nada muda na sua VPS: nenhuma migration, nenhuma variável, nenhuma imagem. O que muda é o que o teste mede. A spec do inbox em tempo real olhava só a saída — o texto na tela, que chega por dois caminhos por causa do refetchOnWindowFocus — e por isso ficava verde com o canal de tempo real mudo. Agora ela assere o que trafega no socket (phx_join autenticado e o postgres_changes com o corpo da mensagem) e reprova quando o conserto do #327 não está no bundle. Crédito: @webtecnica.
A hora na linha da Fila passa a ser a do tempo de espera
Na aba Fila a lista ordena por quem espera resposta há mais tempo, mas a hora mostrada à direita de cada linha era a da última mensagem de qualquer lado: responder uma conversa fazia o horário dela pular para agora sem que ela saísse do lugar, e a coluna de horas saía fora de ordem. Agora a hora na Fila é a da última mensagem do cliente — a mesma que ordena a lista e a mesma que a pílula "Aguardando há…" já usava. Nas demais abas nada muda, e a ordem da Fila continua por tempo de espera, agora com teste que a prende. Crédito: @webtecnica.
A resposta da IA não aparece mais duplicada depois de o WhatsApp reconectar
Quando o WhatsApp caía e voltava, as respostas da IA que tinham ficado esperando eram reenviadas sozinhas — e a mesma frase podia aparecer duas vezes na conversa. O reenvio automático era o único caminho que não apagava a cópia criada pelo eco do WhatsApp. Agora ele apaga, do mesmo jeito que o envio normal já fazia.
Quem usa o motor WEBJS tinha um problema pior no mesmo caminho: a mensagem podia ficar presa e ser mandada ao cliente de novo a cada minuto. Isso também foi corrigido.
Mídia recebida volta a usar o endereço do provedor configurado no ponto
Quando um ponto de IA era apontado para um serviço compatível — um endereço que não é o oficial do provedor, como um gateway interno —, o atendimento pelo chat funcionava, mas as imagens que os clientes enviavam continuavam sendo descritas pelo endereço oficial, e falhavam, porque a chave era daquele outro serviço. A leitura de mídia agora pega o endereço cadastrado no mesmo lugar em que o chat pega, então imagem e conversa usam o mesmo provedor. Quem nunca cadastrou endereço próprio não percebe diferença: vale o padrão do provedor, como antes. A transcrição de áudio não era afetada por este caminho.
Duas recusas passam a existir nesse caminho, e as duas abrem aviso na Central em vez de falharem em silêncio: se o endereço cadastrado apontar para dentro do próprio servidor (endereço local, rede interna do Docker, metadados da nuvem), a imagem e a chave não saem para lá; e se a empresa tiver endereço próprio cadastrado mas estiver usando a chave de IA da instalação, a leitura é recusada com a instrução de cadastrar a chave da empresa — a chave que paga a conta da instalação inteira não viaja para um endereço escolhido por uma das empresas.
O worker passa a dizer se o laço do event_log carregou, e a publicação exige isso antes de marcar stable
Nada muda na sua VPS: nenhuma migration, nenhuma variável, nenhum comando. O /healthz do worker passa a publicar um campo a mais (event_log_drain, com o motivo quando o laço não carregou) e a falha ao carregar o laço deixa de ser um aviso de rotina para ser erro — era o aviso que fazia um drain parado parecer normal, e foi assim que a fila do event_log ficou dez dias sem drenar com o worker respondendo saudável. Do lado da publicação, o CI passa a executar as imagens do worker e do scheduler antes de publicá-las: worker que não sobe ou laço que não carrega não vira a versão stable de quem self-hospeda. Crédito: @webtecnica.
No Inbox, o botão de tags diz que a tag é do contato
No painel lateral do Inbox, o botão que abre as tags do contato dizia apenas "Tag", enquanto logo abaixo, no mesmo painel, fica a seção "Tags da conversa". Os dois lugares guardam tags diferentes, e quem atende não sabia em qual estava mexendo. Agora o botão se chama "Tags do contato". Nada muda no comportamento. Crédito: @rafaelbatistazz.
O provisionamento do Supabase lê as chaves em qualquer ordem e não perde mais a senha do banco
Na instalação, o passo que busca as chaves de API do projeto novo lia a resposta da Management API por POSIÇÃO: procurava anon e, só no que vinha depois dela, api_key. Quando a API do Supabase passou a devolver api_key antes de name, a leitura passou a voltar vazia e a instalação morria no passo 5 com "Não consegui ler anon/service_role" — num projeto que já estava criado e de pé. A leitura agora é por objeto, e a ordem dos campos deixou de importar.
O estrago maior era o outro lado. A senha do banco é gerada no começo e a API não a devolve depois, então quem morria no passo 5 ficava com um projeto ocupando uma das duas vagas do plano grátis e sem a credencial à mão. A senha passa a ser gravada em .env.supabase-provision (só leitura pelo dono, 600) antes de o projeto ser criado; quando um passo falha, a mensagem diz onde ela está; e uma segunda tentativa reaproveita a mesma senha em vez de gerar outra.