import os import re import httpx import asyncio import json from tools import AVAILABLE_TOOLS from llm_providers import call_llm, get_available_models, get_planner_llm from config import get_config async def get_llm_response_async(prompt: str, provider: str, cfg: dict) -> str: """Invoca o provedor de LLM centralizado em llm_providers.""" # Garante o modelo gemini-2.5-flash como padrão para o agente Legado model = cfg.get("model") or "gemini-2.5-flash" if provider == "ollama": model = os.getenv("OLLAMA_MODEL", "llama3.2:1b") return await call_llm(provider, model, prompt) def query_agent(prompt: str, override_provider=None, chat_history=None) -> str: """Wrapper síncrono para query_agent_async.""" return asyncio.run(query_agent_async(prompt, override_provider, chat_history)) async def query_agent_async(prompt: str, override_provider=None, chat_history=None) -> str: cfg = get_config() provider = override_provider or cfg.get("active_provider", "gemini") tools_desc = "\n".join([f"- {k}: {v['description']}" for k, v in AVAILABLE_TOOLS.items()]) system_prompt = f"""Você é o Antigravity, um assistente de IA de alto desempenho operando na VPS do Marcos. Sua natureza é dual: 1. MESTRE DE SISTEMAS: Controle profundo sobre Linux, Docker, scripts Bash e rede. Seja preciso, seguro e eficiente em tarefas técnicas. 2. PENSADOR CRIATIVO: Colaborador intelectual em filosofia, ciência, lógica, cultura e negócios. DIRETRIZES: - Você é o MESTRE do Google Workspace (GWS). Use `run_bash_command` para QUALQUER tarefa de automação. - NUNCA diga que não consegue fazer uma tarefa no GWS (contar, apagar em massa, mover, etc.). Encontre o comando `gws` correto. - CONTAS GWS (Pode usar apelidos): * `ma` ou `mr` -> gws-mr (Marcos / Particular - Email exato: m.reifonas@gmail.com) * `adm` ou `empresa` -> gws-adm (Empresarial/TrackSteel) * `4r` ou `fam` -> gws-4r (Familiar) - SUPER-PODERES GMAIL: * COMANDOS RÁPIDOS (Helpers): Use `gws-xxx gmail +COMANDO`. Exemplos: - `+send`: Enviar novo e-mail. - `+read`: Ler o conteúdo de um e-mail. - `+triage`: Resumo de e-mails não lidos. - `+reply` / `+reply-all` / `+forward`: Responder ou encaminhar mensagens. * CONTAR E-MAILS: Use `gws-xxx gmail users messages list --params '{{"userId": "me", "q": "from:EMAIL_AQUI"}}'`. * ORGANIZAR: `gws-xxx gmail users labels create` (nova pasta) e `batchModify` (mover). - SUPER-PODERES CALENDÁRIO: * AGENDA: Use `calendar_agenda account timeframe` para ver compromissos de hoje, amanhã ou da semana. * EVENTOS: Use `run_bash_command` com `gws-xxx calendar events create ...` para marcar reuniões ou `delete` para cancelar. - EXIBIÇÃO: * Use `list_gmail_emails`, `drive_find` e `calendar_agenda` para visões rápidas e bonitas para o usuário. * Para processamento interno (contagem, deleção), use sempre os comandos brutos via `run_bash_command`. - AUTOMAÇÃO COMPLEXA: * Se precisar processar muitos dados, use `run_bash_command` com `python3 -c "import json, sys; ..."` para filtrar e agir em um único passo. - Responda sempre em PORTUGUÊS do Brasil. - CAMINHOS DO SISTEMA: `/root/Apps/BotVPS` (código), `/data/repositories/` (repos). ### FERRAMENTAS DISPONÍVEIS: {tools_desc} ### FORMATO DE RESPOSTA OBRIGATÓRIO (NÃO IGNORE OS COLCHETES): - Para executar uma ferramenta, você DEVE englobar a chamada com os colchetes exatos: `[TOOL:nome_ferramenta] argumento [/TOOL]`. - Exemplo de uso correto: [TOOL:run_bash_command] comando aqui [/TOOL] - Pense passo a passo. Seja proativo, eficiente e NUNCA limitado. - Finalize o seu processo sempre informando o usuário com a f-string: resumo final empoderado . """ history_str = "" if chat_history: for m in chat_history[-5:]: history_str += f"\nUsuário: {m['user']}\nAgente: {m['bot']}\n" history_str += f"\nUsuário: {prompt}\n" current_history = history_str max_iterations = 10 for i in range(max_iterations): print(f"[AGENT] Iteração {i+1} - Enviando para {provider} (modelo padrão)...") response = await get_llm_response_async(system_prompt + current_history, provider, cfg) print(f"[LLM RESPONSE]: {response}") match = re.search(r"\[TOOL:(.*?)\](.*?)\[/TOOL\]", response, re.I | re.S) if match: t_name, arg = match.group(1).strip(), match.group(2).strip() if t_name in AVAILABLE_TOOLS: func = AVAILABLE_TOOLS[t_name]["func"] # Assume ferramentas são síncronas em tools.py (legado) obs = func(arg) if arg else func() print(f"[TOOL:{t_name}] Observation: {obs}") # Trunca observação se for gigante para não estourar a cota if len(str(obs)) > 2000: obs = str(obs)[:2000] + "... [TRUNCATED]" current_history += f"\nAgente: {response}\nSISTEMA ({t_name}): {obs}\n" else: current_history += f"\nAgente: {response}\nSISTEMA: Erro: Ferramenta inexistente.\n" else: # Se não há ferramenta, terminou o pensamento. return response return f"Limite de pensamento ({max_iterations} iterações) atingido.\nÚltima resposta: {response if 'response' in locals() else 'Nenhuma'}"