theguywhosucks commited on
Commit
15b5624
Β·
verified Β·
1 Parent(s): c8b55ab

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +821 -248
app.py CHANGED
@@ -54,28 +54,28 @@ class SandboxManager:
54
  def connect(self):
55
  """Connect to a backend engine"""
56
  if self.sandbox_created:
57
- return "⚠️ Sandbox already created. You can only create one sandbox per session.", self.current_engine
58
 
59
  engine = self.select_random_engine()
60
  try:
61
  self.client = Client(engine)
62
  self.is_connected = True
63
- return f"βœ… Connected to: {engine}", engine
64
  except Exception as e:
65
  self.is_connected = False
66
  self.current_engine = None
67
- return f"❌ Connection failed to {engine}: {str(e)}", "Connection Failed"
68
 
69
  def launch_sandbox(self, main_py_code, requirements_txt):
70
  """Launch the sandbox (only once per session)"""
71
  if self.sandbox_created:
72
  remaining = self.get_remaining_time()
73
  if remaining == "EXPIRED":
74
- return "⏰ Your sandbox has expired (2-hour limit reached). Please refresh the page to start a new session.", ""
75
- return f"⚠️ Sandbox already running. Remaining time: {remaining}", self.get_status()
76
 
77
  if not self.is_connected:
78
- return "❌ Not connected to backend. Please connect first.", ""
79
 
80
  try:
