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"""
CLICK HERE FOR COMFIT COPILOT
""" 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 = """ """ # 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("

📖 Instructions for Visitors

") 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("

Thanks to our supporters & collaborators:

") 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())