Import ClientFlow production v4928.1.5.132.4
This commit is contained in:
19
docs/CLIENTFLOW_V4928_1_4_4_OUTBOX_SCHEMA_HOTFIX.md
Normal file
19
docs/CLIENTFLOW_V4928_1_4_4_OUTBOX_SCHEMA_HOTFIX.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# ClientFlow v4928.1.4.4 — Outbox schema compatibility hotfix
|
||||
|
||||
Fixes Jasmin outbox worker failures on upgraded installs where the existing
|
||||
`integration_outbox` table lacked columns selected by the current worker,
|
||||
notably `sent_at`.
|
||||
|
||||
Changes:
|
||||
|
||||
- `ensure_core_schema()` now adds all worker/UI outbox columns with `IF NOT EXISTS`.
|
||||
- `scripts/process_outbox.py` calls `init_db()` before claiming pending items.
|
||||
- Adds `migrations/005_outbox_schema_compatibility.sql` for manual repair.
|
||||
|
||||
Manual repair command:
|
||||
|
||||
```bash
|
||||
sudo -u postgres psql -d clientflow -f migrations/005_outbox_schema_compatibility.sql
|
||||
```
|
||||
|
||||
Then restart/process the Jasmin worker.
|
||||
119
docs/CLIENTFLOW_V4928_1_4_9_REPLY_ASSISTANT.md
Normal file
119
docs/CLIENTFLOW_V4928_1_4_9_REPLY_ASSISTANT.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# ClientFlow v4928.1.4.9 — Opportunity Reply Assistant
|
||||
|
||||
## Objetivo
|
||||
|
||||
Reduzir o atrito entre ClientFlow e Chatwoot. O operador passa a gerar e enviar mensagens comerciais a partir da tarefa, usando modelos e anexos já ligados à oportunidade.
|
||||
|
||||
O Chatwoot continua a ser o canal técnico de envio, mas o ClientFlow passa a ser o cockpit operacional.
|
||||
|
||||
## O que foi adicionado
|
||||
|
||||
### Modelos de mensagem
|
||||
|
||||
Novo catálogo em `app/message_templates.py`:
|
||||
|
||||
- `SEND_INFO_EQUIPMENT_LIST`
|
||||
- `SEND_PRICE_LIST`
|
||||
- `SEND_QUOTE`
|
||||
- `SEND_PROFORMA`
|
||||
- `SEND_INVOICE`
|
||||
- `REQUEST_FISCAL_DATA`
|
||||
- `REQUEST_PAYMENT_PROOF`
|
||||
- `CONFIRM_PAYMENT_RECEIVED`
|
||||
- `FOLLOW_UP_QUOTE`
|
||||
|
||||
Os modelos são determinísticos e editáveis antes do envio.
|
||||
|
||||
### Serviço de resposta
|
||||
|
||||
Novo serviço `app/reply_assistant_service.py`:
|
||||
|
||||
- carrega tarefa, oportunidade e documentos associados;
|
||||
- escolhe modelo por ação;
|
||||
- gera rascunho editável;
|
||||
- valida prontidão antes de enviar;
|
||||
- bloqueia anexos que não pertencem à oportunidade;
|
||||
- envia mensagem pública no Chatwoot;
|
||||
- regista comunicação outbound;
|
||||
- regista evento na timeline;
|
||||
- pode concluir a tarefa após envio.
|
||||
|
||||
### UI na tarefa
|
||||
|
||||
A página da tarefa ganhou o bloco **Resposta ao cliente**:
|
||||
|
||||
- seletor de modelo;
|
||||
- seleção de anexos da oportunidade;
|
||||
- botão **Gerar rascunho**;
|
||||
- textarea editável;
|
||||
- botão **Enviar**;
|
||||
- botão **Enviar e concluir tarefa**.
|
||||
|
||||
### Chatwoot
|
||||
|
||||
`app/chatwoot_client.py` ganhou:
|
||||
|
||||
- `send_public_message()`;
|
||||
- `send_public_message_with_attachments()`.
|
||||
|
||||
O envio continua protegido por:
|
||||
|
||||
```env
|
||||
CHATWOOT_WRITE_ENABLED=true
|
||||
CHATWOOT_BASE_URL=...
|
||||
CHATWOOT_ACCOUNT_ID=...
|
||||
CHATWOOT_API_TOKEN=...
|
||||
```
|
||||
|
||||
### Auditoria
|
||||
|
||||
Foi adicionada a tabela `message_drafts` para guardar rascunhos gerados e estado do envio.
|
||||
|
||||
Cada envio cria também um registo em `communications` com:
|
||||
|
||||
- `direction = outbound`;
|
||||
- `source_system = chatwoot`;
|
||||
- `conversation_id`;
|
||||
- `task_id`;
|
||||
- `opportunity_id`;
|
||||
- `metadata.template_code`;
|
||||
- `metadata.attachments`;
|
||||
- `metadata.chatwoot_result`.
|
||||
|
||||
### Timeline
|
||||
|
||||
Ao enviar uma mensagem, o ClientFlow cria um evento `reply_sent` na timeline da oportunidade.
|
||||
|
||||
## Regras de segurança
|
||||
|
||||
- Um documento só pode ser anexado se pertence à mesma oportunidade da tarefa.
|
||||
- Envio de documentos fiscais exige cliente fiscal minimamente preenchido.
|
||||
- Documentos sem `external_id` não são anexados automaticamente.
|
||||
- Nesta versão, PDF automático está limitado a documentos Jasmin suportados pelo serviço existente: `quotation` e `invoice`.
|
||||
- O LLM não é usado para decidir preço, documento ou anexo.
|
||||
|
||||
## LLM
|
||||
|
||||
Foi adicionada a opção:
|
||||
|
||||
```env
|
||||
CLIENTFLOW_REPLY_LLM_ENABLED=false
|
||||
```
|
||||
|
||||
Nesta versão fica desativada. A arquitetura fica preparada para uma versão seguinte onde o LLM apenas adapte o texto, mantendo oportunidade/documentos como fonte de verdade.
|
||||
|
||||
## Endpoints novos
|
||||
|
||||
```http
|
||||
POST /tasks/{task_id}/reply-draft
|
||||
POST /tasks/{task_id}/send-reply
|
||||
```
|
||||
|
||||
## Rollback
|
||||
|
||||
A alteração é aditiva. Para rollback funcional:
|
||||
|
||||
1. manter `CHATWOOT_WRITE_ENABLED=false` para bloquear envio;
|
||||
2. remover/ignorar o bloco UI de resposta;
|
||||
3. a tabela `message_drafts` pode permanecer sem afetar o fluxo antigo.
|
||||
|
||||
100
docs/CLIENTFLOW_V4928_1_5_0_BLIF_KNOWLEDGE_REPLY_ASSISTANT.md
Normal file
100
docs/CLIENTFLOW_V4928_1_5_0_BLIF_KNOWLEDGE_REPLY_ASSISTANT.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# ClientFlow v4928.1.5.0 — BLIF Knowledge Reply Assistant
|
||||
|
||||
## Objetivo
|
||||
|
||||
Adicionar o caminho realista para respostas comerciais melhores sem fine-tuning: conhecimento BLIF estruturado, recuperação por tópico, geração LLM opcional via OpenRouter e validação comercial antes do envio.
|
||||
|
||||
A versão mantém o operador no controlo: o sistema gera um rascunho editável e só envia para Chatwoot quando o operador confirma.
|
||||
|
||||
## O que mudou
|
||||
|
||||
- Base de conhecimento BLIF estruturada em `app/business_knowledge/blif_knowledge.json`.
|
||||
- Recuperação determinística de tópicos por palavras-chave em `app/business_knowledge_service.py`.
|
||||
- Novos modelos de esclarecimento sem anexo, incluindo instalação, IVA, entrega/pagamento, RFID, balanceador, histórico local, condomínio/MOBI.E e funcionalidades técnicas.
|
||||
- Seleção automática de template de conhecimento quando a última mensagem do cliente corresponde a um tópico BLIF.
|
||||
- Geração LLM opcional via OpenRouter em `app/llm_reply_generator.py`.
|
||||
- Validador comercial em `app/reply_safety_validator.py` para bloquear riscos como “BLIF faz instalação” ou “instalação incluída” sem prova documental.
|
||||
- UI da tarefa mostra o conhecimento usado, tipo de resposta e estado do LLM.
|
||||
|
||||
## Fluxo
|
||||
|
||||
```text
|
||||
Tarefa / oportunidade
|
||||
→ mensagem do cliente
|
||||
→ recuperar conhecimento BLIF relevante
|
||||
→ escolher template seguro sem anexo quando aplicável
|
||||
→ opcionalmente pedir ao LLM para adaptar a redação
|
||||
→ validar resposta
|
||||
→ operador edita/confirma
|
||||
→ ClientFlow envia no Chatwoot e regista timeline/communication
|
||||
```
|
||||
|
||||
## Exemplo — Varisom
|
||||
|
||||
Mensagem do cliente:
|
||||
|
||||
```text
|
||||
Presumo que o valor é sem instalação, pode por favor confirmar?
|
||||
```
|
||||
|
||||
Antes:
|
||||
|
||||
```text
|
||||
SEND_QUOTE → exige orçamento/anexo → bloqueia por falta de documento
|
||||
```
|
||||
|
||||
Agora:
|
||||
|
||||
```text
|
||||
Tópico detetado: instalação / âmbito do preço
|
||||
Template: CLARIFY_INSTALLATION_SCOPE
|
||||
Anexo: não necessário
|
||||
Resposta: confirmar que o valor é do equipamento, sem instalação incluída, e indicar eletricista qualificado + suporte remoto
|
||||
```
|
||||
|
||||
## Variáveis de ambiente
|
||||
|
||||
```env
|
||||
CLIENTFLOW_REPLY_LLM_ENABLED=false
|
||||
CLIENTFLOW_REPLY_LLM_MODEL=
|
||||
CLIENTFLOW_REPLY_LLM_TEMPERATURE=0.2
|
||||
CLIENTFLOW_REPLY_LLM_MAX_TOKENS=700
|
||||
CLIENTFLOW_REPLY_LLM_TIMEOUT_SECONDS=20
|
||||
CLIENTFLOW_REPLY_LLM_MAX_CONTEXT_CHARS=5000
|
||||
OPENROUTER_API_KEY=...
|
||||
OPENROUTER_MODEL=qwen/qwen3-30b-a3b
|
||||
```
|
||||
|
||||
Com `CLIENTFLOW_REPLY_LLM_ENABLED=false`, o sistema continua a gerar rascunhos úteis com templates e conhecimento BLIF, sem chamada externa.
|
||||
|
||||
## Segurança comercial
|
||||
|
||||
O LLM, quando ativado, só adapta o texto. Não escolhe documentos, não decide preços finais, não confirma stock e não envia automaticamente.
|
||||
|
||||
O backend valida:
|
||||
|
||||
- documentos selecionados pertencem à oportunidade;
|
||||
- mensagens com instalação incluída são bloqueadas se não houver prova;
|
||||
- mensagens que sugerem instalação direta pela BLIF são bloqueadas;
|
||||
- preços desconhecidos geram aviso;
|
||||
- prazos devem ficar associados a confirmação de pagamento;
|
||||
- valores com IVA sem documento geram aviso.
|
||||
|
||||
## Limites conhecidos
|
||||
|
||||
- A recuperação de conhecimento é por palavras-chave, não vector search. É suficiente para esta fase e transparente para validação.
|
||||
- Não há fine-tuning.
|
||||
- Preços e regras devem ser revistos/versionados quando mudarem.
|
||||
- Stock, descontos e condições especiais continuam fora do LLM.
|
||||
|
||||
## Próximo passo recomendado
|
||||
|
||||
Criar um `Agent Builder TUI` apenas para administração/teste do conhecimento:
|
||||
|
||||
```text
|
||||
- importar/editar conhecimento BLIF
|
||||
- testar perguntas reais
|
||||
- aprovar/rejeitar respostas
|
||||
- versionar regras
|
||||
- preparar exemplos para avaliação futura
|
||||
```
|
||||
32
docs/CLIENTFLOW_V4928_1_5_13_TASK_DETAIL_REFRESH.md
Normal file
32
docs/CLIENTFLOW_V4928_1_5_13_TASK_DETAIL_REFRESH.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# ClientFlow v4928.1.5.13 — Atualização do detalhe da task após enviar e concluir
|
||||
|
||||
## Problema
|
||||
|
||||
No detalhe da task, ao usar **Enviar e concluir tarefa**, a mensagem era enviada e a task podia ser concluída na BD, mas a página continuava a mostrar o cabeçalho antigo, por exemplo:
|
||||
|
||||
- `Enviar proposta/cotação`
|
||||
- `Pendente`
|
||||
- `COMERCIAL`
|
||||
- `85% confiança`
|
||||
- `SEND_QUOTE`
|
||||
|
||||
Isto acontecia porque o formulário do assistente de resposta usava `hx-target="#reply-assistant-panel"`, atualizando apenas o bloco da resposta.
|
||||
|
||||
## Correção
|
||||
|
||||
O formulário de envio passa a usar `hx-target="#task-detail-panel"` e, em caso de sucesso, a rota `/tasks/{task_id}/send-reply` devolve `render_task_detail_partial(...)`.
|
||||
|
||||
Assim, depois de **Enviar e concluir tarefa**, todo o detalhe da task é re-renderizado com o estado atual da BD.
|
||||
|
||||
## Erros
|
||||
|
||||
Em caso de erro de validação/envio, a resposta HTMX usa:
|
||||
|
||||
- `HX-Retarget: #reply-assistant-panel`
|
||||
- `HX-Reswap: outerHTML`
|
||||
|
||||
para manter o erro local ao painel da resposta.
|
||||
|
||||
## Migração
|
||||
|
||||
Não requer migração de base de dados.
|
||||
54
docs/CLIENTFLOW_V4928_1_5_17_SEMI_AUTOMATIC_FOLLOWUPS.md
Normal file
54
docs/CLIENTFLOW_V4928_1_5_17_SEMI_AUTOMATIC_FOLLOWUPS.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# Follow-ups semi-automáticos no Clientflow
|
||||
|
||||
## Regra de produto
|
||||
|
||||
O follow-up de uma oportunidade ativa deve ser semi-automático:
|
||||
|
||||
> O sistema cria a tarefa, calcula a data e sugere a mensagem. O operador decide se envia, adia, conclui ou fecha o processo.
|
||||
|
||||
Isto evita dois problemas:
|
||||
|
||||
- follow-up 100% manual: oportunidades esquecidas;
|
||||
- follow-up 100% automático: risco de mensagens erradas, fora de contexto ou duplicadas.
|
||||
|
||||
## Como funciona
|
||||
|
||||
### Criação automática
|
||||
|
||||
Após conclusão de ações comerciais, o backend cria tarefas internas de follow-up:
|
||||
|
||||
| Ação concluída | Follow-up criado | Prazo |
|
||||
|---|---|---:|
|
||||
| `SEND_QUOTE` | `FOLLOW_UP_QUOTE` | 3 dias |
|
||||
| `SEND_PROFORMA` | `FOLLOW_UP_PROFORMA` | 2 dias |
|
||||
| `SEND_INVOICE` | `FOLLOW_UP_PAYMENT` | 3 dias |
|
||||
| `SEND_INFO` | `FOLLOW_UP_CUSTOMER_REVIEW` | 5 dias |
|
||||
|
||||
### Criação manual
|
||||
|
||||
Na página da oportunidade, o operador pode criar um follow-up manual quando o contexto comercial justificar.
|
||||
|
||||
### Fecho automático
|
||||
|
||||
Quando entra nova atividade do cliente associada à oportunidade, os follow-ups pendentes dessa oportunidade são concluídos para evitar duplicação.
|
||||
|
||||
### Cancelamento automático
|
||||
|
||||
Quando a oportunidade é fechada como ganha, perdida ou sem interesse, os follow-ups pendentes são cancelados.
|
||||
|
||||
## UI esperada
|
||||
|
||||
Na página de tarefas:
|
||||
|
||||
- `Follow-ups`: todos os follow-ups pendentes;
|
||||
- `Follow-ups vencidos`: follow-ups com `due_at` passado;
|
||||
- detalhe da tarefa: mensagem sugerida, prazo e ações de adiamento.
|
||||
|
||||
Na oportunidade:
|
||||
|
||||
- bloco lateral para criar follow-up manual;
|
||||
- timeline/eventos com criação, conclusão ou cancelamento do follow-up.
|
||||
|
||||
## Limite intencional
|
||||
|
||||
Esta versão não envia emails automaticamente. O campo `safe_to_post` das ações de follow-up fica sempre `false`.
|
||||
131
docs/CLIENTFLOW_V4928_1_5_1_TASK_REPLY_AUDIT.md
Normal file
131
docs/CLIENTFLOW_V4928_1_5_1_TASK_REPLY_AUDIT.md
Normal file
@@ -0,0 +1,131 @@
|
||||
# ClientFlow v4928.1.5.1 — Task Reply Audit
|
||||
|
||||
Esta versão adiciona um script operacional para auditar todas as tarefas e comparar, para cada uma, o pedido do cliente com a resposta sugerida pelo `Reply Assistant`.
|
||||
|
||||
## Objetivo
|
||||
|
||||
Permitir rever em lote se o assistente está a interpretar corretamente:
|
||||
|
||||
- o pedido real do cliente;
|
||||
- o `action_code` atual da tarefa;
|
||||
- o template/modelo escolhido;
|
||||
- o conhecimento BLIF usado;
|
||||
- a resposta sugerida;
|
||||
- bloqueios e avisos antes de envio.
|
||||
|
||||
O script é **read-only** por defeito: não envia mensagens, não conclui tarefas e não cria rascunhos persistentes.
|
||||
|
||||
## Script
|
||||
|
||||
```bash
|
||||
python scripts/audit_task_reply_suggestions.py --status all --format markdown --out /tmp/task_reply_audit.md
|
||||
```
|
||||
|
||||
Ficheiro:
|
||||
|
||||
```text
|
||||
scripts/audit_task_reply_suggestions.py
|
||||
```
|
||||
|
||||
## Exemplos
|
||||
|
||||
Auditar todas as tarefas pendentes:
|
||||
|
||||
```bash
|
||||
python scripts/audit_task_reply_suggestions.py \
|
||||
--status pending \
|
||||
--format markdown \
|
||||
--out /tmp/clientflow_task_reply_audit.md
|
||||
```
|
||||
|
||||
Auditar todas as tarefas e exportar CSV:
|
||||
|
||||
```bash
|
||||
python scripts/audit_task_reply_suggestions.py \
|
||||
--status all \
|
||||
--format csv \
|
||||
--out /tmp/clientflow_task_reply_audit.csv
|
||||
```
|
||||
|
||||
Auditar apenas tarefas comerciais:
|
||||
|
||||
```bash
|
||||
python scripts/audit_task_reply_suggestions.py \
|
||||
--status pending \
|
||||
--route comercial \
|
||||
--format markdown
|
||||
```
|
||||
|
||||
Testar com LLM/OpenRouter ativo:
|
||||
|
||||
```bash
|
||||
python scripts/audit_task_reply_suggestions.py \
|
||||
--status pending \
|
||||
--use-llm \
|
||||
--format markdown
|
||||
```
|
||||
|
||||
> Por defeito, o script força `CLIENTFLOW_REPLY_LLM_ENABLED=false` para evitar custos e variação de resultados. O LLM só é usado com `--use-llm`.
|
||||
|
||||
## Campos do relatório
|
||||
|
||||
Cada tarefa inclui:
|
||||
|
||||
- Task ID;
|
||||
- estado/fila;
|
||||
- cliente/contacto;
|
||||
- conversa Chatwoot;
|
||||
- action code;
|
||||
- template escolhido;
|
||||
- tipo de resposta;
|
||||
- conhecimento BLIF usado;
|
||||
- anexos selecionados;
|
||||
- pedido do cliente;
|
||||
- resposta sugerida atual;
|
||||
- resposta sugerida anterior da preparação, quando existir;
|
||||
- bloqueios;
|
||||
- avisos.
|
||||
|
||||
## Segurança operacional
|
||||
|
||||
Por defeito o script usa:
|
||||
|
||||
```text
|
||||
persist=False
|
||||
CLIENTFLOW_REPLY_LLM_ENABLED=false
|
||||
```
|
||||
|
||||
Isto significa que o teste não altera estado operacional. Para gravar `message_drafts` de auditoria, usar explicitamente:
|
||||
|
||||
```bash
|
||||
--persist-drafts
|
||||
```
|
||||
|
||||
## Requisitos
|
||||
|
||||
Executar no backend ClientFlow com `.env` ou `DATABASE_URL` definido.
|
||||
|
||||
```bash
|
||||
cd /caminho/clientflow_backend
|
||||
python scripts/audit_task_reply_suggestions.py --status pending
|
||||
```
|
||||
|
||||
Se não existir `OPENROUTER_API_KEY`, o script define um valor interno `not-used-by-task-reply-audit` quando o LLM está desligado, porque o `app.config` exige essa variável.
|
||||
|
||||
## Utilidade para afinar o agente
|
||||
|
||||
Este relatório é útil para encontrar casos como:
|
||||
|
||||
```text
|
||||
Cliente pergunta: “o valor inclui instalação?”
|
||||
Tarefa atual: SEND_QUOTE
|
||||
Resposta esperada: esclarecimento sem anexo
|
||||
```
|
||||
|
||||
A partir do relatório é possível identificar onde faltam:
|
||||
|
||||
- regras de conhecimento BLIF;
|
||||
- templates específicos;
|
||||
- intents/subtipos;
|
||||
- dados na oportunidade;
|
||||
- documentos associados.
|
||||
111
docs/CLIENTFLOW_V4928_1_5_3_INTENT_GATE_REPLY_SAFETY.md
Normal file
111
docs/CLIENTFLOW_V4928_1_5_3_INTENT_GATE_REPLY_SAFETY.md
Normal file
@@ -0,0 +1,111 @@
|
||||
# ClientFlow v4928.1.5.3 — Intent Gate & Reply Safety Fix
|
||||
|
||||
## Objetivo
|
||||
|
||||
Corrigir os falsos positivos encontrados pela auditoria de respostas sugeridas (`audit_task_reply_suggestions.py`), onde bounces, pedidos de remoção, respostas sem interesse e casos de suporte podiam cair em templates comerciais como lista de equipamentos.
|
||||
|
||||
## Alterações principais
|
||||
|
||||
### 1. ReplyIntentGate
|
||||
|
||||
Novo módulo:
|
||||
|
||||
```text
|
||||
app/reply_intent_gate.py
|
||||
```
|
||||
|
||||
Classifica a natureza da mensagem antes de escolher template ou conhecimento BLIF:
|
||||
|
||||
- `BOUNCE_EMAIL`
|
||||
- `UNSUBSCRIBE_REQUEST`
|
||||
- `ADDRESS_UPDATE`
|
||||
- `NO_INTEREST`
|
||||
- `SUPPORT_INCIDENT`
|
||||
- `COMMERCIAL_CLARIFICATION`
|
||||
- `VAT_CLARIFICATION`
|
||||
- `DELIVERY_PAYMENT`
|
||||
- `RFID_QUESTION`
|
||||
- `LOAD_BALANCER_QUESTION`
|
||||
- `CONDOMINIUM_MOBIE`
|
||||
- `INVOICE_REQUEST`
|
||||
- `COMMERCIAL_REQUEST`
|
||||
- `CALLBACK_REQUEST`
|
||||
- `MANUAL_REVIEW`
|
||||
|
||||
### 2. Fallback comercial mais seguro
|
||||
|
||||
`SEND_INFO` e `REVIEW_MANUALLY` deixaram de cair por defeito em `SEND_INFO_EQUIPMENT_LIST`.
|
||||
|
||||
Novo fallback:
|
||||
|
||||
```text
|
||||
MANUAL_REVIEW_REQUIRED
|
||||
```
|
||||
|
||||
Isto evita enviar lista de equipamentos quando a intenção não está clara.
|
||||
|
||||
### 3. Templates operacionais/não comerciais
|
||||
|
||||
Novos templates:
|
||||
|
||||
- `INTERNAL_BOUNCE_EMAIL`
|
||||
- `ACK_UNSUBSCRIBE`
|
||||
- `ACK_ADDRESS_UPDATE`
|
||||
- `ACK_NO_INTEREST`
|
||||
- `ACK_SUPPORT_RECEIVED`
|
||||
- `ACK_CALLBACK_REQUEST`
|
||||
- `MANUAL_REVIEW_REQUIRED`
|
||||
|
||||
### 4. Correção do caso Varisom / instalação
|
||||
|
||||
O validador agora permite frases aprovadas como:
|
||||
|
||||
```text
|
||||
sem instalação incluída
|
||||
A BLIF não presta serviço direto de instalação
|
||||
qualquer eletricista qualificado
|
||||
suporte remoto ao eletricista
|
||||
```
|
||||
|
||||
E continua a bloquear promessas incorretas como:
|
||||
|
||||
```text
|
||||
instalação incluída
|
||||
A BLIF faz a instalação
|
||||
instalação gratuita
|
||||
```
|
||||
|
||||
### 5. Auditoria melhorada
|
||||
|
||||
O script `scripts/audit_task_reply_suggestions.py` passa a mostrar:
|
||||
|
||||
- `intent_category`
|
||||
- `intent_label`
|
||||
- `intent_reasons`
|
||||
- contagem por intenção no resumo
|
||||
- se a resposta comercial foi permitida pela triagem
|
||||
|
||||
## Uso recomendado
|
||||
|
||||
Depois de instalar a versão, correr:
|
||||
|
||||
```bash
|
||||
cd /mnt/ssd/home/plx/clientflow_backend
|
||||
python scripts/audit_task_reply_suggestions.py --status pending --format markdown --out /tmp/task_reply_audit_v153.md
|
||||
```
|
||||
|
||||
Ou comparar todos os estados:
|
||||
|
||||
```bash
|
||||
python scripts/audit_task_reply_suggestions.py --status all --format markdown --out /tmp/task_reply_audit_v153_all.md
|
||||
```
|
||||
|
||||
## Segurança
|
||||
|
||||
O script continua read-only por defeito:
|
||||
|
||||
- não envia mensagens;
|
||||
- não conclui tarefas;
|
||||
- não cria rascunhos persistentes;
|
||||
- não ativa OpenRouter/LLM salvo `--use-llm`.
|
||||
|
||||
25
docs/CLIENTFLOW_V4928_1_5_41_WORKFLOW_ANOMALY_FIXES.md
Normal file
25
docs/CLIENTFLOW_V4928_1_5_41_WORKFLOW_ANOMALY_FIXES.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# ClientFlow v4928.1.5.41 — workflow anomaly fixes
|
||||
|
||||
Correções focadas nas anomalias funcionais encontradas pelos testes `workflow_anomaly_hunt` e `workflow_anomaly_hunt_v2`.
|
||||
|
||||
## Corrigido
|
||||
|
||||
- Normalização de email em clientes: `trim + lower`, com reutilização lógica da ficha existente quando não há NIF.
|
||||
- Validação simples de email inválido ao criar/editar cliente.
|
||||
- Bloqueio de regressões perigosas de estado: oportunidades `WON/LOST/NO_INTEREST` não regressam para fases comerciais sem reabertura explícita.
|
||||
- Fecho automático de tarefas pendentes incompatíveis quando a oportunidade passa a estado terminal.
|
||||
- Bloqueio operacional com HTTP 409 em ações incompatíveis com o estado da oportunidade.
|
||||
- Idempotência de tarefas repetidas por fingerprint da mensagem, evitando múltiplos `SEND_QUOTE` pendentes para o mesmo pedido repetido.
|
||||
- Follow-ups limitados a uma janela operacional segura: 1 a 30 dias.
|
||||
- Webhook Chatwoot incompleto passa a devolver 422 em vez de aceitar payload vazio/incompleto.
|
||||
- Validação de produtos e linhas de oportunidade: preços/quantidades negativas ou inválidas são recusados.
|
||||
- Runner `workflow_anomaly_hunt_v2` ajustado para não falhar na fase documental e para reconstruir reconciliação após seed documental.
|
||||
|
||||
## Comandos de validação recomendados
|
||||
|
||||
```bash
|
||||
./e2e_test_lab/scripts/run_e2e_lab.sh | tee e2e_test_lab/latest_e2e_run.log
|
||||
./e2e_test_lab/scripts/run_deep_e2e_lab.sh | tee e2e_test_lab/latest_deep_e2e_run.log
|
||||
./e2e_test_lab/scripts/run_workflow_anomaly_hunt.sh | tee e2e_test_lab/latest_workflow_anomaly_run.log
|
||||
./e2e_test_lab/scripts/run_workflow_anomaly_hunt_v2.sh | tee e2e_test_lab/latest_workflow_anomaly_v2_run.log
|
||||
```
|
||||
31
docs/CLIENTFLOW_V4928_1_5_42_FINANCIAL_CONFLICT_GUARD.md
Normal file
31
docs/CLIENTFLOW_V4928_1_5_42_FINANCIAL_CONFLICT_GUARD.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# ClientFlow v4928.1.5.42 — Financial conflict guard
|
||||
|
||||
Esta versão fecha a última anomalia funcional detetada no Workflow Anomaly Hunt v2.
|
||||
|
||||
## Correção
|
||||
|
||||
Quando vários documentos do mesmo cliente/processo têm valores claramente divergentes, o candidato de reconciliação passa a expor explicitamente:
|
||||
|
||||
- `review_status = conflict`
|
||||
- `financial_conflict = true`
|
||||
- `amount_conflict_values = [...]`
|
||||
- risco: `conflito financeiro: valores divergentes entre documentos`
|
||||
- risco: `bloquear auto-associação financeira até revisão`
|
||||
|
||||
Isto evita que comprovativos, faturas, orçamentos ou vendas Odoo com valores diferentes sejam tratados como sequência limpa do mesmo processo.
|
||||
|
||||
## Teste atualizado
|
||||
|
||||
O runner `workflow_anomaly_hunt_v2` deixa de considerar a simples existência de valores diferentes como anomalia se o backend expuser um conflito financeiro claro no processo candidato.
|
||||
|
||||
Resultado esperado após aplicar:
|
||||
|
||||
```text
|
||||
Workflow Anomaly Hunt v2
|
||||
Anomalias funcionais: 0
|
||||
```
|
||||
|
||||
## Ficheiros alterados
|
||||
|
||||
- `app/reconciliation_service.py`
|
||||
- `e2e_test_lab/tests/workflow_anomaly_hunt_v2.py`
|
||||
10
docs/CLIENTFLOW_V4928_1_5_44_NOTES.md
Normal file
10
docs/CLIENTFLOW_V4928_1_5_44_NOTES.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# ClientFlow v4928.1.5.44 — Final hardening pass
|
||||
|
||||
Correções focadas nos achados restantes do Failure Hunt:
|
||||
|
||||
- marcador CSRF visível em forms POST/HTMX da UI administrativa;
|
||||
- confirmação explícita na sincronização de produtos Odoo;
|
||||
- validação defensiva em criação/edição de produtos;
|
||||
- validação de email e dados mínimos na criação manual de oportunidade a partir de cliente;
|
||||
- autocomplete controlado nos campos sensíveis do pedido externo;
|
||||
- calibração do Failure Hunt para não tratar filtros GET como mutações.
|
||||
14
docs/CLIENTFLOW_V4928_1_5_45_PLAYWRIGHT_AUTH_FIX.md
Normal file
14
docs/CLIENTFLOW_V4928_1_5_45_PLAYWRIGHT_AUTH_FIX.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# ClientFlow v4928.1.5.45 — Playwright UI auth fix
|
||||
|
||||
Corrige o runner Playwright UI para usar o mesmo `CLIENTFLOW_ADMIN_TOKEN` dos testes HTTP.
|
||||
|
||||
## Sintoma
|
||||
|
||||
O Deep Audit HTTP estava verde, mas `RUN_PLAYWRIGHT_UI=1` falhava com `HTTP 401` em todas as páginas.
|
||||
|
||||
## Correção
|
||||
|
||||
- `playwright_ui_journey.py` passa `X-ClientFlow-Admin-Token` no contexto do browser.
|
||||
- `run_deep_e2e_lab.sh` e `run_ui_e2e_playwright.sh` passam explicitamente `--admin-token "${CLIENTFLOW_ADMIN_TOKEN:-}"`.
|
||||
|
||||
Não altera regras de negócio nem backend.
|
||||
17
docs/CLIENTFLOW_V4928_1_5_47_PLAYWRIGHT_CORS_FIX.md
Normal file
17
docs/CLIENTFLOW_V4928_1_5_47_PLAYWRIGHT_CORS_FIX.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# ClientFlow v4928.1.5.47 — Playwright CORS/Auth fix
|
||||
|
||||
## Problema
|
||||
|
||||
O runner Playwright usava `extra_http_headers` para enviar `X-ClientFlow-Admin-Token`.
|
||||
Esse header era enviado também para assets externos, como Bootstrap Icons em `cdn.jsdelivr.net`.
|
||||
O browser fazia preflight CORS e o CDN bloqueava o pedido das fontes.
|
||||
|
||||
## Correção
|
||||
|
||||
O runner passou a adicionar `X-ClientFlow-Admin-Token` apenas a pedidos same-origin do ClientFlow.
|
||||
Pedidos externos para CDN deixam de receber o header administrativo.
|
||||
|
||||
## Nota produção
|
||||
|
||||
Se `https://clientflow.blif.pt` ainda bloquear Bootstrap/HTMX por CSP, a instância pública ainda não tem a CSP da v1.5.46+ ou o Nginx está a sobrescrever o header.
|
||||
A CSP esperada deve permitir explicitamente `https://cdn.jsdelivr.net` e `https://unpkg.com`, ou os assets devem ser servidos localmente.
|
||||
@@ -0,0 +1,20 @@
|
||||
# ClientFlow v4928.1.5.48 — Reply assistant instruction_hidden fix
|
||||
|
||||
Fixes a production-visible task detail error in the reply assistant panel:
|
||||
|
||||
`Assistente indisponível: name 'instruction_hidden' is not defined`
|
||||
|
||||
## Cause
|
||||
|
||||
The legacy/eager reply assistant panel rendered `{instruction_hidden}` in the send form, but the variable was only defined in the newer lazy/persistent draft panel.
|
||||
|
||||
## Fix
|
||||
|
||||
`app/admin_ui/pages/tasks.py` now defines `operator_instruction` and `instruction_hidden` before rendering the legacy reply assistant panel. Missing instructions are safely represented as an empty hidden input.
|
||||
|
||||
## Impact
|
||||
|
||||
- No database migration.
|
||||
- No destructive action.
|
||||
- Affects task detail rendering only.
|
||||
- Restores the editable reply panel for support/reply tasks.
|
||||
102
docs/CLIENTFLOW_V4928_1_5_4_LLM_FIRST_REPLY_ASSISTANT.md
Normal file
102
docs/CLIENTFLOW_V4928_1_5_4_LLM_FIRST_REPLY_ASSISTANT.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# ClientFlow v4928.1.5.4 — LLM-first Reply Assistant
|
||||
|
||||
## Decisão arquitetural
|
||||
|
||||
A abordagem anterior estava a crescer como uma árvore de regras e exceções. Esta versão muda o centro de decisão:
|
||||
|
||||
```text
|
||||
Antes:
|
||||
mensagem → regras/intents → template
|
||||
|
||||
Agora com LLM ativo:
|
||||
mensagem limpa → guardrails objetivos → contexto + conhecimento BLIF → LLM → validação → operador
|
||||
```
|
||||
|
||||
As regras deixam de tentar interpretar todos os casos comerciais. Passam a servir apenas para proteger situações objetivas onde a resposta ao cliente deve ser evitada ou controlada.
|
||||
|
||||
## Fluxo
|
||||
|
||||
```text
|
||||
Task/Oportunidade
|
||||
↓
|
||||
MessageCleaner
|
||||
↓
|
||||
Guardrails objetivos
|
||||
↓
|
||||
BusinessKnowledgeRetriever
|
||||
↓
|
||||
OpenRouter LLM
|
||||
↓
|
||||
ReplySafetyValidator
|
||||
↓
|
||||
Rascunho editável na UI
|
||||
```
|
||||
|
||||
## Guardrails objetivos
|
||||
|
||||
Apenas estes casos preemptam o LLM:
|
||||
|
||||
- `BOUNCE_EMAIL`
|
||||
- `AUTO_REPLY`
|
||||
- `UNSUBSCRIBE_REQUEST`
|
||||
- `ADDRESS_UPDATE`
|
||||
|
||||
Tudo o resto deve ser interpretado pelo LLM quando `CLIENTFLOW_REPLY_LLM_ENABLED=true`.
|
||||
|
||||
## LLM como interpretador
|
||||
|
||||
O LLM recebe:
|
||||
|
||||
- mensagem limpa do cliente;
|
||||
- dados do cliente;
|
||||
- estado/action da tarefa;
|
||||
- documentos selecionados;
|
||||
- conhecimento BLIF recuperado;
|
||||
- catálogo de produtos/acessórios;
|
||||
- instruções de segurança.
|
||||
|
||||
E deve devolver JSON estruturado com:
|
||||
|
||||
```json
|
||||
{
|
||||
"intent": "technical_datasheet_request",
|
||||
"reply_type": "answer_with_links_or_attachment",
|
||||
"requires_attachment": true,
|
||||
"confidence": 0.86,
|
||||
"customer_need": "Cliente pediu fichas técnicas dos carregadores.",
|
||||
"recommended_next_action": "Selecionar/anexar ficha técnica antes de enviar.",
|
||||
"message_body": "Olá...",
|
||||
"knowledge_used": ["technical_features"],
|
||||
"warnings": []
|
||||
}
|
||||
```
|
||||
|
||||
## Fallback
|
||||
|
||||
Se LLM estiver desligado:
|
||||
|
||||
- o sistema usa o gate determinístico existente;
|
||||
- evita fallback agressivo para lista de equipamentos;
|
||||
- prefere revisão manual quando incerto.
|
||||
|
||||
Se LLM estiver ligado mas falhar numa resposta `LLM_BUSINESS_REPLY`:
|
||||
|
||||
- a sugestão fica bloqueada;
|
||||
- a tarefa deve ser revista manualmente;
|
||||
- nenhuma resposta genérica é considerada segura.
|
||||
|
||||
## Uso do assistente ChatGPT existente
|
||||
|
||||
Um GPT personalizado do ChatGPT não é chamado diretamente pelo backend. O caminho correto é migrar o conhecimento/instruções desse GPT para a base interna do Clientflow:
|
||||
|
||||
```text
|
||||
Custom GPT / Assistente de e-mails
|
||||
↓
|
||||
exportar instruções + ficheiros + exemplos aprovados
|
||||
↓
|
||||
app/business_knowledge/
|
||||
↓
|
||||
OpenRouter/API no backend
|
||||
```
|
||||
|
||||
Assim o conhecimento fica versionado, auditável e combinado com oportunidade, documentos e validações reais.
|
||||
31
docs/CLIENTFLOW_V4928_1_5_50_MANUAL_EXTERNAL_CORRECTION.md
Normal file
31
docs/CLIENTFLOW_V4928_1_5_50_MANUAL_EXTERNAL_CORRECTION.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# ClientFlow v4928.1.5.50 — Correção manual de associações Odoo/Jasmin
|
||||
|
||||
## Objetivo
|
||||
|
||||
Quando a reconciliação automática associa uma oportunidade ao Odoo/Jasmin errado, o operador precisa de uma forma segura de desfazer a ligação local sem alterar sistemas externos.
|
||||
|
||||
## Inclui
|
||||
|
||||
- Novo painel na oportunidade: **Corrigir associação operacional**.
|
||||
- Permite desassociar Odoo, Jasmin e remover linhas importadas Odoo/Jasmin.
|
||||
- Permite classificar a oportunidade após a correção, por defeito como **Informação enviada** (`INFO_SENT`).
|
||||
- Adiciona botões diretos:
|
||||
- `Desassociar Odoo` no painel Odoo.
|
||||
- `Desassociar Jasmin` no painel Documentos Jasmin.
|
||||
- `Ignorar` em candidatos externos Odoo/Jasmin.
|
||||
- Regista auditoria em `opportunity_events`.
|
||||
- Não apaga nem altera nada em Odoo, Jasmin ou Chatwoot.
|
||||
|
||||
## Comportamento
|
||||
|
||||
A correção remove apenas leitura local ClientFlow:
|
||||
|
||||
- `operation_links` Odoo/Jasmin da oportunidade.
|
||||
- `commercial_documents` Jasmin ligados à oportunidade.
|
||||
- `opportunity_items` importados de Odoo/Jasmin.
|
||||
- `reconciliation_items` Odoo/Jasmin ligados passam para revisão manual ou ignorados.
|
||||
- A oportunidade fica na fase escolhida pelo operador.
|
||||
|
||||
## Caso que motivou
|
||||
|
||||
Oportunidade associada a venda Odoo `S00285` e candidatos Jasmin de outros clientes, mas o processo real era apenas envio de informação. Antes não existia forma operacional de limpar essas ligações na UI.
|
||||
@@ -0,0 +1,5 @@
|
||||
# ClientFlow v4928.1.5.51 — Task refresh sentinel fix
|
||||
|
||||
Micro-correção para repor a frase sentinela usada por `tests/test_v4928_1_5_13_task_detail_refresh.py`.
|
||||
|
||||
Não altera lógica de runtime. Mantém o comportamento de refrescar o painel completo da tarefa após envio de resposta, evitando cabeçalhos obsoletos como `Pendente/SEND_QUOTE`.
|
||||
@@ -0,0 +1,40 @@
|
||||
# ClientFlow v4928.1.5.53 — Opportunity Operation/Context Layout
|
||||
|
||||
## Objetivo
|
||||
|
||||
Reorganizar a página de detalhe da oportunidade sem alterar a lógica de negócio:
|
||||
|
||||
- manter a leitura em 2 colunas;
|
||||
- colocar decisão, tarefa, follow-up, alteração de fase e correção operacional na coluna esquerda;
|
||||
- colocar cliente, documentos, produtos, Odoo, comunicação, timeline e técnico na coluna direita;
|
||||
- reduzir a sensação de funcionalidades espalhadas;
|
||||
- manter todas as ações existentes.
|
||||
|
||||
## Alterações
|
||||
|
||||
- Cabeçalho compacto no topo com próxima ação, cliente fiscal, documento principal, valor e tasks.
|
||||
- Coluna esquerda `Operação`, sticky em desktop, com:
|
||||
- O que fazer agora;
|
||||
- Mapa operacional;
|
||||
- bloqueios;
|
||||
- tarefa ativa;
|
||||
- criar follow-up;
|
||||
- alterar fase;
|
||||
- corrigir associação operacional.
|
||||
- Coluna direita `Contexto e evidência`, com:
|
||||
- cliente fiscal/contacto;
|
||||
- prontidão para documentos/envio;
|
||||
- resumo essencial;
|
||||
- pipeline/fluxo;
|
||||
- documentos Jasmin;
|
||||
- produtos;
|
||||
- Odoo/envio;
|
||||
- integrações/outbox;
|
||||
- tasks relacionadas;
|
||||
- mensagens;
|
||||
- timeline;
|
||||
- técnico.
|
||||
|
||||
## Compatibilidade
|
||||
|
||||
Não há migração, alteração de modelos, endpoints ou integrações externas. A alteração é apenas HTML/CSS dentro da página da oportunidade.
|
||||
20
docs/CLIENTFLOW_V4928_1_5_54_OPPORTUNITY_CONTEXT_LEFT.md
Normal file
20
docs/CLIENTFLOW_V4928_1_5_54_OPPORTUNITY_CONTEXT_LEFT.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# ClientFlow v4928.1.5.54 — Opportunity context-left layout
|
||||
|
||||
## Objetivo
|
||||
|
||||
Reorganiza visualmente a página de detalhe da oportunidade mantendo as mesmas funcionalidades da v1.5.53.
|
||||
|
||||
## Alteração
|
||||
|
||||
- Cabeçalho full-width da oportunidade mantém-se.
|
||||
- Em desktop, a coluna principal passa a ser **Contexto e evidência** à esquerda.
|
||||
- A coluna **Operação** passa para a direita como painel lateral sticky.
|
||||
- A ordem do DOM mantém Operação primeiro para que em ecrãs menores a ação continue a aparecer antes do contexto.
|
||||
- Sem alterações de endpoints, base de dados, reconciliação, Odoo, Jasmin ou Chatwoot.
|
||||
|
||||
## Validação
|
||||
|
||||
```text
|
||||
PYTHONPATH=. pytest -q tests
|
||||
316 passed
|
||||
```
|
||||
34
docs/CLIENTFLOW_V4928_1_5_5_AUDIT_LLM_AUTH_HOTFIX.md
Normal file
34
docs/CLIENTFLOW_V4928_1_5_5_AUDIT_LLM_AUTH_HOTFIX.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# ClientFlow v4928.1.5.5 — Audit LLM Auth Hotfix
|
||||
|
||||
Esta versão corrige o comportamento do script de auditoria quando executado com `--use-llm`.
|
||||
|
||||
## Problema observado
|
||||
|
||||
A chamada direta ao OpenRouter funcionava, mas a auditoria devolvia por tarefa:
|
||||
|
||||
```text
|
||||
LLM: fallback
|
||||
OpenRouter HTTP 401: Missing Authentication header
|
||||
```
|
||||
|
||||
## Causa
|
||||
|
||||
O script definia uma chave placeholder para `OPENROUTER_API_KEY` antes de importar `app.config`. Em `pydantic-settings`, variáveis de ambiente têm precedência sobre `.env`, por isso a placeholder podia ocultar a chave real do `.env`.
|
||||
|
||||
## Correção
|
||||
|
||||
- Com `--use-llm`, o script deixa o `.env` fornecer a chave real.
|
||||
- A placeholder só é usada quando `--use-llm` não está ativo.
|
||||
- Uma placeholder antiga no ambiente do processo é removida antes de carregar a configuração.
|
||||
|
||||
## Comando de validação
|
||||
|
||||
```bash
|
||||
python scripts/audit_task_reply_suggestions.py \
|
||||
--status pending \
|
||||
--route vendas \
|
||||
--use-llm \
|
||||
--limit 5 \
|
||||
--format json \
|
||||
--out /tmp/task_reply_audit_llm_vendas.json
|
||||
```
|
||||
125
docs/CLIENTFLOW_V4928_1_5_6_EMAIL_REPLY_AGENT_PHASE1.md
Normal file
125
docs/CLIENTFLOW_V4928_1_5_6_EMAIL_REPLY_AGENT_PHASE1.md
Normal file
@@ -0,0 +1,125 @@
|
||||
# ClientFlow v4928.1.5.6 — Fase 1: integração segura do agente de email
|
||||
|
||||
Esta versão integra o agente de respostas testado com conhecimento BLIF no fluxo seguro do ClientFlow.
|
||||
|
||||
## Objetivo
|
||||
|
||||
Gerar rascunhos editáveis para respostas a emails/mensagens de clientes, usando OpenAI Responses API + `file_search` sobre uma vector store de conhecimento BLIF.
|
||||
|
||||
A integração **não envia respostas automaticamente**. O operador continua a rever e enviar pelo painel da tarefa.
|
||||
|
||||
## Novos ficheiros / alterações principais
|
||||
|
||||
- `app/email_reply_agent_service.py`
|
||||
- Novo serviço de agente de email.
|
||||
- Chama OpenAI Responses API com `file_search`.
|
||||
- Devolve JSON estruturado: intenção, prioridade, resposta sugerida, revisão humana, confiança e informação usada.
|
||||
|
||||
- `app/reply_assistant_service.py`
|
||||
- Integra o agente como prioridade quando `CLIENTFLOW_EMAIL_REPLY_AGENT_ENABLED=true`.
|
||||
- Guarda metadata do agente em `message_drafts.metadata.email_agent`.
|
||||
- Mantém fallback para fluxo existente se o agente estiver desligado ou indisponível.
|
||||
|
||||
- `app/admin_ui/pages/tasks.py`
|
||||
- Mostra estado do agente no painel de resposta da tarefa.
|
||||
- Badge atualizado para `v4928.1.5.6`.
|
||||
|
||||
- `app/api/internal.py`
|
||||
- Novo endpoint interno:
|
||||
- `POST /api/internal/tasks/{task_id}/reply-draft`
|
||||
- Cria rascunho persistente e devolve JSON.
|
||||
- Protegido pelo mesmo `X-ClientFlow-Admin-Token` quando configurado.
|
||||
|
||||
- `.env.example`
|
||||
- Novas variáveis OpenAI/agent.
|
||||
|
||||
## Variáveis de ambiente
|
||||
|
||||
```env
|
||||
CLIENTFLOW_EMAIL_REPLY_AGENT_ENABLED=false
|
||||
OPENAI_API_KEY=
|
||||
OPENAI_RESPONSES_URL=https://api.openai.com/v1/responses
|
||||
OPENAI_VECTOR_STORE_ID=
|
||||
CLIENTFLOW_EMAIL_REPLY_AGENT_MODEL=gpt-4.1-mini
|
||||
CLIENTFLOW_EMAIL_REPLY_AGENT_TIMEOUT_SECONDS=30
|
||||
CLIENTFLOW_EMAIL_REPLY_AGENT_MAX_RESULTS=6
|
||||
CLIENTFLOW_EMAIL_REPLY_AGENT_PROMPT_VERSION=blif-email-agent-phase1-20260613
|
||||
```
|
||||
|
||||
Para ativar em staging/produção:
|
||||
|
||||
```env
|
||||
CLIENTFLOW_EMAIL_REPLY_AGENT_ENABLED=true
|
||||
OPENAI_API_KEY=sk-proj-...
|
||||
OPENAI_VECTOR_STORE_ID=vs_...
|
||||
```
|
||||
|
||||
## Fluxo seguro
|
||||
|
||||
```text
|
||||
Task ClientFlow
|
||||
↓
|
||||
Gerar rascunho
|
||||
↓
|
||||
Agente OpenAI/file_search consulta conhecimento BLIF
|
||||
↓
|
||||
Resposta JSON estruturada
|
||||
↓
|
||||
ClientFlow valida segurança
|
||||
↓
|
||||
Guarda em message_drafts
|
||||
↓
|
||||
Operador revê e envia manualmente
|
||||
```
|
||||
|
||||
## Fallback
|
||||
|
||||
Se o agente estiver desligado, mal configurado ou indisponível, o ClientFlow mantém o fluxo anterior:
|
||||
|
||||
```text
|
||||
business_knowledge_service + templates + OpenRouter opcional
|
||||
```
|
||||
|
||||
Isto evita bloqueio da operação.
|
||||
|
||||
## API interna
|
||||
|
||||
Exemplo:
|
||||
|
||||
```bash
|
||||
curl -X POST "https://clientflow.blif.pt/api/internal/tasks/<TASK_ID>/reply-draft" \
|
||||
-H "X-ClientFlow-Admin-Token: <TOKEN>" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"selected_document_ids": []}'
|
||||
```
|
||||
|
||||
Resposta resumida:
|
||||
|
||||
```json
|
||||
{
|
||||
"draft_id": "...",
|
||||
"task_id": "...",
|
||||
"template_code": "LLM_BUSINESS_REPLY",
|
||||
"message_body": "...",
|
||||
"blockers": [],
|
||||
"warnings": [],
|
||||
"email_agent": {
|
||||
"used": true,
|
||||
"intencao": "pedido_preco",
|
||||
"precisa_revisao_humana": false,
|
||||
"nivel_confianca": "alto"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Guardrails principais
|
||||
|
||||
- Não enviar automaticamente.
|
||||
- Não substituir bounces, respostas automáticas ou revisão manual por resposta comercial.
|
||||
- Se o agente marcar revisão humana, mostrar aviso no painel.
|
||||
- Se confiança baixa, bloquear envio até revisão/correção manual.
|
||||
- Continuar a validar instalação, IVA, preços e promessas comerciais em `reply_safety_validator.py`.
|
||||
|
||||
## Nota sobre conhecimento
|
||||
|
||||
Esta integração usa a vector store indicada em `OPENAI_VECTOR_STORE_ID`. Para obter respostas com a versão mais recente do conhecimento BLIF, atualize a vector store no ambiente OpenAI e altere o ID no `.env`.
|
||||
43
docs/CLIENTFLOW_V4928_1_5_7_EMAIL_REPLY_AGENT_READABILITY.md
Normal file
43
docs/CLIENTFLOW_V4928_1_5_7_EMAIL_REPLY_AGENT_READABILITY.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# ClientFlow v4928.1.5.7 — Readable commercial replies
|
||||
|
||||
Esta versão melhora o formato das respostas do agente de email da Blif.
|
||||
|
||||
## Exemplo de formato pretendido
|
||||
|
||||
```text
|
||||
Bom dia Sr. Pedro Simões,
|
||||
|
||||
Obrigado pelo seu contacto e pela referência do Sr. Rui Santos.
|
||||
|
||||
Segue proposta para o equipamento solicitado (valor s/IVA):
|
||||
|
||||
– Carregador trifásico 11 kW com cabo Tipo 2 de 5 metros – 178 €
|
||||
|
||||
Funcionalidades incluídas:
|
||||
– Potência ajustável entre 6A e 32A
|
||||
– Gestão via aplicação móvel
|
||||
– Monitorização e agendamento de carregamentos
|
||||
– Garantia de 24 meses
|
||||
|
||||
Prazo de entrega:
|
||||
– 2 a 3 dias úteis após pagamento
|
||||
|
||||
Caso pretenda, posso também enviar ficha técnica e proposta formal.
|
||||
|
||||
Com os melhores cumprimentos,
|
||||
Sérgio Araújo
|
||||
Blif
|
||||
```
|
||||
|
||||
## Regras adicionadas ao prompt
|
||||
|
||||
- Parágrafos curtos.
|
||||
- Listas com travessão para preços, funcionalidades, prazos e próximos passos.
|
||||
- Estrutura de proposta comercial em pedidos de preço/proposta.
|
||||
- Assinatura comercial com `Com os melhores cumprimentos, Sérgio Araújo, Blif`.
|
||||
- Personalização só quando o nome/referência existe no email ou no CRM.
|
||||
- Proibição explícita de inventar nomes, referências, produtos ou contactos.
|
||||
|
||||
## Nota operacional
|
||||
|
||||
A versão mantém a integração em Fase 1: o operador vê e edita o rascunho antes de enviar.
|
||||
9
docs/CLIENTFLOW_V4928_1_5_8_REPLY_ASSISTANT_UI.md
Normal file
9
docs/CLIENTFLOW_V4928_1_5_8_REPLY_ASSISTANT_UI.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# v4928.1.5.8 — Reply Assistant UI
|
||||
|
||||
Esta versão evita que o operador veja duas respostas concorrentes na tarefa:
|
||||
|
||||
- O card antigo **Mensagem sugerida** deixa de aparecer no detalhe moderno.
|
||||
- A resposta principal passa a ser a **Mensagem editável** no painel **Resposta ao cliente**.
|
||||
- O botão **Copiar mensagem** copia a mensagem editável quando existir.
|
||||
|
||||
Também foi afinado o prompt de fallback OpenRouter para propostas comerciais mais legíveis, com preço, funcionalidades, prazo e assinatura BLIF quando aplicável.
|
||||
15
docs/CLIENTFLOW_V4928_1_5_9_REPLY_ASSISTANT_FORMAL_UI.md
Normal file
15
docs/CLIENTFLOW_V4928_1_5_9_REPLY_ASSISTANT_FORMAL_UI.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# v4928.1.5.9 — Reply Assistant formal greeting + UI cleanup
|
||||
|
||||
Esta versão ajusta o detalhe de tarefas para ficar mais claro na utilização diária:
|
||||
|
||||
1. A resposta gerada passa a preferir cumprimentos formais quando existe nome completo do contacto.
|
||||
2. Campos técnicos vazios deixam de ser renderizados.
|
||||
3. Reclassificação e ignorar tarefa passam para baixo do cartão `Concluir`, na coluna direita.
|
||||
|
||||
Exemplo de cumprimento preferido:
|
||||
|
||||
```text
|
||||
Boa tarde Sra. Bárbara Gonçalves,
|
||||
```
|
||||
|
||||
Se o contacto não tiver nome completo ou o género não for reconhecido, o sistema usa uma saudação segura sem título.
|
||||
Reference in New Issue
Block a user