TheEdict commited on
Commit
52a6037
·
verified ·
1 Parent(s): 6f3820e

Clean: Remove all old UI files

Browse files
Files changed (5) hide show
  1. README.md +0 -116
  2. marimo-zero-ui.html +0 -337
  3. nginx.conf +0 -57
  4. proxy_server.py +0 -94
  5. static/index.html +0 -337
README.md DELETED
@@ -1,116 +0,0 @@
1
- ---
2
- title: Marimo Zero
3
- emoji: 🦀
4
- colorFrom: blue
5
- colorTo: purple
6
- sdk: docker
7
- pinned: false
8
- license: mit
9
- short_description: Agent Zero chat + Marimo sandbox with OmniRoute LLM gateway
10
- app_port: 7860
11
- tags:
12
- - agent-zero
13
- - marimo
14
- - llm
15
- - ai
16
- - zeroclaw
17
- - omniroute
18
- - ai-assistant
19
- ---
20
-
21
- <div align="center">
22
- <img src="https://via.placeholder.com/720x400/1a1a2e/00d9ff?text=Marimo+Zero" alt="Marimo Zero" width="720"/>
23
- <br/><br/>
24
- <strong>Agent Zero + Marimo Sandbox</strong>
25
- <br/>
26
- <sub>Chat-first AI with toggleable code execution environment</sub>
27
- <br/><br/>
28
-
29
- [![Agent Zero](https://img.shields.io/badge/Agent%20Zero-Powered-blue)](https://github.com/zeroclaw-labs/zeroclaw)
30
- [![Marimo](https://img.shields.io/badge/Marimo-Reactive-orange)](https://marimo.io)
31
- [![OmniRoute](https://img.shields.io/badge/OmniRoute-Multi--Account-green)](https://github.com/omniroute/omniroute)
32
- </div>
33
-
34
- ---
35
-
36
- ## Architecture
37
-
38
- This Space uses a custom Docker image with **Agent Zero**, **Marimo**, and **OmniRoute**.
39
-
40
- - **🤖 Agent Zero:** Fast Rust-based AI agent framework
41
- - **📓 Marimo:** Reactive Python notebook for code execution
42
- - **🔀 OmniRoute:** Multi-account LLM routing with automatic failover
43
- - **🔒 Secure:** All API keys managed via HF Spaces secrets
44
-
45
- ## Quick Start
46
-
47
- 1. **Duplicate this Space**
48
- 2. **Set Secrets:**
49
- - `API_KEYS_JSON`: JSON with your LLM API keys (see below)
50
- 3. **Wait for build** (~5-10 minutes)
51
- 4. **Start chatting!**
52
-
53
- ### API Keys Format
54
-
55
- Set `API_KEYS_JSON` in **Space Settings → Repository secrets**:
56
-
57
- ```json
58
- {
59
- "openai": "sk-...",
60
- "anthropic": "sk-ant-...",
61
- "nvidia": "nvapi-...",
62
- "groq": "gsk_..."
63
- }
64
- ```
65
-
66
- Supports key rotation: `openai_2`, `openai_3`, etc.
67
-
68
- ## Features
69
-
70
- ### Agent Zero Chat
71
- - Natural language conversations
72
- - Tool calling (file operations, HTTP requests)
73
- - Persistent memory per project
74
- - Code generation with execution context
75
-
76
- ### Marimo Sandbox (Toggleable)
77
- - **Code Editor:** Write and execute Python code
78
- - **File Browser:** View workspace files
79
- - **File Editor:** Create/edit files directly
80
- - **Reactive:** Changes propagate instantly
81
-
82
- ### OmniRoute Integration
83
- - Multiple LLM account pooling
84
- - Automatic failover between accounts
85
- - Support for OpenAI, Anthropic, NVIDIA, Groq
86
- - Local proxy for privacy
87
-
88
- ## Routes
89
-
90
- | Path | Service | Description |
91
- |------|---------|-------------|
92
- | `/` | Main UI | Agent Zero chat + Marimo toggle |
93
- | `/chat/*` | Agent Zero | Chat API |
94
- | `/sandbox/*` | Marimo | Sandbox notebook |
95
- | `/api/*` | OmniRoute | LLM proxy |
96
- | `/health` | Healthcheck | HF Spaces monitoring |
97
-
98
- ## Workspace
99
-
100
- All files are stored in `/app/workspace` and persist across restarts:
101
-
102
- ```
103
- /workspace
104
- ├── projects/ # Agent Zero project data
105
- ├── memory/ # Persistent memory files
106
- ├── code/ # Generated code
107
- └── files/ # User files
108
- ```
109
-
110
- ## Development
111
-
112
- See full documentation: [GitHub Repository](https://github.com/YOUR_REPO/marimo-zero)
113
-
114
- ## License
115
-
116
- MIT
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
marimo-zero-ui.html DELETED
@@ -1,337 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Marimo Zero - Toggle Sandbox</title>
7
- <style>
8
- * {
9
- margin: 0;
10
- padding: 0;
11
- box-sizing: border-box;
12
- }
13
-
14
- body {
15
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
16
- background: #1a1a2e;
17
- color: #eee;
18
- height: 100vh;
19
- overflow: hidden;
20
- }
21
-
22
- .container {
23
- display: flex;
24
- height: 100vh;
25
- }
26
-
27
- /* Agent Zero Chat Panel */
28
- .chat-panel {
29
- flex: 1;
30
- display: flex;
31
- flex-direction: column;
32
- border-right: 1px solid #333;
33
- transition: all 0.3s ease;
34
- }
35
-
36
- .chat-panel.collapsed {
37
- flex: 0;
38
- opacity: 0;
39
- pointer-events: none;
40
- }
41
-
42
- .chat-header {
43
- padding: 1rem;
44
- background: #16213e;
45
- border-bottom: 1px solid #333;
46
- display: flex;
47
- justify-content: space-between;
48
- align-items: center;
49
- }
50
-
51
- .chat-header h1 {
52
- font-size: 1.2rem;
53
- color: #00d9ff;
54
- }
55
-
56
- .chat-body {
57
- flex: 1;
58
- overflow-y: auto;
59
- padding: 1rem;
60
- }
61
-
62
- .chat-input {
63
- padding: 1rem;
64
- background: #16213e;
65
- border-top: 1px solid #333;
66
- }
67
-
68
- .chat-input textarea {
69
- width: 100%;
70
- padding: 0.75rem;
71
- border: 1px solid #333;
72
- border-radius: 8px;
73
- background: #0f0f23;
74
- color: #eee;
75
- resize: none;
76
- font-family: inherit;
77
- }
78
-
79
- .chat-input button {
80
- margin-top: 0.5rem;
81
- padding: 0.5rem 1rem;
82
- background: #00d9ff;
83
- color: #000;
84
- border: none;
85
- border-radius: 6px;
86
- cursor: pointer;
87
- font-weight: 600;
88
- }
89
-
90
- .chat-input button:hover {
91
- background: #00b8d9;
92
- }
93
-
94
- /* Marimo Sandbox Panel */
95
- .marimo-panel {
96
- width: 50%;
97
- display: flex;
98
- flex-direction: column;
99
- transition: all 0.3s ease;
100
- }
101
-
102
- .marimo-panel.hidden {
103
- width: 0;
104
- opacity: 0;
105
- overflow: hidden;
106
- }
107
-
108
- .marimo-header {
109
- padding: 1rem;
110
- background: #16213e;
111
- border-bottom: 1px solid #333;
112
- display: flex;
113
- justify-content: space-between;
114
- align-items: center;
115
- }
116
-
117
- .marimo-header h2 {
118
- font-size: 1.2rem;
119
- color: #ff6b6b;
120
- }
121
-
122
- .marimo-frame {
123
- flex: 1;
124
- border: none;
125
- background: #fff;
126
- }
127
-
128
- /* Toggle Button */
129
- .toggle-btn {
130
- padding: 0.5rem 1rem;
131
- background: #ff6b6b;
132
- color: #fff;
133
- border: none;
134
- border-radius: 6px;
135
- cursor: pointer;
136
- font-weight: 600;
137
- transition: background 0.2s;
138
- }
139
-
140
- .toggle-btn:hover {
141
- background: #ff5252;
142
- }
143
-
144
- .toggle-btn.active {
145
- background: #4ecdc4;
146
- }
147
-
148
- /* Resize Handle */
149
- .resize-handle {
150
- width: 4px;
151
- background: #333;
152
- cursor: col-resize;
153
- transition: background 0.2s;
154
- }
155
-
156
- .resize-handle:hover {
157
- background: #00d9ff;
158
- }
159
-
160
- /* Message Styles */
161
- .message {
162
- margin-bottom: 1rem;
163
- padding: 0.75rem;
164
- border-radius: 8px;
165
- max-width: 80%;
166
- }
167
-
168
- .message.user {
169
- background: #00d9ff;
170
- color: #000;
171
- margin-left: auto;
172
- }
173
-
174
- .message.assistant {
175
- background: #2a2a4a;
176
- color: #eee;
177
- }
178
-
179
- .message pre {
180
- background: #0f0f23;
181
- padding: 0.5rem;
182
- border-radius: 4px;
183
- overflow-x: auto;
184
- margin-top: 0.5rem;
185
- }
186
-
187
- .message code {
188
- font-family: 'Consolas', 'Monaco', monospace;
189
- font-size: 0.9rem;
190
- }
191
- </style>
192
- </head>
193
- <body>
194
- <div class="container">
195
- <!-- Agent Zero Chat Panel -->
196
- <div class="chat-panel" id="chatPanel">
197
- <div class="chat-header">
198
- <h1>🤖 Agent Zero</h1>
199
- <button class="toggle-btn" id="toggleChatBtn" onclick="toggleChat()">Hide Chat</button>
200
- </div>
201
- <div class="chat-body" id="chatBody">
202
- <div class="message assistant">
203
- <strong>Agent Zero:</strong>
204
- <p>Welcome to Marimo Zero! I'm your AI assistant. Use the toggle button to show/hide the Marimo sandbox for code execution.</p>
205
- </div>
206
- </div>
207
- <div class="chat-input">
208
- <textarea id="chatInput" rows="3" placeholder="Type your message..."></textarea>
209
- <button onclick="sendMessage()">Send</button>
210
- </div>
211
- </div>
212
-
213
- <!-- Resize Handle -->
214
- <div class="resize-handle" id="resizeHandle"></div>
215
-
216
- <!-- Marimo Sandbox Panel -->
217
- <div class="marimo-panel hidden" id="marimoPanel">
218
- <div class="marimo-header">
219
- <h2>📓 Marimo Sandbox</h2>
220
- <button class="toggle-btn active" id="toggleMarimoBtn" onclick="toggleMarimo()">Hide Sandbox</button>
221
- </div>
222
- <iframe
223
- class="marimo-frame"
224
- id="marimoFrame"
225
- src="http://localhost:8080"
226
- sandbox="allow-scripts allow-same-origin allow-downloads"
227
- ></iframe>
228
- </div>
229
- </div>
230
-
231
- <script>
232
- const chatPanel = document.getElementById('chatPanel');
233
- const marimoPanel = document.getElementById('marimoPanel');
234
- const chatBody = document.getElementById('chatBody');
235
- const chatInput = document.getElementById('chatInput');
236
- const resizeHandle = document.getElementById('resizeHandle');
237
-
238
- // Toggle Marimo Sandbox
239
- function toggleMarimo() {
240
- marimoPanel.classList.toggle('hidden');
241
- const btn = document.getElementById('toggleMarimoBtn');
242
- btn.textContent = marimoPanel.classList.contains('hidden') ? 'Show Sandbox' : 'Hide Sandbox';
243
- btn.classList.toggle('active');
244
- }
245
-
246
- // Toggle Chat Panel
247
- function toggleChat() {
248
- chatPanel.classList.toggle('collapsed');
249
- const btn = document.getElementById('toggleChatBtn');
250
- btn.textContent = chatPanel.classList.contains('collapsed') ? 'Show Chat' : 'Hide Chat';
251
- }
252
-
253
- // Send Message (simulated - replace with actual Agent Zero API call)
254
- async function sendMessage() {
255
- const message = chatInput.value.trim();
256
- if (!message) return;
257
-
258
- // Add user message
259
- chatBody.innerHTML += `
260
- <div class="message user">
261
- <strong>You:</strong>
262
- <p>${escapeHtml(message)}</p>
263
- </div>
264
- `;
265
-
266
- chatInput.value = '';
267
- chatBody.scrollTop = chatBody.scrollHeight;
268
-
269
- // Call Agent Zero API (replace with actual endpoint)
270
- try {
271
- const response = await fetch('http://localhost:80/chat', {
272
- method: 'POST',
273
- headers: { 'Content-Type': 'application/json' },
274
- body: JSON.stringify({ message })
275
- });
276
- const data = await response.json();
277
-
278
- chatBody.innerHTML += `
279
- <div class="message assistant">
280
- <strong>Agent Zero:</strong>
281
- <p>${escapeHtml(data.response || 'No response')}</p>
282
- </div>
283
- `;
284
- } catch (err) {
285
- chatBody.innerHTML += `
286
- <div class="message assistant">
287
- <strong>Agent Zero:</strong>
288
- <p>⚠️ Could not connect to Agent Zero. Make sure it's running on port 80.</p>
289
- </div>
290
- `;
291
- }
292
-
293
- chatBody.scrollTop = chatBody.scrollHeight;
294
- }
295
-
296
- // Escape HTML
297
- function escapeHtml(text) {
298
- const div = document.createElement('div');
299
- div.textContent = text;
300
- return div.innerHTML;
301
- }
302
-
303
- // Resize functionality
304
- let isResizing = false;
305
-
306
- resizeHandle.addEventListener('mousedown', (e) => {
307
- isResizing = true;
308
- document.body.style.cursor = 'col-resize';
309
- });
310
-
311
- document.addEventListener('mousemove', (e) => {
312
- if (!isResizing) return;
313
-
314
- const containerWidth = document.querySelector('.container').offsetWidth;
315
- const newMarimoWidth = ((containerWidth - e.clientX) / containerWidth) * 100;
316
-
317
- if (newMarimoWidth > 20 && newMarimoWidth < 80) {
318
- marimoPanel.style.width = `${newMarimoWidth}%`;
319
- chatPanel.style.flex = `0 0 ${100 - newMarimoWidth}%`;
320
- }
321
- });
322
-
323
- document.addEventListener('mouseup', () => {
324
- isResizing = false;
325
- document.body.style.cursor = 'default';
326
- });
327
-
328
- // Enter to send
329
- chatInput.addEventListener('keydown', (e) => {
330
- if (e.key === 'Enter' && !e.shiftKey) {
331
- e.preventDefault();
332
- sendMessage();
333
- }
334
- });
335
- </script>
336
- </body>
337
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
nginx.conf DELETED
@@ -1,57 +0,0 @@
1
- events {
2
- worker_connections 1024;
3
- }
4
-
5
- http {
6
- upstream agent_zero {
7
- server localhost:80;
8
- }
9
-
10
- upstream marimo {
11
- server localhost:8080;
12
- }
13
-
14
- upstream omniroute {
15
- server localhost:20128;
16
- }
17
-
18
- server {
19
- listen 7860;
20
-
21
- # Health check
22
- location /health {
23
- return 200 '{"status":"healthy"}';
24
- add_header Content-Type application/json;
25
- }
26
-
27
- # Main UI
28
- location / {
29
- root /app/static;
30
- try_files $uri $uri/ /index.html;
31
- }
32
-
33
- # Agent Zero
34
- location /chat/ {
35
- proxy_pass http://agent_zero/;
36
- proxy_http_version 1.1;
37
- proxy_set_header Upgrade $http_upgrade;
38
- proxy_set_header Connection "upgrade";
39
- proxy_set_header Host $host;
40
- }
41
-
42
- # Marimo Sandbox
43
- location /sandbox/ {
44
- proxy_pass http://marimo/;
45
- proxy_http_version 1.1;
46
- proxy_set_header Upgrade $http_upgrade;
47
- proxy_set_header Connection "upgrade";
48
- proxy_set_header Host $host;
49
- }
50
-
51
- # OmniRoute API
52
- location /api/ {
53
- proxy_pass http://omniroute/;
54
- proxy_set_header Host $host;
55
- }
56
- }
57
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
proxy_server.py DELETED
@@ -1,94 +0,0 @@
1
- # HF Spaces requires all traffic through port 7860
2
- # This proxy routes:
3
- # /chat/* → Agent Zero (port 80)
4
- # /sandbox/* → Marimo (port 8080)
5
- # /api/* → OmniRoute (port 20128)
6
-
7
- from fastapi import FastAPI, Request, HTTPException
8
- from fastapi.responses import HTMLResponse, StreamingResponse
9
- from fastapi.staticfiles import StaticFiles
10
- import httpx
11
- import asyncio
12
-
13
- app = FastAPI()
14
-
15
- # Service ports (internal)
16
- AGENT_ZERO_PORT = 80
17
- MARIMO_PORT = 8080
18
- OMNIROUTE_PORT = 20128
19
- HF_PORT = 7860
20
-
21
- # HTTP client with connection pooling
22
- http_client = httpx.AsyncClient(timeout=60.0)
23
-
24
-
25
- @app.get("/health")
26
- async def health():
27
- """HF Spaces healthcheck endpoint"""
28
- return {"status": "healthy", "service": "marimo-zero"}
29
-
30
-
31
- @app.get("/")
32
- async def root():
33
- """Serve main UI"""
34
- try:
35
- with open("/app/static/index.html", "r") as f:
36
- return HTMLResponse(content=f.read())
37
- except FileNotFoundError:
38
- return HTMLResponse("<h1>Marimo Zero</h1><p>UI not found</p>", status_code=404)
39
-
40
-
41
- @app.api_route("/chat/{path:path}", methods=["GET", "POST", "PUT", "DELETE"])
42
- async def proxy_agent_zero(request: Request, path: str):
43
- """Proxy to Agent Zero"""
44
- return await proxy_request(AGENT_ZERO_PORT, path, request)
45
-
46
-
47
- @app.api_route("/sandbox/{path:path}", methods=["GET", "POST", "PUT", "DELETE"])
48
- async def proxy_marimo(request: Request, path: str):
49
- """Proxy to Marimo"""
50
- return await proxy_request(MARIMO_PORT, path, request)
51
-
52
-
53
- @app.api_route("/api/{path:path}", methods=["GET", "POST", "PUT", "DELETE"])
54
- async def proxy_omniroute(request: Request, path: str):
55
- """Proxy to OmniRoute"""
56
- return await proxy_request(OMNIROUTE_PORT, path, request)
57
-
58
-
59
- async def proxy_request(target_port: int, path: str, request: Request):
60
- """Generic proxy handler"""
61
- url = f"http://localhost:{target_port}/{path}"
62
-
63
- try:
64
- # Forward headers
65
- headers = dict(request.headers)
66
- headers.pop("host", None)
67
- headers.pop("content-length", None)
68
-
69
- # Get body
70
- body = await request.body() if request.method in ["POST", "PUT"] else None
71
-
72
- # Make request
73
- response = await http_client.request(
74
- method=request.method,
75
- url=url,
76
- headers=headers,
77
- content=body
78
- )
79
-
80
- # Return response
81
- return StreamingResponse(
82
- response.aiter_bytes(),
83
- status_code=response.status_code,
84
- headers=dict(response.headers)
85
- )
86
- except httpx.ConnectError as e:
87
- raise HTTPException(status_code=503, detail=f"Service unavailable (port {target_port})")
88
- except Exception as e:
89
- raise HTTPException(status_code=500, detail=str(e))
90
-
91
-
92
- if __name__ == "__main__":
93
- import uvicorn
94
- uvicorn.run(app, host="0.0.0.0", port=HF_PORT)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
static/index.html DELETED
@@ -1,337 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Marimo Zero - Toggle Sandbox</title>
7
- <style>
8
- * {
9
- margin: 0;
10
- padding: 0;
11
- box-sizing: border-box;
12
- }
13
-
14
- body {
15
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
16
- background: #1a1a2e;
17
- color: #eee;
18
- height: 100vh;
19
- overflow: hidden;
20
- }
21
-
22
- .container {
23
- display: flex;
24
- height: 100vh;
25
- }
26
-
27
- /* Agent Zero Chat Panel */
28
- .chat-panel {
29
- flex: 1;
30
- display: flex;
31
- flex-direction: column;
32
- border-right: 1px solid #333;
33
- transition: all 0.3s ease;
34
- }
35
-
36
- .chat-panel.collapsed {
37
- flex: 0;
38
- opacity: 0;
39
- pointer-events: none;
40
- }
41
-
42
- .chat-header {
43
- padding: 1rem;
44
- background: #16213e;
45
- border-bottom: 1px solid #333;
46
- display: flex;
47
- justify-content: space-between;
48
- align-items: center;
49
- }
50
-
51
- .chat-header h1 {
52
- font-size: 1.2rem;
53
- color: #00d9ff;
54
- }
55
-
56
- .chat-body {
57
- flex: 1;
58
- overflow-y: auto;
59
- padding: 1rem;
60
- }
61
-
62
- .chat-input {
63
- padding: 1rem;
64
- background: #16213e;
65
- border-top: 1px solid #333;
66
- }
67
-
68
- .chat-input textarea {
69
- width: 100%;
70
- padding: 0.75rem;
71
- border: 1px solid #333;
72
- border-radius: 8px;
73
- background: #0f0f23;
74
- color: #eee;
75
- resize: none;
76
- font-family: inherit;
77
- }
78
-
79
- .chat-input button {
80
- margin-top: 0.5rem;
81
- padding: 0.5rem 1rem;
82
- background: #00d9ff;
83
- color: #000;
84
- border: none;
85
- border-radius: 6px;
86
- cursor: pointer;
87
- font-weight: 600;
88
- }
89
-
90
- .chat-input button:hover {
91
- background: #00b8d9;
92
- }
93
-
94
- /* Marimo Sandbox Panel */
95
- .marimo-panel {
96
- width: 50%;
97
- display: flex;
98
- flex-direction: column;
99
- transition: all 0.3s ease;
100
- }
101
-
102
- .marimo-panel.hidden {
103
- width: 0;
104
- opacity: 0;
105
- overflow: hidden;
106
- }
107
-
108
- .marimo-header {
109
- padding: 1rem;
110
- background: #16213e;
111
- border-bottom: 1px solid #333;
112
- display: flex;
113
- justify-content: space-between;
114
- align-items: center;
115
- }
116
-
117
- .marimo-header h2 {
118
- font-size: 1.2rem;
119
- color: #ff6b6b;
120
- }
121
-
122
- .marimo-frame {
123
- flex: 1;
124
- border: none;
125
- background: #fff;
126
- }
127
-
128
- /* Toggle Button */
129
- .toggle-btn {
130
- padding: 0.5rem 1rem;
131
- background: #ff6b6b;
132
- color: #fff;
133
- border: none;
134
- border-radius: 6px;
135
- cursor: pointer;
136
- font-weight: 600;
137
- transition: background 0.2s;
138
- }
139
-
140
- .toggle-btn:hover {
141
- background: #ff5252;
142
- }
143
-
144
- .toggle-btn.active {
145
- background: #4ecdc4;
146
- }
147
-
148
- /* Resize Handle */
149
- .resize-handle {
150
- width: 4px;
151
- background: #333;
152
- cursor: col-resize;
153
- transition: background 0.2s;
154
- }
155
-
156
- .resize-handle:hover {
157
- background: #00d9ff;
158
- }
159
-
160
- /* Message Styles */
161
- .message {
162
- margin-bottom: 1rem;
163
- padding: 0.75rem;
164
- border-radius: 8px;
165
- max-width: 80%;
166
- }
167
-
168
- .message.user {
169
- background: #00d9ff;
170
- color: #000;
171
- margin-left: auto;
172
- }
173
-
174
- .message.assistant {
175
- background: #2a2a4a;
176
- color: #eee;
177
- }
178
-
179
- .message pre {
180
- background: #0f0f23;
181
- padding: 0.5rem;
182
- border-radius: 4px;
183
- overflow-x: auto;
184
- margin-top: 0.5rem;
185
- }
186
-
187
- .message code {
188
- font-family: 'Consolas', 'Monaco', monospace;
189
- font-size: 0.9rem;
190
- }
191
- </style>
192
- </head>
193
- <body>
194
- <div class="container">
195
- <!-- Agent Zero Chat Panel -->
196
- <div class="chat-panel" id="chatPanel">
197
- <div class="chat-header">
198
- <h1>🤖 Agent Zero</h1>
199
- <button class="toggle-btn" id="toggleChatBtn" onclick="toggleChat()">Hide Chat</button>
200
- </div>
201
- <div class="chat-body" id="chatBody">
202
- <div class="message assistant">
203
- <strong>Agent Zero:</strong>
204
- <p>Welcome to Marimo Zero! I'm your AI assistant. Use the toggle button to show/hide the Marimo sandbox for code execution.</p>
205
- </div>
206
- </div>
207
- <div class="chat-input">
208
- <textarea id="chatInput" rows="3" placeholder="Type your message..."></textarea>
209
- <button onclick="sendMessage()">Send</button>
210
- </div>
211
- </div>
212
-
213
- <!-- Resize Handle -->
214
- <div class="resize-handle" id="resizeHandle"></div>
215
-
216
- <!-- Marimo Sandbox Panel -->
217
- <div class="marimo-panel hidden" id="marimoPanel">
218
- <div class="marimo-header">
219
- <h2>📓 Marimo Sandbox</h2>
220
- <button class="toggle-btn active" id="toggleMarimoBtn" onclick="toggleMarimo()">Hide Sandbox</button>
221
- </div>
222
- <iframe
223
- class="marimo-frame"
224
- id="marimoFrame"
225
- src="http://localhost:8080"
226
- sandbox="allow-scripts allow-same-origin allow-downloads"
227
- ></iframe>
228
- </div>
229
- </div>
230
-
231
- <script>
232
- const chatPanel = document.getElementById('chatPanel');
233
- const marimoPanel = document.getElementById('marimoPanel');
234
- const chatBody = document.getElementById('chatBody');
235
- const chatInput = document.getElementById('chatInput');
236
- const resizeHandle = document.getElementById('resizeHandle');
237
-
238
- // Toggle Marimo Sandbox
239
- function toggleMarimo() {
240
- marimoPanel.classList.toggle('hidden');
241
- const btn = document.getElementById('toggleMarimoBtn');
242
- btn.textContent = marimoPanel.classList.contains('hidden') ? 'Show Sandbox' : 'Hide Sandbox';
243
- btn.classList.toggle('active');
244
- }
245
-
246
- // Toggle Chat Panel
247
- function toggleChat() {
248
- chatPanel.classList.toggle('collapsed');
249
- const btn = document.getElementById('toggleChatBtn');
250
- btn.textContent = chatPanel.classList.contains('collapsed') ? 'Show Chat' : 'Hide Chat';
251
- }
252
-
253
- // Send Message (simulated - replace with actual Agent Zero API call)
254
- async function sendMessage() {
255
- const message = chatInput.value.trim();
256
- if (!message) return;
257
-
258
- // Add user message
259
- chatBody.innerHTML += `
260
- <div class="message user">
261
- <strong>You:</strong>
262
- <p>${escapeHtml(message)}</p>
263
- </div>
264
- `;
265
-
266
- chatInput.value = '';
267
- chatBody.scrollTop = chatBody.scrollHeight;
268
-
269
- // Call Agent Zero API (replace with actual endpoint)
270
- try {
271
- const response = await fetch('http://localhost:80/chat', {
272
- method: 'POST',
273
- headers: { 'Content-Type': 'application/json' },
274
- body: JSON.stringify({ message })
275
- });
276
- const data = await response.json();
277
-
278
- chatBody.innerHTML += `
279
- <div class="message assistant">
280
- <strong>Agent Zero:</strong>
281
- <p>${escapeHtml(data.response || 'No response')}</p>
282
- </div>
283
- `;
284
- } catch (err) {
285
- chatBody.innerHTML += `
286
- <div class="message assistant">
287
- <strong>Agent Zero:</strong>
288
- <p>⚠️ Could not connect to Agent Zero. Make sure it's running on port 80.</p>
289
- </div>
290
- `;
291
- }
292
-
293
- chatBody.scrollTop = chatBody.scrollHeight;
294
- }
295
-
296
- // Escape HTML
297
- function escapeHtml(text) {
298
- const div = document.createElement('div');
299
- div.textContent = text;
300
- return div.innerHTML;
301
- }
302
-
303
- // Resize functionality
304
- let isResizing = false;
305
-
306
- resizeHandle.addEventListener('mousedown', (e) => {
307
- isResizing = true;
308
- document.body.style.cursor = 'col-resize';
309
- });
310
-
311
- document.addEventListener('mousemove', (e) => {
312
- if (!isResizing) return;
313
-
314
- const containerWidth = document.querySelector('.container').offsetWidth;
315
- const newMarimoWidth = ((containerWidth - e.clientX) / containerWidth) * 100;
316
-
317
- if (newMarimoWidth > 20 && newMarimoWidth < 80) {
318
- marimoPanel.style.width = `${newMarimoWidth}%`;
319
- chatPanel.style.flex = `0 0 ${100 - newMarimoWidth}%`;
320
- }
321
- });
322
-
323
- document.addEventListener('mouseup', () => {
324
- isResizing = false;
325
- document.body.style.cursor = 'default';
326
- });
327
-
328
- // Enter to send
329
- chatInput.addEventListener('keydown', (e) => {
330
- if (e.key === 'Enter' && !e.shiftKey) {
331
- e.preventDefault();
332
- sendMessage();
333
- }
334
- });
335
- </script>
336
- </body>
337
- </html>