ComFit-Copilot / app.py
JatinkInnovision's picture
Update app.py
d52e04f verified
import os
import time
import requests
import gradio as gr
import openstack
from openstack import exceptions
# GLOBAL SHARED STATE
active_user_count = 0
is_comfit_alive = False
clean_link = "comfit-copilot.mch250095.projects.jetstream-cloud.org:3000"
full_url = f"http://{clean_link}"
# Styled HTML for a flashing neon green block with black text
GREEN_FLASHING_LINK = f"""
<style>
@keyframes flash {{
0% {{ opacity: 1; }}
50% {{ opacity: 0.4; }}
100% {{ opacity: 1; }}
}}
.flashing-btn {{
display: inline-block;
padding: 20px 40px;
font-size: 26px;
font-weight: 900;
text-decoration: none;
color: black !important;
background-color: #39FF14;
border: 5px solid black;
border-radius: 4px;
text-align: center;
animation: flash 1s infinite;
box-shadow: 0 0 20px #39FF14;
transition: transform 0.2s;
}}
.flashing-btn:hover {{
animation: none;
transform: scale(1.05);
opacity: 1;
}}
</style>
<div style="text-align: center; margin: 30px 0;">
<a href="{full_url}" target="_blank" class="flashing-btn">
CLICK HERE FOR COMFIT COPILOT
</a>
</div>
"""
def get_conn():
"""Authenticates with Jetstream2 (OpenStack) using Application Credentials."""
return openstack.connect(
auth_url=os.getenv("OS_AUTH_URL"),
application_credential_id=os.getenv("OS_APPLICATION_CREDENTIAL_ID"),
application_credential_secret=os.getenv("OS_APPLICATION_CREDENTIAL_SECRET"),
auth_type="v3applicationcredential",
region_name="IU",
interface="public"
)
def get_current_status():
global active_user_count, is_comfit_alive
try:
conn = get_conn()
instance_id = os.getenv("OS_INSTANCE_ID")
server = conn.compute.find_server(instance_id)
status_text = "❌ Error: Instance Not Found"
if server:
status_map = {
"ACTIVE": "🟒 RUNNING (ACTIVE)",
"SHELVED_OFFLOADED": "πŸ’€ SLEEPING (SHELVED)",
"SHUTOFF": "πŸ”΄ POWERED OFF",
"BUILD": "πŸ› οΈ STARTING...",
"SHELVING": "⏳ SAVING STATE..."
}
status_text = status_map.get(server.status, f"❓ STATE: {server.status}")
if "RUNNING" in status_text:
try:
if requests.get(full_url, timeout=2).status_code < 500:
is_comfit_alive = True
else:
is_comfit_alive = False
except:
is_comfit_alive = False
else:
is_comfit_alive = False
link_update = gr.update(value=GREEN_FLASHING_LINK if is_comfit_alive else "", visible=is_comfit_alive)
return status_text, f"πŸ‘₯ Active Users: {active_user_count}", link_update
except Exception as e:
return f"❌ Error: {str(e)}", f"πŸ‘₯ Active Users: {active_user_count}", gr.update()
def user_joined():
global active_user_count
active_user_count += 1
return f"πŸ‘₯ Active Users: {active_user_count}"
def user_left():
global active_user_count
active_user_count = max(0, active_user_count - 1)
def manage_instance():
global is_comfit_alive
try:
conn = get_conn()
instance_id = os.getenv("OS_INSTANCE_ID")
server = conn.compute.find_server(instance_id)
if not server:
yield ("❌ Error: Instance Not Found", gr.update(visible=False))
return
if server.status != "ACTIVE":
yield ("⏳ Milestone 1/3: Un-shelving Begin...", gr.update(visible=False))
if server.status == "SHELVED_OFFLOADED":
conn.compute.unshelve_server(server)
conn.compute.wait_for_server(server, status='ACTIVE', wait=600)
yield ("βœ… Milestone 2/3: Unshelved! VM is now ACTIVE.", gr.update(visible=False))
yield ("πŸ”„ Milestone 3/3: Connecting to ComFit...", gr.update(visible=False))
for i in range(24):
try:
if requests.get(full_url, timeout=3).status_code < 500:
is_comfit_alive = True
yield ("πŸŽ‰ Success! ComFit is ready.", gr.update(value=GREEN_FLASHING_LINK, visible=True))
return
except: pass
yield (f"πŸ”„ Milestone 3/3: Software booting ({i+1}/24)...", gr.update(visible=False))
time.sleep(5)
except Exception as e:
yield (f"❌ Error: {str(e)}", gr.update(visible=False))
combined_js = """
<script>
let idleTime = 0;
const MAX_IDLE = 10;
function playNotification(status) {
if (status.includes("RUNNING")) {
var audio = new Audio('https://cdn.freesound.org');
audio.play().catch(e => console.log("Audio play blocked."));
}
}
function resetTimer() { idleTime = 0; }
window.onmousemove = resetTimer; window.onmousedown = resetTimer; window.onclick = resetTimer; window.onkeypress = resetTimer;
setInterval(function() {
idleTime++;
if (idleTime >= MAX_IDLE) {
alert("Session Expired due to inactivity. Please refresh.");
window.location.reload();
}
}, 60000);
</script>
"""
# FIX 1: Removed theme=gr.themes.Soft() from here
with gr.Blocks() as demo:
gr.HTML(combined_js)
session_tracker = gr.State(value="active", delete_callback=user_left)
gr.Markdown("# ComFit Copilot (Comfort & Fit Copilot) By Innovision")
with gr.Row():
live_status = gr.Textbox(label="Live Jetstream2 Status (5s refresh)", interactive=False)
user_display = gr.Textbox(label="Space Activity", interactive=False)
with gr.Row():
activate_btn = gr.Button("πŸš€ Activate / Access ComFit Copilot", variant="primary")
refresh_btn = gr.Button("πŸ”„ Force Refresh Status", variant="secondary")
status_label = gr.Label(value="Ready")
# Flashing link box
link_box = gr.HTML(visible=False)
gr.Markdown("---")
# CENTER ALIGNED INSTRUCTIONS HEADER
gr.Markdown("<center><h3>πŸ“– Instructions for Visitors</h3></center>")
gr.Markdown("""
**Access or Wake Up**
- If a flashing **Green Button** is already visible (above these instructions), simply click it to open ComFit Copilot.
- If no flashing green button is visible, click **Activate / Access ComFit Copilot** button (top left). This will trigger the un-shelving process, which may take up to 2+ mins.
**Note A: Track Milestones**
The control panel will cycle through three milestones: Un-shelving, VM Activation, and Software Booting. Please wait while the cloud prepares your environment.
**Note B: Automatic Session Timeout**
If you do not interact with this page(or next page - ComFit Copilot interface) for **10 minutes**, your session will expire.
**Note C: What to do after clicking on flashing green button**
Once you sign-up using your email on ComFit Copilot page (next page), a button will pop-up showing that you need to confirm email. You can safely ignore this step(no need to open your inbox) and continue with login using information you just used for sign-up. Gmail/Microsoft 3rd party sign-up may not work for some users.
""")
# Logo Footer Section
gr.Markdown("---")
gr.Markdown("<center><h3>Thanks to our supporters & collaborators:</h3></center>")
with gr.Row():
gr.Image("logo1.png", show_label=False, interactive=False, container=False, scale=1)
gr.Image("logo2.png", show_label=False, interactive=False, container=False, scale=1)
gr.Image("logo3.png", show_label=False, interactive=False, container=False, scale=1)
live_status.change(None, inputs=live_status, js="(s) => playNotification(s)")
activate_btn.click(fn=manage_instance, outputs=[status_label, link_box])
refresh_btn.click(fn=get_current_status, outputs=[live_status, user_display, link_box])
timer = gr.Timer(5)
timer.tick(fn=get_current_status, outputs=[live_status, user_display, link_box])
demo.load(fn=user_joined, outputs=user_display)
demo.load(fn=get_current_status, outputs=[live_status, user_display, link_box])
if __name__ == "__main__":
# FIX 2: Added theme=gr.themes.Soft() here inside launch()
demo.launch(theme=gr.themes.Soft())