Agnuxo commited on
Commit
062ecfe
Β·
verified Β·
1 Parent(s): 62ff259

Upload app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +171 -146
app.py CHANGED
@@ -1,7 +1,7 @@
1
  """
2
- OpenCLAW Agent β€” HuggingFace Spaces Dashboard
3
- ================================================
4
- Gradio interface with background agent loop.
5
  """
6
  import os
7
  import sys
@@ -13,7 +13,6 @@ import gradio as gr
13
  from datetime import datetime, timezone
14
  from pathlib import Path
15
 
16
- # Setup path
17
  sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
18
 
19
  from core.config import Config
@@ -21,192 +20,218 @@ from core.agent import OpenCLAWAgent, AgentState
21
  from core.strategy import StrategyReflector
22
  from research.arxiv_fetcher import ArxivFetcher
23
 
24
- # Logging
25
  logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
26
  logger = logging.getLogger("openclaw")
27
 
28
  STATE_DIR = Path(os.getenv("STATE_DIR", "state"))
 
 
29
 
30
- # Background agent thread
31
  agent_running = False
32
  cycle_log = []
 
33
 
34
 
 
 
 
35
  def run_background_agent():
36
- """Background thread for autonomous operation."""
37
- global agent_running, cycle_log
38
  agent_running = True
39
  interval = int(os.getenv("DAEMON_INTERVAL", "3600"))
40
 
41
- while agent_running:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  try:
43
- config = Config.from_env()
44
- agent = OpenCLAWAgent(config)
45
  results = agent.run_cycle()
46
-
47
- cycle_log.append({
48
- "time": datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M UTC"),
49
- "cycle": results.get("cycle", "?"),
50
- "actions": len(results.get("actions", [])),
51
- "details": results.get("actions", [])
52
- })
53
- # Keep last 50 entries
54
- cycle_log = cycle_log[-50:]
55
-
56
  except Exception as e:
57
- logger.error(f"Cycle error: {e}")
58
- cycle_log.append({
59
- "time": datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M UTC"),
60
- "error": str(e)
61
- })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
 
63
  time.sleep(interval)
64
 
65
 
66
- def get_status():
67
- """Get current agent status as formatted text."""
68
- try:
69
- config = Config.from_env()
70
- agent = OpenCLAWAgent(config)
71
- status = agent.get_status()
72
-
73
- lines = [
74
- "πŸ€– **OpenCLAW Autonomous Agent**",
75
- f"Advanced AI Systems Laboratory, Madrid",
76
- "",
77
- f"πŸ“Š **Statistics:**",
78
- f" β€’ Cycles completed: {status['cycle_count']}",
79
- f" β€’ Posts created: {status['posts_created']}",
80
- f" β€’ Engagements: {status['engagement_count']}",
81
- f" β€’ Papers shared: {status['papers_posted']}",
82
- "",
83
- f"πŸ”§ **Services:** {', '.join(status['services']) or 'None configured'}",
84
- f"🧠 **LLM:** {'βœ… Online' if status['llm_available'] else '⚠️ Offline'}",
85
- f"⚠️ **Errors:** {status['errors_count']}",
86
- "",
87
- f"πŸ• **Last Research:** {status['last_research'] or 'Never'}",
88
- f"πŸ“ **Last Post:** {status['last_post'] or 'Never'}",
89
- f"πŸ’¬ **Last Engage:** {status['last_engage'] or 'Never'}",
90
- ]
91
- return "\n".join(lines)
92
- except Exception as e:
93
- return f"Error getting status: {e}"
94
 
95
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  def get_papers():
97
- """Get cached research papers."""
98
- try:
99
- fetcher = ArxivFetcher()
100
- papers = fetcher.get_all_papers()
101
-
102
- lines = [f"πŸ“š **{len(papers)} papers available:**\n"]
103
- for p in papers:
104
- lines.append(f"**{p.title}**")
105
- lines.append(f" Authors: {', '.join(p.authors)}")
106
- lines.append(f" URL: {p.url}")
107
- lines.append("")
108
- return "\n".join(lines)
109
- except Exception as e:
110
- return f"Error fetching papers: {e}"
111
 
 
 
 
 
