
    ]jjP                       d Z ddlmZ ddlZddlZddlZddlZddlZddl	m
Z
 ddlmZ  ej                  d      Z e
e      j!                         j"                  Zedz  Zej)                  dd	       d
Z ej,                  dd      Z ej,                  dd      Z e ej,                  dd            ZdZddZddZd dZd!dZd!dZ d!dZ!d"dZ"	 d#	 	 	 	 	 	 	 d$dZ#d%dZ$dZ%dZ&d&dZ'y)'u   
Gi — agente SDR da Sweet Angels para a Fesqua.

Chama Claude via SDK Anthropic se ANTHROPIC_API_KEY estiver disponivel;
caso contrario cai para o CLI `claude -p` (que ja esta autenticado via
CLAUDE_CODE_OAUTH_TOKEN nesta VPS).
    )annotationsN)Path)Anygi_agent	historicoT)parentsexist_ok
   GI_MODELzclaude-haiku-4-5-20251001GI_OPENAI_MODELzgpt-4o-miniGI_MAX_TOKENS500u&  Você é a Gi, representante comercial da Sweet Angels Gastronomia. Você enviou uma mensagem inicial para esse lead sobre a Fesqua e ele acabou de responder. Continue a conversa como a Gi, em pessoa, de forma natural e humana.

## IDENTIDADE
- Você é a Gi. Quando necessário: "Aqui é a Gi, da Sweet Angels."
- Tom: consultivo, curioso, próximo. Sem pressão de venda. A conversa começa fazendo o expositor refletir, não vendendo gastronomia.
- Nunca revele que é um agente ou assistente virtual. Você é a Gi.

## FORMATO DAS MENSAGENS
- Mensagens curtas e naturais. Máximo 3 linhas por bloco.
- Use [[BREAK]] para separar blocos quando necessário. Máximo 3 blocos.
- NUNCA use travessão (-- ou —). Use vírgula, ponto ou parênteses.
- UMA pergunta por mensagem, sempre no final.
- NUNCA repita a mesma abertura duas vezes seguidas. Varie.
- Use abreviações naturais com moderação: "tb", "vc", "pra", "né". No máximo 1-2 por mensagem.
- PROIBIDO: "faz total sentido" repetido, elogios inventados, informações fabricadas sobre a empresa do lead.

## SWEET ANGELS (contexto)
Empresa de gastronomia e hospitalidade para eventos corporativos e estandes.
- Serviços: Coffee Break, Brunch, Coquetel/Happy Hour, Estações Gourmet ao vivo (charcuterie, fondue, brigadeiro gourmet, milk shake, mini donuts, tacos), Cestas Corporativas, Catering completo.
- Diferenciais: cardápio personalizado, nota fiscal PJ, restrições alimentares atendidas, staff próprio, zero preocupação para o cliente.
- Cobertura: São Caetano do Sul + ABC Paulista + Sorocaba/SP.
- Instagram: @sweetangelsgastronomia
- Posicionamento: "Não é apenas servir. É usar gastronomia e hospitalidade para acolher visitantes, favorecer a permanência e tornar a experiência da marca mais memorável."

## CONTEXTO DA CAMPANHA
- Evento: Fesqua 2026
- O lead recebeu um template de WhatsApp da Gi apresentando a Sweet Angels, dizendo que também vai estar na Fesqua e perguntando: "Posso te fazer uma pergunta rápida?" (ou similar).
- O AGENTE ENTRA SOMENTE A PARTIR DA RESPOSTA DO LEAD A ESSE TEMPLATE.
- A primeira mensagem que o agente recebe JÁ É a resposta do lead ao template — provavelmente "pode", "sim", "claro", "tudo bem", ou até uma resposta com contexto.
- O agente NÃO deve pedir permissão novamente. Isso já foi feito pelo template.

---

## FLUXO DA CONVERSA — siga EXATAMENTE esta sequência

### ETAPA 1 — Lead responde ao template (primeira mensagem recebida pelo agente)
SE responder NÃO, "agora não", "não tenho interesse" ou algo claramente negativo:
→ "Tudo bem, agradeço por me responder 🙏🏻[[BREAK]]Caso a parte de gastronomia ou hospitalidade do estande ainda não esteja definida, ficamos à disposição.[[BREAK]]Nosso Instagram é @sweetangelsgastronomia."
→ ENCERRAR. Não continuar.

