File size: 3,871 Bytes
09e8c1e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6104a7e
 
 
09e8c1e
 
 
 
 
 
 
 
 
 
 
4c3abf9
 
 
 
 
 
 
 
09e8c1e
 
 
 
 
 
 
 
 
581bd1c
 
 
 
09e8c1e
 
7bd04f5
 
 
 
581bd1c
 
 
 
 
09e8c1e
 
 
581bd1c
 
7bd04f5
 
 
 
 
 
581bd1c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
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)