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: @classmethod def save_token(cls, token): pass @classmethod 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)