81
  result = self.client.predict(
@@ -92,41 +92,42 @@ class SandboxManager:
92
  self.start_time_monitor()
93
 
94
  remaining = self.get_remaining_time()
95
- return (f"πŸš€ Sandbox deployed successfully on {self.current_engine}\n"
96
- f"⏱️ Time limit: 2 hours | Remaining: {remaining}\n\n"
97
- f"Response: {result}"), self.get_status()
 
98
  except Exception as e:
99
- return f"❌ Deployment failed: {str(e)}", ""
100
 
101
  def fetch_logs(self):
102
  """Fetch logs from the sandbox"""
103
  if not self.is_connected:
104
- return "❌ Not connected to backend"
105
 
106
  if self.is_sandbox_expired():
107
- return "⏰ Sandbox expired. Logs are no longer available."
108
 
109
  try:
110
  result = self.client.predict(api_name="/fetch_logs")
111
  timestamp = datetime.now().strftime("%H:%M:%S")
112
  remaining = self.get_remaining_time()
113
- return f"[{timestamp}] Remaining time: {remaining}\nLogs from {self.current_engine}:\n\n{result}"
114
  except Exception as e:
115
- return f"[ERROR] Failed to fetch logs: {str(e)}"
116
 
117
  def kill_sandbox(self):
118
  """Terminate the sandbox"""
119
  if not self.is_connected:
120
- return "❌ Not connected to backend", ""
121
 
122
  try:
123
  result = self.client.predict(api_name="/kill_sandbox")
124
  self.sandbox_created = False
125
  self.creation_time = None
126
  self.stop_auto_refresh = True
127
- return f"πŸ›‘ Sandbox terminated on {self.current_engine}\n\nResponse: {result}", "TERMINATED"
128
  except Exception as e:
129
- return f"❌ Termination failed: {str(e)}", ""
130
 
131
  def get_status(self):
132
  """Get current sandbox status"""
@@ -138,14 +139,13 @@ class SandboxManager:
138
 
139
  try:
140
  result = self.client.predict(api_name="/status_sandbox")
 
141
  if "running" in str(result).lower():
142
- remaining = self.get_remaining_time()
143
- return f"RUNNING ({remaining} left) - {result}"
144
  else:
145
- remaining = self.get_remaining_time()
146
- return f"IDLE ({remaining} left) - {result}"
147
  except Exception as e:
148
- return f"ERROR - {str(e)}"
149
 
150
  def start_time_monitor(self):
151
  """Start monitoring thread for time limits"""
@@ -166,248 +166,648 @@ class SandboxManager:
166
  sandbox = SandboxManager()
167
 
168
  # Sample files
169
- SAMPLE_MAIN_PY = """# Enterprise Python Application
 
 
 
170
  import os
 
171
  import time
172
- from datetime import datetime
 
 
 
 
173
 
174
- def main():
175
- print("πŸš€ Sandbox Compute Platform - Initialized")
176
- print(f"πŸ“… Started at: {datetime.now()}")
177
- print("βœ… Environment ready for development")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
 
179
- # Your application code here
180
- while True:
181
- print(f"⏱️ Running... {datetime.now().strftime('%H:%M:%S')}")
182
- time.sleep(30)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
 
184
  if __name__ == "__main__":
185
  main()
186
  """
187
 
188
- SAMPLE_REQUIREMENTS_TXT = """# Production Dependencies
189
- # Specify exact versions for reproducibility
190
 
191
- # Web framework
192
- flask==2.3.3
193
  requests==2.31.0
194
 
195
- # Data processing
196
- pandas==2.1.1
197
- numpy==1.24.3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
 
199
- # Utilities
 
 
 
 
200
  python-dotenv==1.0.0
 
 
 
 
 
 
 
 
 
 
201
  """
202
 
203
- # Enhanced CSS with modern design
204
  industrial_css = """
205
- @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap');
206
 
 
207
  :root {
208
- --primary: #2563eb;
209
- --primary-hover: #1d4ed8;
 
210
  --secondary: #64748b;
211
- --success: #10b981;
212
- --warning: #f59e0b;
213
- --danger: #ef4444;
214
- --surface: #ffffff;
215
- --surface-elevated: #f8fafc;
216
- --border: #e2e8f0;
217
- --text: #0f172a;
218
- --text-muted: #64748b;
219
- --shadow: rgba(15, 23, 42, 0.1);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
220
  }
221
 
 
222
  * {
223
- font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important;
 
 
 
 
 
 
 
 
 
 
 
 
224
  }
225
 
 
226
  .gradio-container {
227
- background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%) !important;
228
- min-height: 100vh;
 
 
 
 
 
 
 
 
229
  }
230
 
231
- /* Header */
232
- .platform-header {
233
- background: linear-gradient(135deg, var(--primary) 0%, var(--primary-hover) 100%) !important;
234
- color: white !important;
235
- padding: 2rem !important;
236
- border-radius: 0 0 1rem 1rem !important;
237
- margin-bottom: 1.5rem !important;
238
- box-shadow: 0 10px 25px var(--shadow) !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
239
  }
240
 
241
  .platform-title {
242
- font-size: 2rem !important;
243
- font-weight: 800 !important;
244
- margin-bottom: 0.5rem !important;
 
 
 
245
  }
246
 
247
  .platform-subtitle {
248
  font-size: 1rem !important;
249
- opacity: 0.9 !important;
 
250
  font-weight: 400 !important;
 
 
251
  }
252
 
253
- .breadcrumb {
254
- background: var(--surface-elevated) !important;
255
- padding: 0.75rem 1.5rem !important;
256
- border-radius: 0.75rem !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
  font-size: 0.875rem !important;
258
  color: var(--text-muted) !important;
259
- border: 1px solid var(--border) !important;
260
- margin-bottom: 1.5rem !important;
261
  }
262
 
263
- /* Cards */
264
- .card {
265
- background: var(--surface) !important;
266
  border: 1px solid var(--border) !important;
267
- border-radius: 1rem !important;
268
- box-shadow: 0 4px 6px -1px var(--shadow) !important;
269
  overflow: hidden !important;
270
- margin-bottom: 1.5rem !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
271
  }
272
 
273
  .card-header {
274
- background: var(--surface-elevated) !important;
275
- padding: 1rem 1.5rem !important;
276
- border-bottom: 1px solid var(--border) !important;
277
- font-weight: 600 !important;
278
  font-size: 1.1rem !important;
 
 
 
279
  display: flex !important;
280
  align-items: center !important;
281
- gap: 0.5rem !important;
282
  }
283
 
284
  .card-content {
285
- padding: 1.5rem !important;
286
  }
287
 
288
- /* Buttons */
289
- .btn {
290
- padding: 0.75rem 1.5rem !important;
 
 
291
  border-radius: 0.5rem !important;
292
- font-weight: 500 !important;
 
293
  font-size: 0.875rem !important;
294
- transition: all 0.2s ease !important;
295
- border: none !important;
 
 
 
 
296
  }
297
 
298
- .btn-primary {
299
- background: linear-gradient(135deg, var(--primary), var(--primary-hover)) !important;
300
- color: white !important;
301
- box-shadow: 0 4px 14px 0 rgba(37, 99, 235, 0.25) !important;
302
  }
303
 
304
- .btn-primary:hover {
305
- transform: translateY(-2px) !important;
306
- box-shadow: 0 6px 20px 0 rgba(37, 99, 235, 0.35) !important;
307
  }
308
 
309
  .btn-secondary {
310
- background: var(--surface) !important;
311
- color: var(--text) !important;
312
- border: 1px solid var(--border) !important;
313
  }
314
 
315
  .btn-secondary:hover {
316
- background: var(--surface-elevated) !important;
317
- border-color: var(--secondary) !important;
318
  }
319
 
320
  .btn-danger {
321
- background: linear-gradient(135deg, var(--danger), #dc2626) !important;
322
- color: white !important;
323
- box-shadow: 0 4px 14px 0 rgba(239, 68, 68, 0.25) !important;
324
  }
325
 
326
  .btn-danger:hover {
327
- transform: translateY(-2px) !important;
328
- box-shadow: 0 6px 20px 0 rgba(239, 68, 68, 0.35) !important;
329
  }
330
 
331
- /* Status indicators */
332
- .status-badge {
333
- padding: 0.5rem 1rem !important;
 
 
334
  border-radius: 0.5rem !important;
 
 
335
  font-weight: 500 !important;
336
- font-size: 0.875rem !important;
337
  text-align: center !important;
 
 
338
  }
339
 
340
  .status-online {
341
- background: #d1fae5 !important;
 
342
  color: var(--success) !important;
343
- border: 1px solid #a7f3d0 !important;
344
  }
345
 
346
  .status-offline {
347
- background: #fee2e2 !important;
 
348
  color: var(--danger) !important;
349
- border: 1px solid #fecaca !important;
350
  }
351
 
352
  .status-warning {
353
- background: #fef3c7 !important;
 
354
  color: var(--warning) !important;
355
- border: 1px solid #fed7aa !important;
356
  }
357
 
358
- /* Code editors */
359
- .code-editor {
360
- font-family: 'JetBrains Mono', monospace !important;
361
- background: #1e293b !important;
362
- color: #e2e8f0 !important;
 
363
  border-radius: 0.75rem !important;
364
- border: 1px solid #334155 !important;
 
365
  }
366
 
367
  .requirements-editor {
368
  font-family: 'JetBrains Mono', monospace !important;
369
- background: #27272a !important;
370
- color: #f4f4f5 !important;
 
371
  border-radius: 0.75rem !important;
372
- border: 1px solid #3f3f46 !important;
373
  }
374
 
375
- .terminal {
 
376
  font-family: 'JetBrains Mono', monospace !important;
377
- background: #0f172a !important;
378
- color: #e2e8f0 !important;
 
379
  border-radius: 0.75rem !important;
380
- padding: 1rem !important;
381
- border: 1px solid #1e293b !important;
 
 
 
 
382
  }
383
 
384
- /* Form labels */
385
- .form-label {
386
- font-weight: 600 !important;
387
- color: var(--text) !important;
388
- margin-bottom: 0.5rem !important;
389
  font-size: 0.875rem !important;
390
  text-transform: uppercase !important;
391
- letter-spacing: 0.025em !important;
 
 
 
 
392
  }
393
 
394
- /* Monitoring panel */
395
  .monitor-panel {
396
- background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%) !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
397
  border: 1px solid var(--border) !important;
398
- border-radius: 1rem !important;
399
- padding: 1.5rem !important;
400
- box-shadow: 0 4px 6px -1px var(--shadow) !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
401
  }
402
 
403
  /* Animations */
404
- @keyframes pulse {
405
- 0%, 100% { opacity: 1; }
406
- 50% { opacity: 0.5; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
407
  }
408
 
409
- .pulse {
410
- animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
411
  }
412
  """
413
 
@@ -424,138 +824,283 @@ def get_session_info():
424
  if sandbox.sandbox_created:
425
  remaining = sandbox.get_remaining_time()
426
  created = sandbox.creation_time.strftime("%H:%M:%S") if sandbox.creation_time else "N/A"
427
- return f"Created: {created} | Remaining: {remaining}"
428
- return "No active sandbox"
 
 
 
 
 
 
 
 
429
 
430
- # Build enhanced Gradio interface
431
- with gr.Blocks(css=industrial_css, title="Sandbox Compute Platform") as demo:
 
 
432
  gr.HTML("""
433
- <div class="platform-header">
434
- <div class="platform-title">πŸš€ Sandbox Compute Platform</div>
435
- <div class="platform-subtitle">Enterprise-grade cloud computing with 2-hour session limits</div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
436
  </div>
437
- <div class="breadcrumb">
438
- 🏠 Dashboard β†’ ⚑ Compute Services β†’ πŸ› οΈ Sandbox Management Console
 
 
 
 
439
  </div>
440
  """)
441
 
442
- # Session Info Bar
443
- with gr.Row():
444
- with gr.Column():
445
- session_info = gr.Textbox(
446
- value=get_session_info(),
447
- label="πŸ“Š Session Information",
448
- interactive=False,
449
- elem_classes=["status-badge"]
450
- )
451
-
452
- with gr.Row():
453
- # Main Content
454
- with gr.Column(scale=2):
455
- # Connection Management
456
- with gr.Group(elem_classes=["card"]):
457
- gr.HTML('<div class="card-header">πŸ”Œ Connection Management</div>')
458
  with gr.Group(elem_classes=["card-content"]):
459
- gr.HTML('<div class="form-label">Initialize Backend Connection</div>')
460
- with gr.Row():
461
- connect_btn = gr.Button("πŸš€ Connect to Backend", elem_classes=["btn-primary"])
462
- load_samples_btn = gr.Button("πŸ“„ Load Templates", elem_classes=["btn-secondary"])
463
-
464
- gr.HTML('<div class="form-label">Active Engine</div>')
465
- current_engine_display = gr.Textbox(
466
- value="No engine selected",
467
  interactive=False,
468
- elem_classes=["status-badge"],
469
  show_label=False
470
  )
471
 
472
- gr.HTML('<div class="form-label">Connection Status</div>')
473
- connection_status = gr.Textbox(
474
- value="DISCONNECTED",
475
- interactive=False,
476
- elem_classes=["status-offline"],
477
- show_label=False
478
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
479
 
480
  # Development Environment
481
- with gr.Group(elem_classes=["card"]):
482
- gr.HTML('<div class="card-header">πŸ’» Development Environment</div>')
483
  with gr.Group(elem_classes=["card-content"]):
484
- with gr.Tab("πŸ“ main.py"):
485
- gr.HTML('<div class="form-label">Application Source Code</div>')
 
486
  main_py_editor = gr.Code(
487
  value=SAMPLE_MAIN_PY,
488
  language="python",
489
- lines=15,
490
- elem_classes=["code-editor"],
491
  show_label=False
492
  )
493
 
494
- with gr.Tab("πŸ“¦ requirements.txt"):
495
- gr.HTML('<div class="form-label">Dependency Specifications</div>')
496
  requirements_editor = gr.Textbox(
497
  value=SAMPLE_REQUIREMENTS_TXT,
498
- lines=15,
499
  elem_classes=["requirements-editor"],
500
  show_label=False,
501
- max_lines=20
502
  )
503
 
504
- gr.HTML('<hr style="margin: 1.5rem 0; border: 1px solid var(--border);">')
 
505
 
506
  with gr.Row():
507
- launch_btn = gr.Button("πŸš€ Deploy Sandbox", elem_classes=["btn-primary"], size="lg")
508
- kill_btn = gr.Button("πŸ›‘ Terminate Sandbox", elem_classes=["btn-danger"], size="lg")
 
 
 
 
 
 
 
 
509
 
510
- gr.HTML('<div class="form-label">Deployment Output</div>')
511
  launch_output = gr.Textbox(
512
- lines=6,
513
  interactive=False,
514
- placeholder="πŸš€ Deployment logs and status information will appear here...",
515
- elem_classes=["terminal"],
516
  show_label=False
517
  )
518
 
519
- # Monitoring Panel
520
- with gr.Column(scale=1):
521
- with gr.Group(elem_classes=["monitor-panel"]):
522
- gr.HTML('<div class="form-label">πŸ“Š System Monitor</div>')
523
-
524
- gr.HTML('<div class="form-label">Instance Status</div>')
525
- status_display = gr.Textbox(
526
- value="OFFLINE",
527
- interactive=False,
528
- elem_classes=["status-offline"],
529
- show_label=False
530
- )
531
-
532
- status_refresh_btn = gr.Button("πŸ”„ Refresh Status", elem_classes=["btn-secondary"], size="sm")
533
-
534
- gr.HTML('<div class="form-label">⚠️ Session Limits</div>')
535
- gr.HTML("""
536
- <div style="background: #fef3c7; padding: 1rem; border-radius: 0.5rem; border: 1px solid #fed7aa;">
537
- <strong>Time Limit:</strong> 2 hours per sandbox<br>
538
- <strong>Sessions:</strong> 1 sandbox per browser session<br>
539
- <strong>Auto-cleanup:</strong> Sandbox terminates when expired
540
- </div>
541
- """)
542
-
543
- # Logs Section
544
- with gr.Group(elem_classes=["card"]):
545
- gr.HTML('<div class="card-header">πŸ“‹ System Logs & Monitoring</div>')
546
- with gr.Group(elem_classes=["card-content"]):
547
- with gr.Row():
548
- fetch_logs_btn = gr.Button("πŸ“‹ Fetch Application Logs", elem_classes=["btn-secondary"])
549
- auto_refresh_btn = gr.Button("πŸ”„ Auto Refresh (30s)", elem_classes=["btn-secondary"])
550
 
551
- gr.HTML('<div class="form-label">Runtime Logs</div>')
552
- logs_display = gr.Textbox(
553
- lines=12,
554
- interactive=False,
555
- elem_classes=["terminal"],
556
- placeholder="[SYSTEM] πŸ“‹ Application logs will appear here...",
557
- show_label=False
558
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
559
 
560
  # Event Handlers
561
  connect_btn.click(
@@ -588,12 +1133,40 @@ with gr.Blocks(css=industrial_css, title="Sandbox Compute Platform") as demo:
588
  fn=auto_refresh_status,
589
  outputs=status_display
590
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
591
 
592
- # Launch the application
593
  if __name__ == "__main__":
594
  demo.launch(
595
  server_name="0.0.0.0",
596
  server_port=7860,
597
  share=False,
598
- debug=False
 
 
599
  )
 
54
  def connect(self):
55
  """Connect to a backend engine"""
56
  if self.sandbox_created:
57
+ return "⚠️ SANDBOX ALREADY ACTIVE - Single session limit enforced", self.current_engine
58
 
59
  engine = self.select_random_engine()
60
  try:
61
  self.client = Client(engine)
62
  self.is_connected = True
63
+ return f"βœ… ENGINE ONLINE - {engine}", engine
64
  except Exception as e:
65
  self.is_connected = False
66
  self.current_engine = None
67
+ return f"❌ CONNECTION FAILED - {engine}: {str(e)}", "CONNECTION FAILED"
68
 
69
  def launch_sandbox(self, main_py_code, requirements_txt):
70
  """Launch the sandbox (only once per session)"""
71
  if self.sandbox_created:
72
  remaining = self.get_remaining_time()
73
  if remaining == "EXPIRED":
74
+ return "⏰ SESSION EXPIRED - 2-hour limit reached. Refresh page for new session.", ""
75
+ return f"⚠️ SANDBOX ACTIVE - Remaining: {remaining}", self.get_status()
76
 
77
  if not self.is_connected:
78
+ return "❌ ENGINE OFFLINE - Connect to backend first", ""
79
 
80
  try:
81
  result = self.client.predict(
 
92
  self.start_time_monitor()
93
 
94
  remaining = self.get_remaining_time()
95
+ return (f"πŸš€ SANDBOX DEPLOYED - Engine: {self.current_engine}\n"
96
+ f"⏱️ SESSION LIMIT: 2 hours | REMAINING: {remaining}\n"
97
+ f"πŸ“Š STATUS: ACTIVE\n\n"
98
+ f"ENGINE RESPONSE:\n{result}"), self.get_status()
99
  except Exception as e:
100
+ return f"❌ DEPLOYMENT FAILED - {str(e)}", ""
101
 
102
  def fetch_logs(self):
103
  """Fetch logs from the sandbox"""
104
  if not self.is_connected:
105
+ return "❌ ENGINE OFFLINE - No connection to backend"
106
 
107
  if self.is_sandbox_expired():
108
+ return "⏰ SESSION EXPIRED - Logs unavailable after 2-hour limit"
109
 
110
  try:
111
  result = self.client.predict(api_name="/fetch_logs")
112
  timestamp = datetime.now().strftime("%H:%M:%S")
113
  remaining = self.get_remaining_time()
114
+ return f"[{timestamp}] REMAINING: {remaining} | ENGINE: {self.current_engine}\n{'='*80}\n{result}"
115
  except Exception as e:
116
+ return f"[ERROR] LOG FETCH FAILED - {str(e)}"
117
 
118
  def kill_sandbox(self):
119
  """Terminate the sandbox"""
120
  if not self.is_connected:
121
+ return "❌ ENGINE OFFLINE - No connection available", ""
122
 
123
  try:
124
  result = self.client.predict(api_name="/kill_sandbox")
125
  self.sandbox_created = False
126
  self.creation_time = None
127
  self.stop_auto_refresh = True
128
+ return f"πŸ›‘ SANDBOX TERMINATED - Engine: {self.current_engine}\n\nENGINE RESPONSE:\n{result}", "TERMINATED"
129
  except Exception as e:
130
+ return f"❌ TERMINATION FAILED - {str(e)}", ""
131
 
132
  def get_status(self):
133
  """Get current sandbox status"""
 
139
 
140
  try:
141
  result = self.client.predict(api_name="/status_sandbox")
142
+ remaining = self.get_remaining_time()
143
  if "running" in str(result).lower():
144
+ return f"RUNNING | {remaining}"
 
145
  else:
146
+ return f"IDLE | {remaining}"
 
147
  except Exception as e:
148
+ return f"ERROR | {str(e)}"
149
 
150
  def start_time_monitor(self):
151
  """Start monitoring thread for time limits"""
 
166
  sandbox = SandboxManager()
167
 
168
  # Sample files
169
+ SAMPLE_MAIN_PY = """#!/usr/bin/env python3
170
+ # SANDBOX COMPUTE PLATFORM - ENTERPRISE APPLICATION
171
+ # Production-ready Python service with monitoring capabilities
172
+
173
  import os
174
+ import sys
175
  import time
176
+ import logging
177
+ from datetime import datetime, timezone
178
+ import json
179
+ import socket
180
+ import psutil
181
 
182
+ # Configure enterprise logging
183
+ logging.basicConfig(
184
+ level=logging.INFO,
185
+ format='[%(asctime)s] %(levelname)s - %(message)s',
186
+ handlers=[
187
+ logging.StreamHandler(sys.stdout),
188
+ logging.FileHandler('/tmp/application.log')
189
+ ]
190
+ )
191
+
192
+ logger = logging.getLogger(__name__)
193
+
194
+ class SandboxApplication:
195
+ def __init__(self):
196
+ self.start_time = datetime.now(timezone.utc)
197
+ self.hostname = socket.gethostname()
198
+ self.pid = os.getpid()
199
+
200
+ def get_system_info(self):
201
+ \"\"\"Collect system metrics\"\"\"
202
+ return {
203
+ 'hostname': self.hostname,
204
+ 'pid': self.pid,
205
+ 'uptime': str(datetime.now(timezone.utc) - self.start_time),
206
+ 'cpu_percent': psutil.cpu_percent(),
207
+ 'memory_mb': psutil.virtual_memory().used // 1024 // 1024,
208
+ 'disk_usage': psutil.disk_usage('/').percent
209
+ }
210
 
211
+ def run(self):
212
+ \"\"\"Main application loop\"\"\"
213
+ logger.info(f"πŸš€ SANDBOX APPLICATION INITIALIZED")
214
+ logger.info(f"πŸ“ HOSTNAME: {self.hostname} | PID: {self.pid}")
215
+ logger.info(f"⏰ START TIME: {self.start_time}")
216
+ logger.info("="*60)
217
+
218
+ cycle = 0
219
+ while True:
220
+ try:
221
+ cycle += 1
222
+ current_time = datetime.now(timezone.utc)
223
+
224
+ # Log system status every 10 cycles (5 minutes)
225
+ if cycle % 10 == 0:
226
+ metrics = self.get_system_info()
227
+ logger.info(f"πŸ“Š METRICS | CPU: {metrics['cpu_percent']:.1f}% | "
228
+ f"RAM: {metrics['memory_mb']}MB | "
229
+ f"UPTIME: {metrics['uptime']}")
230
+
231
+ # Regular heartbeat
232
+ logger.info(f"⚑ CYCLE {cycle:04d} | {current_time.strftime('%H:%M:%S UTC')} | STATUS: OPERATIONAL")
233
+
234
+ # Application logic here
235
+ time.sleep(30) # 30-second intervals
236
+
237
+ except KeyboardInterrupt:
238
+ logger.info("πŸ›‘ SHUTDOWN SIGNAL RECEIVED")
239
+ break
240
+ except Exception as e:
241
+ logger.error(f"❌ ERROR: {str(e)}")
242
+ time.sleep(5)
243
+
244
+ logger.info("🏁 APPLICATION TERMINATED")
245
+
246
+ def main():
247
+ app = SandboxApplication()
248
+ app.run()
249
 
250
  if __name__ == "__main__":
251
  main()
252
  """
253
 
254
+ SAMPLE_REQUIREMENTS_TXT = """# SANDBOX COMPUTE PLATFORM - PRODUCTION DEPENDENCIES
255
+ # Enterprise-grade package specifications with version pinning
256
 
257
+ # System monitoring and utilities
258
+ psutil==5.9.6
259
  requests==2.31.0
260
 
261
+ # Web framework and APIs
262
+ flask==3.0.0
263
+ flask-cors==4.0.0
264
+ gunicorn==21.2.0
265
+
266
+ # Data processing and analysis
267
+ pandas==2.1.3
268
+ numpy==1.25.2
269
+ scipy==1.11.4
270
+
271
+ # Database connectivity
272
+ sqlalchemy==2.0.23
273
+ pymongo==4.6.0
274
+
275
+ # Caching and performance
276
+ redis==5.0.1
277
+ celery==5.3.4
278
 
279
+ # Security and authentication
280
+ cryptography==41.0.8
281
+ pyjwt==2.8.0
282
+
283
+ # Configuration and environment
284
  python-dotenv==1.0.0
285
+ pydantic==2.5.0
286
+
287
+ # Logging and monitoring
288
+ structlog==23.2.0
289
+ prometheus-client==0.19.0
290
+
291
+ # Development and testing
292
+ pytest==7.4.3
293
+ black==23.11.0
294
+ flake8==6.1.0
295
  """
296
 
297
+ # Industrial-grade full-screen CSS
298
  industrial_css = """
299
+ @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,400;0,500;0,600;0,700;1,400&family=Inter:wght@300;400;500;600;700;800;900&display=swap');
300
 
301
+ /* CSS Variables for Industrial Theme */
302
  :root {
303
+ --primary: #0ea5e9;
304
+ --primary-dark: #0284c7;
305
+ --primary-darker: #0369a1;
306
  --secondary: #64748b;
307
+ --accent: #06b6d4;
308
+ --success: #059669;
309
+ --warning: #d97706;
310
+ --danger: #dc2626;
311
+ --info: #2563eb;
312
+
313
+ --bg-primary: #0f172a;
314
+ --bg-secondary: #1e293b;
315
+ --bg-tertiary: #334155;
316
+ --bg-surface: #475569;
317
+ --bg-elevated: #64748b;
318
+
319
+ --text-primary: #f8fafc;
320
+ --text-secondary: #e2e8f0;
321
+ --text-muted: #94a3b8;
322
+ --text-inverse: #0f172a;
323
+
324
+ --border: #334155;
325
+ --border-light: #475569;
326
+ --border-accent: #0ea5e9;
327
+
328
+ --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.3);
329
+ --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.4);
330
+ --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.5);
331
+ --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.6);
332
+
333
+ --glow-primary: 0 0 20px rgba(14, 165, 233, 0.3);
334
+ --glow-success: 0 0 20px rgba(5, 150, 105, 0.3);
335
+ --glow-danger: 0 0 20px rgba(220, 38, 38, 0.3);
336
+ --glow-warning: 0 0 20px rgba(217, 119, 6, 0.3);
337
  }
338
 
339
+ /* Global Reset and Base Styles */
340
  * {
341
+ margin: 0;
342
+ padding: 0;
343
+ box-sizing: border-box;
344
+ }
345
+
346
+ html, body {
347
+ height: 100vh !important;
348
+ width: 100vw !important;
349
+ overflow-x: hidden !important;
350
+ background: var(--bg-primary) !important;
351
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, system-ui, sans-serif !important;
352
+ color: var(--text-primary) !important;
353
+ line-height: 1.5 !important;
354
  }
355
 
356
+ /* Gradio Container - Full Screen */
357
  .gradio-container {
358
+ max-width: 100vw !important;
359
+ width: 100vw !important;
360
+ min-height: 100vh !important;
361
+ height: 100vh !important;
362
+ margin: 0 !important;
363
+ padding: 0 !important;
364
+ background: linear-gradient(135deg, var(--bg-primary) 0%, #0c1420 50%, var(--bg-primary) 100%) !important;
365
+ display: flex !important;
366
+ flex-direction: column !important;
367
+ overflow-y: auto !important;
368
  }
369
 
370
+ /* Main Content Wrapper */
371
+ .main-content {
372
+ flex: 1 !important;
373
+ padding: 0 !important;
374
+ margin: 0 !important;
375
+ }
376
+
377
+ /* Industrial Header */
378
+ .industrial-header {
379
+ background: linear-gradient(135deg, var(--bg-secondary) 0%, var(--bg-tertiary) 100%) !important;
380
+ border-bottom: 3px solid var(--primary) !important;
381
+ padding: 1.5rem 2rem !important;
382
+ box-shadow: var(--shadow-lg) !important;
383
+ position: relative !important;
384
+ overflow: hidden !important;
385
+ }
386
+
387
+ .industrial-header::before {
388
+ content: '';
389
+ position: absolute;
390
+ top: 0;
391
+ left: 0;
392
+ right: 0;
393
+ bottom: 0;
394
+ background: repeating-linear-gradient(
395
+ 90deg,
396
+ transparent,
397
+ transparent 2px,
398
+ rgba(14, 165, 233, 0.1) 2px,
399
+ rgba(14, 165, 233, 0.1) 4px
400
+ );
401
+ pointer-events: none;
402
+ }
403
+
404
+ .header-content {
405
+ position: relative !important;
406
+ z-index: 2 !important;
407
+ display: flex !important;
408
+ justify-content: space-between !important;
409
+ align-items: center !important;
410
  }
411
 
412
  .platform-title {
413
+ font-size: 2.5rem !important;
414
+ font-weight: 900 !important;
415
+ color: var(--text-primary) !important;
416
+ text-shadow: 0 0 20px var(--primary) !important;
417
+ letter-spacing: -0.025em !important;
418
+ margin: 0 !important;
419
  }
420
 
421
  .platform-subtitle {
422
  font-size: 1rem !important;
423
+ color: var(--text-muted) !important;
424
+ margin-top: 0.5rem !important;
425
  font-weight: 400 !important;
426
+ text-transform: uppercase !important;
427
+ letter-spacing: 0.05em !important;
428
  }
429
 
430
+ .system-status {
431
+ text-align: right !important;
432
+ font-family: 'JetBrains Mono', monospace !important;
433
+ font-size: 0.875rem !important;
434
+ }
435
+
436
+ .status-indicator {
437
+ display: flex !important;
438
+ align-items: center !important;
439
+ gap: 0.5rem !important;
440
+ margin-bottom: 0.25rem !important;
441
+ color: var(--text-secondary) !important;
442
+ }
443
+
444
+ .status-dot {
445
+ width: 8px !important;
446
+ height: 8px !important;
447
+ background: var(--success) !important;
448
+ border-radius: 50% !important;
449
+ box-shadow: var(--glow-success) !important;
450
+ animation: pulse-dot 2s ease-in-out infinite !important;
451
+ }
452
+
453
+ /* Navigation Breadcrumb */
454
+ .nav-breadcrumb {
455
+ background: var(--bg-secondary) !important;
456
+ border-bottom: 1px solid var(--border) !important;
457
+ padding: 0.75rem 2rem !important;
458
+ font-family: 'JetBrains Mono', monospace !important;
459
  font-size: 0.875rem !important;
460
  color: var(--text-muted) !important;
461
+ text-transform: uppercase !important;
462
+ letter-spacing: 0.05em !important;
463
  }
464
 
465
+ /* Industrial Cards */
466
+ .industrial-card {
467
+ background: linear-gradient(135deg, var(--bg-secondary) 0%, rgba(30, 41, 59, 0.95) 100%) !important;
468
  border: 1px solid var(--border) !important;
469
+ border-radius: 0.75rem !important;
470
+ margin: 1rem !important;
471
  overflow: hidden !important;
472
+ box-shadow: var(--shadow-lg) !important;
473
+ backdrop-filter: blur(10px) !important;
474
+ position: relative !important;
475
+ }
476
+
477
+ .industrial-card::before {
478
+ content: '';
479
+ position: absolute;
480
+ top: 0;
481
+ left: 0;
482
+ right: 0;
483
+ height: 2px;
484
+ background: linear-gradient(90deg, var(--primary), var(--accent), var(--primary));
485
+ opacity: 0.8;
486
  }
487
 
488
  .card-header {
489
+ background: linear-gradient(135deg, var(--bg-tertiary), var(--bg-surface)) !important;
490
+ border-bottom: 1px solid var(--border-light) !important;
491
+ padding: 1.25rem 2rem !important;
492
+ font-weight: 700 !important;
493
  font-size: 1.1rem !important;
494
+ color: var(--text-primary) !important;
495
+ text-transform: uppercase !important;
496
+ letter-spacing: 0.025em !important;
497
  display: flex !important;
498
  align-items: center !important;
499
+ gap: 0.75rem !important;
500
  }
501
 
502
  .card-content {
503
+ padding: 2rem !important;
504
  }
505
 
506
+ /* Industrial Buttons */
507
+ .btn-industrial {
508
+ background: linear-gradient(135deg, var(--primary), var(--primary-dark)) !important;
509
+ color: var(--text-primary) !important;
510
+ border: 1px solid var(--primary-darker) !important;
511
  border-radius: 0.5rem !important;
512
+ padding: 1rem 2rem !important;
513
+ font-weight: 600 !important;
514
  font-size: 0.875rem !important;
515
+ text-transform: uppercase !important;
516
+ letter-spacing: 0.025em !important;
517
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
518
+ box-shadow: var(--shadow-md) !important;
519
+ position: relative !important;
520
+ overflow: hidden !important;
521
  }
522
 
523
+ .btn-industrial:hover {
524
+ transform: translateY(-2px) !important;
525
+ box-shadow: var(--shadow-xl), var(--glow-primary) !important;
526
+ background: linear-gradient(135deg, var(--primary-dark), var(--primary-darker)) !important;
527
  }
528
 
529
+ .btn-industrial:active {
530
+ transform: translateY(0) !important;
 
531
  }
532
 
533
  .btn-secondary {
534
+ background: linear-gradient(135deg, var(--bg-surface), var(--bg-elevated)) !important;
535
+ color: var(--text-primary) !important;
536
+ border: 1px solid var(--border-light) !important;
537
  }
538
 
539
  .btn-secondary:hover {
540
+ background: linear-gradient(135deg, var(--bg-elevated), var(--secondary)) !important;
541
+ box-shadow: var(--shadow-lg) !important;
542
  }
543
 
544
  .btn-danger {
545
+ background: linear-gradient(135deg, var(--danger), #b91c1c) !important;
546
+ border: 1px solid #7f1d1d !important;
 
547
  }
548
 
549
  .btn-danger:hover {
550
+ box-shadow: var(--shadow-xl), var(--glow-danger) !important;
 
551
  }
552
 
553
+ /* Status Displays */
554
+ .status-display {
555
+ background: var(--bg-tertiary) !important;
556
+ color: var(--text-primary) !important;
557
+ border: 1px solid var(--border) !important;
558
  border-radius: 0.5rem !important;
559
+ padding: 1rem 1.5rem !important;
560
+ font-family: 'JetBrains Mono', monospace !important;
561
  font-weight: 500 !important;
 
562
  text-align: center !important;
563
+ text-transform: uppercase !important;
564
+ letter-spacing: 0.05em !important;
565
  }
566
 
567
  .status-online {
568
+ background: linear-gradient(135deg, rgba(5, 150, 105, 0.2), rgba(5, 150, 105, 0.1)) !important;
569
+ border-color: var(--success) !important;
570
  color: var(--success) !important;
571
+ box-shadow: var(--glow-success) !important;
572
  }
573
 
574
  .status-offline {
575
+ background: linear-gradient(135deg, rgba(220, 38, 38, 0.2), rgba(220, 38, 38, 0.1)) !important;
576
+ border-color: var(--danger) !important;
577
  color: var(--danger) !important;
578
+ box-shadow: var(--glow-danger) !important;
579
  }
580
 
581
  .status-warning {
582
+ background: linear-gradient(135deg, rgba(217, 119, 6, 0.2), rgba(217, 119, 6, 0.1)) !important;
583
+ border-color: var(--warning) !important;
584
  color: var(--warning) !important;
585
+ box-shadow: var(--glow-warning) !important;
586
  }
587
 
588
+ /* Code Editors */
589
+ .code-editor-industrial {
590
+ font-family: 'JetBrains Mono', 'Fira Code', Consolas, monospace !important;
591
+ background: linear-gradient(135deg, #0c1420 0%, #0f172a 100%) !important;
592
+ color: var(--text-secondary) !important;
593
+ border: 1px solid var(--border) !important;
594
  border-radius: 0.75rem !important;
595
+ box-shadow: inset var(--shadow-lg) !important;
596
+ line-height: 1.6 !important;
597
  }
598
 
599
  .requirements-editor {
600
  font-family: 'JetBrains Mono', monospace !important;
601
+ background: linear-gradient(135deg, #1a1a1a 0%, #2d2d2d 100%) !important;
602
+ color: #e5e5e5 !important;
603
+ border: 1px solid var(--border) !important;
604
  border-radius: 0.75rem !important;
 
605
  }
606
 
607
+ /* Terminal Output */
608
+ .terminal-industrial {
609
  font-family: 'JetBrains Mono', monospace !important;
610
+ background: linear-gradient(135deg, #000000 0%, #0a0a0a 100%) !important;
611
+ color: #00ff88 !important;
612
+ border: 1px solid var(--border) !important;
613
  border-radius: 0.75rem !important;
614
+ padding: 1.5rem !important;
615
+ box-shadow: inset var(--shadow-lg) !important;
616
+ line-height: 1.4 !important;
617
+ font-size: 0.875rem !important;
618
+ white-space: pre-wrap !important;
619
+ overflow-y: auto !important;
620
  }
621
 
622
+ /* Form Labels */
623
+ .form-label-industrial {
624
+ font-weight: 700 !important;
625
+ color: var(--text-primary) !important;
 
626
  font-size: 0.875rem !important;
627
  text-transform: uppercase !important;
628
+ letter-spacing: 0.05em !important;
629
+ margin-bottom: 0.75rem !important;
630
+ display: block !important;
631
+ border-left: 3px solid var(--primary) !important;
632
+ padding-left: 0.75rem !important;
633
  }
634
 
635
+ /* Monitoring Panel */
636
  .monitor-panel {
637
+ background: linear-gradient(135deg, var(--bg-secondary) 0%, var(--bg-tertiary) 100%) !important;
638
+ border: 1px solid var(--border-accent) !important;
639
+ border-radius: 0.75rem !important;
640
+ box-shadow: var(--shadow-lg), var(--glow-primary) !important;
641
+ position: relative !important;
642
+ overflow: hidden !important;
643
+ }
644
+
645
+ .monitor-panel::before {
646
+ content: '';
647
+ position: absolute;
648
+ top: 0;
649
+ left: 0;
650
+ right: 0;
651
+ height: 2px;
652
+ background: linear-gradient(90deg, var(--primary), var(--accent), var(--primary));
653
+ animation: scan-line 3s ease-in-out infinite;
654
+ }
655
+
656
+ /* System Metrics */
657
+ .metric-grid {
658
+ display: grid !important;
659
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)) !important;
660
+ gap: 1rem !important;
661
+ margin-bottom: 1.5rem !important;
662
+ }
663
+
664
+ .metric-card {
665
+ background: rgba(15, 23, 42, 0.8) !important;
666
  border: 1px solid var(--border) !important;
667
+ border-radius: 0.5rem !important;
668
+ padding: 1rem !important;
669
+ text-align: center !important;
670
+ }
671
+
672
+ .metric-value {
673
+ font-family: 'JetBrains Mono', monospace !important;
674
+ font-size: 1.5rem !important;
675
+ font-weight: 700 !important;
676
+ color: var(--primary) !important;
677
+ text-shadow: var(--glow-primary) !important;
678
+ }
679
+
680
+ .metric-label {
681
+ font-size: 0.75rem !important;
682
+ color: var(--text-muted) !important;
683
+ text-transform: uppercase !important;
684
+ letter-spacing: 0.05em !important;
685
+ margin-top: 0.25rem !important;
686
+ }
687
+
688
+ /* Layouts */
689
+ .main-grid {
690
+ display: grid !important;
691
+ grid-template-columns: 1fr 350px !important;
692
+ gap: 0 !important;
693
+ height: calc(100vh - 140px) !important;
694
+ overflow: hidden !important;
695
+ }
696
+
697
+ .content-area {
698
+ display: flex !important;
699
+ flex-direction: column !important;
700
+ gap: 0 !important;
701
+ overflow-y: auto !important;
702
+ }
703
+
704
+ .sidebar {
705
+ background: var(--bg-secondary) !important;
706
+ border-left: 1px solid var(--border) !important;
707
+ overflow-y: auto !important;
708
  }
709
 
710
  /* Animations */
711
+ @keyframes pulse-dot {
712
+ 0%, 100% { opacity: 1; transform: scale(1); }
713
+ 50% { opacity: 0.5; transform: scale(1.2); }
714
+ }
715
+
716
+ @keyframes scan-line {
717
+ 0% { transform: translateX(-100%); }
718
+ 100% { transform: translateX(100vw); }
719
+ }
720
+
721
+ @keyframes glow-pulse {
722
+ 0%, 100% { box-shadow: var(--shadow-lg); }
723
+ 50% { box-shadow: var(--shadow-lg), var(--glow-primary); }
724
+ }
725
+
726
+ /* Tab Styling */
727
+ .tab-nav {
728
+ background: var(--bg-tertiary) !important;
729
+ border-bottom: 1px solid var(--border) !important;
730
+ }
731
+
732
+ .tab-nav button {
733
+ background: transparent !important;
734
+ color: var(--text-muted) !important;
735
+ border: none !important;
736
+ padding: 1rem 2rem !important;
737
+ font-weight: 500 !important;
738
+ text-transform: uppercase !important;
739
+ letter-spacing: 0.025em !important;
740
+ transition: all 0.3s ease !important;
741
+ }
742
+
743
+ .tab-nav button.selected {
744
+ background: var(--primary) !important;
745
+ color: var(--text-primary) !important;
746
+ box-shadow: var(--glow-primary) !important;
747
+ }
748
+
749
+ /* Warning Boxes */
750
+ .warning-box {
751
+ background: linear-gradient(135deg, rgba(217, 119, 6, 0.1), rgba(217, 119, 6, 0.05)) !important;
752
+ border: 1px solid var(--warning) !important;
753
+ border-radius: 0.5rem !important;
754
+ padding: 1.5rem !important;
755
+ margin: 1rem 0 !important;
756
+ color: var(--text-primary) !important;
757
+ }
758
+
759
+ .warning-title {
760
+ font-weight: 700 !important;
761
+ color: var(--warning) !important;
762
+ font-size: 0.875rem !important;
763
+ text-transform: uppercase !important;
764
+ letter-spacing: 0.05em !important;
765
+ margin-bottom: 0.5rem !important;
766
  }
767
 
768
+ /* Responsive Design */
769
+ @media (max-width: 1200px) {
770
+ .main-grid {
771
+ grid-template-columns: 1fr !important;
772
+ }
773
+
774
+ .sidebar {
775
+ border-left: none !important;
776
+ border-top: 1px solid var(--border) !important;
777
+ }
778
+ }
779
+
780
+ /* Scrollbar Styling */
781
+ ::-webkit-scrollbar {
782
+ width: 8px !important;
783
+ height: 8px !important;
784
+ }
785
+
786
+ ::-webkit-scrollbar-track {
787
+ background: var(--bg-primary) !important;
788
+ }
789
+
790
+ ::-webkit-scrollbar-thumb {
791
+ background: var(--primary) !important;
792
+ border-radius: 4px !important;
793
+ }
794
+
795
+ ::-webkit-scrollbar-thumb:hover {
796
+ background: var(--primary-dark) !important;
797
+ }
798
+
799
+ /* Loading States */
800
+ .loading {
801
+ animation: glow-pulse 2s ease-in-out infinite !important;
802
+ }
803
+
804
+ /* Focus States */
805
+ .btn-industrial:focus,
806
+ .status-display:focus,
807
+ input:focus,
808
+ textarea:focus {
809
+ outline: 2px solid var(--primary) !important;
810
+ outline-offset: 2px !important;
811
  }
812
  """
813
 
 
824
  if sandbox.sandbox_created:
825
  remaining = sandbox.get_remaining_time()
826
  created = sandbox.creation_time.strftime("%H:%M:%S") if sandbox.creation_time else "N/A"
827
+ return f"SESSION ACTIVE | CREATED: {created} | REMAINING: {remaining}"
828
+ return "NO ACTIVE SESSION"
829
+
830
+ def get_system_metrics():
831
+ return {
832
+ 'timestamp': datetime.now().strftime("%H:%M:%S"),
833
+ 'engine': sandbox.current_engine or "NONE",
834
+ 'status': sandbox.get_status(),
835
+ 'connection': "ONLINE" if sandbox.is_connected else "OFFLINE"
836
+ }
837
 
838
+ # Build industrial-grade full-screen interface
839
+ with gr.Blocks(css=industrial_css, title="SANDBOX COMPUTE PLATFORM") as demo:
840
+
841
+ # Industrial Header
842
  gr.HTML("""
843
+ <div class="industrial-header">
844
+ <div class="header-content">
845
+ <div>
846
+ <div class="platform-title">⚑ SANDBOX COMPUTE PLATFORM</div>
847
+ <div class="platform-subtitle">ENTERPRISE-GRADE CLOUD COMPUTING INFRASTRUCTURE</div>
848
+ </div>
849
+ <div class="system-status">
850
+ <div class="status-indicator">
851
+ <div class="status-dot"></div>
852
+ <span>SYSTEM ONLINE</span>
853
+ </div>
854
+ <div class="status-indicator">
855
+ <span>VERSION 2.1.0</span>
856
+ </div>
857
+ <div class="status-indicator">
858
+ <span>SECURITY LEVEL: MAXIMUM</span>
859
+ </div>
860
+ </div>
861
+ </div>
862
  </div>
863
+ """)
864
+
865
+ # Navigation Breadcrumb
866
+ gr.HTML("""
867
+ <div class="nav-breadcrumb">
868
+ 🏠 CONTROL CENTER β†’ ⚑ COMPUTE SERVICES β†’ πŸ› οΈ SANDBOX MANAGEMENT CONSOLE β†’ πŸš€ DEPLOYMENT INTERFACE
869
  </div>
870
  """)
871
 
872
+ # Main Grid Layout
873
+ with gr.Row(elem_classes=["main-grid"]):
874
+
875
+ # Main Content Area
876
+ with gr.Column(elem_classes=["content-area"], scale=3):
877
+
878
+ # Session Status Bar
879
+ with gr.Group(elem_classes=["industrial-card"]):
880
+ gr.HTML('<div class="card-header">πŸ“Š SESSION CONTROL CENTER</div>')
 
 
 
 
 
 
 
881
  with gr.Group(elem_classes=["card-content"]):
882
+ session_info = gr.Textbox(
883
+ value=get_session_info(),
884
+ label="",
 
 
 
 
 
885
  interactive=False,
886
+ elem_classes=["status-display"],
887
  show_label=False
888
  )
889
 
890
+ with gr.Row():
891
+ with gr.Column():
892
+ gr.HTML('<div class="form-label-industrial">⚑ ENGINE STATUS</div>')
893
+ current_engine_display = gr.Textbox(
894
+ value="NO ENGINE SELECTED",
895
+ interactive=False,
896
+ elem_classes=["status-display", "status-offline"],
897
+ show_label=False
898
+ )
899
+
900
+ with gr.Column():
901
+ gr.HTML('<div class="form-label-industrial">πŸ”— CONNECTION STATUS</div>')
902
+ connection_status = gr.Textbox(
903
+ value="DISCONNECTED",
904
+ interactive=False,
905
+ elem_classes=["status-display", "status-offline"],
906
+ show_label=False
907
+ )
908
+
909
+ # Infrastructure Management
910
+ with gr.Group(elem_classes=["industrial-card"]):
911
+ gr.HTML('<div class="card-header">πŸ”§ INFRASTRUCTURE MANAGEMENT</div>')
912
+ with gr.Group(elem_classes=["card-content"]):
913
+ with gr.Row():
914
+ connect_btn = gr.Button("πŸš€ INITIALIZE ENGINE", elem_classes=["btn-industrial"])
915
+ load_samples_btn = gr.Button("πŸ“‹ LOAD TEMPLATES", elem_classes=["btn-secondary"])
916
+
917
+ # Warning Box
918
+ gr.HTML("""
919
+ <div class="warning-box">
920
+ <div class="warning-title">⚠️ SESSION RESTRICTIONS</div>
921
+ <strong>β€’ SINGLE SANDBOX LIMIT:</strong> One sandbox per browser session<br>
922
+ <strong>β€’ TIME LIMIT:</strong> 2 hours maximum runtime<br>
923
+ <strong>β€’ AUTO-TERMINATION:</strong> Sandbox terminates when time expires<br>
924
+ <strong>β€’ NO PERSISTENCE:</strong> All data is lost after termination
925
+ </div>
926
+ """)
927
 
928
  # Development Environment
929
+ with gr.Group(elem_classes=["industrial-card"]):
930
+ gr.HTML('<div class="card-header">πŸ’» DEVELOPMENT ENVIRONMENT</div>')
931
  with gr.Group(elem_classes=["card-content"]):
932
+
933
+ with gr.Tab("πŸ“ MAIN.PY - APPLICATION SOURCE"):
934
+ gr.HTML('<div class="form-label-industrial">🐍 PYTHON APPLICATION CODE</div>')
935
  main_py_editor = gr.Code(
936
  value=SAMPLE_MAIN_PY,
937
  language="python",
938
+ lines=20,
939
+ elem_classes=["code-editor-industrial"],
940
  show_label=False
941
  )
942
 
943
+ with gr.Tab("πŸ“¦ REQUIREMENTS.TXT - DEPENDENCIES"):
944
+ gr.HTML('<div class="form-label-industrial">πŸ“‹ PACKAGE SPECIFICATIONS</div>')
945
  requirements_editor = gr.Textbox(
946
  value=SAMPLE_REQUIREMENTS_TXT,
947
+ lines=20,
948
  elem_classes=["requirements-editor"],
949
  show_label=False,
950
+ max_lines=25
951
  )
952
 
953
+ # Deployment Controls
954
+ gr.HTML('<hr style="margin: 2rem 0; border: 1px solid var(--border); opacity: 0.5;">')
955
 
956
  with gr.Row():
957
+ launch_btn = gr.Button(
958
+ "πŸš€ DEPLOY SANDBOX",
959
+ elem_classes=["btn-industrial"],
960
+ size="lg"
961
+ )
962
+ kill_btn = gr.Button(
963
+ "πŸ›‘ TERMINATE SANDBOX",
964
+ elem_classes=["btn-danger"],
965
+ size="lg"
966
+ )
967
 
968
+ gr.HTML('<div class="form-label-industrial">πŸ“Š DEPLOYMENT OUTPUT</div>')
969
  launch_output = gr.Textbox(
970
+ lines=8,
971
  interactive=False,
972
+ placeholder="[SYSTEM] Deployment logs and status information will appear here...",
973
+ elem_classes=["terminal-industrial"],
974
  show_label=False
975
  )
976
 
977
+ # System Logs
978
+ with gr.Group(elem_classes=["industrial-card"]):
979
+ gr.HTML('<div class="card-header">πŸ“‹ SYSTEM LOGS & MONITORING</div>')
980
+ with gr.Group(elem_classes=["card-content"]):
981
+
982
+ with gr.Row():
983
+ fetch_logs_btn = gr.Button("πŸ“‹ FETCH LOGS", elem_classes=["btn-secondary"])
984
+ auto_refresh_btn = gr.Button("πŸ”„ AUTO REFRESH", elem_classes=["btn-secondary"])
985
+ clear_logs_btn = gr.Button("πŸ—‘οΈ CLEAR LOGS", elem_classes=["btn-secondary"])
986
+
987
+ gr.HTML('<div class="form-label-industrial">πŸ“Š RUNTIME LOGS</div>')
988
+ logs_display = gr.Textbox(
989
+ lines=15,
990
+ interactive=False,
991
+ elem_classes=["terminal-industrial"],
992
+ placeholder="[SYSTEM] Application logs and runtime information will appear here...",
993
+ show_label=False
994
+ )
995
+
996
+ # Monitoring Sidebar
997
+ with gr.Column(elem_classes=["sidebar"], scale=1):
 
 
 
 
 
 
 
 
 
 
998
 
999
+ # System Monitor
1000
+ with gr.Group(elem_classes=["monitor-panel"]):
1001
+ gr.HTML('<div class="card-header">πŸ“Š SYSTEM MONITOR</div>')
1002
+ with gr.Group(elem_classes=["card-content"]):
1003
+
1004
+ gr.HTML('<div class="form-label-industrial">πŸ” INSTANCE STATUS</div>')
1005
+ status_display = gr.Textbox(
1006
+ value="OFFLINE",
1007
+ interactive=False,
1008
+ elem_classes=["status-display", "status-offline"],
1009
+ show_label=False
1010
+ )
1011
+
1012
+ status_refresh_btn = gr.Button("πŸ”„ REFRESH STATUS", elem_classes=["btn-secondary"], size="sm")
1013
+
1014
+ # System Metrics
1015
+ gr.HTML('<div class="form-label-industrial">πŸ“ˆ SYSTEM METRICS</div>')
1016
+ gr.HTML("""
1017
+ <div class="metric-grid">
1018
+ <div class="metric-card">
1019
+ <div class="metric-value" id="uptime">00:00:00</div>
1020
+ <div class="metric-label">UPTIME</div>
1021
+ </div>
1022
+ <div class="metric-card">
1023
+ <div class="metric-value" id="sessions">1</div>
1024
+ <div class="metric-label">SESSIONS</div>
1025
+ </div>
1026
+ <div class="metric-card">
1027
+ <div class="metric-value" id="cpu">0%</div>
1028
+ <div class="metric-label">CPU USAGE</div>
1029
+ </div>
1030
+ <div class="metric-card">
1031
+ <div class="metric-value" id="memory">0MB</div>
1032
+ <div class="metric-label">MEMORY</div>
1033
+ </div>
1034
+ </div>
1035
+ """)
1036
+
1037
+ # Time Remaining
1038
+ gr.HTML('<div class="form-label-industrial">⏱️ SESSION TIMER</div>')
1039
+ time_remaining = gr.Textbox(
1040
+ value="NO ACTIVE SESSION",
1041
+ interactive=False,
1042
+ elem_classes=["status-display"],
1043
+ show_label=False
1044
+ )
1045
+
1046
+ # Auto-refresh Controls
1047
+ gr.HTML('<div class="form-label-industrial">πŸ”„ AUTO-REFRESH</div>')
1048
+ with gr.Column():
1049
+ auto_refresh_status_cb = gr.Checkbox(
1050
+ label="Auto-refresh status (5s interval)",
1051
+ value=False
1052
+ )
1053
+ auto_refresh_logs_cb = gr.Checkbox(
1054
+ label="Auto-refresh logs (10s interval)",
1055
+ value=False
1056
+ )
1057
+
1058
+ # Security & Compliance
1059
+ with gr.Group(elem_classes=["industrial-card"]):
1060
+ gr.HTML('<div class="card-header">πŸ”’ SECURITY & COMPLIANCE</div>')
1061
+ with gr.Group(elem_classes=["card-content"]):
1062
+ gr.HTML("""
1063
+ <div style="font-family: 'JetBrains Mono', monospace; font-size: 0.8rem; color: var(--text-muted);">
1064
+ <div style="margin-bottom: 0.5rem;"><strong>πŸ” ENCRYPTION:</strong> AES-256</div>
1065
+ <div style="margin-bottom: 0.5rem;"><strong>πŸ›‘οΈ ISOLATION:</strong> CONTAINER</div>
1066
+ <div style="margin-bottom: 0.5rem;"><strong>🚫 NETWORK:</strong> RESTRICTED</div>
1067
+ <div style="margin-bottom: 0.5rem;"><strong>πŸ“Š MONITORING:</strong> ACTIVE</div>
1068
+ <div style="margin-bottom: 0.5rem;"><strong>πŸ—‚οΈ LOGGING:</strong> ENABLED</div>
1069
+ <div><strong>⏰ RETENTION:</strong> 2 HOURS</div>
1070
+ </div>
1071
+ """)
1072
+
1073
+ # Resource Usage
1074
+ with gr.Group(elem_classes=["industrial-card"]):
1075
+ gr.HTML('<div class="card-header">πŸ“ˆ RESOURCE ALLOCATION</div>')
1076
+ with gr.Group(elem_classes=["card-content"]):
1077
+ gr.HTML("""
1078
+ <div style="font-family: 'JetBrains Mono', monospace; font-size: 0.8rem;">
1079
+ <div style="margin-bottom: 1rem;">
1080
+ <div style="color: var(--text-muted); margin-bottom: 0.25rem;">CPU ALLOCATION</div>
1081
+ <div style="background: var(--bg-tertiary); height: 8px; border-radius: 4px; overflow: hidden;">
1082
+ <div style="background: var(--primary); height: 100%; width: 25%; transition: width 0.3s;"></div>
1083
+ </div>
1084
+ <div style="color: var(--text-primary); font-size: 0.75rem; margin-top: 0.25rem;">1 vCPU / 4 vCPU MAX</div>
1085
+ </div>
1086
+
1087
+ <div style="margin-bottom: 1rem;">
1088
+ <div style="color: var(--text-muted); margin-bottom: 0.25rem;">MEMORY ALLOCATION</div>
1089
+ <div style="background: var(--bg-tertiary); height: 8px; border-radius: 4px; overflow: hidden;">
1090
+ <div style="background: var(--success); height: 100%; width: 40%; transition: width 0.3s;"></div>
1091
+ </div>
1092
+ <div style="color: var(--text-primary); font-size: 0.75rem; margin-top: 0.25rem;">2GB / 8GB MAX</div>
1093
+ </div>
1094
+
1095
+ <div>
1096
+ <div style="color: var(--text-muted); margin-bottom: 0.25rem;">STORAGE ALLOCATION</div>
1097
+ <div style="background: var(--bg-tertiary); height: 8px; border-radius: 4px; overflow: hidden;">
1098
+ <div style="background: var(--warning); height: 100%; width: 15%; transition: width 0.3s;"></div>
1099
+ </div>
1100
+ <div style="color: var(--text-primary); font-size: 0.75rem; margin-top: 0.25rem;">5GB / 20GB MAX</div>
1101
+ </div>
1102
+ </div>
1103
+ """)
1104
 
1105
  # Event Handlers
1106
  connect_btn.click(
 
1133
  fn=auto_refresh_status,
1134
  outputs=status_display
1135
  )
1136
+
1137
+ # Clear logs function
1138
+ def clear_logs():
1139
+ return "[SYSTEM] Logs cleared by user request."
1140
+
1141
+ clear_logs_btn.click(
1142
+ fn=clear_logs,
1143
+ outputs=logs_display
1144
+ )
1145
+
1146
+ # Update session info periodically
1147
+ def update_session_info():
1148
+ return get_session_info()
1149
+
1150
+ # Auto-refresh timer updates
1151
+ def update_time_remaining():
1152
+ if sandbox.sandbox_created:
1153
+ return sandbox.get_remaining_time()
1154
+ return "NO ACTIVE SESSION"
1155
+
1156
+ # Periodic updates every 5 seconds for time display
1157
+ demo.load(
1158
+ fn=update_time_remaining,
1159
+ outputs=time_remaining,
1160
+ every=5
1161
+ )
1162
 
1163
+ # Launch the industrial-grade application
1164
  if __name__ == "__main__":
1165
  demo.launch(
1166
  server_name="0.0.0.0",
1167
  server_port=7860,
1168
  share=False,
1169
+ debug=False,
1170
+ show_error=True,
1171
+ inbrowser=True
1172
  )