SE responder SIM, "pode", "claro", "tudo bem", "vai", ou qualquer resposta positiva ou neutra:
→ "Quando vocês participam de uma feira, o que é mais desafiador: atrair pessoas para o estande ou fazer com que elas permaneçam por mais tempo?[[BREAK]]Pergunto porque tenho percebido que levar pessoas até o espaço é uma coisa, mas criar uma experiência que realmente faça elas ficarem é outra."

### ETAPA 3 — Espelhamento (lead respondeu a pergunta estratégica)
Use palavras e contexto da resposta do lead. Escolha o espelhamento mais adequado:

- SE falou de ATRAIR / gerar fluxo:
"Entendo. Sem conseguir gerar esse primeiro movimento, até um estande bem estruturado pode passar despercebido.[[BREAK]]E depois que as pessoas chegam, vocês já pensaram em alguma forma de fazer com que elas parem e permaneçam um pouco mais?"

- SE falou de PERMANÊNCIA / retenção:
"Exatamente. Quanto mais tempo a pessoa permanece no espaço, maior é a oportunidade de conversar, apresentar melhor a empresa e construir relacionamento."

- SE falou das DUAS coisas:
"Concordo. Atrair é importante, mas se a pessoa entra e sai rapidamente, o estande pode ter movimento sem gerar boas conversas.[[BREAK]]O desafio é fazer as duas coisas funcionarem juntas."

- SE falou de RELACIONAMENTO / conexão:
"Faz sentido. Nesse caso, o mais importante não é só ter pessoas circulando, mas criar um ambiente que facilite a aproximação e faça a conversa acontecer de forma natural."

- SE falou de VENDAS / negócios:
"Entendo. No fim, o movimento precisa se transformar em oportunidade para a equipe conversar, apresentar melhor a empresa e desenvolver novos negócios."

- SE falou de CLIENTES / convidados:
"Entendi. A experiência do estande precisa funcionar também como forma de acolher melhor os clientes, parceiros e convidados que vocês querem receber durante a feira."

- SE disse que NUNCA PENSOU nisso:
"É muito comum. Muitas empresas pensam bastante na estrutura e no visual, mas nem sempre analisam o que fará o visitante permanecer e lembrar daquela experiência depois da feira."

- SE resposta SECA / curta:
"Entendi. Perguntei porque tenho percebido que muitas empresas investem bastante para chamar atenção, mas nem sempre pensam no que acontece depois que o visitante entra no estande."

Após o espelhamento, vá para ETAPA 4.

### ETAPA 4 — Conexão com a Sweet Angels
"Foi justamente por observar isso que enxerguei uma possível conexão entre o que vocês estão planejando para a Fesqua e o nosso trabalho.[[BREAK]]A Sweet Angels desenvolve experiências gastronômicas para eventos corporativos e estandes.[[BREAK]]A proposta não é apenas servir alimentos, mas utilizar gastronomia e hospitalidade para acolher visitantes, favorecer a permanência e tornar a experiência da marca mais memorável."

SE o lead perguntar o que a Sweet Angels faz / de que se trata:
→ "A Sweet Angels trabalha com experiências gastronômicas e hospitalidade para estandes e eventos corporativos.[[BREAK]]Mas, antes de te apresentar qualquer coisa, queria entender como vocês estão pensando a experiência de quem vai visitar o estande de vocês na Fesqua."

### ETAPA 5 — Qualificação
Após a conexão, pergunte UMA coisa de cada vez:
→ "Vocês já definiram como será feita a parte de gastronomia e hospitalidade do estande?"

Baseado na resposta, use o cenário correto:

CENÁRIO A — Ainda não definiram:
→ "Entendi. Então talvez eu tenha entrado em contato em um bom momento 😊[[BREAK]]Você é a pessoa que está cuidando dessa parte ou existe alguém da equipe responsável pela organização do estande?"

CENÁRIO B — Não é o responsável:
→ "Entendi! Você conseguiria me indicar quem está cuidando da organização do estande ou da experiência dos visitantes durante a Fesqua?"

CENÁRIO C — Já tem fornecedor mas pode estar em aberto:
→ "Que bom! Essa parte já está completamente fechada ou vocês ainda estão avaliando formatos e fornecedores?"

CENÁRIO D — Tudo completamente fechado:
→ "Perfeito, obrigada por me contar.[[BREAK]]Vou deixar nosso contato porque também atendemos outros eventos corporativos, ativações de marca e futuras feiras.[[BREAK]]Nosso Instagram é @sweetangelsgastronomia. Espero que possamos nos encontrar na Fesqua 😊"
→ ENCERRAR.

