File size: 7,385 Bytes
c330796
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
"""
OpenCLAW Agent β€” HuggingFace Spaces Dashboard
================================================
Gradio interface with background agent loop.
"""
import os
import sys
import json
import threading
import time
import logging
import gradio as gr
from datetime import datetime, timezone
from pathlib import Path

# Setup path
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))

from core.config import Config
from core.agent import OpenCLAWAgent, AgentState
from core.strategy import StrategyReflector
from research.arxiv_fetcher import ArxivFetcher

# Logging
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger("openclaw")

STATE_DIR = Path(os.getenv("STATE_DIR", "state"))

# Background agent thread
agent_running = False
cycle_log = []


def run_background_agent():
    """Background thread for autonomous operation."""
    global agent_running, cycle_log
    agent_running = True
    interval = int(os.getenv("DAEMON_INTERVAL", "3600"))
    
    while agent_running:
        try:
            config = Config.from_env()
            agent = OpenCLAWAgent(config)
            results = agent.run_cycle()
            
            cycle_log.append({
                "time": datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M UTC"),
                "cycle": results.get("cycle", "?"),
                "actions": len(results.get("actions", [])),
                "details": results.get("actions", [])
            })
            # Keep last 50 entries
            cycle_log = cycle_log[-50:]
            
        except Exception as e:
            logger.error(f"Cycle error: {e}")
            cycle_log.append({
                "time": datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M UTC"),
                "error": str(e)
            })
        
        time.sleep(interval)


def get_status():
    """Get current agent status as formatted text."""
    try:
        config = Config.from_env()
        agent = OpenCLAWAgent(config)
        status = agent.get_status()
        
        lines = [
            "πŸ€– **OpenCLAW Autonomous Agent**",
            f"Advanced AI Systems Laboratory, Madrid",
            "",
            f"πŸ“Š **Statistics:**",
            f"  β€’ Cycles completed: {status['cycle_count']}",
            f"  β€’ Posts created: {status['posts_created']}",
            f"  β€’ Engagements: {status['engagement_count']}",
            f"  β€’ Papers shared: {status['papers_posted']}",
            "",
            f"πŸ”§ **Services:** {', '.join(status['services']) or 'None configured'}",
            f"🧠 **LLM:** {'βœ… Online' if status['llm_available'] else '⚠️ Offline'}",
            f"⚠️  **Errors:** {status['errors_count']}",
            "",
            f"πŸ• **Last Research:** {status['last_research'] or 'Never'}",
            f"πŸ“ **Last Post:** {status['last_post'] or 'Never'}",
            f"πŸ’¬ **Last Engage:** {status['last_engage'] or 'Never'}",
        ]
        return "\n".join(lines)
    except Exception as e:
        return f"Error getting status: {e}"


def get_papers():
    """Get cached research papers."""
    try:
        fetcher = ArxivFetcher()
        papers = fetcher.get_all_papers()
        
        lines = [f"πŸ“š **{len(papers)} papers available:**\n"]
        for p in papers:
            lines.append(f"**{p.title}**")
            lines.append(f"  Authors: {', '.join(p.authors)}")
            lines.append(f"  URL: {p.url}")
            lines.append("")
        return "\n".join(lines)
    except Exception as e:
        return f"Error fetching papers: {e}"


def get_cycle_log():
    """Get recent cycle log."""
    if not cycle_log:
        return "No cycles completed yet. Agent will run its first cycle within 1 hour."
    
    lines = ["πŸ“‹ **Recent Agent Activity:**\n"]
    for entry in reversed(cycle_log[-20:]):
        if "error" in entry:
            lines.append(f"❌ {entry['time']}: Error - {entry['error']}")
        else:
            lines.append(f"βœ… {entry['time']}: Cycle #{entry['cycle']} β€” {entry['actions']} actions")
            for a in entry.get("details", []):
                status = "βœ…" if a.get("status") == "ok" else "⚠️"
                lines.append(f"    {status} {a.get('task')}: {a.get('status')}")
    
    return "\n".join(lines)


def run_manual_cycle():
    """Manually trigger an agent cycle."""
    try:
        config = Config.from_env()
        agent = OpenCLAWAgent(config)
        results = agent.run_cycle()
        
        lines = [f"βœ… Cycle #{results['cycle']} completed!\n"]
        for a in results.get("actions", []):
            status = "βœ…" if a.get("status") == "ok" else "⚠️"
            lines.append(f"{status} {a.get('task')}: {json.dumps(a, indent=2)}")
        
        return "\n".join(lines)
    except Exception as e:
        return f"❌ Error: {e}"


def get_strategy():
    """Run strategy analysis."""
    try:
        reflector = StrategyReflector(str(STATE_DIR))
        report = reflector.analyze()
        
        lines = [
            "🧠 **Strategy Analysis**\n",
            "**Metrics:**"
        ]
        for k, v in report["metrics"].items():
            lines.append(f"  β€’ {k}: {v}")
        
        lines.append("\n**Insights:**")
        for i in report["insights"]:
            lines.append(f"  πŸ’‘ {i}")
        
        lines.append("\n**Recommended Actions:**")
        for a in report["strategy"]["actions"]:
            lines.append(f"  🎯 {a}")
        
        return "\n".join(lines)
    except Exception as e:
        return f"Error: {e}"


# Start background agent
bg_thread = threading.Thread(target=run_background_agent, daemon=True)
bg_thread.start()
logger.info("πŸ€– Background agent started")

# Gradio Interface
with gr.Blocks(title="OpenCLAW Agent", theme=gr.themes.Monochrome()) as demo:
    gr.Markdown("""
    # πŸ€– OpenCLAW β€” Autonomous Multi-Agent Scientific Research Platform
    **Advanced AI Systems Laboratory, Madrid, Spain**  
    *Francisco Angulo de Lafuente β€” Winner NVIDIA & LlamaIndex Developer Contest 2024*
    
    [GitHub](https://github.com/Agnuxo1) | [Scholar](https://scholar.google.com/citations?user=6nOpJ9IAAAAJ) | [ArXiv](https://arxiv.org/search/cs?searchtype=author&query=de+Lafuente,+F+A) | [Moltbook](https://www.moltbook.com/u/OpenCLAW-Neuromorphic)
    """)
    
    with gr.Tab("πŸ“Š Status"):
        status_output = gr.Markdown(get_status())
        gr.Button("πŸ”„ Refresh").click(fn=get_status, outputs=status_output)
    
    with gr.Tab("πŸ“‹ Activity Log"):
        log_output = gr.Markdown(get_cycle_log())
        gr.Button("πŸ”„ Refresh").click(fn=get_cycle_log, outputs=log_output)
    
    with gr.Tab("πŸ“š Research Papers"):
        papers_output = gr.Markdown(get_papers())
        gr.Button("πŸ”„ Refresh").click(fn=get_papers, outputs=papers_output)
    
    with gr.Tab("🧠 Strategy"):
        strategy_output = gr.Markdown(get_strategy())
        gr.Button("πŸ”„ Analyze").click(fn=get_strategy, outputs=strategy_output)
    
    with gr.Tab("⚑ Manual Trigger"):
        gr.Markdown("Manually trigger an agent cycle:")
        trigger_output = gr.Markdown("")
        gr.Button("πŸš€ Run Cycle Now").click(fn=run_manual_cycle, outputs=trigger_output)


if __name__ == "__main__":
    demo.launch(server_name="0.0.0.0", server_port=7860)