Update Hermes integration
This commit is contained in:
@@ -138,7 +138,7 @@ async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|||||||
text_normalized = text.strip()
|
text_normalized = text.strip()
|
||||||
starts_with_slash = text_normalized.startswith('/')
|
starts_with_slash = text_normalized.startswith('/')
|
||||||
text_clean = text_normalized.lstrip('/')
|
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'))
|
is_cmd = text_clean.lower().startswith(('bash', 'vps', 'cmd'))
|
||||||
text_lower = text.lower().strip()
|
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)
|
reply = await call_antigravity_api("/api/chat", payload)
|
||||||
add_message(chat_id, text, reply)
|
add_message(chat_id, text, reply)
|
||||||
elif is_hermes:
|
elif is_hermes:
|
||||||
# Extrai a tarefa (remove "hermes" do início, com ou sem barra)
|
# Extrai a tarefa (remove "hermes" ou "h" do início)
|
||||||
task = text_clean[6:].strip() if len(text_clean) > 6 else ""
|
if text_clean.lower().startswith('hermes'):
|
||||||
|
task = text_clean[6:].strip()
|
||||||
|
else:
|
||||||
|
task = text_clean[1:].strip()
|
||||||
|
|
||||||
if not task:
|
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
|
return
|
||||||
await update.message.reply_text("🤖 *Hermes assumindo o controle. Isso pode demorar alguns minutos...*", parse_mode='Markdown')
|
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
|
# Passa contexto completo: user_id, chat_id e histórico
|
||||||
|
|||||||
@@ -485,12 +485,40 @@ class BrowserCloudTools:
|
|||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
def delegate_to_hermes(task: str) -> str:
|
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
|
import shlex
|
||||||
safe_task = shlex.quote(task)
|
import urllib.request
|
||||||
# Executa o hermes no modo oneshot (-z), com timeout estendido de 5 min
|
import json
|
||||||
command = f"hermes -z {safe_task}"
|
|
||||||
return run_bash(command, timeout=300)
|
# 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
|
# REGISTRY CENTRALIZADO
|
||||||
|
|||||||
16
main.py
16
main.py
@@ -177,11 +177,21 @@ async def web_chat_audio(audio: UploadFile = File(...), is_auth: bool = Depends(
|
|||||||
if not text:
|
if not text:
|
||||||
return {"reply": "Não entendi seu áudio.", "text": ""}
|
return {"reply": "Não entendi seu áudio.", "text": ""}
|
||||||
|
|
||||||
# 3. Processa na IA
|
# 3. Verifica se é para o Hermes
|
||||||
reply = await query_agent_async(text)
|
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)
|
# 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)
|
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
|
audio_text = refined_match.group(1).strip() if refined_match else reply
|
||||||
filename = await text_to_speech_async(audio_text)
|
filename = await text_to_speech_async(audio_text)
|
||||||
|
|||||||
Reference in New Issue
Block a user