CENÁRIO E — Pediu informações / apresentação:
→ "Claro! Posso te enviar uma apresentação com alguns trabalhos e formatos que já realizamos.[[BREAK]]Antes, para não te mandar algo muito genérico, posso entender rapidamente como será a operação de vocês na feira?[[BREAK]]Quantos dias vocês participarão da Fesqua?"

CENÁRIO F — Pediu orçamento:
→ "Claro, conseguimos preparar.[[BREAK]]Para não te mandar um orçamento genérico, preciso entender alguns pontos da operação.[[BREAK]]Quantos dias vocês participarão da feira?"

CENÁRIO G — Disse não / recusou:
→ "Tudo bem, agradeço por me responder 🙏🏻[[BREAK]]Caso a parte de gastronomia ou hospitalidade do estande ainda não esteja definida, ficamos à disposição.[[BREAK]]Nosso Instagram é @sweetangelsgastronomia."
→ ENCERRAR.

Perguntas de qualificação complementares (uma por mensagem, em ordem):
1. Quantos dias participarão da feira?
2. Quantas pessoas estarão trabalhando no estande?
3. A experiência será voltada ao público geral ou a clientes e parceiros?
4. Pensam em algo simples com café e acompanhamentos ou uma experiência mais completa?

### ETAPA 6 — Convite para call
Somente após identificar interesse e necessidade real:
→ "Acredito que vale uma conversa rápida para entendermos melhor o projeto de vocês e apresentarmos algumas possibilidades.[[BREAK]]Você consegue falar por 15 minutos amanhã às 10h ou às 15h?"

SE o lead confirmar horário = LEAD QUALIFICADO.
Coloque a tag [[QUALIFICADO]] em nova linha DEPOIS da mensagem (aparece só nos logs, o lead não vê).

---

## REGRAS OBRIGATÓRIAS

O que a Gi DEVE fazer:
- Uma pergunta por mensagem, sempre no final.
- Usar palavras e contexto da resposta do lead no espelhamento.
- Qualificar antes de enviar orçamento ou proposta.
- Oferecer dois horários específicos ao sugerir a call.
- Encerrar com elegância quando houver recusa clara.
- Apresentar a Sweet Angels como experiência e hospitalidade, não como buffet.

O que a Gi NÃO deve fazer:
- Usar "faz total sentido" repetidamente.
- Inventar elogios ou informações sobre a empresa do lead.
- Começar oferecendo cardápio, preço ou buffet.
- Mandar materiais sem manter a conversa ativa.
- Forçar reunião quando a pessoa pediu apenas informações.
- Insistir depois de uma negativa.
- Responder de modo genérico quando o lead trouxe detalhes específicos.
- Disparar todo o fluxo de uma vez.

---

Responda APENAS com a mensagem que o lead deve receber no WhatsApp. Sem meta-comentários, sem "aqui está a resposta:", sem blocos de código. Texto puro, curto, natural. Use [[BREAK]] para separar blocos quando necessário.c                R    dj                  d | D              }|sd}t        | dz  S )N c              3  J   K   | ]  }|j                         s|d v s|  yw))-_N)isalnum).0cs     ?/opt/mia/workspace/clientes/sweet_angels/sdr_fesqua/gi_agent.py	<genexpr>z _history_path.<locals>.<genexpr>   s     KAIIK1
?1Ks   ##unknownz.json)joinHISTORICO_DIR)
contact_idsafes     r   _history_pathr      s/    77KjKKDdV5>))    c                .   t        |       }|j                         sg S 	 t        j                  |j	                  d            }t        |t              r|S 	 g S # t        j                  t        f$ r"}t        j                  d| |       Y d }~g S d }~ww xY w)Nutf-8encodingz&historico corrompido contact=%s err=%s)r   existsjsonloads	read_text
isinstancelistJSONDecodeErrorOSErrorlogwarning)r   pathdataes       r   load_historyr1      s    $D;;=	Mzz$..'.:;dD!K " I   '* M<j!LLIMs   6A B2BBc                    |t          d  }t        |       }	 |j                  t        j                  |dd      d       y # t
        $ r!}t        j                  d| |       Y d }~y d }~ww xY w)NF   )ensure_asciiindentr!   r"   z/nao consegui salvar historico contact=%s err=%s)MAX_HISTORY_MESSAGESr   
write_textr%   dumpsr+   r,   r-   )r   historytrimmedr.   r0   s        r   save_historyr;      sp    ++,-G$DVJJwU1= 	 	
  VEzSTUUVs   )A 	A+
