theguywhosucks commited on
Commit
43b8ce7
·
verified ·
1 Parent(s): 4af518a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +92 -68
app.py CHANGED
@@ -1,38 +1,47 @@
1
  import gradio as gr
2
  import requests
 
 
3
 
4
  # -------------------------
5
  # Backend Space URLs
6
  # -------------------------
7
  BACKENDS = {
8
- "Sandbox Backend 1": "https://chocolaboratory-sandbox-backend.hf.space/",
9
- "Sandbox Backend 2": "https://chocolaboratory-sandboxbackend2.hf.space/"
10
  }
11
 
12
- # Track running sandboxes per backend for automatic selection
13
  backend_load = {name: 0 for name in BACKENDS.keys()}
 
 
 
14
 
15
  # -------------------------
16
- # Frontend functions
17
  # -------------------------
18
  def choose_backend():
19
- # Select backend with fewest sandboxes
20
  return min(backend_load, key=lambda k: backend_load[k])
21
 
22
- def launch_sandbox(code):
23
  backend_name = choose_backend()
24
- url = BACKENDS[backend_name] + "/launch_sandbox"
25
  try:
26
  r = requests.post(url, json={"code": code})
27
  r.raise_for_status()
28
  sandbox_id = r.json()["sandbox_id"]
29
  backend_load[backend_name] += 1
30
- return f"Sandbox {sandbox_id} launched on {backend_name}", sandbox_id, backend_name
 
31
  except Exception as e:
32
- return f"Error: {e}", None, None
33
-
34
- def fetch_logs(sandbox_id, backend_name):
35
- url = f"{BACKENDS[backend_name]}/fetch_logs/{sandbox_id}"
 
 
 
 
36
  try:
37
  r = requests.get(url)
38
  r.raise_for_status()
@@ -41,18 +50,27 @@ def fetch_logs(sandbox_id, backend_name):
41
  except Exception as e:
42
  return str(e)
43
 
44
- def kill_sandbox(sandbox_id, backend_name):
45
- url = f"{BACKENDS[backend_name]}/kill_sandbox/{sandbox_id}"
 
 
 
 
46
  try:
47
  r = requests.post(url)
48
  r.raise_for_status()
49
- backend_load[backend_name] -= 1
50
- return r.json().get("status", "Killed")
 
51
  except Exception as e:
52
  return str(e)
53
 
54
- def status_sandbox(sandbox_id, backend_name):
55
- url = f"{BACKENDS[backend_name]}/status_sandbox/{sandbox_id}"
 
 
 
 
56
  try:
57
  r = requests.get(url)
58
  r.raise_for_status()
@@ -61,65 +79,71 @@ def status_sandbox(sandbox_id, backend_name):
61
  return str(e)
62
 
63
  # -------------------------
64
- # AWS-style frontend UI
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  # -------------------------
66
  with gr.Blocks(css="""
67
  .sandbox-card {
68
  border-radius: 12px;
69
  padding: 15px;
70
- margin: 5px;
71
- background-color: #ffffff;
72
- box-shadow: 0 3px 6px rgba(0,0,0,0.1);
73
  }
74
- .header {font-size: 24px; font-weight: bold; margin-bottom: 15px;}
75
  """) as demo:
 
76
 
77
- gr.Markdown("<div class='header'>🛡 Sandbox Service Dashboard</div>", elem_classes="header")
78
-
79
- # Code editor & launch
80
- code_input = gr.Textbox(label="Python Code", lines=15, placeholder="Write your code here...")
81
  launch_btn = gr.Button("Launch Sandbox")
82
-
83
- # Status and storage
84
  launch_status = gr.Textbox(label="Launch Status")
85
- sandbox_id_storage = gr.State(value=None)
86
- backend_storage = gr.State(value=None)
87
-
88
- # Sandbox cards container
89
- with gr.Column():
90
- logs_btn = gr.Button("Fetch Logs")
91
- kill_btn = gr.Button("Kill Sandbox")
92
- status_btn = gr.Button("Check Status")
93
-
94
- logs_output = gr.Textbox(label="Logs", lines=12)
95
- kill_output = gr.Textbox(label="Kill Status")
96
- status_output = gr.Textbox(label="Sandbox Status")
97
-
98
- # -------------------------
99
- # Button actions
100
- # -------------------------
101
- launch_btn.click(
102
- launch_sandbox,
103
- inputs=[code_input],
104
- outputs=[launch_status, sandbox_id_storage, backend_storage]
105
- )
106
-
107
- logs_btn.click(
108
- fetch_logs,
109
- inputs=[sandbox_id_storage, backend_storage],
110
- outputs=logs_output
111
- )
112
-
113
- kill_btn.click(
114
- kill_sandbox,
115
- inputs=[sandbox_id_storage, backend_storage],
116
- outputs=kill_output
117
- )
118
-
119
- status_btn.click(
120
- status_sandbox,
121
- inputs=[sandbox_id_storage, backend_storage],
122
- outputs=status_output
123
- )
124
 
125
  demo.launch()
 
1
  import gradio as gr
2
  import requests
3
+ import threading
4
+ import time
5
 
6
  # -------------------------
7
  # Backend Space URLs
8
  # -------------------------
9
  BACKENDS = {
10
+ "Sandbox Backend 1": "https://chocolaboratory-sandboxbackend2.hf.space",
11
+ "Sandbox Backend 2": "https://chocolaboratory-sandbox-backend.hf.space"
12
  }
13
 
14
+ # Track running sandboxes per backend
15
  backend_load = {name: 0 for name in BACKENDS.keys()}