112
 
113
- def get_cycle_log():
114
- """Get recent cycle log."""
115
- if not cycle_log:
116
- return "No cycles completed yet. Agent will run its first cycle within 1 hour."
117
-
118
- lines = ["πŸ“‹ **Recent Agent Activity:**\n"]
119
- for entry in reversed(cycle_log[-20:]):
120
- if "error" in entry:
121
- lines.append(f"❌ {entry['time']}: Error - {entry['error']}")
122
- else:
123
- lines.append(f"βœ… {entry['time']}: Cycle #{entry['cycle']} β€” {entry['actions']} actions")
124
- for a in entry.get("details", []):
125
- status = "βœ…" if a.get("status") == "ok" else "⚠️"
126
- lines.append(f" {status} {a.get('task')}: {a.get('status')}")
127
-
128
- return "\n".join(lines)
129
 
 
 
130
 
131
- def run_manual_cycle():
132
- """Manually trigger an agent cycle."""
133
  try:
134
- config = Config.from_env()
135
- agent = OpenCLAWAgent(config)
136
- results = agent.run_cycle()
137
-
138
- lines = [f"βœ… Cycle #{results['cycle']} completed!\n"]
139
- for a in results.get("actions", []):
140
- status = "βœ…" if a.get("status") == "ok" else "⚠️"
141
- lines.append(f"{status} {a.get('task')}: {json.dumps(a, indent=2)}")
142
-
143
- return "\n".join(lines)
144
  except Exception as e:
145
- return f"❌ Error: {e}"
146
-
147
 
148
- def get_strategy():
149
- """Run strategy analysis."""
150
  try:
151
- reflector = StrategyReflector(str(STATE_DIR))
152
- report = reflector.analyze()
153
-
154
- lines = [
155
- "🧠 **Strategy Analysis**\n",
156
- "**Metrics:**"
157
- ]
158
- for k, v in report["metrics"].items():
159
- lines.append(f" β€’ {k}: {v}")
160
-
161
- lines.append("\n**Insights:**")
162
- for i in report["insights"]:
163
- lines.append(f" πŸ’‘ {i}")
164
-
165
- lines.append("\n**Recommended Actions:**")
166
- for a in report["strategy"]["actions"]:
167
- lines.append(f" 🎯 {a}")
168
-
169
- return "\n".join(lines)
170
  except Exception as e:
171
  return f"Error: {e}"
172
 
173
 
174
- # Start background agent
175
- bg_thread = threading.Thread(target=run_background_agent, daemon=True)
176
- bg_thread.start()
177
- logger.info("πŸ€– Background agent started")
178
-
179
- # Gradio Interface
180
- with gr.Blocks(title="OpenCLAW Agent", theme=gr.themes.Monochrome()) as demo:
181
  gr.Markdown("""
182
- # πŸ€– OpenCLAW β€” Autonomous Multi-Agent Scientific Research Platform
183
- **Advanced AI Systems Laboratory, Madrid, Spain**
184
- *Francisco Angulo de Lafuente β€” Winner NVIDIA & LlamaIndex Developer Contest 2024*
185
 
186
- [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)
187
  """)
188
 
189
- with gr.Tab("πŸ“Š Status"):
190
- status_output = gr.Markdown(get_status())
191
- gr.Button("πŸ”„ Refresh").click(fn=get_status, outputs=status_output)
 
192
 
193
- with gr.Tab("πŸ“‹ Activity Log"):
194
- log_output = gr.Markdown(get_cycle_log())
195
- gr.Button("πŸ”„ Refresh").click(fn=get_cycle_log, outputs=log_output)
 
196
 
