KarianaUMCP / main.py
barlowski's picture
Upload folder using huggingface_hub
63d80c4 verified
#!/usr/bin/env python3
"""
Kariana Unified UI - Main Entry Point
=====================================
Unified Gradio dashboard for KarianaUMCP with PIN-based authentication.
Usage:
python main.py [--port PORT] [--host HOST] [--share]
Features:
- 5-tab dashboard: Monitor, Scene Control, Skills/Agents, Workflow, Setup
- PIN-based authentication with auto-discovery
- Works both locally and on HuggingFace Spaces
"""
import argparse
import logging
import os
import sys
import gradio as gr
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
# Add parent directory to path for imports
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from core.config import Config
from core.connection import get_connection, UnrealConnection
from core.auth import get_authenticator
from core.session import get_session_manager
from tabs.monitoring import create_monitoring_tab
from tabs.scene_control import create_scene_control_tab
from tabs.skills_agents import create_skills_agents_tab
from tabs.workflow_builder import create_workflow_builder_tab
from tabs.setup import create_setup_tab
def create_app(config: Config) -> gr.Blocks:
"""Create the main Gradio application"""
# Custom theme
theme = gr.themes.Soft(
primary_hue="blue",
secondary_hue="slate",
)
with gr.Blocks(
title="Kariana UMCP Dashboard",
theme=theme,
css="""
.status-connected { color: #10b981; font-weight: bold; }
.status-disconnected { color: #ef4444; font-weight: bold; }
.pin-input input {
font-size: 2em !important;
text-align: center !important;
letter-spacing: 0.5em !important;
}
"""
) as app:
# Header
gr.Markdown("""
# Kariana UMCP Dashboard
**Unified Control Panel for Unreal Engine MCP Integration**
""")
# Connection status bar
with gr.Row():
connection_status = gr.Markdown(
"**Status:** Not Connected",
elem_classes=["status-disconnected"]
)
refresh_btn = gr.Button("Refresh Status", size="sm", scale=0)
# Main tabs
with gr.Tabs() as tabs:
# Tab 1: Monitoring
with gr.Tab("Monitor", id="monitor"):
monitoring_components = create_monitoring_tab()
# Tab 2: Scene Control
with gr.Tab("Scene", id="scene"):
scene_components = create_scene_control_tab()
# Tab 3: Skills & Agents
with gr.Tab("Skills", id="skills"):
skills_components = create_skills_agents_tab()
# Tab 4: Workflow Builder
with gr.Tab("Workflow", id="workflow"):
workflow_components = create_workflow_builder_tab()
# Tab 5: Setup & Configuration
with gr.Tab("Setup", id="setup"):
setup_components = create_setup_tab()
# Footer
gr.Markdown("""
---
*Kariana UMCP v1.0.0 | [Documentation](https://github.com/kariana) | [Report Issue](https://github.com/kariana/issues)*
""")
# Event handlers for connection status
def update_connection_status():
conn = get_connection()
if conn.is_connected:
instance = conn.instance
return gr.Markdown(
f"**Status:** Connected to {instance.project_name or 'Unreal'} on port {instance.port}",
elem_classes=["status-connected"]
)
return gr.Markdown(
"**Status:** Not Connected - Enter PIN in Setup tab",
elem_classes=["status-disconnected"]
)
refresh_btn.click(
fn=update_connection_status,
outputs=[connection_status]
)
# Update status on app load
app.load(
fn=update_connection_status,
outputs=[connection_status]
)
return app
def main():
"""Main entry point"""
parser = argparse.ArgumentParser(description="Kariana UMCP Dashboard")
parser.add_argument("--port", type=int, default=7860, help="Port to run on")
parser.add_argument("--host", type=str, default="0.0.0.0", help="Host to bind to")
parser.add_argument("--share", action="store_true", help="Create public share link")
parser.add_argument("--debug", action="store_true", help="Enable debug mode")
args = parser.parse_args()
# Load configuration
config = Config.from_env()
config.gradio_port = args.port
config.gradio_host = args.host
if args.debug:
logging.getLogger().setLevel(logging.DEBUG)
config.log_level = "DEBUG"
logger.info(f"Starting Kariana UMCP Dashboard on {args.host}:{args.port}")
# Create and launch app
app = create_app(config)
app.launch(
server_name=args.host,
server_port=args.port,
share=args.share,
show_error=True,
)
if __name__ == "__main__":
main()