From 8b577242ff070fd001d997d0960fb4ec6bc0c683 Mon Sep 17 00:00:00 2001 From: Antigravity Date: Sun, 10 May 2026 00:37:18 -0300 Subject: [PATCH] Update Hermes integration --- bridge_telegram.py | 12 ++++++++---- core_tools.py | 38 +++++++++++++++++++++++++++++++++----- main.py | 16 +++++++++++++--- 3 files changed, 54 insertions(+), 12 deletions(-) diff --git a/bridge_telegram.py b/bridge_telegram.py index beaaba6..c7d9bdc 100644 --- a/bridge_telegram.py +++ b/bridge_telegram.py @@ -138,7 +138,7 @@ async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE): text_normalized = text.strip() starts_with_slash = text_normalized.startswith('/') text_clean = text_normalized.lstrip('/') - is_hermes = text_clean.lower().startswith('hermes') + is_hermes = text_clean.lower().startswith('hermes') or text_clean.lower().startswith('h ') or text_clean.lower() == 'h' is_cmd = text_clean.lower().startswith(('bash', 'vps', 'cmd')) text_lower = text.lower().strip() @@ -172,10 +172,14 @@ async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE): reply = await call_antigravity_api("/api/chat", payload) add_message(chat_id, text, reply) elif is_hermes: - # Extrai a tarefa (remove "hermes" do início, com ou sem barra) - task = text_clean[6:].strip() if len(text_clean) > 6 else "" + # Extrai a tarefa (remove "hermes" ou "h" do início) + if text_clean.lower().startswith('hermes'): + task = text_clean[6:].strip() + else: + task = text_clean[1:].strip() + if not task: - await update.message.reply_text("❓ Digite sua tarefa após 'hermes'. Ex: `hermes Instale o nginx`") + await update.message.reply_text("❓ Digite sua tarefa após 'hermes' ou 'h'. Ex: `/h Instale o nginx`") return await update.message.reply_text("🤖 *Hermes assumindo o controle. Isso pode demorar alguns minutos...*", parse_mode='Markdown') # Passa contexto completo: user_id, chat_id e histórico diff --git a/core_tools.py b/core_tools.py index 4123506..86bdef6 100644 --- a/core_tools.py +++ b/core_tools.py @@ -485,12 +485,40 @@ class BrowserCloudTools: # ============================================================ def delegate_to_hermes(task: str) -> str: - """Delega uma tarefa complexa para o Hermes Agent (MiniMax 2.7) resolver na VPS.""" + """Delega uma tarefa complexa para o NOVO Hermes Agent no Coolify.""" import shlex - safe_task = shlex.quote(task) - # Executa o hermes no modo oneshot (-z), com timeout estendido de 5 min - command = f"hermes -z {safe_task}" - return run_bash(command, timeout=300) + import urllib.request + import json + + # Tentativa 1: Via API HTTP Interna do Coolify para o novo Hermes + url = "http://qfduyd1pvznx1z53mxbj46ee-hermes:8642/chat" + headers = { + "Content-Type": "application/json", + "Authorization": "Bearer hermes-vps-513d26e0-secure-key" + } + data = json.dumps({"message": task, "text": task}).encode("utf-8") + + try: + req = urllib.request.Request(url, data=data, headers=headers, method="POST") + with urllib.request.urlopen(req, timeout=300) as response: + res_data = json.loads(response.read().decode()) + return res_data.get("reply", res_data.get("response", str(res_data))) + except Exception as api_err: + # Tentativa 2: Fallback via docker exec no container do Coolify + safe_task = shlex.quote(task) + # Primeiro, pegamos o ID exato do container do hermes no Coolify + get_id_cmd = "docker ps -q -f name=qfduyd1pvznx1z53mxbj46ee-hermes" + container_id = run_bash(get_id_cmd).strip() + + if container_id and not "ERRO" in container_id: + # Tenta rodar o CLI dentro do container + exec_cmd = f"docker exec {container_id} hermes -z {safe_task}" + res = run_bash(exec_cmd, timeout=300) + if "not found" not in res.lower() and "no such file" not in res.lower(): + return res + + # Tentativa 3: Fallback para o CLI antigo do host (Antigravity original) + return run_bash(f"hermes -z {safe_task}", timeout=300) # ============================================================ # REGISTRY CENTRALIZADO diff --git a/main.py b/main.py index eee1ed7..4404ef4 100644 --- a/main.py +++ b/main.py @@ -177,11 +177,21 @@ async def web_chat_audio(audio: UploadFile = File(...), is_auth: bool = Depends( if not text: return {"reply": "Não entendi seu áudio.", "text": ""} - # 3. Processa na IA - reply = await query_agent_async(text) + # 3. Verifica se é para o Hermes + text_clean = text.lower().strip() + is_hermes = text_clean.startswith('hermes') or text_clean.startswith('h ') + + if is_hermes: + # Extrai a tarefa + task = text[6:].strip() if text_clean.startswith('hermes') else text[2:].strip() + from core_tools import delegate_to_hermes + reply = await run_in_threadpool(delegate_to_hermes, f"[Áudio] {task}") + reply = f"🤖 **Hermes Agent:**\n\n{reply}" + else: + # Processa na IA padrão do BotVPS + reply = await query_agent_async(text) # 4. Gera áudio da resposta (TTS) - # Se houver RESUMO:, usa apenas ele para o áudio. Caso contrário, usa tudo. refined_match = re.search(r'RESUMO:\s*(.*)', reply, flags=re.DOTALL | re.IGNORECASE) audio_text = refined_match.group(1).strip() if refined_match else reply filename = await text_to_speech_async(audio_text)