197
- with gr.Tab("πŸ“š Research Papers"):
198
- papers_output = gr.Markdown(get_papers())
199
- gr.Button("πŸ”„ Refresh").click(fn=get_papers, outputs=papers_output)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
 
201
  with gr.Tab("🧠 Strategy"):
202
- strategy_output = gr.Markdown(get_strategy())
203
- gr.Button("πŸ”„ Analyze").click(fn=get_strategy, outputs=strategy_output)
204
 
205
  with gr.Tab("⚑ Manual Trigger"):
206
- gr.Markdown("Manually trigger an agent cycle:")
207
- trigger_output = gr.Markdown("")
208
- gr.Button("πŸš€ Run Cycle Now").click(fn=run_manual_cycle, outputs=trigger_output)
209
-
210
 
211
  if __name__ == "__main__":
212
- demo.launch(server_name="0.0.0.0", server_port=7860)
 
 
1
  """
2
+ OpenCLAW Agent + SEED β€” HuggingFace Spaces Dashboard
3
+ ======================================================
4
+ Gradio interface with background agent loop and autonomous model growth.
5
  """
6
  import os
7
  import sys
 
13
  from datetime import datetime, timezone
14
  from pathlib import Path
15
 
 
16
  sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
17
 
18
  from core.config import Config
 
20
  from core.strategy import StrategyReflector
21
  from research.arxiv_fetcher import ArxivFetcher
22
 
 
23
  logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
24
  logger = logging.getLogger("openclaw")
25
 
26
  STATE_DIR = Path(os.getenv("STATE_DIR", "state"))
27
+ SEED_STATE_DIR = Path(os.getenv("SEED_STATE_DIR", "seed_state"))
28
+ SEED_DATA_DIR = Path(os.getenv("SEED_DATA_DIR", "seed_data"))
29
 
 
30
  agent_running = False
31
  cycle_log = []
32
+ seed_log = []
33
 
34
 
35
+ # ==========================================================================
36
+ # BACKGROUND AGENT + SEED GROWTH
37
+ # ==========================================================================
38
  def run_background_agent():
39
+ """Background thread: agent + SEED growth combined."""
40
+ global agent_running, cycle_log, seed_log
41
  agent_running = True
42
  interval = int(os.getenv("DAEMON_INTERVAL", "3600"))
43
 
44
+ agent = OpenCLAWAgent(state_dir=str(STATE_DIR))
45
+
46
+ # Initialize SEED
47
+ seed_engine = None
48
+ try:
49
+ from seed.growth_engine import GrowthEngine
50
+ seed_engine = GrowthEngine(
51
+ hf_token=os.environ.get("HF_TOKEN", ""),
52
+ state_dir=str(SEED_STATE_DIR),
53
+ data_dir=str(SEED_DATA_DIR),
54
+ )
55
+ logger.info("🌱 SEED Growth Engine initialized")
56
+ except Exception as e:
57
+ logger.warning(f"SEED init failed (will retry): {e}")
58
+
59
+ cycle_num = 0
60
+ while True:
61
+ cycle_num += 1
62
+ now = datetime.now(timezone.utc).isoformat()
63
+
64
+ # === AGENT CYCLE ===
65
  try:
 
 
66
  results = agent.run_cycle()
67
+ entry = f"[{now}] Agent cycle #{cycle_num}: " + ", ".join(
68
+ f"{a['task']}={a['status']}" for a in results.get("actions", [])
69
+ )
70
+ cycle_log.append(entry)
71
+ logger.info(entry)
 
 
 
 
 
72
  except Exception as e:
