{body.replace(chr(10), '
')}
From 76c2b8408d991edd7f0058e9e91b69070f23ce87 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 19 Dec 2025 23:05:19 +0000 Subject: [PATCH 1/7] Initial plan From cfc1075617fb2cb8f76b9f410dab7e1ff8a085d9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 19 Dec 2025 23:12:02 +0000 Subject: [PATCH 2/7] Add Docker, systemd deployment, monitoring, and 24/7 automation infrastructure Co-authored-by: ManoAlee <153291497+ManoAlee@users.noreply.github.com> --- .env.example | 49 ++++ .gitignore | 14 + Dockerfile | 56 ++++ README.md | 56 ++++ docker-compose.yml | 31 +++ docs/DEPLOYMENT_GUIDE.md | 340 +++++++++++++++++++++++ system/ai_engine/autonomous_loop.py | 214 +++++++++++--- system/config/config.py | 70 ++++- system/config/freelanceros-agent.service | 49 ++++ system/requirements.txt | 4 + system/scripts/backup.sh | 111 ++++++++ system/scripts/deploy_docker.sh | 66 +++++ system/scripts/deploy_systemd.sh | 109 ++++++++ system/scripts/health_check.py | 163 +++++++++++ 14 files changed, 1283 insertions(+), 49 deletions(-) create mode 100644 .env.example create mode 100644 Dockerfile create mode 100644 docker-compose.yml create mode 100644 docs/DEPLOYMENT_GUIDE.md create mode 100644 system/config/freelanceros-agent.service create mode 100755 system/scripts/backup.sh create mode 100755 system/scripts/deploy_docker.sh create mode 100755 system/scripts/deploy_systemd.sh create mode 100755 system/scripts/health_check.py diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..7d60a84 --- /dev/null +++ b/.env.example @@ -0,0 +1,49 @@ +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# FreelancerOS: Environment Configuration Template +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# Copy this file to .env and fill in your credentials + +# 🎯 TARGET CONFIGURATION +TARGET_NICHE=advogados em são paulo +MAX_LEADS_PER_DAY=50 + +# 🤖 AGENT BEHAVIOR +MODE=AGGRESSIVE +WORK_HOURS_START=9 +WORK_HOURS_END=18 +LOOP_INTERVAL_SECONDS=60 + +# 📧 EMAIL AUTOMATION +AUTO_SEND_EMAIL=True +SMTP_HOST=smtp.gmail.com +SMTP_PORT=587 +MY_EMAIL=your_email@gmail.com +MY_PASSWORD=your_app_password_here + +# 🔑 API KEYS (if needed for future integrations) +# OPENAI_API_KEY=your_openai_key_here +# ANTHROPIC_API_KEY=your_anthropic_key_here + +# 📱 SOCIAL MEDIA CREDENTIALS (optional) +LINKEDIN_EMAIL= +LINKEDIN_PASSWORD= +INSTAGRAM_USERNAME= +INSTAGRAM_PASSWORD= + +# 🌐 RSS FEEDS +RSS_FEED_1=https://weworkremotely.com/categories/remote-back-end-programming-jobs.rss +RSS_FEED_2=https://weworkremotely.com/categories/remote-design-jobs.rss + +# 🛡️ SECURITY & FILTERS +MIN_CONFIDENCE_SCORE=75 +BLACKLIST_WORDS=senior,lead,architect,10+years + +# 📊 LOGGING +LOG_LEVEL=INFO +LOG_FILE=/app/logs/agent.log + +# 🔧 ADVANCED SETTINGS +HEADLESS_BROWSER=true +MAX_RETRIES=3 +RETRY_DELAY_SECONDS=10 +HEALTH_CHECK_INTERVAL=300 diff --git a/.gitignore b/.gitignore index 14ae42a..e239d3e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,17 @@ __pycache__/ mission_memory.json .env venv/ +*.db +*.sqlite +*.sqlite3 +data/ +logs/ +.DS_Store +*.swp +*.swo +*~ +.vscode/ +.idea/ +node_modules/ +dist/ +build/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..57e5429 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,56 @@ +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# FreelancerOS: Self-Sustainable Agent Container +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +FROM python:3.12-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y \ + wget \ + gnupg \ + unzip \ + curl \ + git \ + && rm -rf /var/lib/apt/lists/* + +# Install Chrome for Selenium (headless browser automation) +RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \ + && echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list \ + && apt-get update \ + && apt-get install -y google-chrome-stable \ + && rm -rf /var/lib/apt/lists/* + +# Install ChromeDriver +RUN CHROMEDRIVER_VERSION=$(curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE) \ + && wget -q "https://chromedriver.storage.googleapis.com/$CHROMEDRIVER_VERSION/chromedriver_linux64.zip" \ + && unzip chromedriver_linux64.zip \ + && mv chromedriver /usr/local/bin/chromedriver \ + && chmod +x /usr/local/bin/chromedriver \ + && rm chromedriver_linux64.zip + +# Set working directory +WORKDIR /app + +# Copy requirements first (for better caching) +COPY system/requirements.txt /app/system/requirements.txt +COPY projects/auto_agent/requirements.txt /app/projects/auto_agent/requirements.txt 2>/dev/null || echo "No auto_agent requirements" + +# Install Python dependencies +RUN pip install --no-cache-dir -r system/requirements.txt + +# Copy the entire application +COPY . /app + +# Create necessary directories +RUN mkdir -p /app/data /app/logs + +# Set environment variables +ENV PYTHONUNBUFFERED=1 +ENV PYTHONPATH=/app + +# Health check +HEALTHCHECK --interval=60s --timeout=10s --start-period=30s --retries=3 \ + CMD python3 -c "import os; exit(0 if os.path.exists('/app/data/agent_memory.db') else 1)" + +# Run the autonomous agent +CMD ["python3", "projects/auto_agent/auto_main.py"] diff --git a/README.md b/README.md index aea4769..8d1f6e1 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,62 @@ python projects/auto_agent/auto_main.py --- +## 🤖 NOVO: Automação 24/7 e Auto-Sustentabilidade + +O FreelancerOS agora suporta **operação totalmente autônoma e contínua** com recuperação automática de erros! + +### 🚀 Implantação Rápida + +**Opção 1: Docker (Recomendado)** +```bash +# Configure suas credenciais +cp .env.example .env +nano .env + +# Implante com um comando +./system/scripts/deploy_docker.sh +``` + +**Opção 2: Systemd (Linux)** +```bash +# Implante como serviço do sistema +sudo ./system/scripts/deploy_systemd.sh +``` + +### 📊 Monitoramento + +```bash +# Verifique a saúde do agente +python3 system/scripts/health_check.py + +# Veja logs em tempo real +docker-compose logs -f # Docker +sudo journalctl -u freelanceros-agent -f # Systemd +``` + +### 💾 Backup Automático + +```bash +# Execute backup manual +./system/scripts/backup.sh + +# Configure cron para backups automáticos diários +0 2 * * * /path/to/FreelancerOS/system/scripts/backup.sh +``` + +### 🔑 Recursos de Auto-Sustentabilidade + +✅ **Recuperação Automática de Erros** - O agente se recupera automaticamente de falhas +✅ **Health Checks Periódicos** - Autodiagnóstico a cada 5 minutos +✅ **Logging Abrangente** - Rastreamento completo de todas as operações +✅ **Retry com Backoff Exponencial** - Tentativas inteligentes em caso de falha +✅ **Reinício Automático** - Docker/Systemd reinicia o agente se ele parar +✅ **Gestão de Recursos** - Monitoramento de memória e CPU + +📖 **[Guia Completo de Implantação](docs/DEPLOYMENT_GUIDE.md)** + +--- + ## 🛡️ Sistema de Regras de IA Este projeto adota uma política de **Tolerância Zero** para desorganização. Todas as IAs que interagirem com este repositório devem seguir estritamente o arquivo `AI_RULES.md`. diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..eb5dd88 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,31 @@ +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# FreelancerOS: Docker Compose Orchestration +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +version: '3.8' + +services: + freelancer-agent: + build: . + container_name: freelanceros-agent + restart: unless-stopped + env_file: + - .env + volumes: + # Persist data and logs + - ./data:/app/data + - ./logs:/app/logs + environment: + - PYTHONUNBUFFERED=1 + - TZ=America/Sao_Paulo + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + healthcheck: + test: ["CMD", "python3", "-c", "import os; exit(0 if os.path.exists('/app/data/agent_memory.db') else 1)"] + interval: 60s + timeout: 10s + retries: 3 + start_period: 30s diff --git a/docs/DEPLOYMENT_GUIDE.md b/docs/DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000..e834753 --- /dev/null +++ b/docs/DEPLOYMENT_GUIDE.md @@ -0,0 +1,340 @@ +# 🚀 GUIA DE IMPLANTAÇÃO - AGENTE AUTÔNOMO 24/7 + +Este guia explica como implantar o FreelancerOS Agent para operação contínua e autossustentável. + +--- + +## 📋 Pré-requisitos + +### Sistema Operacional +- Linux (Ubuntu 20.04+, Debian 10+, CentOS 8+) +- macOS 10.15+ +- Windows 10+ (com WSL2) + +### Software Necessário +- Python 3.8 ou superior +- Docker (opcional, recomendado) +- Git + +--- + +## 🐳 Opção 1: Implantação com Docker (Recomendado) + +Docker facilita a implantação e garante consistência em qualquer ambiente. + +### Passo 1: Instalar Docker + +```bash +# Ubuntu/Debian +curl -fsSL https://get.docker.com -o get-docker.sh +sudo sh get-docker.sh +sudo usermod -aG docker $USER + +# Instalar Docker Compose +sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose +sudo chmod +x /usr/local/bin/docker-compose +``` + +### Passo 2: Configurar Ambiente + +```bash +# Clone o repositório (se ainda não o fez) +git clone https://github.com/ManoAlee/FreelancerOS.git +cd FreelancerOS + +# Copie e edite o arquivo de configuração +cp .env.example .env +nano .env # ou use seu editor preferido +``` + +**Configure as seguintes variáveis importantes:** + +```bash +# Suas credenciais de email +MY_EMAIL=seu_email@gmail.com +MY_PASSWORD=sua_senha_de_app_aqui + +# Nicho alvo +TARGET_NICHE=advogados em são paulo + +# Comportamento +MODE=AGGRESSIVE +AUTO_SEND_EMAIL=True +``` + +### Passo 3: Implantar + +```bash +# Execute o script de implantação +./system/scripts/deploy_docker.sh +``` + +### Passo 4: Gerenciar o Agente + +```bash +# Ver logs em tempo real +docker-compose logs -f + +# Parar o agente +docker-compose down + +# Reiniciar o agente +docker-compose restart + +# Ver status +docker-compose ps +``` + +--- + +## 🖥️ Opção 2: Implantação com Systemd (Linux Nativo) + +Para servidores Linux sem Docker, use systemd para gerenciar o serviço. + +### Passo 1: Preparar o Ambiente + +```bash +# Clone o repositório +git clone https://github.com/ManoAlee/FreelancerOS.git +cd FreelancerOS + +# Configurar ambiente +cp .env.example .env +nano .env # edite suas credenciais +``` + +### Passo 2: Implantar como Serviço + +```bash +# Execute com sudo +sudo ./system/scripts/deploy_systemd.sh +``` + +Este script irá: +- Instalar dependências Python +- Criar o serviço systemd +- Habilitar início automático +- Iniciar o serviço + +### Passo 3: Gerenciar o Serviço + +```bash +# Ver logs em tempo real +sudo journalctl -u freelanceros-agent -f + +# Parar +sudo systemctl stop freelanceros-agent + +# Iniciar +sudo systemctl start freelanceros-agent + +# Reiniciar +sudo systemctl restart freelanceros-agent + +# Ver status +sudo systemctl status freelanceros-agent + +# Desabilitar início automático +sudo systemctl disable freelanceros-agent +``` + +--- + +## ☁️ Opção 3: Implantação na Nuvem + +### AWS EC2 + +```bash +# 1. Crie uma instância EC2 (Ubuntu 22.04) +# 2. Conecte via SSH +ssh -i sua-chave.pem ubuntu@seu-ip + +# 3. Instale Docker +curl -fsSL https://get.docker.com -o get-docker.sh +sudo sh get-docker.sh + +# 4. Clone e configure +git clone https://github.com/ManoAlee/FreelancerOS.git +cd FreelancerOS +cp .env.example .env +nano .env + +# 5. Implante +./system/scripts/deploy_docker.sh +``` + +### Google Cloud Platform (GCP) + +```bash +# 1. Crie uma VM Compute Engine +# 2. Mesmo processo da AWS EC2 +``` + +### DigitalOcean + +```bash +# 1. Crie um Droplet (Ubuntu) +# 2. Mesmo processo da AWS EC2 +``` + +### Heroku + +```bash +# 1. Instale Heroku CLI +curl https://cli-assets.heroku.com/install.sh | sh + +# 2. Login +heroku login + +# 3. Crie app +heroku create seu-app-freelanceros + +# 4. Configure variáveis de ambiente +heroku config:set MY_EMAIL=seu_email@gmail.com +heroku config:set MY_PASSWORD=sua_senha + +# 5. Deploy +git push heroku main +``` + +--- + +## 🔒 Segurança + +### Proteção de Credenciais + +1. **Nunca commite o arquivo .env** + ```bash + # Já está no .gitignore + echo ".env" >> .gitignore + ``` + +2. **Use senhas de aplicativo** (não sua senha real) + - Gmail: https://myaccount.google.com/apppasswords + - Gere uma senha específica para o agente + +3. **Restrinja acesso SSH** (se em servidor) + ```bash + # Edite sshd_config + sudo nano /etc/ssh/sshd_config + # PasswordAuthentication no + # PubkeyAuthentication yes + ``` + +--- + +## 📊 Monitoramento + +### Verificar Saúde do Agente + +```bash +# Docker +docker-compose ps +docker-compose logs --tail=50 + +# Systemd +systemctl status freelanceros-agent +journalctl -u freelanceros-agent --since "10 minutes ago" +``` + +### Métricas no Banco de Dados + +```bash +# Conecte ao container +docker-compose exec freelancer-agent python3 + +# No Python: +from system.data_pipeline.recorder import JobRecorder +recorder = JobRecorder() +print(recorder.get_stats()) +``` + +--- + +## 🔧 Troubleshooting + +### Problema: O agente não inicia + +**Solução:** +```bash +# Verifique logs +docker-compose logs + +# Verifique configuração +cat .env + +# Reconstrua a imagem +docker-compose build --no-cache +docker-compose up -d +``` + +### Problema: Erros de autenticação de email + +**Solução:** +1. Verifique se está usando senha de aplicativo +2. Habilite "Acesso de apps menos seguros" (Gmail) +3. Teste credenciais manualmente + +### Problema: O agente para após algum tempo + +**Solução:** +```bash +# Verifique memória e recursos +docker stats + +# Aumente recursos do container (docker-compose.yml) +# Ou use systemd que gerencia melhor +``` + +### Problema: Não encontra jobs + +**Solução:** +1. Verifique se os RSS feeds estão acessíveis +2. Ajuste `TARGET_NICHE` no .env +3. Reduza `MIN_CONFIDENCE_SCORE` + +--- + +## 🔄 Atualização + +### Atualizar o Agente + +```bash +# Para a execução +docker-compose down # ou sudo systemctl stop freelanceros-agent + +# Atualize o código +git pull origin main + +# Reconstrua e reinicie +docker-compose build +docker-compose up -d + +# Ou para systemd +sudo systemctl restart freelanceros-agent +``` + +--- + +## 📞 Suporte + +- **Issues:** https://github.com/ManoAlee/FreelancerOS/issues +- **Documentação:** README.md +- **Ética:** docs/ETHICS_AND_OPERATIONS.md + +--- + +## ✅ Checklist de Implantação + +- [ ] Docker instalado (ou Python 3.8+) +- [ ] Repositório clonado +- [ ] Arquivo .env configurado com credenciais +- [ ] Script de implantação executado +- [ ] Agente rodando (verificar logs) +- [ ] Health check passando +- [ ] Monitoramento configurado +- [ ] Backup de dados configurado + +--- + +**🎉 Parabéns! Seu agente está operacional 24/7!** diff --git a/system/ai_engine/autonomous_loop.py b/system/ai_engine/autonomous_loop.py index d876964..8aeaa89 100644 --- a/system/ai_engine/autonomous_loop.py +++ b/system/ai_engine/autonomous_loop.py @@ -1,66 +1,152 @@ # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ # ARCHON v5.0 AUTONOMOUS LOOP ENGINE +# Enhanced with error handling, logging, and recovery # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ import time import json import logging +import os +import sys +from datetime import datetime from typing import Dict, Any, List +from pathlib import Path from system.ai_engine.core import LLMEngine from system.data_pipeline.recorder import JobRecorder +from system.config.config import CONFIG + +# Configure logging +log_dir = Path(CONFIG.get('LOG_FILE', '/app/logs/agent.log')).parent +log_dir.mkdir(parents=True, exist_ok=True) + +logging.basicConfig( + level=getattr(logging, CONFIG.get('LOG_LEVEL', 'INFO')), + format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', + handlers=[ + logging.FileHandler(CONFIG.get('LOG_FILE', '/app/logs/agent.log')), + logging.StreamHandler(sys.stdout) + ] +) class AutonomousLoop: """ ARCHON: The Autonomous Reasoning System. Implements the Cycle: Evaluation -> Refinement -> High Value Action. + Enhanced with error handling and self-recovery. """ def __init__(self, objective: str): self.objective = objective - self.ai = LLMEngine() - self.memory = JobRecorder() + self.logger = logging.getLogger("ARCHON") + self.logger.info(f"🏛️ [ARCHON] Initializing with objective: {objective}") + + try: + self.ai = LLMEngine() + self.memory = JobRecorder() + except Exception as e: + self.logger.error(f"❌ [ARCHON] Initialization error: {e}") + raise + self.context = { "technical_scenario": {"status": "IDLE"}, "human_practices": {}, "synthesis": [] } - self.logger = logging.getLogger("ARCHON") + self.error_count = 0 + self.max_errors = CONFIG.get('MAX_RETRIES', 3) + self.retry_delay = CONFIG.get('RETRY_DELAY_SECONDS', 10) + self.last_health_check = time.time() + self.health_check_interval = CONFIG.get('HEALTH_CHECK_INTERVAL', 300) # 5 minutes + + self.logger.info("✅ [ARCHON] Initialization complete") + + def health_check(self): + """Performs self-diagnostic checks.""" + try: + current_time = time.time() + if current_time - self.last_health_check < self.health_check_interval: + return True + + self.logger.info("🏥 [ARCHON] Performing health check...") + + # Check database connectivity + stats = self.memory.get_stats() + self.logger.info(f"📊 [ARCHON] Database status: {stats}") + + # Check memory usage (basic check) + import psutil + process = psutil.Process() + memory_mb = process.memory_info().rss / 1024 / 1024 + self.logger.info(f"💾 [ARCHON] Memory usage: {memory_mb:.2f} MB") + + # Reset error count on successful health check + self.error_count = 0 + self.last_health_check = current_time + + self.logger.info("✅ [ARCHON] Health check passed") + return True + except Exception as e: + self.logger.error(f"⚠️ [ARCHON] Health check failed: {e}") + return False def cycle(self): - """Runs one full ARCHON cycle.""" - print("\n🏛️ [ARCHON] Starting Reasoning Cycle...") - - # 1. EVALUATION (Avaliação de Estado) - state = self._evaluate_state() - print(f" 1️⃣ State Assessment: {state['status']}") - - if state['status'] == "COMPLETED": - return "SLEEP" + """Runs one full ARCHON cycle with error handling.""" + try: + self.logger.info("\n🏛️ [ARCHON] Starting Reasoning Cycle...") + + # 1. EVALUATION (Avaliação de Estado) + state = self._evaluate_state() + self.logger.info(f" 1️⃣ State Assessment: {state['status']}") + + if state['status'] == "COMPLETED": + return "SLEEP" - # 2. REFINEMENT (Refinamento Contínuo) - refined_context = self._refine_context(state) - print(f" 2️⃣ Context Refined: {refined_context['ambiguity_level']}") + # 2. REFINEMENT (Refinamento Contínuo) + refined_context = self._refine_context(state) + self.logger.info(f" 2️⃣ Context Refined: {refined_context['ambiguity_level']}") - # 3. HIGH VALUE ACTION (Ação de Maior Valor) - actions = self._generate_actions(refined_context) - best_action = self._prioritize(actions) - print(f" 3️⃣ Selected High-Value Action: {best_action['name']} (Impact: {best_action['impact']})") + # 3. HIGH VALUE ACTION (Ação de Maior Valor) + actions = self._generate_actions(refined_context) + best_action = self._prioritize(actions) + self.logger.info(f" 3️⃣ Selected High-Value Action: {best_action['name']} (Impact: {best_action['impact']})") - # 4. EXECUTION w/ KERNEL PROTOCOL - self._execute(best_action) + # 4. EXECUTION w/ KERNEL PROTOCOL + self._execute(best_action) + + # Reset error count on successful cycle + self.error_count = 0 + return "SUCCESS" + + except Exception as e: + self.error_count += 1 + self.logger.error(f"❌ [ARCHON] Cycle error (attempt {self.error_count}/{self.max_errors}): {e}", exc_info=True) + + if self.error_count >= self.max_errors: + self.logger.critical("🚨 [ARCHON] Max errors reached. Initiating recovery...") + self._recovery_mode() + + return "ERROR" def _evaluate_state(self) -> Dict: """Checks objective measurability and evidence sufficiency.""" - stats = self.memory.get_stats() - - # ARCHON Epistemological Check - has_evidence = sum(stats.values()) > 0 - - return { - "status": "ACTIVE", - "evidence_quality": "HIGH" if has_evidence else "LOW", - "metrics": stats - } + try: + stats = self.memory.get_stats() + + # ARCHON Epistemological Check + has_evidence = sum(stats.values()) > 0 + + return { + "status": "ACTIVE", + "evidence_quality": "HIGH" if has_evidence else "LOW", + "metrics": stats + } + except Exception as e: + self.logger.error(f"⚠️ [ARCHON] State evaluation error: {e}") + return { + "status": "ERROR", + "evidence_quality": "UNKNOWN", + "metrics": {} + } def _refine_context(self, state) -> Dict: """Reduces ambiguity and increases technical precision.""" @@ -99,19 +185,71 @@ def _prioritize(self, actions: List[Dict]) -> Dict: def _execute(self, action): """Runs the action following KERNEL protocol.""" - print(f" 🚀 [KERNEL] Executing: {action['name']} as {action['persona']}...") - time.sleep(1) - print(f" ✅ [KERNEL] Output Evaluated. Logic Traceable.") + try: + self.logger.info(f" 🚀 [KERNEL] Executing: {action['name']} as {action['persona']}...") + time.sleep(1) + self.logger.info(f" ✅ [KERNEL] Output Evaluated. Logic Traceable.") + except Exception as e: + self.logger.error(f" ❌ [KERNEL] Execution error: {e}") + raise + + def _recovery_mode(self): + """Attempts to recover from critical errors.""" + self.logger.info("🔧 [ARCHON] Entering recovery mode...") + + try: + # Wait for a longer period + time.sleep(self.retry_delay * 3) + + # Reset internal state + self.context = { + "technical_scenario": {"status": "IDLE"}, + "human_practices": {}, + "synthesis": [] + } + + # Reset error count + self.error_count = 0 + + self.logger.info("✅ [ARCHON] Recovery complete. Resuming operations...") + except Exception as e: + self.logger.critical(f"🚨 [ARCHON] Recovery failed: {e}") + # Let the system restart via Docker/systemd def run_forever(self): - """The Main ARCHON Thread.""" + """The Main ARCHON Thread with enhanced reliability.""" + self.logger.info("🚀 [ARCHON] Starting infinite loop...") + + loop_count = 0 + while True: try: + loop_count += 1 + self.logger.info(f"\n{'='*60}") + self.logger.info(f"🔄 [ARCHON] Loop #{loop_count} | {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") + self.logger.info(f"{'='*60}") + + # Perform health check periodically + if not self.health_check(): + self.logger.warning("⚠️ [ARCHON] Health check failed, but continuing...") + + # Run cycle decision = self.cycle() + if decision == "SLEEP": - print("💤 Telos Achieved. Standing by...") - time.sleep(60) + self.logger.info("💤 Telos Achieved. Standing by...") + time.sleep(CONFIG.get('LOOP_INTERVAL_SECONDS', 60)) + elif decision == "ERROR": + self.logger.warning(f"⚠️ [ARCHON] Error in cycle. Waiting {self.retry_delay}s before retry...") + time.sleep(self.retry_delay) else: - time.sleep(5) + time.sleep(CONFIG.get('LOOP_INTERVAL_SECONDS', 60) / 10) # Quick iteration on success + except KeyboardInterrupt: + self.logger.info("\n⛔ [ARCHON] Shutdown signal received. Exiting gracefully...") break + except Exception as e: + self.logger.critical(f"🚨 [ARCHON] Unhandled exception in main loop: {e}", exc_info=True) + time.sleep(self.retry_delay * 2) + + self.logger.info("👋 [ARCHON] Shutdown complete.") diff --git a/system/config/config.py b/system/config/config.py index 33e987a..4244a89 100644 --- a/system/config/config.py +++ b/system/config/config.py @@ -1,24 +1,72 @@ # ⚙️ CENTRAL DE COMANDO (Configure uma vez, esqueça depois) +import os +from typing import List + +def get_env_bool(key: str, default: bool = False) -> bool: + """Convert environment variable to boolean.""" + value = os.getenv(key, str(default)) + return value.lower() in ('true', '1', 'yes', 'on') + +def get_env_int(key: str, default: int) -> int: + """Convert environment variable to integer.""" + try: + return int(os.getenv(key, str(default))) + except ValueError: + return default + +def get_env_list(key: str, default: List[str] = None) -> List[str]: + """Convert comma-separated environment variable to list.""" + value = os.getenv(key, '') + if value: + return [item.strip() for item in value.split(',')] + return default or [] + +# RSS Feeds from environment or defaults +rss_feeds = [] +for i in range(1, 11): # Support up to 10 RSS feeds + feed = os.getenv(f'RSS_FEED_{i}', '') + if feed: + rss_feeds.append(feed) + +if not rss_feeds: + rss_feeds = [ + "https://weworkremotely.com/categories/remote-back-end-programming-jobs.rss", + "https://weworkremotely.com/categories/remote-design-jobs.rss" + ] CONFIG = { # 🎯 QUEM VAMOS ATACAR? - "TARGET_NICHE": "advogados em são paulo", - "MAX_LEADS_PER_DAY": 50, + "TARGET_NICHE": os.getenv("TARGET_NICHE", "advogados em são paulo"), + "MAX_LEADS_PER_DAY": get_env_int("MAX_LEADS_PER_DAY", 50), # 🤖 COMPORTAMENTO DO ROBÔ - "MODE": "AGGRESSIVE", # 'SAFE' (Lento/Seguro) ou 'AGGRESSIVE' (Rápido) - "WORK_HOURS": [9, 18], # Trabalha apenas das 09h às 18h + "MODE": os.getenv("MODE", "AGGRESSIVE"), # 'SAFE' (Lento/Seguro) ou 'AGGRESSIVE' (Rápido) + "WORK_HOURS": [ + get_env_int("WORK_HOURS_START", 9), + get_env_int("WORK_HOURS_END", 18) + ], + "LOOP_INTERVAL_SECONDS": get_env_int("LOOP_INTERVAL_SECONDS", 60), + "MAX_RETRIES": get_env_int("MAX_RETRIES", 3), + "RETRY_DELAY_SECONDS": get_env_int("RETRY_DELAY_SECONDS", 10), # 📧 AUTOMAÇÃO DE VENDAS - "AUTO_SEND_EMAIL": True, # Se False, apenas salva o rascunho - "MY_EMAIL": "seu_email@gmail.com", - "MY_PASSWORD": "sua_senha_de_app", + "AUTO_SEND_EMAIL": get_env_bool("AUTO_SEND_EMAIL", True), + "MY_EMAIL": os.getenv("MY_EMAIL", "seu_email@gmail.com"), + "MY_PASSWORD": os.getenv("MY_PASSWORD", "sua_senha_de_app"), + "SMTP_HOST": os.getenv("SMTP_HOST", "smtp.gmail.com"), + "SMTP_PORT": get_env_int("SMTP_PORT", 587), # 🕷️ FONTES DE DADOS - "SOURCES": [ - "https://www.google.com/search?q={niche}", - "https://www.instagram.com/explore/tags/{niche}/" - ], + "SOURCES": rss_feeds, + + # 🛡️ SECURITY & FILTERS + "MIN_CONFIDENCE_SCORE": get_env_int("MIN_CONFIDENCE_SCORE", 75), + "BLACKLIST_WORDS": get_env_list("BLACKLIST_WORDS", ["senior", "lead", "architect"]), + "HEADLESS_BROWSER": get_env_bool("HEADLESS_BROWSER", True), + + # 📊 LOGGING + "LOG_LEVEL": os.getenv("LOG_LEVEL", "INFO"), + "LOG_FILE": os.getenv("LOG_FILE", "/app/logs/agent.log"), # 📝 MODELO DE PROPOSTA (O Robô preenche sozinho) "EMAIL_SUBJECT": "Parceria para {empresa}", diff --git a/system/config/freelanceros-agent.service b/system/config/freelanceros-agent.service new file mode 100644 index 0000000..5f67b94 --- /dev/null +++ b/system/config/freelanceros-agent.service @@ -0,0 +1,49 @@ +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# FreelancerOS: Systemd Service Configuration +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# +# Installation Instructions: +# 1. Edit this file and replace /path/to/FreelancerOS with your actual path +# 2. Copy to systemd: sudo cp freelanceros-agent.service /etc/systemd/system/ +# 3. Reload systemd: sudo systemctl daemon-reload +# 4. Enable service: sudo systemctl enable freelanceros-agent +# 5. Start service: sudo systemctl start freelanceros-agent +# 6. Check status: sudo systemctl status freelanceros-agent +# +# View logs: sudo journalctl -u freelanceros-agent -f + +[Unit] +Description=FreelancerOS Autonomous Agent +After=network.target +Wants=network-online.target + +[Service] +Type=simple +User=www-data +Group=www-data +WorkingDirectory=/path/to/FreelancerOS +Environment="PYTHONUNBUFFERED=1" +Environment="PYTHONPATH=/path/to/FreelancerOS" +EnvironmentFile=/path/to/FreelancerOS/.env + +# Main command +ExecStart=/usr/bin/python3 /path/to/FreelancerOS/projects/auto_agent/auto_main.py + +# Restart policy for 24/7 operation +Restart=always +RestartSec=10 +StartLimitInterval=60 +StartLimitBurst=5 + +# Logging +StandardOutput=journal +StandardError=journal +SyslogIdentifier=freelanceros-agent + +# Security hardening (optional) +NoNewPrivileges=true +PrivateTmp=true +ReadWritePaths=/path/to/FreelancerOS/data /path/to/FreelancerOS/logs + +[Install] +WantedBy=multi-user.target diff --git a/system/requirements.txt b/system/requirements.txt index e83b221..7e8538e 100644 --- a/system/requirements.txt +++ b/system/requirements.txt @@ -6,3 +6,7 @@ selenium webdriver-manager instagrapi tweepy +feedparser +python-dotenv +psutil +pyyaml diff --git a/system/scripts/backup.sh b/system/scripts/backup.sh new file mode 100755 index 0000000..b7a7b92 --- /dev/null +++ b/system/scripts/backup.sh @@ -0,0 +1,111 @@ +#!/bin/bash +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# FreelancerOS: Automated Backup Script +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +set -e + +# Configuration +PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +BACKUP_DIR="${PROJECT_DIR}/backups" +TIMESTAMP=$(date +"%Y%m%d_%H%M%S") +BACKUP_NAME="freelanceros_backup_${TIMESTAMP}" + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +echo "🔄 FreelancerOS Backup Script" +echo "=============================" +echo "" + +# Create backup directory +mkdir -p "${BACKUP_DIR}" + +# Create temporary backup location +TEMP_BACKUP="${BACKUP_DIR}/${BACKUP_NAME}" +mkdir -p "${TEMP_BACKUP}" + +echo "📦 Backing up to: ${TEMP_BACKUP}" +echo "" + +# Backup database +if [ -f "${PROJECT_DIR}/data/agent_memory.db" ]; then + echo -e "${GREEN}✓${NC} Backing up database..." + cp "${PROJECT_DIR}/data/agent_memory.db" "${TEMP_BACKUP}/" +else + echo -e "${YELLOW}⚠${NC} Database not found, skipping..." +fi + +# Backup logs (last 7 days) +if [ -d "${PROJECT_DIR}/logs" ]; then + echo -e "${GREEN}✓${NC} Backing up logs..." + mkdir -p "${TEMP_BACKUP}/logs" + find "${PROJECT_DIR}/logs" -type f -mtime -7 -exec cp {} "${TEMP_BACKUP}/logs/" \; +else + echo -e "${YELLOW}⚠${NC} Logs directory not found, skipping..." +fi + +# Backup configuration (excluding sensitive data) +if [ -f "${PROJECT_DIR}/.env.example" ]; then + echo -e "${GREEN}✓${NC} Backing up configuration template..." + cp "${PROJECT_DIR}/.env.example" "${TEMP_BACKUP}/" +fi + +if [ -f "${PROJECT_DIR}/projects/auto_agent/config.yaml" ]; then + echo -e "${GREEN}✓${NC} Backing up agent config..." + cp "${PROJECT_DIR}/projects/auto_agent/config.yaml" "${TEMP_BACKUP}/" +fi + +# Create backup metadata +echo -e "${GREEN}✓${NC} Creating backup metadata..." +cat > "${TEMP_BACKUP}/backup_info.txt" << EOF +FreelancerOS Backup +=================== +Date: $(date) +Hostname: $(hostname) +Project: FreelancerOS +Version: $(git describe --tags --always 2>/dev/null || echo "unknown") +Commit: $(git rev-parse HEAD 2>/dev/null || echo "unknown") + +Contents: +- Database (agent_memory.db) +- Logs (last 7 days) +- Configuration files + +Restore Instructions: +1. Extract this backup to your FreelancerOS directory +2. Copy agent_memory.db to data/ +3. Copy logs to logs/ +4. Reconfigure .env with your credentials +EOF + +# Compress backup +echo "" +echo "🗜️ Compressing backup..." +cd "${BACKUP_DIR}" +tar -czf "${BACKUP_NAME}.tar.gz" "${BACKUP_NAME}" +rm -rf "${BACKUP_NAME}" + +# Get backup size +BACKUP_SIZE=$(du -h "${BACKUP_NAME}.tar.gz" | cut -f1) + +echo "" +echo -e "${GREEN}✅ Backup completed successfully!${NC}" +echo "" +echo "📊 Backup Details:" +echo " File: ${BACKUP_NAME}.tar.gz" +echo " Size: ${BACKUP_SIZE}" +echo " Location: ${BACKUP_DIR}" +echo "" + +# Cleanup old backups (keep last 30 days) +echo "🧹 Cleaning up old backups (keeping last 30 days)..." +find "${BACKUP_DIR}" -name "freelanceros_backup_*.tar.gz" -mtime +30 -delete +REMAINING=$(find "${BACKUP_DIR}" -name "freelanceros_backup_*.tar.gz" | wc -l) +echo " Remaining backups: ${REMAINING}" + +echo "" +echo "✅ Done!" diff --git a/system/scripts/deploy_docker.sh b/system/scripts/deploy_docker.sh new file mode 100755 index 0000000..e635e41 --- /dev/null +++ b/system/scripts/deploy_docker.sh @@ -0,0 +1,66 @@ +#!/bin/bash +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# FreelancerOS: Docker Deployment Script +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +set -e + +echo "🚀 FreelancerOS Agent Deployment Script" +echo "========================================" + +# Check if Docker is installed +if ! command -v docker &> /dev/null; then + echo "❌ Docker is not installed. Please install Docker first." + exit 1 +fi + +# Check if docker-compose is installed +if ! command -v docker-compose &> /dev/null; then + echo "⚠️ docker-compose not found. Using 'docker compose' instead." + DOCKER_COMPOSE="docker compose" +else + DOCKER_COMPOSE="docker-compose" +fi + +# Check if .env exists +if [ ! -f .env ]; then + echo "⚠️ .env file not found. Creating from .env.example..." + if [ -f .env.example ]; then + cp .env.example .env + echo "✅ Created .env file. Please edit it with your credentials." + echo " Then run this script again." + exit 0 + else + echo "❌ .env.example not found. Cannot continue." + exit 1 + fi +fi + +# Create necessary directories +echo "📁 Creating necessary directories..." +mkdir -p data logs + +# Build the Docker image +echo "🔨 Building Docker image..." +$DOCKER_COMPOSE build + +# Start the service +echo "🚀 Starting FreelancerOS Agent..." +$DOCKER_COMPOSE up -d + +# Show status +echo "" +echo "✅ Deployment complete!" +echo "" +echo "📊 Service Status:" +$DOCKER_COMPOSE ps + +echo "" +echo "📝 To view logs:" +echo " $DOCKER_COMPOSE logs -f" +echo "" +echo "🛑 To stop the agent:" +echo " $DOCKER_COMPOSE down" +echo "" +echo "🔄 To restart the agent:" +echo " $DOCKER_COMPOSE restart" diff --git a/system/scripts/deploy_systemd.sh b/system/scripts/deploy_systemd.sh new file mode 100755 index 0000000..f941a63 --- /dev/null +++ b/system/scripts/deploy_systemd.sh @@ -0,0 +1,109 @@ +#!/bin/bash +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# FreelancerOS: Systemd Deployment Script +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +set -e + +echo "🚀 FreelancerOS Systemd Deployment Script" +echo "==========================================" + +# Check if running as root +if [ "$EUID" -ne 0 ]; then + echo "❌ Please run as root (use sudo)" + exit 1 +fi + +# Get the project directory +PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +echo "📁 Project directory: $PROJECT_DIR" + +# Check if .env exists +if [ ! -f "$PROJECT_DIR/.env" ]; then + echo "⚠️ .env file not found. Creating from .env.example..." + if [ -f "$PROJECT_DIR/.env.example" ]; then + cp "$PROJECT_DIR/.env.example" "$PROJECT_DIR/.env" + echo "✅ Created .env file. Please edit it with your credentials." + echo " Location: $PROJECT_DIR/.env" + echo " Then run this script again." + exit 0 + else + echo "❌ .env.example not found. Cannot continue." + exit 1 + fi +fi + +# Create necessary directories +echo "📁 Creating necessary directories..." +mkdir -p "$PROJECT_DIR/data" "$PROJECT_DIR/logs" + +# Install Python dependencies +echo "📦 Installing Python dependencies..." +pip3 install -r "$PROJECT_DIR/system/requirements.txt" + +# Create systemd service file +SERVICE_FILE="/etc/systemd/system/freelanceros-agent.service" +echo "📝 Creating systemd service file..." + +cat > "$SERVICE_FILE" << EOF +[Unit] +Description=FreelancerOS Autonomous Agent +After=network.target +Wants=network-online.target + +[Service] +Type=simple +User=$SUDO_USER +Group=$SUDO_USER +WorkingDirectory=$PROJECT_DIR +Environment="PYTHONUNBUFFERED=1" +Environment="PYTHONPATH=$PROJECT_DIR" +EnvironmentFile=$PROJECT_DIR/.env + +ExecStart=/usr/bin/python3 $PROJECT_DIR/projects/auto_agent/auto_main.py + +Restart=always +RestartSec=10 +StartLimitInterval=60 +StartLimitBurst=5 + +StandardOutput=journal +StandardError=journal +SyslogIdentifier=freelanceros-agent + +NoNewPrivileges=true +PrivateTmp=true +ReadWritePaths=$PROJECT_DIR/data $PROJECT_DIR/logs + +[Install] +WantedBy=multi-user.target +EOF + +echo "✅ Service file created: $SERVICE_FILE" + +# Reload systemd +echo "🔄 Reloading systemd..." +systemctl daemon-reload + +# Enable service +echo "✅ Enabling service..." +systemctl enable freelanceros-agent + +# Start service +echo "🚀 Starting service..." +systemctl start freelanceros-agent + +# Show status +echo "" +echo "✅ Deployment complete!" +echo "" +echo "📊 Service Status:" +systemctl status freelanceros-agent --no-pager + +echo "" +echo "📝 Useful commands:" +echo " View logs: sudo journalctl -u freelanceros-agent -f" +echo " Stop: sudo systemctl stop freelanceros-agent" +echo " Start: sudo systemctl start freelanceros-agent" +echo " Restart: sudo systemctl restart freelanceros-agent" +echo " Disable: sudo systemctl disable freelanceros-agent" diff --git a/system/scripts/health_check.py b/system/scripts/health_check.py new file mode 100755 index 0000000..4cd11a8 --- /dev/null +++ b/system/scripts/health_check.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python3 +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# FreelancerOS: Health Monitor & Status Reporter +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +import sys +import os +from pathlib import Path +from datetime import datetime, timedelta + +# Add project root to path +project_root = Path(__file__).parent.parent.parent +sys.path.insert(0, str(project_root)) + +from system.data_pipeline.recorder import JobRecorder + +def print_header(text): + """Print formatted header.""" + print(f"\n{'='*60}") + print(f" {text}") + print(f"{'='*60}\n") + +def check_database(): + """Check database connectivity and status.""" + try: + recorder = JobRecorder() + stats = recorder.get_stats() + + print("📊 Database Status: ✅ CONNECTED") + print(f" Location: {recorder.cursor.connection}") + return True, stats + except Exception as e: + print(f"📊 Database Status: ❌ ERROR") + print(f" Error: {e}") + return False, {} + +def check_logs(): + """Check log file status.""" + log_file = project_root / "logs" / "agent.log" + + if log_file.exists(): + size_mb = log_file.stat().st_size / (1024 * 1024) + modified = datetime.fromtimestamp(log_file.stat().st_mtime) + time_since = datetime.now() - modified + + print(f"📝 Log File: ✅ EXISTS") + print(f" Location: {log_file}") + print(f" Size: {size_mb:.2f} MB") + print(f" Last Modified: {modified.strftime('%Y-%m-%d %H:%M:%S')}") + print(f" ({time_since.seconds // 60} minutes ago)") + + # Check if log is recent (within last hour) + if time_since < timedelta(hours=1): + print(" Activity: 🟢 RECENT") + return True + else: + print(" Activity: 🟡 STALE") + return False + else: + print(f"📝 Log File: ❌ NOT FOUND") + print(f" Expected at: {log_file}") + return False + +def check_data_directory(): + """Check data directory status.""" + data_dir = project_root / "data" + + if data_dir.exists(): + files = list(data_dir.glob("*")) + print(f"💾 Data Directory: ✅ EXISTS") + print(f" Location: {data_dir}") + print(f" Files: {len(files)}") + return True + else: + print(f"💾 Data Directory: ❌ NOT FOUND") + return False + +def display_statistics(stats): + """Display job statistics.""" + print_header("Job Statistics") + + if not stats: + print(" No jobs recorded yet.") + return + + total = sum(stats.values()) + print(f" Total Jobs Tracked: {total}") + print() + + for status, count in stats.items(): + percentage = (count / total * 100) if total > 0 else 0 + bar_length = int(percentage / 2) + bar = "█" * bar_length + "░" * (50 - bar_length) + + emoji = { + "NEW": "🆕", + "ANALYZED": "🧠", + "APPLIED": "✅", + "REJECTED": "❌", + "ERROR": "⚠️" + }.get(status, "📋") + + print(f" {emoji} {status:12s}: {count:4d} [{bar}] {percentage:5.1f}%") + +def check_docker(): + """Check if running in Docker.""" + if os.path.exists('/.dockerenv'): + print("🐳 Environment: DOCKER") + return True + else: + print("💻 Environment: NATIVE") + return False + +def main(): + """Main health check routine.""" + print_header("FreelancerOS Agent Health Monitor") + print(f"🕐 Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") + print() + + # Environment check + check_docker() + print() + + # Component checks + issues = [] + + print_header("Component Status") + + db_ok, stats = check_database() + if not db_ok: + issues.append("Database connection failed") + print() + + log_ok = check_logs() + if not log_ok: + issues.append("Log file issues detected") + print() + + data_ok = check_data_directory() + if not data_ok: + issues.append("Data directory missing") + print() + + # Statistics + if db_ok: + display_statistics(stats) + + # Overall status + print_header("Overall Status") + + if not issues: + print(" 🎉 ALL SYSTEMS OPERATIONAL") + print(" ✅ Agent is running smoothly") + return 0 + else: + print(" ⚠️ ISSUES DETECTED:") + for issue in issues: + print(f" - {issue}") + return 1 + +if __name__ == "__main__": + exit_code = main() + sys.exit(exit_code) From b4c0d5d8d53162bc3b4b29d718513d4a3c821e7c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 19 Dec 2025 23:16:00 +0000 Subject: [PATCH 3/7] Add watchdog supervisor, notification system, and complete 24/7 automation Co-authored-by: ManoAlee <153291497+ManoAlee@users.noreply.github.com> --- .env.example | 4 + QUICKSTART.md | 190 +++++++++++++++++++++++ README.md | 9 +- system/ai_engine/autonomous_loop.py | 22 +++ system/modules/notifier.py | 163 ++++++++++++++++++++ system/scripts/setup_backup_cron.sh | 96 ++++++++++++ system/scripts/watchdog.py | 226 ++++++++++++++++++++++++++++ 7 files changed, 707 insertions(+), 3 deletions(-) create mode 100644 QUICKSTART.md create mode 100644 system/modules/notifier.py create mode 100755 system/scripts/setup_backup_cron.sh create mode 100755 system/scripts/watchdog.py diff --git a/.env.example b/.env.example index 7d60a84..7c2b4db 100644 --- a/.env.example +++ b/.env.example @@ -20,6 +20,10 @@ SMTP_PORT=587 MY_EMAIL=your_email@gmail.com MY_PASSWORD=your_app_password_here +# 🔔 NOTIFICATION SETTINGS +NOTIFICATION_EMAIL_ENABLED=true +NOTIFICATION_EMAIL=your_email@gmail.com + # 🔑 API KEYS (if needed for future integrations) # OPENAI_API_KEY=your_openai_key_here # ANTHROPIC_API_KEY=your_anthropic_key_here diff --git a/QUICKSTART.md b/QUICKSTART.md new file mode 100644 index 0000000..80b3060 --- /dev/null +++ b/QUICKSTART.md @@ -0,0 +1,190 @@ +# 🚀 QUICK START - FreelancerOS 24/7 Agent + +Guia rápido para colocar seu agente autônomo em operação em menos de 5 minutos! + +--- + +## ⚡ Início Rápido com Docker + +### 1. Clone e Configure (2 minutos) + +```bash +# Clone o repositório +git clone https://github.com/ManoAlee/FreelancerOS.git +cd FreelancerOS + +# Configure credenciais +cp .env.example .env +nano .env # ou seu editor preferido +``` + +**Configurações Mínimas Necessárias:** +```bash +MY_EMAIL=seu_email@gmail.com +MY_PASSWORD=sua_senha_de_app +TARGET_NICHE=seu_nicho_aqui +``` + +### 2. Implante (1 minuto) + +```bash +# Execute o script de deployment +chmod +x system/scripts/deploy_docker.sh +./system/scripts/deploy_docker.sh +``` + +### 3. Monitore + +```bash +# Ver logs em tempo real +docker-compose logs -f + +# Ver status de saúde +python3 system/scripts/health_check.py +``` + +✅ **Pronto!** Seu agente está rodando 24/7 e se recuperando automaticamente de erros. + +--- + +## 📊 Comandos Úteis + +### Gerenciamento Docker + +```bash +# Ver status +docker-compose ps + +# Parar +docker-compose down + +# Reiniciar +docker-compose restart + +# Ver logs (últimas 100 linhas) +docker-compose logs --tail=100 +``` + +### Monitoramento + +```bash +# Health check completo +python3 system/scripts/health_check.py + +# Ver estatísticas do banco de dados +python3 -c "from system.data_pipeline.recorder import JobRecorder; print(JobRecorder().get_stats())" +``` + +### Backup + +```bash +# Backup manual +./system/scripts/backup.sh + +# Configurar backups automáticos +./system/scripts/setup_backup_cron.sh +``` + +--- + +## 🔧 Troubleshooting Rápido + +### Problema: Container não inicia + +```bash +# Ver erros +docker-compose logs + +# Reconstruir imagem +docker-compose build --no-cache +docker-compose up -d +``` + +### Problema: Erros de autenticação email + +1. Use **senha de aplicativo**, não sua senha normal +2. Gmail: https://myaccount.google.com/apppasswords +3. Habilite acesso a apps menos seguros (se necessário) + +### Problema: Não encontra jobs + +1. Verifique RSS feeds no .env +2. Ajuste `MIN_CONFIDENCE_SCORE` (tente 50 para testes) +3. Mude `TARGET_NICHE` para algo mais amplo + +--- + +## 🌐 Opção 2: Deployment em VPS/Servidor + +### Requerimentos +- Ubuntu 20.04+ / Debian 10+ / CentOS 8+ +- Python 3.8+ +- Acesso root/sudo + +### Passos + +```bash +# 1. Clone +git clone https://github.com/ManoAlee/FreelancerOS.git +cd FreelancerOS + +# 2. Configure +cp .env.example .env +nano .env + +# 3. Implante como serviço systemd +sudo ./system/scripts/deploy_systemd.sh + +# 4. Verifique status +sudo systemctl status freelanceros-agent +``` + +--- + +## 📱 Notificações + +Para receber alertas por email sobre o status do agente: + +```bash +# No .env, configure: +NOTIFICATION_EMAIL_ENABLED=true +NOTIFICATION_EMAIL=seu_email@gmail.com +``` + +Você receberá notificações sobre: +- ✅ Início do agente +- ⚠️ Erros críticos +- 🔄 Reinicializações +- 📊 Resumo diário de atividades +- 🎯 Marcos (100, 200, 300 jobs processados) + +--- + +## 🎯 Próximos Passos + +Após ter o agente rodando: + +1. **Monitore os logs** nas primeiras horas +2. **Ajuste configurações** baseado nos resultados +3. **Configure backups automáticos** +4. **Personalize propostas** em `system/config/config.py` +5. **Expanda fontes** adicionando mais RSS feeds + +--- + +## 📚 Documentação Completa + +- **Guia de Implantação Detalhado**: [docs/DEPLOYMENT_GUIDE.md](docs/DEPLOYMENT_GUIDE.md) +- **README Principal**: [README.md](README.md) +- **Código de Ética**: [docs/ETHICS_AND_OPERATIONS.md](docs/ETHICS_AND_OPERATIONS.md) + +--- + +## 🆘 Suporte + +- **Issues**: https://github.com/ManoAlee/FreelancerOS/issues +- **Documentação**: https://github.com/ManoAlee/FreelancerOS + +--- + +**🎉 Bem-vindo ao FreelancerOS - Seu negócio agora opera 24/7!** diff --git a/README.md b/README.md index 8d1f6e1..9a2b9a2 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ Bem-vindo ao seu escritório virtual. Este repositório centraliza todas as oper **Filosofia:** Alta Performance, Ética Profissional e Resultados Reais. +> 🚀 **NOVO**: Agente 24/7 Totalmente Autônomo! [Quick Start em 5 minutos →](QUICKSTART.md) + --- ## 📜 Índice @@ -11,9 +13,10 @@ Bem-vindo ao seu escritório virtual. Este repositório centraliza todas as oper 1. [Diretrizes & Ética](#-diretrizes--ética) 2. [FreelancerOS (Utility Core)](#-freelanceros-the-ultimate-utility-core) 3. [Agentes Autônomos (Zero-Touch)](#-agente-freelancer-autônomo-zero-touch) -4. [Ventures (Triple Threat)](#-ventures-the-freelancer-triple-threat-engine) -5. [Plano de Ação](#-plano-de-ação-diário) -6. [Sistema de Regras de IA](#-sistema-de-regras-para-ia) +4. [Automação 24/7](#-novo-automação-247-e-auto-sustentabilidade) +5. [Ventures (Triple Threat)](#-ventures-the-freelancer-triple-threat-engine) +6. [Plano de Ação](#-plano-de-ação-diário) +7. [Sistema de Regras de IA](#-sistema-de-regras-para-ia) --- diff --git a/system/ai_engine/autonomous_loop.py b/system/ai_engine/autonomous_loop.py index 8aeaa89..e438f7f 100644 --- a/system/ai_engine/autonomous_loop.py +++ b/system/ai_engine/autonomous_loop.py @@ -15,6 +15,7 @@ from system.ai_engine.core import LLMEngine from system.data_pipeline.recorder import JobRecorder from system.config.config import CONFIG +from system.modules.notifier import get_notifier # Configure logging log_dir = Path(CONFIG.get('LOG_FILE', '/app/logs/agent.log')).parent @@ -38,6 +39,7 @@ class AutonomousLoop: def __init__(self, objective: str): self.objective = objective self.logger = logging.getLogger("ARCHON") + self.notifier = get_notifier() self.logger.info(f"🏛️ [ARCHON] Initializing with objective: {objective}") try: @@ -45,6 +47,7 @@ def __init__(self, objective: str): self.memory = JobRecorder() except Exception as e: self.logger.error(f"❌ [ARCHON] Initialization error: {e}") + self.notifier.notify_error(str(e), "Initialization") raise self.context = { @@ -57,8 +60,10 @@ def __init__(self, objective: str): self.retry_delay = CONFIG.get('RETRY_DELAY_SECONDS', 10) self.last_health_check = time.time() self.health_check_interval = CONFIG.get('HEALTH_CHECK_INTERVAL', 300) # 5 minutes + self.jobs_processed_count = 0 self.logger.info("✅ [ARCHON] Initialization complete") + self.notifier.notify_agent_started() def health_check(self): """Performs self-diagnostic checks.""" @@ -196,6 +201,7 @@ def _execute(self, action): def _recovery_mode(self): """Attempts to recover from critical errors.""" self.logger.info("🔧 [ARCHON] Entering recovery mode...") + self.notifier.notify_restart(self.error_count, self.max_errors) try: # Wait for a longer period @@ -214,6 +220,7 @@ def _recovery_mode(self): self.logger.info("✅ [ARCHON] Recovery complete. Resuming operations...") except Exception as e: self.logger.critical(f"🚨 [ARCHON] Recovery failed: {e}") + self.notifier.notify_critical(f"Recovery failed: {e}") # Let the system restart via Docker/systemd def run_forever(self): @@ -221,6 +228,7 @@ def run_forever(self): self.logger.info("🚀 [ARCHON] Starting infinite loop...") loop_count = 0 + last_daily_report = datetime.now().date() while True: try: @@ -233,6 +241,17 @@ def run_forever(self): if not self.health_check(): self.logger.warning("⚠️ [ARCHON] Health check failed, but continuing...") + # Send daily summary + current_date = datetime.now().date() + if current_date != last_daily_report: + stats = self.memory.get_stats() + self.notifier.notify_daily_summary(stats) + last_daily_report = current_date + + # Check for milestones + if self.jobs_processed_count > 0 and self.jobs_processed_count % 100 == 0: + self.notifier.notify_job_milestone(f"{self.jobs_processed_count} jobs processed", self.jobs_processed_count) + # Run cycle decision = self.cycle() @@ -243,13 +262,16 @@ def run_forever(self): self.logger.warning(f"⚠️ [ARCHON] Error in cycle. Waiting {self.retry_delay}s before retry...") time.sleep(self.retry_delay) else: + self.jobs_processed_count += 1 time.sleep(CONFIG.get('LOOP_INTERVAL_SECONDS', 60) / 10) # Quick iteration on success except KeyboardInterrupt: self.logger.info("\n⛔ [ARCHON] Shutdown signal received. Exiting gracefully...") + self.notifier.notify_agent_stopped("User interrupt") break except Exception as e: self.logger.critical(f"🚨 [ARCHON] Unhandled exception in main loop: {e}", exc_info=True) + self.notifier.notify_error(str(e), "Main loop exception") time.sleep(self.retry_delay * 2) self.logger.info("👋 [ARCHON] Shutdown complete.") diff --git a/system/modules/notifier.py b/system/modules/notifier.py new file mode 100644 index 0000000..85eedb1 --- /dev/null +++ b/system/modules/notifier.py @@ -0,0 +1,163 @@ +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# FreelancerOS: Notification System +# Sends alerts for critical events +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +import os +import logging +import smtplib +from email.mime.text import MIMEText +from email.mime.multipart import MIMEMultipart +from datetime import datetime +from typing import Optional + +logger = logging.getLogger("Notifier") + +class Notifier: + """Handles notifications via email and other channels.""" + + def __init__(self): + self.email_enabled = os.getenv("NOTIFICATION_EMAIL_ENABLED", "false").lower() == "true" + self.smtp_host = os.getenv("SMTP_HOST", "smtp.gmail.com") + self.smtp_port = int(os.getenv("SMTP_PORT", "587")) + self.from_email = os.getenv("MY_EMAIL", "") + self.from_password = os.getenv("MY_PASSWORD", "") + self.to_email = os.getenv("NOTIFICATION_EMAIL", self.from_email) + + def send_email(self, subject: str, body: str, priority: str = "normal"): + """Send email notification.""" + if not self.email_enabled: + logger.debug("Email notifications disabled") + return False + + if not self.from_email or not self.from_password: + logger.warning("Email credentials not configured") + return False + + try: + # Create message + msg = MIMEMultipart() + msg['From'] = self.from_email + msg['To'] = self.to_email + msg['Subject'] = f"[FreelancerOS] {subject}" + + # Add priority header + if priority == "high": + msg['X-Priority'] = '1' + msg['Importance'] = 'high' + + # HTML body with styling + html_body = f""" + +
+ + + +{body.replace(chr(10), '
')}
{body.replace(chr(10), '
')}
{html.escape(body).replace(chr(10), '
')}
{html.escape(body).replace(chr(10), '
')}
{html.escape(body).replace('\n', '
')}