16
+ # Store user sandboxes: sandbox_id -> {"backend": ..., "start_time": ..., "card": ...}
17
+ user_sandboxes = {}
18
+ SANDBOX_TTL = 2*3600 # 2 hours
19
 
20
  # -------------------------
21
+ # API calls
22
  # -------------------------
23
  def choose_backend():
 
24
  return min(backend_load, key=lambda k: backend_load[k])
25
 
26
+ def launch_sandbox_api(code):
27
  backend_name = choose_backend()
28
+ url = f"{BACKENDS[backend_name]}/launch_sandbox"
29
  try:
30
  r = requests.post(url, json={"code": code})
31
  r.raise_for_status()
32
  sandbox_id = r.json()["sandbox_id"]
33
  backend_load[backend_name] += 1
34
+ user_sandboxes[sandbox_id] = {"backend": backend_name, "start_time": time.time(), "card": None}
35
+ return sandbox_id, backend_name
36
  except Exception as e:
37
+ return None, str(e)
38
+
39
+ def fetch_logs_api(sandbox_id):
40
+ info = user_sandboxes.get(sandbox_id)
41
+ if not info:
42
+ return "Sandbox not found"
43
+ backend = info["backend"]
44
+ url = f"{BACKENDS[backend]}/fetch_logs/{sandbox_id}"
45
  try:
46
  r = requests.get(url)
47
  r.raise_for_status()
 
50
  except Exception as e:
51
  return str(e)
52
 
53
+ def kill_sandbox_api(sandbox_id):
54
+ info = user_sandboxes.get(sandbox_id)
55
+ if not info:
56
+ return "Sandbox not found"
57
+ backend = info["backend"]
58
+ url = f"{BACKENDS[backend]}/kill_sandbox/{sandbox_id}"
59
  try:
60
  r = requests.post(url)
61
  r.raise_for_status()
62
+ backend_load[backend] -= 1
63
+ del user_sandboxes[sandbox_id]
64
+ return f"Sandbox {sandbox_id} killed"
65
  except Exception as e:
66
  return str(e)
67
 
68
+ def status_sandbox_api(sandbox_id):
69
+ info = user_sandboxes.get(sandbox_id)
70
+ if not info:
71
+ return "Sandbox not found"
72
+ backend = info["backend"]
73
+ url = f"{BACKENDS[backend]}/status_sandbox/{sandbox_id}"
74
  try:
75
  r = requests.get(url)
76
  r.raise_for_status()
 
79
  return str(e)
80
 
81
  # -------------------------
82
+ # Sandbox card creation
83
+ # -------------------------
84
+ def create_sandbox_card(sandbox_id, sandbox_container):
85
+ info = user_sandboxes[sandbox_id]
86
+ backend = info["backend"]
87
+
88
+ with gr.Column(elem_classes="sandbox-card") as card:
89
+ gr.Markdown(f"**Sandbox ID:** {sandbox_id}")
90
+ status_badge = gr.Markdown(f"<span style='color:green'>Running</span>")
91
+ gr.Markdown(f"**Backend:** {backend}")
92
+ runtime_box = gr.Textbox(label="Runtime (sec)", value="0", interactive=False)
93
+ logs_box = gr.Textbox(label="Logs", lines=10, interactive=False)
94
+
95
+ # Buttons inside card
96
+ with gr.Row():
97
+ logs_btn = gr.Button("Fetch Logs")
98
+ kill_btn = gr.Button("Kill Sandbox")
99
+ status_btn = gr.Button("Check Status")
100
+
101
+ # Button actions
102
+ logs_btn.click(lambda sid=sandbox_id: fetch_logs_api(sid), inputs=[], outputs=logs_box)
103
+ kill_btn.click(lambda sid=sandbox_id: kill_sandbox_api(sid), inputs=[], outputs=status_badge)
104
+ status_btn.click(lambda sid=sandbox_id: status_sandbox_api(sid), inputs=[], outputs=runtime_box)
105
+
106
+ # Background updater
107
+ def updater():
108
+ while sandbox_id in user_sandboxes:
109
+ elapsed = int(time.time() - info["start_time"])
110
+ runtime_box.value = str(elapsed)
111
+ logs_box.value = fetch_logs_api(sandbox_id)
112
+ time.sleep(2)
113
+ # Remove card if sandbox killed/expired
114
+ sandbox_container.remove(card)
115
+
116
+ threading.Thread(target=updater, daemon=True).start()
117
+ info["card"] = card
118
+ return card
119
+
120
+ # -------------------------
121
+ # Main Gradio UI
122
  # -------------------------
123
  with gr.Blocks(css="""
124
  .sandbox-card {
125
  border-radius: 12px;
126
  padding: 15px;
127
+ margin: 10px;
128
+ background-color: #fefefe;
129
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15);
130
  }
 
131
  """) as demo:
132
+ gr.Markdown("# 🛡 Sandbox Dashboard (AWS-style)")
133
 
134
+ code_input = gr.Textbox(label="Python Code", lines=10)
 
 
 
135
  launch_btn = gr.Button("Launch Sandbox")
 
 
136
  launch_status = gr.Textbox(label="Launch Status")
137
+
138
+ sandbox_container = gr.Column()
139
+
140
+ def on_launch(code):
141
+ sandbox_id, backend_or_error = launch_sandbox_api(code)
142
+ if not sandbox_id:
143
+ return f"Error: {backend_or_error}"
144
+ create_sandbox_card(sandbox_id, sandbox_container)
145
+ return f"Sandbox {sandbox_id} launched on {user_sandboxes[sandbox_id]['backend']}"
146
+
147
+ launch_btn.click(on_launch, inputs=code_input, outputs=launch_status)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
 
149
  demo.launch()