73
+ cycle_log.append(f"[{now}] Agent error: {e}")
74
+ logger.error(f"Agent cycle error: {e}")
75
+
76
+ # === SEED GROWTH (every 6th cycle = ~6 hours) ===
77
+ if seed_engine and cycle_num % 6 == 0:
78
+ try:
79
+ logger.info("🌱 Running SEED growth cycle...")
80
+ seed_results = seed_engine.run_cycle()
81
+ seed_entry = (
82
+ f"[{now}] SEED cycle #{seed_results.get('cycle', '?')}: "
83
+ f"stage={seed_engine.cycle_log.get('current_stage', '?')}, "
84
+ f"data={seed_engine.cycle_log.get('total_data_harvested', 0)}"
85
+ )
86
+ seed_log.append(seed_entry)
87
+ logger.info(seed_entry)
88
+ except Exception as e:
89
+ seed_log.append(f"[{now}] SEED error: {e}")
90
+ logger.error(f"SEED cycle error: {e}")
91
+ elif seed_engine is None:
92
+ # Retry SEED init
93
+ try:
94
+ from seed.growth_engine import GrowthEngine
95
+ seed_engine = GrowthEngine(
96
+ hf_token=os.environ.get("HF_TOKEN", ""),
97
+ state_dir=str(SEED_STATE_DIR),
98
+ data_dir=str(SEED_DATA_DIR),
99
+ )
100
+ except Exception:
101
+ pass
102
+
103
+ # Keep logs bounded
104
+ cycle_log[:] = cycle_log[-200:]
105
+ seed_log[:] = seed_log[-100:]
106
 
107
  time.sleep(interval)
108
 
109
 
110
+ # Start background
111
+ bg_thread = threading.Thread(target=run_background_agent, daemon=True)
112
+ bg_thread.start()
113
+ logger.info("πŸš€ Background agent + SEED started")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
 
115
 
116
+ # ==========================================================================
117
+ # DASHBOARD FUNCTIONS
118
+ # ==========================================================================
119
+ def get_status():
120
+ state_file = STATE_DIR / "agent_state.json"
121
+ if state_file.exists():
122
+ try:
123
+ state = json.loads(state_file.read_text())
124
+ return json.dumps(state, indent=2)
125
+ except Exception:
126
+ pass
127
+ return json.dumps({
128
+ "status": "running" if agent_running else "starting",
129
+ "message": "Agent initializing...",
130
+ }, indent=2)
131
+
132
+ def get_activity():
133
+ return "\n".join(cycle_log[-50:]) if cycle_log else "No activity yet β€” first cycle in progress..."
134
+
135
  def get_papers():
136
+ fetcher = ArxivFetcher()
137
+ papers = fetcher.known_papers
138
+ lines = []
139
+ for p in papers:
140
+ lines.append(f"πŸ“„ {p['title']}")
141
+ lines.append(f" ID: {p['arxiv_id']} | Year: {p.get('year', '?')}")
142
+ lines.append(f" {p.get('abstract', '')[:150]}...")
143
+ lines.append("")
144
+ return "\n".join(lines) if lines else "No papers loaded yet."
 
 
 
 
 
145
 
146
+ def get_strategy():
147
+ reflector = StrategyReflector(state_dir=str(STATE_DIR))
148
+ report = reflector.analyze()
149
+ return json.dumps(report, indent=2)
150
 
151
+ def get_seed_status():
152
+ """Get SEED growth status."""
153
+ try:
154
+ from seed.growth_engine import GrowthEngine
155
+ engine = GrowthEngine(
156
+ hf_token=os.environ.get("HF_TOKEN", ""),
157
+ state_dir=str(SEED_STATE_DIR),
158
+ data_dir=str(SEED_DATA_DIR),
159
+ )
160
+ status = engine.get_status()
161
+ return json.dumps(status, indent=2, default=str)
162
+ except Exception as e:
163
+ return json.dumps({"status": "initializing", "note": str(e)}, indent=2)
 
 
 
164
 
165
+ def get_seed_log():
166
+ return "\n".join(seed_log[-50:]) if seed_log else "SEED not yet active β€” first growth cycle pending..."
167
 
168
+ def trigger_harvest():
169
+ """Manually trigger data harvest."""
170
  try:
171
+ from seed.data.harvester import DataHarvester
172
+ h = DataHarvester(str(SEED_DATA_DIR))
173
+ stats = h.harvest_all()
174
+ return f"βœ… Harvested {stats['total']} entries:\n" + json.dumps(stats, indent=2)
 
 
 
 
 
 
175
  except Exception as e:
176
+ return f"❌ Harvest failed: {e}"
 
177
 
178
+ def trigger_cycle():
 
179
  try:
180
+ agent = OpenCLAWAgent(state_dir=str(STATE_DIR))
181
+ results = agent.run_cycle()
182
+ return json.dumps(results, indent=2, default=str)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
  except Exception as e:
184
  return f"Error: {e}"
185
 
186
 
187
+ # ==========================================================================
188
+ # GRADIO INTERFACE
189
+ # ==========================================================================
190
+ with gr.Blocks(title="🌱 OpenCLAW SEED β€” Self-Evolving Agent", theme=gr.themes.Soft()) as demo:
 
 
 
191
  gr.Markdown("""
192
+ # 🌱 OpenCLAW SEED β€” Self-Evolving Autonomous Agent
193
+ *A seed that grows into a tree. Autonomous 24/7 research agent with self-training AI.*
 
194
 
195
+ **By Francisco Angulo de Lafuente** | [GitHub](https://github.com/Agnuxo1) | [Scholar](https://scholar.google.com/citations?user=6nOpJ9IAAAAJ)
196
  """)
197
 
198
+ with gr.Tab("πŸ“Š Agent Status"):
199
+ status_box = gr.Code(label="Agent State", language="json")
200
+ gr.Button("Refresh").click(get_status, outputs=status_box)
201
+ demo.load(get_status, outputs=status_box)
202
 
203
+ with gr.Tab("πŸ“ Activity Log"):
204
+ log_box = gr.Textbox(label="Recent Activity", lines=20, max_lines=30)
205
+ gr.Button("Refresh").click(get_activity, outputs=log_box)
206
+ demo.load(get_activity, outputs=log_box)
207
 
208
+ with gr.Tab("🌱 SEED Growth"):
209
+ gr.Markdown("""
210
+ ### Self-Evolving Model Growth
211
+ SEED harvests knowledge, trains itself, and grows autonomously.
212
+
213
+ **Growth stages:** GERMINATION (0.5B) β†’ SEEDLING (1B) β†’ SAPLING (3B) β†’ YOUNG_TREE (7B) β†’ MATURE_TREE (13B+)
214
+ """)
215
+ seed_status_box = gr.Code(label="SEED Status", language="json")
216
+ seed_log_box = gr.Textbox(label="Growth Log", lines=10)
217
+ with gr.Row():
218
+ gr.Button("πŸ”„ Refresh Status").click(get_seed_status, outputs=seed_status_box)
219
+ gr.Button("🌾 Harvest Data Now").click(trigger_harvest, outputs=seed_log_box)
220
+ demo.load(get_seed_status, outputs=seed_status_box)
221
+
222
+ with gr.Tab("πŸ“„ Research Papers"):
223
+ papers_box = gr.Textbox(label="Known Papers", lines=20, max_lines=30)
224
+ gr.Button("Refresh").click(get_papers, outputs=papers_box)
225
+ demo.load(get_papers, outputs=papers_box)
226
 
227
  with gr.Tab("🧠 Strategy"):
228
+ strategy_box = gr.Code(label="Strategy Analysis", language="json")
229
+ gr.Button("Analyze").click(get_strategy, outputs=strategy_box)
230
 
231
  with gr.Tab("⚑ Manual Trigger"):
232
+ trigger_box = gr.Code(label="Cycle Results", language="json")
233
+ gr.Button("πŸ€– Run Agent Cycle").click(trigger_cycle, outputs=trigger_box)
 
 
234
 
235
  if __name__ == "__main__":
236
+ port = int(os.environ.get("PORT", 7860))
237
+ demo.launch(server_name="0.0.0.0", server_port=port)