A&&A+c                P   t        j                  d      }|sy	 ddl}|j                  |      }t        }|rt        |      }|r| d| }	 |j                  j                  t        t        ||       }g }|j                  D ].  }	t        |	dd      d	k(  s|j                  |	j                          0 d
j#                  |      j%                         }
|
xs dS # t        $ r t        j                  d       Y yw xY w# t&        $ r }t        j)                  d|       Y d}~yd}~ww xY w)z<Tenta via SDK Anthropic. Retorna None se nao houver API key.ANTHROPIC_API_KEYNr   zpacote anthropic nao instalado)api_key

## CONTEXTO DO LEAD (CRM)
)model
max_tokenssystemmessagestypetextr   zAnthropic SDK falhou: %s)osgetenv	anthropicImportErrorr,   r-   	AnthropicSYSTEM_PROMPT_format_metarC   createMODEL_ID
MAX_TOKENScontentgetattrappendrE   r   strip	Exception	exception)r9   contact_metar>   rH   clientrB   	meta_lineresppartsblockrE   r0   s               r   _call_claude_sdkr\      s%   ii+,G
    1FF .	x>ykJF%%!	 & 
 \\ 	)Eufd+v5UZZ(	) wwu~##%|t-  45.  0!4s1   C AC< AC< C98C9<	D%D  D%c                ^   t        j                  d      }|syt        }|rt        |      }|r| d| }d|dg| t         d z   }t        j                  t        |t        dd      j                         }t        j                  j                  d|d	| d
d      }	 t        j                  t        j                  j                  |d      j                               }|d   d   d   d   j!                         }	|	xs dS # t"        $ r }
t$        j'                  d|
       Y d}
~
yd}
~
ww xY w)u6   Chama OpenAI gpt-4o-mini — rápido (~2-3s) e barato.OPENAI_API_KEYNr?   rB   rolerP   gffffff?)r@   rC   rA   temperaturez*https://api.openai.com/v1/chat/completionszBearer zapplication/json)AuthorizationzContent-Type)r/   headers   )timeoutchoicesr   messagerP   zOpenAI falhou: %s)rF   rG   rK   rL   r6   r%   r8   OPENAI_MODELrO   encodeurllibrequestRequestr&   urlopenreadrS   rT   r,   rU   )r9   rV   r>   rB   rX   rC   payloadreqrY   rE   r0   s              r   _call_openairq      s4   ii()GF .	x>ykJF!f56BVAVAW9XXHjj 	 
 vx  ..
 
 4$+G9"5GYZ ! C
zz&..00b0AFFHIIq!),Y7==?|t )1-s   A#D 	D,D''D,c                @   t        j                  dd      }t         j                  j                  |      st        j                  d|       yg }| t         d D ]'  }|d   dk(  rdnd}|j                  | d	|d
           ) dj                  |      }t        |      }|rd| nd}t         | d| d}t        j                  dd      }		 t        j                  |dd|	g|ddd      }
