@@ -76,6 +76,163 @@ def _unregister_cleanup_handlers(original_sigint, original_sigterm):
7676 # so we keep the atexit handler but check if process list is empty
7777
7878
79+ def _auto_start_services (console , host : str ):
80+ """Auto-start PraisonAI services like the 'up' command does."""
81+ import os
82+ import sys
83+
84+ # Services to start
85+ services = [
86+ ("flow" , 7860 ),
87+ ("claw" , 8082 ),
88+ ("ui" , 8081 )
89+ ]
90+
91+ for service_name , service_port in services :
92+ # Check if service is already running
93+ sock = socket .socket (socket .AF_INET , socket .SOCK_STREAM )
94+ check_host = "127.0.0.1" if host == "0.0.0.0" else host
95+ try :
96+ connection_result = sock .connect_ex ((check_host , service_port ))
97+ if connection_result == 0 :
98+ console .print (f"[yellow]✓ { service_name } already running on port { service_port } [/yellow]" )
99+ sock .close ()
100+ continue
101+ except OSError :
102+ pass
103+ finally :
104+ sock .close ()
105+
106+ # Start the service
107+ console .print (f"[cyan]Starting { service_name } on port { service_port } ...[/cyan]" )
108+ try :
109+ # Create log directory for troubleshooting
110+ log_dir = Path .home () / ".praisonai" / "unified" / "logs"
111+ log_dir .mkdir (parents = True , exist_ok = True )
112+ log_file = log_dir / f"{ service_name } .log"
113+
114+ log_handle = open (log_file , "a" , encoding = "utf-8" )
115+ try :
116+ if service_name == "flow" :
117+ proc = subprocess .Popen ([
118+ sys .executable , "-m" , "praisonai" , "flow" ,
119+ "--port" , str (service_port ), "--host" , host , "--no-open"
120+ ], stdout = log_handle , stderr = subprocess .STDOUT )
121+ elif service_name == "claw" :
122+ proc = subprocess .Popen ([
123+ sys .executable , "-m" , "praisonai" , "claw" ,
124+ "--port" , str (service_port ), "--host" , host
125+ ], stdout = log_handle , stderr = subprocess .STDOUT )
126+ elif service_name == "ui" :
127+ proc = subprocess .Popen ([
128+ sys .executable , "-m" , "praisonai" , "ui" ,
129+ "--port" , str (service_port ), "--host" , host
130+ ], stdout = log_handle , stderr = subprocess .STDOUT )
131+
132+ # Track process for cleanup
133+ _ACTIVE_PROCESSES .add (proc )
134+ _PROCESS_LOG_HANDLES [proc ] = log_handle
135+
136+ # Wait briefly for service to start
137+ time .sleep (1.5 )
138+
139+ # Check if process is still alive
140+ if proc .poll () is not None :
141+ console .print (f"[red]✗ { service_name } failed to start (exit code: { proc .returncode } )[/red]" )
142+ console .print (f"[dim]Check log: { log_file } [/dim]" )
143+ # Clean up failed process
144+ _ACTIVE_PROCESSES .discard (proc )
145+ if proc in _PROCESS_LOG_HANDLES :
146+ _PROCESS_LOG_HANDLES .pop (proc ).close ()
147+ else :
148+ console .print (f"[green]✓ { service_name } started successfully[/green]" )
149+ except Exception :
150+ log_handle .close ()
151+ raise
152+
153+ except Exception as e :
154+ console .print (f"[red]✗ Failed to start { service_name } : { e } [/red]" )
155+
156+
157+ def _run_aiui_dashboard (port : int , host : str , console ):
158+ """Run the aiui dashboard interface."""
159+ console .print ("[bold green]🦞 Starting aiui Dashboard...[/bold green]" )
160+
161+ try :
162+ # Try to import and run aiui directly
163+ import sys
164+ import tempfile
165+ import os
166+
167+ # Create a temporary script for aiui dashboard
168+ aiui_script = f'''
169+ import praisonaiui as aiui
170+
171+ # Configure aiui for dashboard style
172+ aiui.set_style("dashboard")
173+ aiui.set_branding(title="PraisonAI Unified Dashboard", logo="🌟")
174+
175+ # Set up pages for unified dashboard
176+ aiui.set_pages([
177+ "chat", "agents", "memory", "knowledge",
178+ "skills", "sessions", "usage", "config", "logs"
179+ ])
180+
181+ # Register a simple reply handler
182+ @aiui.reply
183+ async def on_reply(message):
184+ return f"Unified Dashboard: {{message.content}}"
185+
186+ # Register a welcome message
187+ @aiui.welcome
188+ async def on_welcome():
189+ return "Welcome to PraisonAI Unified Dashboard! 🌟"
190+
191+ # Start aiui server
192+ if __name__ == "__main__":
193+ import uvicorn
194+ app = aiui.create_app()
195+ uvicorn.run(app, host="{ host } ", port={ port } )
196+ '''
197+
198+ with tempfile .NamedTemporaryFile (mode = 'w' , suffix = '.py' , delete = False ) as f :
199+ f .write (aiui_script )
200+ temp_script = f .name
201+
202+ try :
203+ console .print (f"[green]✓ Starting aiui dashboard on { host } :{ port } [/green]" )
204+
205+ # Check if aiui is available first
206+ result = subprocess .run ([
207+ sys .executable , "-c" , "import praisonaiui"
208+ ], capture_output = True , text = True )
209+
210+ if result .returncode != 0 :
211+ console .print ("[red]Error: aiui package not installed.[/red]" )
212+ console .print ("[yellow]Install with: pip install aiui[/yellow]" )
213+ return False
214+
215+ # Run the aiui script
216+ subprocess .run ([sys .executable , temp_script ])
217+
218+ finally :
219+ # Clean up temp file
220+ try :
221+ os .unlink (temp_script )
222+ except :
223+ pass
224+
225+ except ImportError :
226+ console .print ("[red]Error: aiui package not installed.[/red]" )
227+ console .print ("[yellow]Install with: pip install aiui[/yellow]" )
228+ return False
229+ except Exception as e :
230+ console .print (f"[red]Error running aiui dashboard: { e } [/red]" )
231+ return False
232+
233+ return True
234+
235+
79236def _generate_dashboard_html (host : str = "localhost" ) -> str :
80237 """Generate dashboard HTML with dynamic host configuration."""
81238 dashboard_html = """<!DOCTYPE html>
@@ -393,6 +550,8 @@ def unified(
393550 ctx : typer .Context ,
394551 port : int = typer .Option (3000 , "--port" , "-p" , help = "Port to run unified dashboard on" ),
395552 host : str = typer .Option ("127.0.0.1" , "--host" , help = "Host to bind to (use 0.0.0.0 to expose remotely)" ),
553+ auto_start : bool = typer .Option (True , "--auto-start/--no-auto-start" , help = "Auto-start all services" ),
554+ aiui : bool = typer .Option (False , "--aiui" , help = "Use aiui dashboard interface (experimental)" ),
396555):
397556 """
398557 Launch the PraisonAI Unified Dashboard.
@@ -402,22 +561,30 @@ def unified(
402561 - Claw Dashboard (Full UI) - port 8082
403562 - Clean Chat UI - port 8081
404563
405- This unified launcher allows you to:
406- 1. Create agents visually using Flow Builder
407- 2. Chat with agents using the Chat UI
408- 3. Manage everything from Claw Dashboard
409- 4. Connect external services like Telegram
564+ This unified launcher:
565+ 1. Auto-starts all services by default (like 'praisonai up')
566+ 2. Creates agents visually using Flow Builder
567+ 3. Chats with agents using the Chat UI
568+ 4. Manages everything from Claw Dashboard
569+ 5. Connects external services like Telegram
570+ 6. Optionally uses aiui for enhanced dashboard experience
410571
411572 Examples:
412- praisonai dashboard
573+ praisonai dashboard # Auto-start all services
574+ praisonai dashboard --no-auto-start # Dashboard only (no auto-start)
413575 praisonai dashboard --port 9000 --host 0.0.0.0
576+ praisonai dashboard --aiui # Use aiui interface (experimental)
414577 """
415578 if ctx .invoked_subcommand is not None :
416579 return
417580
418581 from rich .console import Console
419582 console = Console ()
420583
584+ # Check for aiui mode first
585+ if aiui :
586+ return _run_aiui_dashboard (port , host , console )
587+
421588 # Import optional dependencies inside function to avoid startup overhead
422589 try :
423590 from fastapi import FastAPI , HTTPException
@@ -429,6 +596,13 @@ def unified(
429596 console .print (f"[dim]Error details: { exc } [/dim]" )
430597 raise typer .Abort ()
431598
599+ # Auto-start services if enabled
600+ if auto_start :
601+ console .print ("[bold green]🚀 Auto-starting PraisonAI services...[/bold green]" )
602+ _auto_start_services (console , host )
603+ console .print ("[green]✅ Auto-start complete[/green]" )
604+ console .print ()
605+
432606 # Register cleanup handlers and save originals for restoration
433607 original_handlers = _register_cleanup_handlers ()
434608
@@ -554,6 +728,8 @@ async def health():
554728 console .print ()
555729 console .print ("[bold green]🌟 Starting PraisonAI Unified Dashboard[/bold green]" )
556730 console .print (f"[dim]Unified interface on { host } :{ port } [/dim]" )
731+ if auto_start :
732+ console .print ("[dim]Services auto-started and dashboard ready[/dim]" )
557733 console .print ("[dim]Access Flow Builder, Claw Dashboard, and Chat UI from one place[/dim]" )
558734 console .print ()
559735
0 commit comments