🚀 Auto-deploy: BotVPS atualizado em 02/05/2026 15:37:40

This commit is contained in:
2026-05-02 15:37:40 +00:00
parent 1c1fac3735
commit 912763b3f1
613 changed files with 169969 additions and 60 deletions

View File

@@ -393,6 +393,93 @@ class WorkspaceTools:
cmd = 'docker exec coolify-db psql -U coolify -d coolify -c "SELECT application_name, status, created_at FROM application_deployment_queues ORDER BY created_at DESC LIMIT 5;"'
return run_bash(cmd)
# ============================================================
# BROWSER CLOUD TOOLS
# ============================================================
BROWSER_CLOUD_URL = "http://localhost:8088"
_current_session_id = None
class BrowserCloudTools:
@staticmethod
def _req(method: str, path: str, data: dict = None):
import urllib.request, json
url = f"{BROWSER_CLOUD_URL}{path}"
body = json.dumps(data).encode() if data else None
req = urllib.request.Request(url, data=body, method=method,
headers={"Content-Type": "application/json"})
try:
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read())
except Exception as e:
return {"error": str(e)}
@staticmethod
def _session():
global _current_session_id
if _current_session_id:
return _current_session_id
r = BrowserCloudTools._req("POST", "/session", {"headless": True})
if "session_id" in r:
_current_session_id = r["session_id"]
return _current_session_id
return None
@staticmethod
def navigate(url: str) -> str:
sid = BrowserCloudTools._session()
if not sid:
return "Erro: não foi possível criar sessão no browser cloud"
r = BrowserCloudTools._req("POST", f"/session/{sid}/navigate",
{"url": url, "wait_until": "load"})
if "error" in r:
return f"Erro: {r['error']}"
return f"OK — {r.get('title', '')} ({url})"
@staticmethod
def screenshot(url_or_current: str = "current") -> str:
sid = BrowserCloudTools._session()
if not sid:
return "Erro: sem sessão"
# If URL provided, navigate first
if url_or_current != "current" and url_or_current.startswith("http"):
nav = BrowserCloudTools.navigate(url_or_current)
if nav.startswith("Erro"):
return nav
r = BrowserCloudTools._req("GET", f"/session/{sid}/screenshot")
if "error" in r:
return f"Erro: {r['error']}"
b64 = r.get("data", "")
size = len(b64) * 3 // 4 # base64 → bytes approx
return f"Screenshot OK — {r.get('format')} {size // 1024}KB (base64)"
@staticmethod
def click(selector: str) -> str:
sid = BrowserCloudTools._session()
if not sid:
return "Erro: sem sessão"
r = BrowserCloudTools._req("POST", f"/session/{sid}/click",
{"selector": selector})
if "error" in r:
return f"Erro: {r['error']}"
return "OK — clicado"
@staticmethod
def fill(input_str: str) -> str:
# Formato: selector|value|submit(optional)
parts = input_str.split("|")
selector = parts[0]
value = parts[1] if len(parts) > 1 else ""
submit = len(parts) > 2 and parts[2].lower() == "true"
sid = BrowserCloudTools._session()
if not sid:
return "Erro: sem sessão"
r = BrowserCloudTools._req("POST", f"/session/{sid}/fill",
{"selector": selector, "value": value, "submit": submit})
if "error" in r:
return f"Erro: {r['error']}"
return "OK — preenchido" + (" e submetido" if submit else "")
# ============================================================
# HERMES ORCHESTRATOR
# ============================================================
@@ -532,6 +619,23 @@ AVAILABLE_TOOLS = {
"description": "Delega tarefas muito complexas para o Operador Master (Hermes Agent)",
"func": delegate_to_hermes
},
# Browser Cloud
"browser_navigate": {
"description": "Navega URL no browser cloud (HEADLESS). Uso: URL completa",
"func": BrowserCloudTools.navigate
},
"browser_screenshot": {
"description": "Tira screenshot do browser cloud (PNG base64). Uso: URL ou 'current'",
"func": BrowserCloudTools.screenshot
},
"browser_click": {
"description": "Clica em elemento CSS no browser cloud. Uso: seletor CSS",
"func": BrowserCloudTools.click
},
"browser_fill": {
"description": "Preenche input e opcionalmente submete. Uso: seletor|valor|submeter(true/false)",
"func": BrowserCloudTools.fill
},
# Legado (aliases)
"get_docker_stats": {
"description": "CPU/RAM por container (legacy)",