""" OpenCLAW Web Server + Dashboard ================================ Lightweight Flask app for Render.com deployment. Serves as health endpoint + agent dashboard + webhook receiver. """ import os import sys import json import threading import time from datetime import datetime, timezone from pathlib import Path sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from flask import Flask, jsonify, render_template_string from core.config import Config from core.agent import OpenCLAWAgent, AgentState app = Flask(__name__) STATE_DIR = Path(os.getenv("STATE_DIR", "state")) # Background agent thread agent_thread = None agent_running = False def run_agent_loop(): """Background thread running the agent.""" global agent_running interval = int(os.getenv("DAEMON_INTERVAL", "3600")) # 1 hour default while agent_running: try: config = Config.from_env() agent = OpenCLAWAgent(config) agent.run_cycle() except Exception as e: print(f"Agent cycle error: {e}") # Sleep in small chunks for graceful shutdown for _ in range(interval): if not agent_running: break time.sleep(1) DASHBOARD_HTML = """ OpenCLAW Agent Dashboard

🤖 OpenCLAW Autonomous Agent

Advanced AI Systems Laboratory — Madrid, Spain

📊 Agent Status

{{ status.cycle_count }}
Cycles
{{ status.posts_created }}
Posts
{{ status.engagement_count }}
Engagements
{{ status.papers_posted }}
Papers Shared

🔧 Services

{% for s in status.services %}✅ {{ s }}  {% endfor %}

LLM: {{ '✅ Online' if status.llm_available else '⚠️ Offline' }}

🔗 Links

GitHub | Moltbook | Scholar | ArXiv

📋 Last Cycle

{{ last_cycle }}
""" @app.route("/") def dashboard(): """Dashboard page.""" config = Config.from_env() agent = OpenCLAWAgent(config) status = agent.get_status() last_cycle = "{}" lc_file = STATE_DIR / "last_cycle.json" if lc_file.exists(): last_cycle = json.dumps(json.loads(lc_file.read_text()), indent=2) return render_template_string(DASHBOARD_HTML, status=status, last_cycle=last_cycle) @app.route("/health") def health(): """Health check endpoint.""" return jsonify({ "status": "healthy", "agent": "OpenCLAW-Neuromorphic", "timestamp": datetime.now(timezone.utc).isoformat(), }) @app.route("/status") def status(): """JSON status endpoint.""" config = Config.from_env() agent = OpenCLAWAgent(config) return jsonify(agent.get_status()) @app.route("/trigger", methods=["POST"]) def trigger(): """Manually trigger an agent cycle.""" try: config = Config.from_env() agent = OpenCLAWAgent(config) results = agent.run_cycle() return jsonify(results) except Exception as e: return jsonify({"error": str(e)}), 500 if __name__ == "__main__": global agent_running, agent_thread # Start background agent thread agent_running = True agent_thread = threading.Thread(target=run_agent_loop, daemon=True) agent_thread.start() print("🤖 Background agent started") # Start web server port = int(os.getenv("PORT", "10000")) app.run(host="0.0.0.0", port=port)