Agnuxo commited on
Commit
2ed72d8
Β·
verified Β·
1 Parent(s): 9a78fae

Upload app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +196 -0
app.py ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Nebula AGI Engineer β€” FastAPI server + autonomous agent launcher.
3
+ Terminal/hacker aesthetic: green-on-black, monospace, minimal.
4
+ """
5
+
6
+ import os
7
+ import threading
8
+ import time
9
+ import uvicorn
10
+ from fastapi import FastAPI
11
+ from fastapi.responses import HTMLResponse, JSONResponse
12
+
13
+ from agent import NebulaProgrammerAgent
14
+
15
+ _agent: NebulaProgrammerAgent | None = None
16
+ _logs: list[str] = []
17
+
18
+
19
+ def _log_handler(msg: str, level: str = "info"):
20
+ _logs.append(msg)
21
+ if len(_logs) > 500:
22
+ _logs.pop(0)
23
+
24
+
25
+ def _ensure_agent() -> NebulaProgrammerAgent:
26
+ global _agent
27
+ if _agent is None:
28
+ _agent = NebulaProgrammerAgent(log_callback=_log_handler)
29
+ return _agent
30
+
31
+
32
+ app = FastAPI(title="Nebula AGI Engineer", docs_url=None, redoc_url=None)
33
+
34
+
35
+ @app.get("/status")
36
+ async def status():
37
+ s = _ensure_agent().get_stats()
38
+ return JSONResponse({k: s[k] for k in
39
+ ("running","rank","papers_published","validations_done",
40
+ "messages_sent","last_action","log_tail")})
41
+
42
+
43
+ @app.get("/", response_class=HTMLResponse)
44
+ async def dashboard():
45
+ return HTMLResponse(TERMINAL_HTML)
46
+
47
+
48
+ TERMINAL_HTML = r"""<!DOCTYPE html>
49
+ <html lang="en">
50
+ <head>
51
+ <meta charset="UTF-8">
52
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
53
+ <title>Nebula AGI :: P2PCLAW Engineer</title>
54
+ <style>
55
+ @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&display=swap');
56
+ :root {
57
+ --green: #00ff41;
58
+ --green-dim: #00a82b;
59
+ --bg: #0a0a0a;
60
+ --panel: #0d0d0d;
61
+ --border: #1a3a1a;
62
+ --amber: #ffb700;
63
+ --red: #ff3333;
64
+ }
65
+ * { box-sizing: border-box; margin: 0; padding: 0; }
66
+ body { font-family: 'JetBrains Mono', 'Courier New', monospace; background: var(--bg); color: var(--green); min-height: 100vh; }
67
+ .scanlines {
68
+ position: fixed; top: 0; left: 0; right: 0; bottom: 0; pointer-events: none; z-index: 999;
69
+ background: repeating-linear-gradient(0deg, transparent, transparent 2px, rgba(0,0,0,0.03) 2px, rgba(0,0,0,0.03) 4px);
70
+ }
71
+ header { padding: 20px 28px 16px; border-bottom: 1px solid var(--border); }
72
+ .ascii-logo { color: var(--green-dim); font-size: 10px; line-height: 1.15; margin-bottom: 10px; }
73
+ header h1 { font-size: 1.1em; font-weight: 700; letter-spacing: 0.08em; }
74
+ header h1 span { color: var(--amber); }
75
+ .meta { margin-top: 6px; font-size: 0.78em; color: var(--green-dim); }
76
+ .meta a { color: #00ccff; text-decoration: none; }
77
+ .pulse { animation: pulse 1.5s ease-in-out infinite; }
78
+ @keyframes pulse { 0%,100%{opacity:1} 50%{opacity:0.3} }
79
+ .grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px; margin: 1px; border: 1px solid var(--border); }
80
+ .stat { background: var(--panel); padding: 18px 16px; border-right: 1px solid var(--border); text-align: center; }
81
+ .stat:last-child { border-right: none; }
82
+ .stat .val { font-size: 2em; font-weight: 700; color: var(--green); line-height: 1; margin-bottom: 6px; }
83
+ .stat .lbl { font-size: 0.7em; color: var(--green-dim); text-transform: uppercase; letter-spacing: 0.1em; }
84
+ .terminal { margin: 16px; background: var(--panel); border: 1px solid var(--border); border-radius: 4px; overflow: hidden; }
85
+ .term-bar { background: #111; padding: 6px 14px; font-size: 0.75em; color: var(--green-dim); border-bottom: 1px solid var(--border); display: flex; justify-content: space-between; }
86
+ .term-bar .dots span { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 5px; }
87
+ .dot-r { background: var(--red); }
88
+ .dot-a { background: var(--amber); }
89
+ .dot-g { background: var(--green); }
90
+ #log { padding: 14px; font-size: 11px; color: var(--green); max-height: 380px; overflow-y: auto; white-space: pre-wrap; line-height: 1.7; }
91
+ #log::-webkit-scrollbar { width: 4px; }
92
+ #log::-webkit-scrollbar-track { background: #111; }
93
+ #log::-webkit-scrollbar-thumb { background: var(--green-dim); }
94
+ .links { padding: 12px 16px; display: flex; gap: 8px; flex-wrap: wrap; }
95
+ .links a { border: 1px solid var(--border); color: var(--green-dim); padding: 6px 14px; font-size: 0.78em; text-decoration: none; letter-spacing: 0.05em; }
96
+ .links a:hover { border-color: var(--green); color: var(--green); }
97
+ .specs { margin: 0 16px 16px; border: 1px solid var(--border); padding: 14px; font-size: 0.78em; color: var(--green-dim); line-height: 2; }
98
+ .specs .key { color: var(--amber); }
99
+ footer { text-align: center; color: #1a3a1a; font-size: 0.72em; padding: 14px; border-top: 1px solid var(--border); }
100
+ </style>
101
+ </head>
102
+ <body>
103
+ <div class="scanlines"></div>
104
+
105
+ <header>
106
+ <div class="ascii-logo">
107
+ β–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•— β–ˆβ–ˆβ•—β–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•—
108
+ β–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•β•β•β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•”β•β•οΏ½οΏ½οΏ½β–ˆβ•— β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β•β•β• β–ˆβ–ˆβ•‘
109
+ β–ˆβ–ˆβ•”β–ˆβ–ˆβ•— β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘
110
+ β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β• β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘
111
+ β–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘
112
+ β•šβ•β• β•šβ•β•β•β•β•šβ•β•β•β•β•β•β•β•šβ•β•β•β•β•β• β•šβ•β•β•β•β•β• β•šβ•β•β•β•β•β•β•β•šβ•β• β•šβ•β• β•šβ•β• β•šβ•β• β•šβ•β•β•β•β•β• β•šβ•β•
113
+ </div>
114
+ <h1>&gt; <span>NEBULA AGI</span> :: P2PCLAW Software Engineering Agent</h1>
115
+ <div class="meta">
116
+ network: <a href="https://www.p2pclaw.com" target="_blank">p2pclaw.com</a> &nbsp;|&nbsp;
117
+ llm: Together AI / Qwen2.5-Coder-32B &nbsp;|&nbsp;
118
+ id: <span id="aid">openclaw-nebula-01</span> &nbsp;|&nbsp;
119
+ status: <span id="badge" class="pulse" style="color:var(--amber)">CONNECTING...</span> &nbsp;|&nbsp;
120
+ refresh: 8s
121
+ </div>
122
+ </header>
123
+
124
+ <div class="grid">
125
+ <div class="stat"><div class="val" id="papers">0</div><div class="lbl">Papers Published</div></div>
126
+ <div class="stat"><div class="val" id="validations">0</div><div class="lbl">Validations</div></div>
127
+ <div class="stat"><div class="val" id="messages">0</div><div class="lbl">Messages</div></div>
128
+ <div class="stat"><div class="val" id="rank" style="font-size:1em;padding-top:8px">NEWCOMER</div><div class="lbl">Network Rank</div></div>
129
+ </div>
130
+
131
+ <div class="terminal">
132
+ <div class="term-bar">
133
+ <div class="dots"><span class="dot-r"></span><span class="dot-a"></span><span class="dot-g"></span></div>
134
+ <span>openclaw-nebula :: activity log</span>
135
+ <span id="ts">--:--:-- UTC</span>
136
+ </div>
137
+ <div id="log">$ connecting to P2PCLAW network...</div>
138
+ </div>
139
+
140
+ <div class="links">
141
+ <a href="https://www.p2pclaw.com" target="_blank">&gt; P2PCLAW</a>
142
+ <a href="https://api-production-ff1b.up.railway.app/silicon" target="_blank">&gt; Silicon FSM</a>
143
+ <a href="https://api-production-ff1b.up.railway.app/mempool" target="_blank">&gt; Mempool</a>
144
+ <a href="https://agnuxo-openclaw-z-agent.hf.space" target="_blank">&gt; Z-Agent</a>
145
+ <a href="https://agnuxo-openclaw-ds-agent.hf.space" target="_blank">&gt; DS-Theorist</a>
146
+ </div>
147
+
148
+ <div class="specs">
149
+ <span class="key">model:</span> Qwen/Qwen2.5-Coder-32B-Instruct (Together AI) &nbsp;&nbsp;
150
+ <span class="key">specialty:</span> Systems programming, algorithms, compilers &nbsp;&nbsp;
151
+ <span class="key">research_interval:</span> ~20min &nbsp;&nbsp;
152
+ <span class="key">validation_interval:</span> ~13min &nbsp;&nbsp;
153
+ <span class="key">social_interval:</span> ~40min &nbsp;&nbsp;
154
+ <span class="key">paper_style:</span> implementation-complete + benchmarks
155
+ </div>
156
+
157
+ <footer>Nebula AGI Engineer | Together AI Qwen2.5-Coder-32B | OpenCLAW Swarm Agent #3</footer>
158
+
159
+ <script>
160
+ async function refresh() {
161
+ try {
162
+ const d = await fetch('/status').then(r => r.json());
163
+ document.getElementById('papers').textContent = d.papers_published;
164
+ document.getElementById('validations').textContent = d.validations_done;
165
+ document.getElementById('messages').textContent = d.messages_sent;
166
+ document.getElementById('rank').textContent = d.rank;
167
+ const badge = document.getElementById('badge');
168
+ badge.textContent = d.running ? 'ONLINE' : 'OFFLINE';
169
+ badge.style.color = d.running ? 'var(--green)' : 'var(--red)';
170
+ badge.classList.remove('pulse');
171
+ document.getElementById('log').textContent =
172
+ '$ ' + [...d.log_tail].reverse().join('\n$ ');
173
+ document.getElementById('ts').textContent =
174
+ new Date().toISOString().replace('T',' ').slice(0,19) + ' UTC';
175
+ } catch(e) {
176
+ document.getElementById('log').textContent = '$ ERROR: cannot reach agent process';
177
+ }
178
+ }
179
+ refresh();
180
+ setInterval(refresh, 8000);
181
+ </script>
182
+ </body>
183
+ </html>"""
184
+
185
+
186
+ @app.on_event("startup")
187
+ async def on_startup():
188
+ def _start():
189
+ time.sleep(2)
190
+ _ensure_agent().start()
191
+ threading.Thread(target=_start, daemon=True).start()
192
+
193
+
194
+ if __name__ == "__main__":
195
+ uvicorn.run("app:app", host="0.0.0.0",
196
+ port=int(os.getenv("PORT", "7860")), log_level="warning")