152 lines
6.4 KiB
Python
152 lines
6.4 KiB
Python
import os, json, redis, subprocess, base64
|
|
from urllib import request, parse
|
|
from anthropic import Anthropic
|
|
|
|
class SwarmAgent:
|
|
def __init__(self, task_data):
|
|
self.data = task_data
|
|
self.repo_name = task_data.get('repository')
|
|
self.repo_url = f"http://10.99.0.3:3000/{self.repo_name}.git"
|
|
self.local_path = os.path.join("/home/deploy/projetos", self.repo_name.split('/')[-1])
|
|
|
|
# Conexão Redis para pegar chaves
|
|
self.r = redis.Redis(host='10.99.0.3', port=6379, password='clube67_dragonfly_pass_9903', db=0, decode_responses=True)
|
|
|
|
def get_api_key(self):
|
|
pool = json.loads(self.r.get('swarm:keys:pool'))
|
|
return random.choice([k['key'] for k in pool['anthropic'] if k['status'] == 'active'])
|
|
|
|
def setup_workspace(self):
|
|
os.makedirs("/home/deploy/projetos", exist_ok=True)
|
|
if not os.path.exists(self.local_path):
|
|
subprocess.run(["git", "clone", self.repo_url, self.local_path])
|
|
else:
|
|
subprocess.run(["git", "-C", self.local_path, "pull"])
|
|
|
|
def run_bash(self, command):
|
|
"""Ferramenta para a IA rodar comandos na VPS 4"""
|
|
result = subprocess.run(command, shell=True, capture_output=True, text=True, cwd=self.local_path)
|
|
return f"STDOUT: {result.stdout}\nSTDERR: {result.stderr}"
|
|
|
|
def post_comment(self, message):
|
|
issue_id = self.data.get('data', {}).get('issue', {}).get('number')
|
|
if not issue_id: return
|
|
url = f"http://10.99.0.3:3000/api/v1/repos/{self.repo_name}/issues/{issue_id}/comments"
|
|
auth_str = 'ruicesar:h$tg@g5aga$ra1E3$C-yHW$-BA@DF2@Grfa!3#'
|
|
base64_auth = base64.b64encode(auth_str.encode('ascii')).decode('ascii')
|
|
req = request.Request(url, data=json.dumps({"body": message}).encode('utf-8'), method='POST')
|
|
req.add_header('Content-Type', 'application/json')
|
|
req.add_header('Authorization', f'Basic {base64_auth}')
|
|
try:
|
|
with request.urlopen(req) as res: pass
|
|
except: pass
|
|
|
|
def run_command(self, command):
|
|
"""Executa comandos shell na VPS 4"""
|
|
print(f" [Exec] Rodando: {command}")
|
|
result = subprocess.run(command, shell=True, capture_output=True, text=True, cwd=self.local_path)
|
|
return {"stdout": result.stdout, "stderr": result.stderr}
|
|
|
|
def write_file(self, path, content):
|
|
"""Escreve/Edita arquivos no projeto"""
|
|
full_path = os.path.join(self.local_path, path)
|
|
os.makedirs(os.path.dirname(full_path), exist_ok=True)
|
|
with open(full_path, "w") as f:
|
|
f.write(content)
|
|
return f"Arquivo {path} escrito com sucesso."
|
|
|
|
def read_file(self, path):
|
|
"""Lê arquivos do projeto"""
|
|
full_path = os.path.join(self.local_path, path)
|
|
if os.path.exists(full_path):
|
|
with open(full_path, "r") as f:
|
|
return f.read()
|
|
return "Erro: Arquivo não encontrado."
|
|
|
|
def execute(self):
|
|
self.setup_workspace()
|
|
|
|
# Identificação de Localização Automática
|
|
vps_ip = subprocess.getoutput("hostname -I").split()[0]
|
|
vps_name = subprocess.getoutput("hostname")
|
|
|
|
with open("/home/deploy/instrucoes/global/doutrina_agentes.md", "r") as f: doutrina = f.read()
|
|
|
|
# Consciência Situacional Injetada
|
|
situational_awareness = f"\n\n[CONSCIÊNCIA SITUACIONAL]: Você está rodando na VPS: {vps_name} (IP: {vps_ip})\n"
|
|
|
|
api_key = self.get_api_key()
|
|
client = Anthropic(api_key=api_key)
|
|
|
|
print(f" [!] Agente iniciando na {vps_name} ({vps_ip})...")
|
|
|
|
task = self.data.get('data', {}).get('issue', {}).get('body', 'Sem descrição')
|
|
|
|
# O Agente agora tem um loop de pensamento e ferramentas
|
|
# Para este MVP, vamos permitir que ele faça uma análise e execute uma rodada de ferramentas
|
|
tools = [
|
|
{
|
|
"name": "read_file",
|
|
"description": "Lê o conteúdo de um arquivo do projeto",
|
|
"input_schema": {
|
|
"type": "object",
|
|
"properties": {"path": {"type": "string"}},
|
|
"required": ["path"]
|
|
}
|
|
},
|
|
{
|
|
"name": "write_file",
|
|
"description": "Escreve ou edita um arquivo no projeto",
|
|
"input_schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"path": {"type": "string"},
|
|
"content": {"type": "string"}
|
|
},
|
|
"required": ["path", "content"]
|
|
}
|
|
},
|
|
{
|
|
"name": "run_command",
|
|
"description": "Executa um comando shell (ex: docker compose up)",
|
|
"input_schema": {
|
|
"type": "object",
|
|
"properties": {"command": {"type": "string"}},
|
|
"required": ["command"]
|
|
}
|
|
}
|
|
]
|
|
|
|
response = client.messages.create(
|
|
model="claude-3-5-sonnet-20240620",
|
|
max_tokens=4000,
|
|
system=doutrina + situational_awareness,
|
|
tools=tools,
|
|
messages=[{"role": "user", "content": f"Tarefa: {task}\nAnalise o diretório {self.local_path} e resolva o problema."}]
|
|
)
|
|
|
|
# Processamento simples de ferramentas (para este estágio)
|
|
final_feedback = f"### 🤖 [VPS 4 - EXECUTOR]:\n\n{response.content[0].text}\n\n"
|
|
|
|
for content in response.content:
|
|
if content.type == "tool_use":
|
|
if content.name == "read_file":
|
|
res = self.read_file(content.input["path"])
|
|
final_feedback += f"* **Lendo**: {content.input['path']}\n"
|
|
elif content.name == "write_file":
|
|
res = self.write_file(content.input["path"], content.input["content"])
|
|
final_feedback += f"* **Escrevendo**: {content.input['path']}\n"
|
|
elif content.name == "run_command":
|
|
res = self.run_command(content.input["command"])
|
|
final_feedback += f"* **Rodando**: `{content.input['command']}`\n"
|
|
|
|
self.post_comment(final_feedback)
|
|
|
|
if __name__ == "__main__":
|
|
import argparse, random
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("--data")
|
|
args = parser.parse_args()
|
|
if args.data:
|
|
SwarmAgent(json.loads(args.data)).execute()
|