""" Hugging Face Spaces Entry Point for ResearchOS This serves as the main entry point when using Gradio SDK fallback, or as a health-check wrapper when using Docker SDK. """ import gradio as gr import os import subprocess import threading import time # Start all backend services in background thread def start_services(): print("[HF Spaces] Starting ResearchOS services...") # Set SQLite fallback for HF Spaces os.environ.setdefault('DATABASE_URL', 'sqlite:///app/researchos.db') os.environ.setdefault('JWT_SECRET', os.getenv('JWT_SECRET', 'hf-spaces-secret')) services = [ ("auth", "python services/auth-service/src/main.py"), ("project", "python services/project-service/src/main.py"), ("manuscript", "python services/manuscript-service/src/main.py"), ("analysis", "python services/analysis-service/src/main.py"), ("agent", "python services/agent-service/src/main.py"), ("verification", "python services/verification-service/src/main.py"), ] for name, cmd in services: try: subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) print(f"[HF Spaces] Started {name} service") time.sleep(1) except Exception as e: print(f"[HF Spaces] Failed to start {name}: {e}") # Start API Gateway time.sleep(2) try: subprocess.Popen("python services/api-gateway/src/main.py", shell=True) print("[HF Spaces] Started API Gateway") except Exception as e: print(f"[HF Spaces] Failed to start API Gateway: {e}") # Start Next.js frontend time.sleep(2) try: subprocess.Popen("cd apps/web && PORT=7860 node server.js", shell=True) print("[HF Spaces] Started Web Frontend on port 7860") except Exception as e: print(f"[HF Spaces] Failed to start frontend: {e}") # Start services in background threading.Thread(target=start_services, daemon=True).start() # Gradio interface as fallback/wrapper def health_check(): import urllib.request try: req = urllib.request.Request('http://localhost:8000/health', method='GET') with urllib.request.urlopen(req, timeout=5) as resp: return resp.read().decode() except Exception as e: return f"Services starting... ({str(e)})" with gr.Blocks(title="ResearchOS") as demo: gr.Markdown("# ResearchOS - AI Research Platform") gr.Markdown("The full Next.js application is running in the background.") with gr.Row(): with gr.Column(): gr.Markdown("### System Status") status_btn = gr.Button("Check Health") status_output = gr.Textbox(label="Status", value="Starting...") status_btn.click(health_check, outputs=status_output) with gr.Column(): gr.Markdown("### Quick Links") gr.Markdown("- [Open Full App](/)") gr.Markdown("- API Gateway: `http://localhost:8000`") gr.Markdown("---") gr.Markdown("If the full app doesn't load, wait 30 seconds for services to boot, then refresh.") # Launch Gradio (this is required for HF Spaces Gradio SDK) # But if using Docker SDK, this file is ignored and start.sh is used instead demo.launch(server_name="0.0.0.0", server_port=7860, share=False)