Spaces:
Running
on
Zero
Running
on
Zero
Commit
Β·
9422bc2
1
Parent(s):
d802f0c
Add LinkedIn post link to UI Help section
Browse files- src/nacc_ui/professional_ui_v2.py +58 -186
src/nacc_ui/professional_ui_v2.py
CHANGED
|
@@ -112,15 +112,15 @@ class ModernNACCUI(NACCConversationUI):
|
|
| 112 |
dashboard = self.get_dashboard_view(session)
|
| 113 |
files = self.list_files_view(session.current_path, session.current_node)
|
| 114 |
|
| 115 |
-
return history, "", dashboard, files, session_id
|
| 116 |
|
| 117 |
def get_dashboard_view(self, session: Optional[SessionState] = None) -> str:
|
| 118 |
"""Get real-time network dashboard with current node highlighted"""
|
| 119 |
# Use default values if no session
|
| 120 |
-
current_node = session.current_node if session else "
|
| 121 |
current_path = session.current_path if session else get_nacc_workspace()
|
| 122 |
try:
|
| 123 |
-
response = requests.get(f"{ORCHESTRATOR_URL}/nodes", timeout=
|
| 124 |
if response.status_code == 200:
|
| 125 |
nodes = response.json()
|
| 126 |
|
|
@@ -157,29 +157,27 @@ class ModernNACCUI(NACCConversationUI):
|
|
| 157 |
except Exception as e:
|
| 158 |
return f"β Dashboard Error: {str(e)}"
|
| 159 |
|
| 160 |
-
def list_files_view(self, path: str = None, node: str = "
|
| 161 |
"""List files in current directory on specified node"""
|
| 162 |
# path and node should always be provided from session context
|
| 163 |
# No fallback to avoid breaking context switching
|
| 164 |
|
| 165 |
try:
|
| 166 |
-
#
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
node_label = node_info.get('display_name', node)
|
| 170 |
-
except:
|
| 171 |
-
node_label = node
|
| 172 |
|
| 173 |
-
# Use orchestrator's execute command endpoint
|
| 174 |
response = requests.post(
|
| 175 |
f"{ORCHESTRATOR_URL}/commands/execute",
|
| 176 |
json={
|
| 177 |
"description": f"List files in {path} on {node}",
|
| 178 |
"command": ["ls", "-lah", path],
|
| 179 |
-
"
|
| 180 |
-
"
|
|
|
|
| 181 |
},
|
| 182 |
-
timeout=
|
| 183 |
)
|
| 184 |
|
| 185 |
if response.status_code == 200:
|
|
@@ -208,42 +206,16 @@ class ModernNACCUI(NACCConversationUI):
|
|
| 208 |
|
| 209 |
def get_available_backends(self) -> Tuple[List[str], str]:
|
| 210 |
"""Fetch available backends from orchestrator"""
|
| 211 |
-
|
| 212 |
-
|
| 213 |
-
|
| 214 |
-
|
| 215 |
-
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
|
| 221 |
-
display = backend["display_name"]
|
| 222 |
-
model = backend.get("model", "N/A")
|
| 223 |
-
is_free = backend["is_free"]
|
| 224 |
-
requires_key = backend["requires_api_key"]
|
| 225 |
-
|
| 226 |
-
# Format: "modal - Modal A100 FREE (IBM Granite MoE)"
|
| 227 |
-
label = f"{name} - {display}"
|
| 228 |
-
if is_free:
|
| 229 |
-
label += " π"
|
| 230 |
-
if requires_key:
|
| 231 |
-
label += " π"
|
| 232 |
-
|
| 233 |
-
choices.append((label, name))
|
| 234 |
-
|
| 235 |
-
# Add to info
|
| 236 |
-
status = "π FREE" if is_free else "π³ Paid"
|
| 237 |
-
key_status = "π API Key Required" if requires_key else "β¨ No Key"
|
| 238 |
-
info += f"**{display}** ({status}, {key_status})\n"
|
| 239 |
-
info += f" β’ Model: {model}\n"
|
| 240 |
-
info += f" β’ Description: {backend['description']}\n\n"
|
| 241 |
-
|
| 242 |
-
return choices, info
|
| 243 |
-
else:
|
| 244 |
-
return [("modal", "modal")], "β οΈ Failed to load backends"
|
| 245 |
-
except Exception as e:
|
| 246 |
-
return [("modal", "modal")], f"β Error: {str(e)}"
|
| 247 |
|
| 248 |
def get_backend_status(self) -> str:
|
| 249 |
"""Get current backend status"""
|
|
@@ -309,10 +281,10 @@ class ModernNACCUI(NACCConversationUI):
|
|
| 309 |
"""Execute comprehensive health checks"""
|
| 310 |
try:
|
| 311 |
# Get orchestrator health
|
| 312 |
-
health_response = requests.get(f"{ORCHESTRATOR_URL}/healthz", timeout=
|
| 313 |
|
| 314 |
# Get nodes status
|
| 315 |
-
nodes_response = requests.get(f"{ORCHESTRATOR_URL}/nodes", timeout=
|
| 316 |
|
| 317 |
result = """β
**Health Check Results**
|
| 318 |
βββββββββββββββββββββββββββββββββββββββ
|
|
@@ -489,7 +461,7 @@ def create_professional_ui_v2():
|
|
| 489 |
demo.title = "NACC Enterprise AI"
|
| 490 |
|
| 491 |
# Session state
|
| 492 |
-
session_id = gr.State(
|
| 493 |
|
| 494 |
# Main Layout: VS Code Style (Left Sidebar | Main Chat)
|
| 495 |
with gr.Row(elem_id="main-container", variant="panel", equal_height=True):
|
|
@@ -557,7 +529,8 @@ def create_professional_ui_v2():
|
|
| 557 |
height=600,
|
| 558 |
show_label=False,
|
| 559 |
avatar_images=(None, "π€"),
|
| 560 |
-
elem_id="main-chatbot"
|
|
|
|
| 561 |
)
|
| 562 |
|
| 563 |
# Input Area
|
|
@@ -577,7 +550,7 @@ def create_professional_ui_v2():
|
|
| 577 |
"""
|
| 578 |
<div style="display: flex; justify-content: space-between; font-size: 0.8em; color: #64748b; margin-top: 5px; margin-bottom: 20px;">
|
| 579 |
<span>β οΈ Blaxel Sandbox: 30-70s processing</span>
|
| 580 |
-
<span>Context:
|
| 581 |
</div>
|
| 582 |
"""
|
| 583 |
)
|
|
@@ -591,142 +564,41 @@ def create_professional_ui_v2():
|
|
| 591 |
# Bottom Section: Help & About (Full Width)
|
| 592 |
with gr.Row(elem_id="bottom-section"):
|
| 593 |
with gr.Column(scale=1):
|
| 594 |
-
with gr.Accordion("π
|
| 595 |
gr.Markdown("""
|
| 596 |
-
|
| 597 |
-
|
| 598 |
-
## Step-by-Step Demo Instructions
|
| 599 |
-
|
| 600 |
-
### Step 1: List Available Nodes
|
| 601 |
-
```
|
| 602 |
-
list nodes
|
| 603 |
-
```
|
| 604 |
-
You'll see two nodes:
|
| 605 |
-
- `vm-node-01` - VM Space (remote computer simulation)
|
| 606 |
-
- `hf-space-local` - Main Space (this project, blocked for protection)
|
| 607 |
-
|
| 608 |
-
### Step 2: Switch to VM Node
|
| 609 |
-
```
|
| 610 |
-
switch to vm-node-01
|
| 611 |
-
```
|
| 612 |
-
Path will automatically set to `/app` (VM's root directory)
|
| 613 |
-
|
| 614 |
-
### Step 3: Explore VM Files
|
| 615 |
-
```
|
| 616 |
-
list files
|
| 617 |
-
```
|
| 618 |
-
Navigate through folders using **absolute paths**:
|
| 619 |
-
```
|
| 620 |
-
navigate to /app/src
|
| 621 |
-
navigate to /app/src/nacc_ui
|
| 622 |
-
navigate to /app
|
| 623 |
-
```
|
| 624 |
-
|
| 625 |
-
### Step 4: File Operations in /tmp
|
| 626 |
-
β οΈ **IMPORTANT**: File creation only works in `/tmp/` directory
|
| 627 |
-
|
| 628 |
-
```
|
| 629 |
-
navigate to /tmp
|
| 630 |
-
```
|
| 631 |
-
|
| 632 |
-
**Create a file (AI-powered)**:
|
| 633 |
-
```
|
| 634 |
-
create a file named demo.txt with content Hello from NACC!
|
| 635 |
-
```
|
| 636 |
-
|
| 637 |
-
**Read the file**:
|
| 638 |
-
```
|
| 639 |
-
run command cat /tmp/demo.txt
|
| 640 |
-
```
|
| 641 |
-
|
| 642 |
-
**List to verify**:
|
| 643 |
-
```
|
| 644 |
-
list files
|
| 645 |
-
```
|
| 646 |
-
|
| 647 |
-
---
|
| 648 |
-
|
| 649 |
-
## β οΈ Important Limitations
|
| 650 |
-
|
| 651 |
-
**Write Operations**:
|
| 652 |
-
- β
Work in: `/tmp/` directory (writable)
|
| 653 |
-
- β Blocked in: `/app/` and other areas (read-only to protect project)
|
| 654 |
|
| 655 |
-
**
|
| 656 |
|
| 657 |
---
|
| 658 |
|
| 659 |
-
|
| 660 |
-
|
| 661 |
-
|
| 662 |
-
|
| 663 |
-
|
| 664 |
-
|
| 665 |
-
|
| 666 |
-
|
| 667 |
-
|
| 668 |
-
-
|
| 669 |
-
|
| 670 |
-
|
| 671 |
-
|
| 672 |
-
|
| 673 |
-
|
| 674 |
-
|
| 675 |
-
|
| 676 |
-
|
| 677 |
-
|
| 678 |
-
|
| 679 |
-
|
| 680 |
-
|
| 681 |
-
|
| 682 |
-
|
| 683 |
-
|
| 684 |
-
-
|
| 685 |
-
-
|
| 686 |
-
- File sharing between any nodes
|
| 687 |
-
- System monitoring and management
|
| 688 |
-
- AI-powered multi-node orchestration
|
| 689 |
-
|
| 690 |
-
**Demo Videos**: Shows both Space demo AND real NACC setup
|
| 691 |
-
|
| 692 |
-
---
|
| 693 |
-
|
| 694 |
-
## π¬ To The Community
|
| 695 |
-
|
| 696 |
-
Thank you for checking out NACC! This entire project was built from zero - no pre-made MCPs, no templates, all original code.
|
| 697 |
-
|
| 698 |
-
### About Me
|
| 699 |
-
I'm **Vasanthadithya** - 3rd year B.E. Computer Science student at **CBIT, Hyderabad**
|
| 700 |
-
|
| 701 |
-
### Looking For
|
| 702 |
-
- π― Internship opportunities
|
| 703 |
-
- π€ Experience and learning
|
| 704 |
-
- π Chance to work on real-world projects
|
| 705 |
-
|
| 706 |
-
If you like this project and its approach, I'd love to connect! I want to learn, explore, and build amazing things.
|
| 707 |
-
|
| 708 |
-
π§ **Reach out**: [LinkedIn](https://www.linkedin.com/in/vasanthadithya-mundrathi-84a54031a/) | [GitHub](https://github.com/Vasanthadithya-mundrathi)
|
| 709 |
-
|
| 710 |
-
---
|
| 711 |
-
|
| 712 |
-
## π€ Competition Tags
|
| 713 |
-
|
| 714 |
-
**PRIMARY TRACKS:**
|
| 715 |
-
- π’ `mcp-in-action-track-enterprise` - Multi-node infrastructure orchestration
|
| 716 |
-
- π€ `mcp-in-action-track-consumer` - Natural language control
|
| 717 |
-
- π¨ `mcp-in-action-track-creative` - Novel cross-Space architecture
|
| 718 |
-
|
| 719 |
-
**SECONDARY TRACKS:**
|
| 720 |
-
- π οΈ `building-mcp-track-enterprise` - Complete MCP implementation
|
| 721 |
-
- π οΈ `building-mcp-track-consumer` - Custom protocol from scratch
|
| 722 |
-
- π οΈ `building-mcp-track-creative` - Zero SDK dependencies
|
| 723 |
-
|
| 724 |
-
---
|
| 725 |
-
|
| 726 |
-
## π€ AI Backend
|
| 727 |
-
**Current**: Blaxel OpenAI (GPT-4o-mini) - Powers natural language understanding
|
| 728 |
-
|
| 729 |
-
Built with β€οΈ for **HF MCP Birthday Hackathon 2025** π
|
| 730 |
""")
|
| 731 |
|
| 732 |
with gr.Accordion("π¨βπ» About Creator & NACC", open=False):
|
|
|
|
| 112 |
dashboard = self.get_dashboard_view(session)
|
| 113 |
files = self.list_files_view(session.current_path, session.current_node)
|
| 114 |
|
| 115 |
+
return history, "", dashboard, files, session.session_id
|
| 116 |
|
| 117 |
def get_dashboard_view(self, session: Optional[SessionState] = None) -> str:
|
| 118 |
"""Get real-time network dashboard with current node highlighted"""
|
| 119 |
# Use default values if no session
|
| 120 |
+
current_node = session.current_node if session else "macbook-local"
|
| 121 |
current_path = session.current_path if session else get_nacc_workspace()
|
| 122 |
try:
|
| 123 |
+
response = requests.get(f"{ORCHESTRATOR_URL}/nodes", timeout=5)
|
| 124 |
if response.status_code == 200:
|
| 125 |
nodes = response.json()
|
| 126 |
|
|
|
|
| 157 |
except Exception as e:
|
| 158 |
return f"β Dashboard Error: {str(e)}"
|
| 159 |
|
| 160 |
+
def list_files_view(self, path: str = None, node: str = "macbook-local") -> str:
|
| 161 |
"""List files in current directory on specified node"""
|
| 162 |
# path and node should always be provided from session context
|
| 163 |
# No fallback to avoid breaking context switching
|
| 164 |
|
| 165 |
try:
|
| 166 |
+
# Determine preferred tags based on node
|
| 167 |
+
preferred_tags = ["mac", "local"] if node == "macbook-local" else ["kali", "vm"]
|
| 168 |
+
node_label = "MacBook Pro" if node == "macbook-local" else "Kali VM"
|
|
|
|
|
|
|
|
|
|
| 169 |
|
| 170 |
+
# Use orchestrator's execute command endpoint
|
| 171 |
response = requests.post(
|
| 172 |
f"{ORCHESTRATOR_URL}/commands/execute",
|
| 173 |
json={
|
| 174 |
"description": f"List files in {path} on {node}",
|
| 175 |
"command": ["ls", "-lah", path],
|
| 176 |
+
"preferred_tags": preferred_tags,
|
| 177 |
+
"target_node": node,
|
| 178 |
+
"timeout": 30
|
| 179 |
},
|
| 180 |
+
timeout=60 # Increased from 15s to 60s
|
| 181 |
)
|
| 182 |
|
| 183 |
if response.status_code == 200:
|
|
|
|
| 206 |
|
| 207 |
def get_available_backends(self) -> Tuple[List[str], str]:
|
| 208 |
"""Fetch available backends from orchestrator"""
|
| 209 |
+
# Hardcoded for now since orchestrator doesn't support dynamic switching yet
|
| 210 |
+
choices = [("Blaxel Sandbox π", "blaxel-openai")]
|
| 211 |
+
info = """**π€ Active Backend:**
|
| 212 |
+
|
| 213 |
+
**Blaxel Sandbox** (vasanthfeb13)
|
| 214 |
+
β’ Model: sandbox-openai
|
| 215 |
+
β’ Status: β
Active
|
| 216 |
+
β’ Provider: Blaxel Model Gateway
|
| 217 |
+
"""
|
| 218 |
+
return choices, info
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 219 |
|
| 220 |
def get_backend_status(self) -> str:
|
| 221 |
"""Get current backend status"""
|
|
|
|
| 281 |
"""Execute comprehensive health checks"""
|
| 282 |
try:
|
| 283 |
# Get orchestrator health
|
| 284 |
+
health_response = requests.get(f"{ORCHESTRATOR_URL}/healthz", timeout=5)
|
| 285 |
|
| 286 |
# Get nodes status
|
| 287 |
+
nodes_response = requests.get(f"{ORCHESTRATOR_URL}/nodes", timeout=5)
|
| 288 |
|
| 289 |
result = """β
**Health Check Results**
|
| 290 |
βββββββββββββββββββββββββββββββββββββββ
|
|
|
|
| 461 |
demo.title = "NACC Enterprise AI"
|
| 462 |
|
| 463 |
# Session state
|
| 464 |
+
session_id = gr.State()
|
| 465 |
|
| 466 |
# Main Layout: VS Code Style (Left Sidebar | Main Chat)
|
| 467 |
with gr.Row(elem_id="main-container", variant="panel", equal_height=True):
|
|
|
|
| 529 |
height=600,
|
| 530 |
show_label=False,
|
| 531 |
avatar_images=(None, "π€"),
|
| 532 |
+
elem_id="main-chatbot",
|
| 533 |
+
type="messages"
|
| 534 |
)
|
| 535 |
|
| 536 |
# Input Area
|
|
|
|
| 550 |
"""
|
| 551 |
<div style="display: flex; justify-content: space-between; font-size: 0.8em; color: #64748b; margin-top: 5px; margin-bottom: 20px;">
|
| 552 |
<span>β οΈ Blaxel Sandbox: 30-70s processing</span>
|
| 553 |
+
<span>Context: macbook-local</span>
|
| 554 |
</div>
|
| 555 |
"""
|
| 556 |
)
|
|
|
|
| 564 |
# Bottom Section: Help & About (Full Width)
|
| 565 |
with gr.Row(elem_id="bottom-section"):
|
| 566 |
with gr.Column(scale=1):
|
| 567 |
+
with gr.Accordion("π Help & Documentation", open=False):
|
| 568 |
gr.Markdown("""
|
| 569 |
+
### π’ **Latest Updates**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 570 |
|
| 571 |
+
**[π Read the Official Launch Post on LinkedIn](https://www.linkedin.com/posts/vasanthadithya-mundrathi-84a54031a_mcp-modelcontextprotocol-mcpbirthday-activity-7400561851106897920-0i1u?utm_source=share&utm_medium=member_desktop&rcm=ACoAAFDhpLoBNcrQ4qiK_sGt54NWi9Zd-0VanIM)**
|
| 572 |
|
| 573 |
---
|
| 574 |
|
| 575 |
+
### π― Quick Start Guide
|
| 576 |
+
|
| 577 |
+
**1. File Operations**
|
| 578 |
+
* `list files` - See what's in your current directory.
|
| 579 |
+
* `read [filename]` - View the contents of a file.
|
| 580 |
+
* `write [content] to [filename]` - Create or update a file.
|
| 581 |
+
|
| 582 |
+
**2. Node Management** β *NEW FEATURES*
|
| 583 |
+
* `list nodes` - See all connected machines.
|
| 584 |
+
* `switch to [node-id]` - Switch by exact node ID (e.g., `switch to kali-vm`, `switch to macbook-local`).
|
| 585 |
+
* `switch to [alias]` - Use aliases (e.g., `switch to kali`, `switch to mac`, `switch to laptop`).
|
| 586 |
+
* **Connect New Nodes**: `connect to [6-digit-code] at [ip-address] and name it as [name]`
|
| 587 |
+
- Example: `connect to 473293 at 192.168.1.50 and name it as my-laptop`
|
| 588 |
+
- First run `nacc-node init` on the remote node to get the pairing code!
|
| 589 |
+
|
| 590 |
+
**3. System Monitoring**
|
| 591 |
+
* `show system metrics` - View CPU, RAM, and Disk usage.
|
| 592 |
+
* `check disk space` - Quick storage check.
|
| 593 |
+
|
| 594 |
+
**4. AI Backends (Top Right Settings)**
|
| 595 |
+
* **Blaxel Sandbox**: β
Default. Free, reliable, ~30-70s response time.
|
| 596 |
+
* **Docker Mistral**: Runs locally on your machine. Fast & Free.
|
| 597 |
+
* **OpenAI/Gemini**: Requires your own API key for max speed.
|
| 598 |
+
|
| 599 |
+
### π‘ Tips
|
| 600 |
+
- Context is preserved! After switching nodes, all file operations use that node's path.
|
| 601 |
+
- You can switch nodes by ID, display name, or alias - whatever you remember!
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 602 |
""")
|
| 603 |
|
| 604 |
with gr.Accordion("π¨βπ» About Creator & NACC", open=False):
|