feat: adicionar sistema de feedback por comentário do agente
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
import os
|
||||
import json
|
||||
import redis
|
||||
import argparse
|
||||
import subprocess
|
||||
from anthropic import Anthropic
|
||||
from key_manager import KeyManager
|
||||
|
||||
# Configurações de Caminho
|
||||
BASE_DIR = "/home/deploy/projetos"
|
||||
INSTRUCOES_DIR = "/home/deploy/instrucoes"
|
||||
|
||||
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(BASE_DIR, self.repo_name.split('/')[-1])
|
||||
self.km = KeyManager()
|
||||
|
||||
def setup_workspace(self):
|
||||
"""Garante que o código e as instruções estão atualizados"""
|
||||
print(f" [>] Sincronizando repositório: {self.repo_name}")
|
||||
os.makedirs(BASE_DIR, 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"])
|
||||
|
||||
# Sincroniza instruções globais
|
||||
subprocess.run(["git", "-C", INSTRUCOES_DIR, "pull"])
|
||||
|
||||
def get_system_prompt(self):
|
||||
"""Carrega a doutrina e as instruções de cada VPS"""
|
||||
with open(f"{INSTRUCOES_DIR}/global/doutrina_agentes.md", "r") as f:
|
||||
doutrina = f.read()
|
||||
with open(f"{INSTRUCOES_DIR}/global/claude.md", "r") as f:
|
||||
especifico = f.read()
|
||||
|
||||
ip_vps = subprocess.getoutput("hostname -I").split()[0]
|
||||
|
||||
return f"""
|
||||
{doutrina}
|
||||
{especifico}
|
||||
|
||||
CONTEXTO ATUAL:
|
||||
- Você está na VPS com IP: {ip_vps}
|
||||
- Projeto: {self.repo_name}
|
||||
- Tarefa (Issue): {json.dumps(self.data.get('data', {}).get('issue', {}))}
|
||||
"""
|
||||
|
||||
def post_comment(self, message):
|
||||
"""Posta um comentário de feedback na Issue do Gitea"""
|
||||
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 = ('ruicesar', 'h$tg@g5aga$ra1E3$C-yHW$-BA@DF2@Grfa!3#')
|
||||
|
||||
try:
|
||||
import requests
|
||||
response = requests.post(url, auth=auth, json={"body": message})
|
||||
if response.status_code == 201:
|
||||
print(f" [✓] Comentário postado na Issue #{issue_id}")
|
||||
else:
|
||||
print(f" [X] Erro ao postar comentário: {response.status_code}")
|
||||
except Exception as e:
|
||||
print(f" [E] Falha na comunicação com Gitea: {e}")
|
||||
|
||||
def execute(self):
|
||||
self.setup_workspace()
|
||||
|
||||
api_key = self.km.get_key('anthropic')
|
||||
if not api_key:
|
||||
return
|
||||
|
||||
client = Anthropic(api_key=api_key)
|
||||
prompt = self.get_system_prompt()
|
||||
|
||||
print(" [!] IA Pensando na solução...")
|
||||
|
||||
# Simulação de resposta da IA para o teste
|
||||
feedback = "### 🤖 [VPS 4 - LABORATÓRIO]:\n* **Status**: Tarefa recebida e ambiente preparado.\n* **Ação**: Sincronização de arquivos concluída.\n* **Próximo**: Iniciando correção do erro de regressão de versão."
|
||||
|
||||
self.post_comment(feedback)
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--data", help="Dados do Webhook JSON")
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.data:
|
||||
agent = SwarmAgent(json.loads(args.data))
|
||||
agent.execute()
|
||||
@@ -0,0 +1,29 @@
|
||||
# 📋 Template de Arquitetura de Projeto
|
||||
|
||||
Este documento define o padrão para a documentação de arquitetura de novos projetos. Copie este arquivo para a pasta do projeto e substitua os valores entre chaves `{}`.
|
||||
|
||||
## 🛠️ Stack Tecnológica
|
||||
- **Backend**: {Linguagem/Framework}
|
||||
- **Frontend**: {Linguagem/Framework}
|
||||
- **Banco de Dados**: {Postgres/DragonflyDB/Redis}
|
||||
- **Servidor Web**: {Nginx/Caddy}
|
||||
|
||||
## 🌐 Infraestrutura (VPS)
|
||||
| Componente | VPS | IP Interno (VPN) | Porta |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| Aplicação | {VPS 1} | 10.99.0.x | {Porta} |
|
||||
| Banco de Dados | {VPS 3} | 10.99.0.3 | 5432 |
|
||||
| Cache/Redis | {VPS 2} | 10.99.0.2 | 6379 |
|
||||
|
||||
## 🔒 Credenciais e Acesso
|
||||
> [!CAUTION]
|
||||
> Jamais coloque senhas reais aqui. Use variáveis de ambiente ou referencie o gerenciador de segredos.
|
||||
|
||||
- **Dono do Projeto**: {Nome}
|
||||
- **Namespace no Gitea**: {URL_REPOS_GITEA}
|
||||
|
||||
## 🔄 Fluxo de Dados
|
||||
{Descrever brevemente como a informação flui entre os serviços}
|
||||
|
||||
---
|
||||
*Documento gerado automaticamente via Template de Arquitetura v1.0*
|
||||
@@ -0,0 +1,41 @@
|
||||
# 🏗️ Template Nginx Wildcard para Staging (VPS 1)
|
||||
|
||||
# Este mapeamento associa o subdomínio à porta na VPS 4
|
||||
map $project_slug $staging_port {
|
||||
mercado 8081;
|
||||
scoreodonto 8082;
|
||||
newwhats 8083;
|
||||
default 8080;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name ~^(?<project_slug>.+)\.staging\.clube67\.com$;
|
||||
|
||||
# Redirecionamento para HTTPS
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name ~^(?<project_slug>.+)\.staging\.clube67\.com$;
|
||||
|
||||
# Certificados SSL (Substituir pelos caminhos reais do Let's Encrypt Wildcard)
|
||||
ssl_certificate /etc/letsencrypt/live/clube67.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/clube67.com/privkey.pem;
|
||||
|
||||
location / {
|
||||
# Encaminha o tráfego via VPN para a VPS 4
|
||||
proxy_pass http://10.99.0.4:$staging_port;
|
||||
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# Timeouts aumentados para desenvolvimento
|
||||
proxy_connect_timeout 90;
|
||||
proxy_send_timeout 90;
|
||||
proxy_read_timeout 90;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import redis
|
||||
import json
|
||||
import subprocess
|
||||
import os
|
||||
|
||||
# Configuração
|
||||
REDIS_HOST = '10.99.0.3'
|
||||
REDIS_PORT = 6379
|
||||
REDIS_PASS = 'clube67_dragonfly_pass_9903'
|
||||
CHANNELS = ['swarm:tasks', 'swarm:updates']
|
||||
|
||||
r = redis.Redis(host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASS, db=0)
|
||||
pubsub = r.pubsub()
|
||||
pubsub.subscribe(*CHANNELS)
|
||||
|
||||
print(f" [*] Aguardando eventos nos canais {CHANNELS}...")
|
||||
|
||||
for message in pubsub.listen():
|
||||
if message['type'] == 'message':
|
||||
try:
|
||||
payload = json.loads(message['data'])
|
||||
event = payload.get('event')
|
||||
repo = payload.get('repository')
|
||||
|
||||
print(f" [!] Novo evento recebido: {event} no repo {repo}")
|
||||
|
||||
# Aqui entrará a lógica de disparar o agente de IA específico
|
||||
# Por enquanto, apenas registramos o recebimento.
|
||||
# Exemplo de comando que seria rodado:
|
||||
# subprocess.run(["python3", "agent_executor.py", "--event", event, "--data", json.dumps(payload)])
|
||||
|
||||
except Exception as e:
|
||||
print(f" [E] Erro ao processar mensagem: {e}")
|
||||
Reference in New Issue
Block a user