import os import re import requests import json from tools import AVAILABLE_TOOLS from config import get_config def get_llm_response(prompt: str, provider: str, cfg: dict, temp: float = 0.7, ctx: int = 4096) -> str: """Invoca o provedor de LLM configurado.""" if provider == "gemini": api_key = cfg.get("gemini_api_key") or os.getenv("GEMINI_API_KEY") url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key={api_key}" payload = {"contents": [{"parts": [{"text": prompt}]}]} res = requests.post(url, json=payload) if res.status_code == 200: return res.json()["candidates"][0]["content"]["parts"][0]["text"] return f"Erro Gemini: {res.text}" elif provider == "ollama": ollama_host = os.getenv("OLLAMA_HOST", "http://ollama-lw4s8g4gc8gss4gkc4gg0wk4:11434") res = requests.post(f"{ollama_host}/api/generate", json={ "model": os.getenv("OLLAMA_MODEL", "qwen2.5-coder:1.5b"), "prompt": prompt, "stream": False, "options": { "temperature": temp, "num_ctx": ctx } }) if res.status_code == 200: return res.json().get("response", "") return f"Erro Ollama: {res.text}" return "Provedor desconhecido." def query_agent(prompt: str, override_provider: str = None, chat_history: list = None) -> str: # 1. Ajuste de Provedor e Configuração 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()]) # 2. Prompt especializado (O manual de elite) system_prompt_base = """Você é o [Antigravity VPS Agent], SysAdmin de elite do Marcos. Você tem acesso root completo à VPS e deve agir de forma profissional e precisa. ### REGRAS DE OURO: 1. Responda em PORTUGUÊS (Brasil). 2. Se o usuário pedir o status da VPS, SEMPRE use a ferramenta 'get_system_health'. 3. Se o usuário pedir algo sobre containers, use 'get_docker_stats'. 4. Antes de decidir que um arquivo não existe, use 'run_bash_command' com 'ls' para verificar o diretório. 5. NUNCA invente links fictícios. Se localizar um arquivo, use `read_vps_file`. 6. O disco da VPS está focado em `/host_root`. Use este caminho para buscar arquivos. 7. Use [TOOL:nome] arg [/TOOL] para ações. Rode UMA por vez. ### RESPOSTA FINAL: - Deve ter um resumo técnico e uma seção com Markdown. - Se localizou imagem, use ![alt](/host_root/caminho/foto.jpg) dentro do . ### FERRAMENTAS: {TOOLS_LIST}""" system_prompt = system_prompt_base.replace("{TOOLS_LIST}", tools_desc) # 3. Contexto e Memória Otimizada num_context = 2048 if provider == "ollama" else 4096 hist_list = chat_history[-4:] if chat_history else [] hist_txt = "\n".join([f"U: {m['user']}\nA: {m['bot']}" for m in hist_list]) execution_context = f"\n{hist_txt}\nU: {prompt}\nA:" current_reasoning = "" max_loops = 12 print(f"--- INICIANDO AGENTE ({provider}) ---") for i in range(max_loops): print(f"\n[LOOP {i+1}/{max_loops}]") full_prompt = f"{system_prompt}\n{execution_context}\n{current_reasoning}\n" # Injeta o num_ctx dinâmico no payload if provider == "ollama": response = get_llm_response(full_prompt, provider, cfg, temp=0.1, ctx=num_context) else: response = get_llm_response(full_prompt, provider, cfg) print(f"PENSAMENTO:\n{response}") match = re.search(r"\[TOOL:(.*?)\](.*?)\[/TOOL\]", response, re.IGNORECASE | re.DOTALL) if match: # ... (lógica de ferramenta existente) ... tool_name = match.group(1).strip() arg = match.group(2).strip() print(f"EXECUTANDO: {tool_name}") if tool_name in AVAILABLE_TOOLS: func = AVAILABLE_TOOLS[tool_name]["func"] observation = func() if tool_name in ["get_system_health", "get_docker_stats"] else func(arg) else: observation = f"Erro: Ferramenta '{tool_name}' não encontrada." current_reasoning += f"\nAção: {response}\nSISTEMA: {observation}\n" else: print("--- RESPOSTA FINAL ENCONTRADA ---") return response return "O agente atingiu o limite de tentativas."