Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
Add firefox start cmd, add cyberpunk theme
Browse files
app.py
CHANGED
@@ -35,34 +35,50 @@ model = QwenVLAPIModel(
|
|
35 |
|
36 |
|
37 |
custom_css = """
|
|
|
|
|
|
|
38 |
.sandbox-container {
|
39 |
position: relative;
|
40 |
width: 910px;
|
41 |
-
height:
|
42 |
overflow: hidden;
|
43 |
margin: auto;
|
44 |
}
|
45 |
|
46 |
-
.sandbox-
|
47 |
position: absolute;
|
48 |
top: 0;
|
49 |
left: 0;
|
50 |
width: 910px;
|
51 |
-
height:
|
|
|
|
|
|
|
|
|
52 |
}
|
53 |
|
54 |
.sandbox-iframe, .bsod-image {
|
55 |
position: absolute;
|
56 |
-
top: 8%;
|
57 |
-
left: 7%;
|
58 |
width: <<WIDTH>>px;
|
59 |
height: <<HEIGHT>>px;
|
60 |
border: 4px solid #444444;
|
61 |
transform-origin: 0 0;
|
62 |
}
|
63 |
-
.sandbox-iframe {
|
64 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
}
|
|
|
|
|
|
|
|
|
66 |
/* Colored label for task textbox */
|
67 |
.primary-color-label label span {
|
68 |
font-weight: bold;
|
@@ -70,31 +86,29 @@ custom_css = """
|
|
70 |
}
|
71 |
|
72 |
/* Status indicator light */
|
73 |
-
.status-
|
|
|
74 |
position: absolute;
|
75 |
-
bottom:
|
76 |
-
left:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
width: 20px;
|
78 |
height: 20px;
|
79 |
border-radius: 50%;
|
80 |
-
border: 2px solid black;
|
81 |
-
z-index: 100;
|
82 |
}
|
83 |
|
84 |
.status-text {
|
85 |
-
position: absolute;
|
86 |
-
bottom: 3.8%;
|
87 |
-
left: 47%;
|
88 |
-
right:40%
|
89 |
font-size: 16px;
|
90 |
font-weight: bold;
|
91 |
-
color:
|
92 |
-
background-color: white;
|
93 |
padding: 0 10px;
|
94 |
-
border-radius: 3px;
|
95 |
-
border: 2px solid black;
|
96 |
text-shadow: none;
|
97 |
-
z-index: 100;
|
98 |
}
|
99 |
|
100 |
.status-interactive {
|
@@ -160,21 +174,19 @@ footer_html="""
|
|
160 |
</div>
|
161 |
"""
|
162 |
sandbox_html_template = """
|
163 |
-
<div class="sandbox-container">
|
164 |
-
<
|
165 |
-
|
166 |
-
|
|
|
167 |
<iframe id="sandbox-iframe"
|
168 |
src="{stream_url}"
|
169 |
class="sandbox-iframe"
|
170 |
style="display: block;"
|
171 |
allowfullscreen>
|
172 |
</iframe>
|
173 |
-
<img
|
174 |
-
|
175 |
-
class="bsod-image"
|
176 |
-
style="display: none;
|
177 |
-
/>
|
178 |
</div>
|
179 |
""".replace("<<WIDTH>>", str(WIDTH+15)).replace("<<HEIGHT>>", str(HEIGHT+10))
|
180 |
|
@@ -383,6 +395,8 @@ def get_or_create_sandbox(session_hash):
|
|
383 |
print(f"Creating new sandbox for session {session_hash}")
|
384 |
desktop = Sandbox(api_key=E2B_API_KEY, resolution=(WIDTH, HEIGHT), dpi=96, timeout=SANDBOX_TIMEOUT)
|
385 |
desktop.stream.start(require_auth=True)
|
|
|
|
|
386 |
|
387 |
# Store sandbox with metadata
|
388 |
SANDBOXES[session_hash] = desktop
|
@@ -393,7 +407,7 @@ def get_or_create_sandbox(session_hash):
|
|
393 |
|
394 |
return desktop
|
395 |
|
396 |
-
def update_html(interactive_mode, request: gr.Request):
|
397 |
session_hash = request.session_hash
|
398 |
desktop = get_or_create_sandbox(session_hash)
|
399 |
auth_key = desktop.stream.get_auth_key()
|
@@ -409,6 +423,7 @@ def update_html(interactive_mode, request: gr.Request):
|
|
409 |
creation_time = SANDBOX_METADATA[session_hash]['created_at'] if session_hash in SANDBOX_METADATA else time.time()
|
410 |
|
411 |
sandbox_html_content = sandbox_html_template.format(
|
|
|
412 |
stream_url=stream_url,
|
413 |
status_class=status_class,
|
414 |
status_text=status_text,
|
@@ -448,7 +463,8 @@ def initialize_session(interactive_mode, request: gr.Request):
|
|
448 |
with open(log_path, 'w') as f:
|
449 |
f.write(f"Ready to go...\n")
|
450 |
# Return HTML and session hash
|
451 |
-
return update_html(interactive_mode, request), session_hash
|
|
|
452 |
|
453 |
# Function to read log content that gets the path from session hash
|
454 |
def update_terminal_from_session(session_hash):
|
@@ -539,6 +555,7 @@ with gr.Blocks(css=custom_css, js=custom_js, fill_width=True) as demo:
|
|
539 |
with gr.Row():
|
540 |
sandbox_html = gr.HTML(
|
541 |
value=sandbox_html_template.format(
|
|
|
542 |
stream_url="",
|
543 |
status_class="status-interactive",
|
544 |
status_text="Interactive"
|
@@ -575,6 +592,7 @@ with gr.Blocks(css=custom_css, js=custom_js, fill_width=True) as demo:
|
|
575 |
)
|
576 |
|
577 |
update_btn = gr.Button("Let's go!", variant="primary")
|
|
|
578 |
cancel_btn = gr.Button("Interrupt running agent")
|
579 |
|
580 |
chatbot_display = gr.Chatbot(
|
@@ -612,31 +630,38 @@ with gr.Blocks(css=custom_css, js=custom_js, fill_width=True) as demo:
|
|
612 |
# Function to set view-only mode
|
613 |
def clear_and_set_view_only(task_input, request: gr.Request):
|
614 |
# First clear the results, then set view-only mode
|
615 |
-
return "", update_html(False, request), gr.update(visible=False)
|
616 |
|
617 |
def set_interactive(request: gr.Request):
|
618 |
-
return update_html(True, request)
|
619 |
|
|
|
620 |
|
621 |
# Chain the events
|
622 |
view_only_event = update_btn.click(
|
623 |
fn=clear_and_set_view_only,
|
624 |
-
inputs=[task_input],
|
625 |
outputs=[results_output, sandbox_html, results_container]
|
626 |
)
|
627 |
view_only_event.then(agent_ui.interact_with_agent, [task_input, stored_messages, session_state, session_hash_state], [chatbot_display]).then(
|
628 |
fn=set_interactive,
|
629 |
-
inputs=[],
|
630 |
outputs=sandbox_html
|
631 |
)
|
632 |
cancel_btn.click(fn=(lambda x: x), cancels=[view_only_event])
|
633 |
|
634 |
demo.load(
|
635 |
fn=initialize_session,
|
636 |
-
inputs=[
|
637 |
outputs=[sandbox_html, session_hash_state]
|
638 |
)
|
639 |
|
|
|
|
|
|
|
|
|
|
|
|
|
640 |
|
641 |
# Launch the app
|
642 |
if __name__ == "__main__":
|
|
|
35 |
|
36 |
|
37 |
custom_css = """
|
38 |
+
.app {
|
39 |
+
background-color:black
|
40 |
+
}
|
41 |
.sandbox-container {
|
42 |
position: relative;
|
43 |
width: 910px;
|
44 |
+
height: 800px;
|
45 |
overflow: hidden;
|
46 |
margin: auto;
|
47 |
}
|
48 |
|
49 |
+
.sandbox-frame {
|
50 |
position: absolute;
|
51 |
top: 0;
|
52 |
left: 0;
|
53 |
width: 910px;
|
54 |
+
height: 800px;
|
55 |
+
pointer-events:none;
|
56 |
+
}
|
57 |
+
.minimal .sandbox-frame {
|
58 |
+
display: none;
|
59 |
}
|
60 |
|
61 |
.sandbox-iframe, .bsod-image {
|
62 |
position: absolute;
|
|
|
|
|
63 |
width: <<WIDTH>>px;
|
64 |
height: <<HEIGHT>>px;
|
65 |
border: 4px solid #444444;
|
66 |
transform-origin: 0 0;
|
67 |
}
|
68 |
+
.minimal .sandbox-iframe, .bsod-image {
|
69 |
+
/* top: 73px; */
|
70 |
+
top: 99px;
|
71 |
+
/* left: 74px; */
|
72 |
+
left: 110px;
|
73 |
+
}
|
74 |
+
.cyberpunk .sandbox-iframe {
|
75 |
+
transform: scale(0.535);
|
76 |
+
/* transform: scale(0.59); */
|
77 |
}
|
78 |
+
.minimal .sandbox-iframe {
|
79 |
+
transform: scale(0.7);
|
80 |
+
}
|
81 |
+
|
82 |
/* Colored label for task textbox */
|
83 |
.primary-color-label label span {
|
84 |
font-weight: bold;
|
|
|
86 |
}
|
87 |
|
88 |
/* Status indicator light */
|
89 |
+
.status-bar {
|
90 |
+
display: flex;
|
91 |
position: absolute;
|
92 |
+
bottom: 86px;
|
93 |
+
left: 355px;
|
94 |
+
flex-direction: row;
|
95 |
+
align-items: center;
|
96 |
+
flex-align:center;
|
97 |
+
z-index: 100;
|
98 |
+
}
|
99 |
+
|
100 |
+
.status-indicator {
|
101 |
width: 20px;
|
102 |
height: 20px;
|
103 |
border-radius: 50%;
|
|
|
|
|
104 |
}
|
105 |
|
106 |
.status-text {
|
|
|
|
|
|
|
|
|
107 |
font-size: 16px;
|
108 |
font-weight: bold;
|
109 |
+
color: #fed244;
|
|
|
110 |
padding: 0 10px;
|
|
|
|
|
111 |
text-shadow: none;
|
|
|
112 |
}
|
113 |
|
114 |
.status-interactive {
|
|
|
174 |
</div>
|
175 |
"""
|
176 |
sandbox_html_template = """
|
177 |
+
<div class="sandbox-container {theme}">
|
178 |
+
<div class="status-bar">
|
179 |
+
<div class="status-indicator {status_class}"></div>
|
180 |
+
<div class="status-text">{status_text}</div>
|
181 |
+
</div>
|
182 |
<iframe id="sandbox-iframe"
|
183 |
src="{stream_url}"
|
184 |
class="sandbox-iframe"
|
185 |
style="display: block;"
|
186 |
allowfullscreen>
|
187 |
</iframe>
|
188 |
+
<img src="https://huggingface.co/datasets/mfarre/servedfiles/resolve/main/blue_screen_of_death.gif" class="bsod-image" style="display: none;"/>
|
189 |
+
<img src="https://huggingface.co/datasets/m-ric/images/resolve/main/HUD_thom.png" class="sandbox-frame" />
|
|
|
|
|
|
|
190 |
</div>
|
191 |
""".replace("<<WIDTH>>", str(WIDTH+15)).replace("<<HEIGHT>>", str(HEIGHT+10))
|
192 |
|
|
|
395 |
print(f"Creating new sandbox for session {session_hash}")
|
396 |
desktop = Sandbox(api_key=E2B_API_KEY, resolution=(WIDTH, HEIGHT), dpi=96, timeout=SANDBOX_TIMEOUT)
|
397 |
desktop.stream.start(require_auth=True)
|
398 |
+
firefox_skipwelcome_cmd = """sudo mkdir -p /usr/lib/firefox-esr/distribution && echo '{"policies":{"OverrideFirstRunPage":"","OverridePostUpdatePage":"","DisableProfileImport":true,"DontCheckDefaultBrowser":true}}' | sudo tee /usr/lib/firefox-esr/distribution/policies.json > /dev/null"""
|
399 |
+
desktop.commands.run(firefox_skipwelcome_cmd)
|
400 |
|
401 |
# Store sandbox with metadata
|
402 |
SANDBOXES[session_hash] = desktop
|
|
|
407 |
|
408 |
return desktop
|
409 |
|
410 |
+
def update_html(interactive_mode: bool, theme_checkbox: bool, request: gr.Request):
|
411 |
session_hash = request.session_hash
|
412 |
desktop = get_or_create_sandbox(session_hash)
|
413 |
auth_key = desktop.stream.get_auth_key()
|
|
|
423 |
creation_time = SANDBOX_METADATA[session_hash]['created_at'] if session_hash in SANDBOX_METADATA else time.time()
|
424 |
|
425 |
sandbox_html_content = sandbox_html_template.format(
|
426 |
+
theme="cyberpunk" if theme_checkbox else "minimal",
|
427 |
stream_url=stream_url,
|
428 |
status_class=status_class,
|
429 |
status_text=status_text,
|
|
|
463 |
with open(log_path, 'w') as f:
|
464 |
f.write(f"Ready to go...\n")
|
465 |
# Return HTML and session hash
|
466 |
+
return update_html(interactive_mode, "cyberpunk", request), session_hash
|
467 |
+
|
468 |
|
469 |
# Function to read log content that gets the path from session hash
|
470 |
def update_terminal_from_session(session_hash):
|
|
|
555 |
with gr.Row():
|
556 |
sandbox_html = gr.HTML(
|
557 |
value=sandbox_html_template.format(
|
558 |
+
theme="cyberpunk",
|
559 |
stream_url="",
|
560 |
status_class="status-interactive",
|
561 |
status_text="Interactive"
|
|
|
592 |
)
|
593 |
|
594 |
update_btn = gr.Button("Let's go!", variant="primary")
|
595 |
+
theme_checkbox = gr.Checkbox(label="Cyberpunk Mode", value=True)
|
596 |
cancel_btn = gr.Button("Interrupt running agent")
|
597 |
|
598 |
chatbot_display = gr.Chatbot(
|
|
|
630 |
# Function to set view-only mode
|
631 |
def clear_and_set_view_only(task_input, request: gr.Request):
|
632 |
# First clear the results, then set view-only mode
|
633 |
+
return "", update_html(False, theme_checkbox, request), gr.update(visible=False)
|
634 |
|
635 |
def set_interactive(request: gr.Request):
|
636 |
+
return update_html(True, theme_checkbox, request)
|
637 |
|
638 |
+
is_interactive = gr.Checkbox(value=True, visible=False)
|
639 |
|
640 |
# Chain the events
|
641 |
view_only_event = update_btn.click(
|
642 |
fn=clear_and_set_view_only,
|
643 |
+
inputs=[task_input, theme_checkbox],
|
644 |
outputs=[results_output, sandbox_html, results_container]
|
645 |
)
|
646 |
view_only_event.then(agent_ui.interact_with_agent, [task_input, stored_messages, session_state, session_hash_state], [chatbot_display]).then(
|
647 |
fn=set_interactive,
|
648 |
+
inputs=[theme_checkbox],
|
649 |
outputs=sandbox_html
|
650 |
)
|
651 |
cancel_btn.click(fn=(lambda x: x), cancels=[view_only_event])
|
652 |
|
653 |
demo.load(
|
654 |
fn=initialize_session,
|
655 |
+
inputs=[is_interactive],
|
656 |
outputs=[sandbox_html, session_hash_state]
|
657 |
)
|
658 |
|
659 |
+
theme_checkbox.change(
|
660 |
+
fn=update_html,
|
661 |
+
inputs=[is_interactive, theme_checkbox],
|
662 |
+
outputs=[sandbox_html]
|
663 |
+
)
|
664 |
+
|
665 |
|
666 |
# Launch the app
|
667 |
if __name__ == "__main__":
|