Coverage for src / osiris_cli / enhanced_commands.py: 0%
230 statements
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-28 16:44 +0200
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-28 16:44 +0200
1#!/usr/bin/env python3
2"""
3Enhanced Commands Module for Osiris CLI
4Adds comprehensive CLI commands for improved UX
5"""
7import typer
8import os
9from rich.console import Console
10from rich.table import Table
11from rich.panel import Panel
12from rich.progress import Progress, SpinnerColumn, TextColumn
13from typing import Optional
14import time
16from .config import settings
17from pathlib import Path
18from .session import session
20# Simple model manager for cache operations
21class ModelManager:
22 def __init__(self):
23 self.model_cache = {}
25 def clear_cache(self):
26 self.model_cache.clear()
28model_manager = ModelManager()
30# Create command apps
31enhanced_app = typer.Typer(name="enhanced", help="Enhanced CLI commands")
32console = Console()
34def _one_click_setup():
35 """One-click automatic setup"""
36 console.print(Panel(
37 "[bold cyan]🚀 One-Click Setup[/bold cyan]\n\n"
38 "[bold white]Detecting available providers...[/bold white]",
39 title="Auto Setup",
40 border_style="blue"
41 ))
43 # Try to find available providers
44 available_providers = []
46 # Check for API keys in environment
47 env_keys = {
48 "openai": ["OPENAI_API_KEY"],
49 "anthropic": ["ANTHROPIC_API_KEY"],
50 "google": ["GOOGLE_API_KEY"],
51 "groq": ["GROQ_API_KEY"],
52 "deepseek": ["DEEPSEEK_API_KEY"],
53 "perplexity": ["PERPLEXITY_API_KEY"]
54 }
56 for provider, keys in env_keys.items():
57 for key in keys:
58 if os.getenv(key):
59 available_providers.append(provider)
60 break
62 if available_providers:
63 # Use first available provider
64 selected_provider = available_providers[0]
65 console.print(f"[green]✅ Found {selected_provider.upper()} API key[/green]")
67 # Update settings
68 settings.provider = selected_provider
69 settings.save()
71 console.print(Panel(
72 f"[bold green]🎉 Setup Complete![/bold green]\n\n"
73 f"Provider: {selected_provider.upper()}\n"
74 "You can now run [cyan]osiris[/cyan] to start chatting!",
75 title="Success",
76 border_style="green"
77 ))
78 else:
79 console.print(Panel(
80 "[bold yellow]⚠️ No API keys found[/bold yellow]\n\n"
81 "Please set up an API key for one of these providers:\n\n"
82 "[cyan]• OpenAI: export OPENAI_API_KEY=your_key[/cyan]\n"
83 "[cyan]• Anthropic: export ANTHROPIC_API_KEY=your_key[/cyan]\n"
84 "[cyan]• Google: export GOOGLE_API_KEY=your_key[/cyan]\n"
85 "[cyan]• Groq: export GROQ_API_KEY=your_key[/cyan]\n\n"
86 "Or run [cyan]osiris enhanced quick-start[/cyan] for guided setup.",
87 title="Manual Setup Required",
88 border_style="yellow"
89 ))
91def _quick_setup_wizard():
92 """Interactive setup wizard"""
93 console.print(Panel(
94 "[bold cyan]🧙 Setup Wizard[/bold cyan]\n\n"
95 "[bold white]Let's configure Osiris step by step...[/bold white]",
96 title="Interactive Setup",
97 border_style="blue"
98 ))
100 try:
101 # Provider selection
102 console.print("\n[bold cyan]Step 1: Choose Provider[/bold cyan]")
103 providers = {
104 "1": ("openai", "OpenAI (GPT-4, GPT-3.5)"),
105 "2": ("anthropic", "Anthropic (Claude)"),
106 "3": ("google", "Google (Gemini)"),
107 "4": ("groq", "Groq (Fast inference)"),
108 "5": ("deepseek", "DeepSeek (Cost-effective)"),
109 "6": ("ollama", "Ollama (Local models)")
110 }
112 for key, (id, name) in providers.items():
113 console.print(f"[cyan]{key}.[/cyan] {name}")
115 choice = console.input("\n[bold white]Choose provider (1-6): [/bold white]").strip()
117 if choice in providers:
118 provider_id, provider_name = providers[choice]
119 settings.provider = provider_id
120 console.print(f"[green]✅ Selected: {provider_name}[/green]")
122 # API key input (skip for ollama)
123 if provider_id != "ollama":
124 console.print(f"\n[bold cyan]Step 2: API Key for {provider_name}[/bold cyan]")
125 api_key = console.input("[bold white]Enter API key: [/bold white]", password=True)
127 if api_key:
128 # Save to environment variable name
129 key_name = f"{provider_id.upper()}_API_KEY"
130 os.environ[key_name] = api_key
131 console.print(f"[green]✅ API key configured[/green]")
132 else:
133 console.print("[yellow]⚠️ No API key entered - you'll need to set it manually[/yellow]")
135 # Model selection
136 console.print(f"\n[bold cyan]Step 3: Default Model[/bold cyan]")
137 if provider_id == "openai":
138 models = ["gpt-4", "gpt-3.5-turbo"]
139 elif provider_id == "anthropic":
140 models = ["claude-3-5-sonnet-20241022", "claude-3-haiku-20240307"]
141 elif provider_id == "google":
142 models = ["gemini-pro", "gemini-1.5-flash"]
143 else:
144 models = ["auto"]
146 for i, model in enumerate(models, 1):
147 console.print(f"[cyan]{i}.[/cyan] {model}")
149 model_choice = console.input(f"[bold white]Choose model (1-{len(models)}): [/bold white]").strip()
151 try:
152 model_index = int(model_choice) - 1
153 if 0 <= model_index < len(models):
154 settings.default_model = models[model_index]
155 console.print(f"[green]✅ Model set to: {models[model_index]}[/green]")
156 except:
157 console.print("[yellow]⚠️ Using default model selection[/yellow]")
159 # Save settings
160 settings.save()
162 console.print(Panel(
163 f"[bold green]🎉 Setup Complete![/bold green]\n\n"
164 f"Provider: {provider_name}\n"
165 f"Model: {settings.default_model}\n\n"
166 "You can now run [cyan]osiris[/cyan] to start chatting!\n\n"
167 "[dim]Pro tip: Run 'osiris enhanced status' to see your current configuration[/dim]",
168 title="Success",
169 border_style="green"
170 ))
172 else:
173 console.print("[red]❌ Invalid choice[/red]")
175 except KeyboardInterrupt:
176 console.print("\n[yellow]👋 Setup cancelled[/yellow]")
177 except Exception as e:
178 console.print(f"[red]❌ Setup error: {e}[/red]")
180def _run_interactive_mode():
181 """Launch the interactive TUI"""
182 from .app import OsirisApp
183 try:
184 # Launch the textual TUI
185 osiris_app = OsirisApp()
186 osiris_app.run()
187 except KeyboardInterrupt:
188 console.print("\n[yellow]👋 Goodbye![/yellow]")
189 except Exception as e:
190 console.print(f"[red]❌ Error launching interface: {e}[/red]")
192@enhanced_app.command()
193def status():
194 """Show detailed system status and statistics"""
196 # Get session stats
197 stats = session.get_session_stats()
199 # Create system status table
200 table = Table(title="🔧 System Status", show_header=True)
201 table.add_column("Component", style="cyan", width=20)
202 table.add_column("Status", style="green", width=15)
203 table.add_column("Details", style="dim")
205 # Core components
206 table.add_row("CLI Version", "✅ Active", "3.2.0")
207 config_file = Path.home() / ".osiris" / "config.toml"
208 table.add_row("Config", "✅ Loaded", str(config_file))
209 table.add_row("Sessions", "✅ Available", f"{stats.get('total_sessions', 0)} sessions")
210 table.add_row("Provider", "🔗 Connected", f"{settings.provider.upper()}")
211 table.add_row("Model", "🤖 Ready", settings.default_model)
212 table.add_row("Theme", "🎨 Active", settings.theme)
214 console.print(table)
216 # Session statistics panel
217 if stats.get('total_sessions', 0) > 0:
218 stats_content = f"""[bold green]📊 Session Statistics[/bold green]
220[cyan]Total Sessions:[/cyan] {stats.get('total_sessions', 0)}
221[cyan]Total Messages:[/cyan] {stats.get('total_messages', 0)}
222[cyan]Total Tokens:[/cyan] {stats.get('total_tokens', 0):,}
223[cyan]Tool Calls:[/cyan] {stats.get('total_tool_calls', 0)}
225[dim]Provider Usage:[/dim]"""
227 for provider, count in stats.get('providers', {}).items():
228 stats_content += f"\n • {provider}: {count} sessions"
230 console.print(Panel(
231 stats_content,
232 title="📈 Usage Analytics",
233 border_style="blue"
234 ))
236 console.print(Panel(
237 "[bold green]🚀 Osiris is running optimally![/bold green]\n\n"
238 "[dim]Run 'osiris enhanced quick-start' for new user setup[/dim]\n"
239 "[dim]Run 'osiris enhanced providers' to check available providers[/dim]",
240 title="System Health",
241 border_style="green"
242 ))
244@enhanced_app.command()
245def quick_start():
246 """Quick start wizard for new users"""
248 console.print(Panel(
249 "[bold cyan]🚀 Osiris Quick Start[/bold cyan]\n\n"
250 "[bold white]Choose your setup path:[/bold white]\n\n"
251 "[bold yellow]1.[/bold yellow] [cyan]Auto-Setup[/cyan] - Configure provider automatically\n"
252 "[dim] Detects and configures the best available provider[/dim]\n\n"
253 "[bold yellow]2.[/bold yellow] [cyan]Manual Setup[/cyan] - Choose specific provider\n"
254 "[dim] Select from OpenAI, Gemini, DeepSeek, Groq, and more[/dim]\n\n"
255 "[bold yellow]3.[/bold yellow] [cyan]Interactive Mode[/cyan] - Start with defaults\n"
256 "[dim] Jump straight into the chat interface[/dim]\n\n"
257 "[bold magenta]💡 Pro Tip:[/bold magenta] [dim]All providers offer free tiers to get started![/dim]",
258 title="🎯 Quick Start Options",
259 border_style="cyan"
260 ))
262 try:
263 choice = console.input("[bold cyan]Choose option (1-3):[/bold cyan] ").strip()
265 if choice == "1":
266 console.print("[green]🚀 Starting Auto-Setup...[/green]")
267 _one_click_setup()
268 elif choice == "2":
269 console.print("[blue]⚙️ Starting Manual Setup...[/blue]")
270 _quick_setup_wizard()
271 else:
272 console.print("[yellow]🎮 Starting Interactive Mode...[/yellow]")
273 _run_interactive_mode()
275 except KeyboardInterrupt:
276 console.print("\n[yellow]👋 Setup cancelled. Run 'osiris' anytime to start![/yellow]")
277 except Exception as e:
278 console.print(f"[red]❌ Error during setup: {e}[/red]")
280@enhanced_app.command()
281def providers():
282 """List and check available providers"""
284 console.print(Panel(
285 "[bold cyan]🔗 Provider Management[/bold cyan]\n\n"
286 "[bold white]Checking provider availability and status...[/bold white]",
287 title="📊 Provider Status",
288 border_style="blue"
289 ))
291 # Create provider status table
292 table = Table(title="Available Providers")
293 table.add_column("Provider", style="cyan")
294 table.add_column("Status", style="green")
295 table.add_column("API Key", style="yellow")
296 table.add_column("Models", style="dim")
298 from .config import KNOWN_PROVIDERS
300 for provider_id, provider_info in KNOWN_PROVIDERS.items():
301 # Check API key status
302 key_name = provider_info.get("api_key_name")
303 has_key = False
305 if key_name:
306 api_key = getattr(settings, key_name, None)
307 has_key = api_key is not None
309 # Status
310 if provider_id == settings.provider:
311 status = "✅ Active"
312 elif has_key:
313 status = "🔑 Available"
314 else:
315 status = "⚠️ Needs Key"
317 # API key display
318 key_status = "✅ Configured" if has_key else "❌ Missing"
320 # Model count
321 model_count = len(provider_info.get("models", []))
323 table.add_row(
324 provider_info["name"],
325 status,
326 key_status,
327 f"{model_count} models"
328 )
330 console.print(table)
332 console.print(Panel(
333 "[bold green]💡 Quick Actions:[/bold green]\n\n"
334 "[cyan]• osiris enhanced quick-start[/cyan] - Setup a provider\n"
335 "[cyan]• osiris setup[/cyan] - Manual provider configuration\n"
336 "[cyan]• osiris config[/cyan] - View/edit settings\n",
337 title="🚀 Next Steps",
338 border_style="green"
339 ))
341@enhanced_app.command()
342def themes():
343 """Manage UI themes"""
345 from .main import theme_manager
347 console.print(Panel(
348 "[bold cyan]🎨 Theme Management[/bold cyan]\n\n"
349 f"[bold white]Current Theme:[/bold white] {settings.theme}",
350 title="🎯 UI Themes",
351 border_style="magenta"
352 ))
354 # Create theme preview table
355 table = Table(title="Available Themes")
356 table.add_column("Theme", style="cyan")
357 table.add_column("Status", style="green")
358 table.add_column("Shortcut", style="yellow")
360 themes = theme_manager.get_theme_names()
361 current_theme = settings.theme
363 for theme in themes:
364 status = "✅ Active" if theme == current_theme else "🔄 Available"
365 shortcut = f"F{themes.index(theme) + 1}" if themes.index(theme) < 4 else "N/A"
366 table.add_row(theme.title(), status, shortcut)
368 console.print(table)
370 console.print(Panel(
371 "[bold green]💡 Theme Shortcuts:[/bold green]\n\n"
372 "[cyan]• F1[/cyan] - Default Theme\n"
373 "[cyan]• F2[/cyan] - Cyberpunk Theme\n"
374 "[cyan]• F3[/cyan] - Minimal Theme\n"
375 "[cyan]• F4[/cyan] - Ocean Theme\n\n"
376 "[dim]Press shortcuts in any interactive screen to change themes[/dim]",
377 title="⌨️ Keyboard Shortcuts",
378 border_style="blue"
379 ))
381@enhanced_app.command()
382def health():
383 """Comprehensive system health check"""
385 console.print(Panel(
386 "[bold cyan]🏥 System Health Check[/bold cyan]\n\n"
387 "[bold white]Running comprehensive diagnostics...[/bold white]",
388 title="🔍 Health Analysis",
389 border_style="blue"
390 ))
392 with Progress(
393 SpinnerColumn(),
394 TextColumn("[progress.description]{task.description}"),
395 console=console,
396 transient=True
397 ) as progress:
399 # Check configuration
400 task1 = progress.add_task("📋 Checking configuration...", total=None)
401 time.sleep(0.5)
403 # Check sessions
404 task2 = progress.add_task("💾 Checking sessions...", total=None)
405 time.sleep(0.5)
407 # Check providers
408 task3 = progress.add_task("🔗 Checking providers...", total=None)
409 time.sleep(0.5)
411 # Check models
412 task4 = progress.add_task("🤖 Checking models...", total=None)
413 time.sleep(0.5)
415 # Health results
416 health_items = []
418 # Config health
419 config_file = Path.home() / ".osiris" / "config.toml"
420 if config_file.exists():
421 health_items.append("✅ Configuration file exists and is readable")
422 else:
423 health_items.append("❌ Configuration file missing")
425 # Session health
426 try:
427 session_count = len(session.list_sessions())
428 health_items.append(f"✅ {session_count} sessions found")
429 except:
430 health_items.append("❌ Session access error")
432 # Provider health
433 if settings.provider != "ollama":
434 health_items.append(f"✅ Provider configured: {settings.provider}")
435 else:
436 health_items.append("⚠️ Using default provider (setup recommended)")
438 # Model health
439 if settings.default_model != "gpt-3.5-turbo":
440 health_items.append(f"✅ Model configured: {settings.default_model}")
441 else:
442 health_items.append("⚠️ Using default model (customization recommended)")
444 # Display results
445 console.print(Panel(
446 "\n".join(health_items),
447 title="🏥 Health Results",
448 border_style="green" if all("✅" in item for item in health_items) else "yellow"
449 ))
451 # Recommendations
452 recommendations = []
454 if settings.provider == "ollama":
455 recommendations.append("🚀 Configure an AI provider for better models")
457 if settings.default_model == "gpt-3.5-turbo":
458 recommendations.append("🎨 Try advanced models like GPT-4, Claude, or Gemini")
460 if len(session.list_sessions()) == 0:
461 recommendations.append("💬 Start your first conversation")
463 if recommendations:
464 console.print(Panel(
465 "[bold yellow]💡 Recommendations:[/bold yellow]\n\n" + "\n".join(recommendations),
466 title="🎯 Improvement Suggestions",
467 border_style="yellow"
468 ))
470@enhanced_app.command()
471def optimize():
472 """Optimize Osiris performance and settings"""
474 console.print(Panel(
475 "[bold cyan]⚡ Performance Optimization[/bold cyan]\n\n"
476 "[bold white]Analyzing and optimizing your setup...[/bold white]",
477 title="🚀 Optimization",
478 border_style="blue"
479 ))
481 optimizations = []
483 # Check cache
484 cache_status = len(model_manager.model_cache)
485 if cache_status > 10:
486 model_manager.clear_cache()
487 optimizations.append("🧹 Cleared excessive model cache")
488 else:
489 optimizations.append(f"✅ Model cache optimal ({cache_status} providers)")
491 # Check theme performance
492 if settings.theme == "cyberpunk":
493 optimizations.append("🎨 Cyberpunk theme detected (may impact performance on some terminals)")
494 else:
495 optimizations.append(f"✅ Theme optimized: {settings.theme}")
497 # Check timeout settings
498 if settings.timeout > 120:
499 settings.timeout = 120
500 settings.save()
501 optimizations.append("⏱️ Optimized timeout for better responsiveness")
502 else:
503 optimizations.append(f"✅ Timeout optimal: {settings.timeout}s")
505 # Check temperature settings
506 if "o1" in settings.default_model.lower() and settings.temperature != 1.0:
507 settings.temperature = 1.0
508 settings.save()
509 optimizations.append("🌡️ Optimized temperature for reasoning model")
510 else:
511 optimizations.append(f"✅ Temperature optimal: {settings.temperature}")
513 console.print(Panel(
514 "\n".join(optimizations),
515 title="⚡ Optimization Results",
516 border_style="green"
517 ))
519 console.print(Panel(
520 "[bold green]🚀 Osiris is now optimized![/bold green]\n\n"
521 "[dim]Run 'osiris enhanced health' to check system health[/dim]\n"
522 "[dim]Run 'osiris enhanced status' to view current status[/dim]",
523 title="✅ Complete",
524 border_style="green"
525 ))