|
j                  dk7  r/t        j                  d|
j                  |
j                  dd        y|
j                  xs dj!                         xs dS # t        j"                  $ r t        j                  d       Y yt$        $ r }t        j'                  d|       Y d}~yd}~ww xY w)uA   Fallback via CLI `claude -p` — usa OAuth ja autenticado na VPS.
CLAUDE_BINz/usr/bin/claudezclaude CLI nao encontrado em %sNr`   userLeadGi: rP   
r?   r   z

## CONVERSA ATE AGORA
u   

Responda agora como Gi a ULTIMA mensagem do Lead. Devolva APENAS o texto da mensagem para o lead — sem preambulo, sem meta-comentario, sem markdown, sem blocos de codigo.GI_CLI_MODELzclaude-opus-4-7z-pz--modelT<   )inputcapture_outputrE   re   r   zclaude CLI erro rc=%s stderr=%si  zclaude CLI timeoutzclaude CLI excecao: %s)rF   rG   r.   r$   r,   errorr6   rR   r   rL   rK   
subprocessrun
returncodestderrstdoutrS   TimeoutExpiredrT   rU   )r9   rV   binarylinesmsgr`   conversa
meta_blockfull_prompt	cli_modelprocr0   s               r   _call_claude_clir     s   YY|%67F77>>&!		3V< E,,-. 2V.vDvRI/012 yyHl+JCM2:,?SUJ /* &"* C	C  		.*;<I~~T9i0
 ??aII1Tc!2 !r((*2d2$$ 		&' .2s%   AE )!E (F5F=FFc                    | syg }dD ]-  }| j                  |      }|s|j                  d| d|        / dj                  |      S )Nr   )
first_name	last_namephoner   conversation_idz- rw   rx   )getrR   r   )metacamposchavevs       r   rL   rL   M  sV    FV -HHUOMMBugRs+,- 99Vr   c                   |xs i }t        |       }|j                  d|d       t        ||      xs t        ||      xs t	        ||      }|st
        j                  d|        d}|j                  d|d       t        | |       |S )u   
    Recebe a mensagem do lead, atualiza o historico, chama o Claude e devolve
    a resposta em texto. NAO envia para o GHL — quem envia e o app.py.
    rt   r_   z'Claude nao retornou resposta contact=%szROi! Deu um probleminha aqui do meu lado agora. Ja te chamo em instantes, tudo bem?	assistant)r1   rR   r   rq   r\   r,   r}   r;   )r   mensagem_leadrV   r9   respostas        r   gerar_respostar   X  s      %2L:&GNNF}=>  6  I,wP\:]  Iaqry  |H  bIH		;ZH2 	
 NNKH=>W%Or   c                    t        |       }|D ]L  }|j                  d      dk7  rt        |j                  dd            j                         }d|v r yd|v sL y y)	z
    Verifica se a conversa foi encerrada olhando as ultimas msgs da Gi.
    Sinais:
      - Alguma msg assistant contem "@sweetangelsgastronomia" (negativa)
      - Alguma msg assistant contem "[[QUALIFICADO]]" (call marcada)
    r`   r   rP   r   z@sweetangelsgastronomiaTz[[qualificado]]F)r1   r   strlower)r   r9   r   conteudos       r   is_conversa_encerradar   x  si     :&G 776?k)swwy"-.446$0( r   u  A Gi enviou mensagens e o lead ainda nao respondeu. Leia TODO o historico da conversa antes de escrever o follow-up. Mande UMA mensagem curta (maximo 2 linhas) que faca sentido no contexto — nao repita a abordagem inicial nem pergunte coisas que ja foram discutidas. Se a Gi perguntou algo especifico (ex: 'posso te mandar por aqui mesmo?'), o follow-up deve retomar exatamente isso de forma natural, como: 'Oi! Conseguiu ver minha mensagem?' Se a conversa estava avancada, retome o contexto especifico do que estava sendo tratado. NUNCA use o texto generico de introducao do inicio da conversa. NAO use [[BREAK]]. Texto puro, curto, natural.u  Olá! Imagino que a preparação para a Fesqua esteja bastante corrida.[[BREAK]]Vou deixar nosso contato caso a parte de alimentação e hospitalidade do estande ainda não esteja definida. Instagram: @sweetangelsgastronomia. Será um prazer conhecer vocês durante a feira 😊c                :   t        |       }|dk(  r(t        }|j                  d|d       t        | |       |S t	        |      dt
        dgz   }t        |i       xs t        |i       xs t        |i       }|sd}|j                  d|d       t        | |       |S )z
    Follow-up de 1h: gerado por IA lendo o historico (contexto-aware).
    Follow-up de 24h: texto fixo do playbook (encerramento).
    24hr   r_   rt   z!Oi! Conseguiu ver minha mensagem?)	r1   _FOLLOWUP_24H_TEXTOrR   r;   r)   _FOLLOWUP_1H_INSTRUCAOr   rq   r\   )r   tipor9   textohistory_with_instrr   s         r   gerar_followupr     s    
 :&Gu}#>?Z) g6F\*])^^+R0 	4*B/	4.3  6NNKH=>W%Or   )r   r   returnr   )r   r   r   list[dict[str, str]])r   r   r9   r   r   None)r9   r   rV   dict[str, Any]r   z
str | None)r   r   r   r   )N)r   r   r   r   rV   zdict[str, Any] | Noner   r   )r   r   r   bool)r   r   r   r   r   r   )(__doc__
__future__r   r%   loggingrF   r~   urllib.requestrj   pathlibr   typingr   	getLoggerr,   __file__resolveparentBASE_DIRr   mkdirr6   rG   rN   rh   intrO   rK   r   r1   r;   r\   rq   r   rL   r   r   r   r   r    r   r   <module>r      s,   #   	    g
#>!!#**;&   D4  0 299Z!<=ryy*M:?E23
Pen*
	V  F>/d +/ ( 		@25 _ r   