Spaces:
Running
on
Zero
Running
on
Zero
| import os | |
| import sys | |
| import threading | |
| import time | |
| import uvicorn | |
| from fastapi import FastAPI | |
| import os | |
| import sys | |
| # --- MONKEY PATCH START --- | |
| # Fix for: ImportError: cannot import name 'HfFolder' from 'huggingface_hub' | |
| try: | |
| import huggingface_hub | |
| if not hasattr(huggingface_hub, "HfFolder"): | |
| print("[NACC] Patching huggingface_hub.HfFolder for Gradio compatibility...") | |
| class HfFolder: | |
| def save_token(cls, token): | |
| pass | |
| def get_token(cls): | |
| return os.getenv("HF_TOKEN") | |
| huggingface_hub.HfFolder = HfFolder | |
| except ImportError: | |
| pass | |
| # --- MONKEY PATCH END --- | |
| import gradio as gr | |
| from pathlib import Path | |
| # Add src to path | |
| sys.path.append(os.path.join(os.path.dirname(__file__), "src")) | |
| from nacc_orchestrator.server import build_service, create_app | |
| from nacc_orchestrator.config import NodeDefinition | |
| from nacc_ui.professional_ui_v2 import create_professional_ui_v2 as create_ui | |
| from nacc_node.tools import NodeServer | |
| from nacc_node.config import NodeConfig | |
| # 1. Build the Orchestrator Service | |
| service = build_service() | |
| # 2. Register the Local Node (Auto-Discovery for HF Space) | |
| local_node_def = NodeDefinition( | |
| node_id="hf-space-local", | |
| transport="http", | |
| base_url="http://127.0.0.1:8001", | |
| display_name="Local Node (Demo)", | |
| tags=["local", "demo", "linux"], | |
| priority=10 | |
| ) | |
| service.registry.add_node(local_node_def) | |
| print(f"β Auto-registered local node: {local_node_def.node_id}") | |
| # 3. Create the FastAPI App | |
| orchestrator_app = create_app(service) | |
| # 4. Create a combined FastAPI app | |
| # 4. Create a combined FastAPI app (renamed to avoid Gradio SDK confusion) | |
| api_app = FastAPI() | |
| api_app.mount("/api", orchestrator_app) | |
| def start_local_node(): | |
| """Start a local node in the background for the HF Space demo.""" | |
| print("π Starting local NACC Node for HF Space...") | |
| try: | |
| # Create a temporary config for the local node | |
| config = NodeConfig( | |
| node_id="hf-space-local", | |
| root_dir=Path.cwd(), | |
| display_name="Local Node (Demo)", | |
| tags=["local", "demo"], | |
| allowed_commands=[ | |
| "/bin/sh", "/bin/bash", # Shell access | |
| "ls", "cat", "echo", "grep", "head", "tail", "pwd", "whoami", | |
| "mkdir", "touch", "rm", "cp", "mv", # File operations | |
| "python", "python3", "pip", "pip3", # Python | |
| "curl", "wget", "git", # Network/Dev tools | |
| "df", "du", "free", "top", "ps" # System info | |
| ], | |
| sync_targets={} | |
| ) | |
| # Start node on port 8001 | |
| server = NodeServer(config, host="127.0.0.1", port=8001) | |
| server.serve_forever() | |
| except Exception as e: | |
| print(f"β Failed to start local node: {e}") | |
| def start_orchestrator_api(): | |
| """Start the orchestrator API in the background.""" | |
| print("π§ Starting NACC Orchestrator API...") | |
| uvicorn.run(orchestrator_app, host="127.0.0.1", port=8888) | |
| # Start background services | |
| # NOTE: For 'sdk: gradio', this must run at import time, not just in __main__ | |
| if not os.environ.get("NACC_SERVICES_STARTED"): | |
| os.environ["NACC_SERVICES_STARTED"] = "1" | |
| # 1. Start the Orchestrator API in a thread | |
| api_thread = threading.Thread(target=start_orchestrator_api, daemon=True) | |
| api_thread.start() | |
| # 2. Start a Local Node in a thread (so the Space works out-of-the-box) | |
| node_thread = threading.Thread(target=start_local_node, daemon=True) | |
| node_thread.start() | |
| # 3. Give services a moment to spin up | |
| time.sleep(3) | |
| # 4. Create the UI (Gradio will launch this) | |
| print("π» Launching NACC UI...") | |
| demo = create_ui() | |
| if __name__ == "__main__": | |
| demo.launch(server_name="0.0.0.0", server_port=7860) | |