Files
BotVPS/tools.py

97 lines
3.7 KiB
Python

import subprocess
import os
import psutil
import time
def run_bash_command(command: str) -> str:
"""Executa um comando bash na VPS e retorna a saída."""
try:
# Executa comando de forma segura dentro da VPS
result = subprocess.run(
command,
shell=True,
capture_output=True,
text=True,
timeout=120 # Aumentado para comandos mais pesados
)
output = result.stdout.strip()
error = result.stderr.strip()
# Se encontrou algo no stdout, retornamos o que achou mesmo com erro (ex: find com permissão negada em algumas pastas)
if output:
return output
if result.returncode != 0:
return f"ERRO ({result.returncode}): {error if error else 'Nada no stderr'}"
return "Sucesso (vazio)"
except subprocess.TimeoutExpired:
return "ERRO: O comando demorou muito e foi cancelado (timeout)."
except Exception as e:
return f"ERRO fatal ao rodar bash: {str(e)}"
def get_system_health() -> str:
"""Retorna um texto detalhado da saúde do servidor para a IA."""
cpu = psutil.cpu_percent(interval=0.1)
vm = psutil.virtual_memory()
disk = psutil.disk_usage('/')
# Uptime aproximado usando psutil
uptime_seconds = time.time() - psutil.boot_time()
uptime_hours = round(uptime_seconds / 3600, 1)
return (f"CPU: {cpu}% | "
f"RAM: {round(vm.used / (1024**3), 2)}GB usada / {round(vm.total / (1024**3), 2)}GB total ({vm.percent}%) | "
f"Disco: {disk.percent}% usado | "
f"Uptime: {uptime_hours}h")
def read_vps_file(filepath: str) -> str:
"""Lê um arquivo do sistema de arquivos da VPS através do mapeamento /host_root."""
# Garante que o caminho comece com /host_root
clean_path = filepath
if clean_path.startswith("/host_root"):
host_path = clean_path
else:
# Se o usuário mandou /root/vps..., vira /host_root/root/vps...
host_path = os.path.join("/host_root", clean_path.lstrip("/"))
try:
if not os.path.exists("/host_root"):
return "ERRO CRÍTICO: O diretório /host_root não existe no container! O mapeamento de volume falhou."
if not os.path.exists(host_path):
# Tenta listar o diretório pai para ajudar no debug
parent = os.path.dirname(host_path)
content = os.listdir(parent) if os.path.exists(parent) else "Pai não existe"
return f"Erro: {filepath} não encontrado (Caminho real: {host_path}). Conteúdo do pai: {content}"
with open(host_path, 'r') as f:
return f.read(2000)
except Exception as e:
return f"Erro ao acessar {filepath}: {e}"
def get_docker_stats() -> str:
"""Retorna o uso de CPU/RAM de todos os containers ativos via comando docker stats."""
return run_bash_command('docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"')
# Mapeamento para o Agente entender quais tools ele possui (será usado no loop ReAct)
AVAILABLE_TOOLS = {
"run_bash_command": {
"description": "Executa comandos Linux na VPS. Use para docker, git, mkdir, touch, etc.",
"func": run_bash_command
},
"get_system_health": {
"description": "Verifica RAM, CPU e Disco globais da VPS.",
"func": get_system_health
},
"read_vps_file": {
"description": "Lê o conteúdo de um arquivo na VPS (logs, configs).",
"func": read_vps_file
},
"get_docker_stats": {
"description": "Retorna uma tabela com o consumo de CPU e Memória de cada container.",
"func": get_docker_stats
}
}