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

1#!/usr/bin/env python3 

2""" 

3Enhanced Commands Module for Osiris CLI 

4Adds comprehensive CLI commands for improved UX 

5""" 

6 

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 

15 

16from .config import settings 

17from pathlib import Path 

18from .session import session 

19 

20# Simple model manager for cache operations 

21class ModelManager: 

22 def __init__(self): 

23 self.model_cache = {} 

24 

25 def clear_cache(self): 

26 self.model_cache.clear() 

27 

28model_manager = ModelManager() 

29 

30# Create command apps 

31enhanced_app = typer.Typer(name="enhanced", help="Enhanced CLI commands") 

32console = Console() 

33 

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 )) 

42 

43 # Try to find available providers 

44 available_providers = [] 

45 

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 } 

55 

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 

61 

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]") 

66 

67 # Update settings 

68 settings.provider = selected_provider 

69 settings.save() 

70 

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 )) 

90 

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 )) 

99 

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 } 

111 

112 for key, (id, name) in providers.items(): 

113 console.print(f"[cyan]{key}.[/cyan] {name}") 

114 

115 choice = console.input("\n[bold white]Choose provider (1-6): [/bold white]").strip() 

116 

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]") 

121 

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) 

126 

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]") 

134 

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"] 

145 

146 for i, model in enumerate(models, 1): 

147 console.print(f"[cyan]{i}.[/cyan] {model}") 

148 

149 model_choice = console.input(f"[bold white]Choose model (1-{len(models)}): [/bold white]").strip() 

150 

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]") 

158 

159 # Save settings 

160 settings.save() 

161 

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 )) 

171 

172 else: 

173 console.print("[red]❌ Invalid choice[/red]") 

174 

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]") 

179 

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]") 

191 

192@enhanced_app.command() 

193def status(): 

194 """Show detailed system status and statistics""" 

195 

196 # Get session stats 

197 stats = session.get_session_stats() 

198 

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") 

204 

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) 

213 

214 console.print(table) 

215 

216 # Session statistics panel 

217 if stats.get('total_sessions', 0) > 0: 

218 stats_content = f"""[bold green]📊 Session Statistics[/bold green] 

219 

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)} 

224 

225[dim]Provider Usage:[/dim]""" 

226 

227 for provider, count in stats.get('providers', {}).items(): 

228 stats_content += f"\n • {provider}: {count} sessions" 

229 

230 console.print(Panel( 

231 stats_content, 

232 title="📈 Usage Analytics", 

233 border_style="blue" 

234 )) 

235 

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 )) 

243 

244@enhanced_app.command() 

245def quick_start(): 

246 """Quick start wizard for new users""" 

247 

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 )) 

261 

262 try: 

263 choice = console.input("[bold cyan]Choose option (1-3):[/bold cyan] ").strip() 

264 

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() 

274 

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]") 

279 

280@enhanced_app.command() 

281def providers(): 

282 """List and check available providers""" 

283 

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 )) 

290 

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") 

297 

298 from .config import KNOWN_PROVIDERS 

299 

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 

304 

305 if key_name: 

306 api_key = getattr(settings, key_name, None) 

307 has_key = api_key is not None 

308 

309 # Status 

310 if provider_id == settings.provider: 

311 status = "✅ Active" 

312 elif has_key: 

313 status = "🔑 Available" 

314 else: 

315 status = "⚠️ Needs Key" 

316 

317 # API key display 

318 key_status = "✅ Configured" if has_key else "❌ Missing" 

319 

320 # Model count 

321 model_count = len(provider_info.get("models", [])) 

322 

323 table.add_row( 

324 provider_info["name"], 

325 status, 

326 key_status, 

327 f"{model_count} models" 

328 ) 

329 

330 console.print(table) 

331 

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 )) 

340 

341@enhanced_app.command() 

342def themes(): 

343 """Manage UI themes""" 

344 

345 from .main import theme_manager 

346 

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 )) 

353 

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") 

359 

360 themes = theme_manager.get_theme_names() 

361 current_theme = settings.theme 

362 

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) 

367 

368 console.print(table) 

369 

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 )) 

380 

381@enhanced_app.command() 

382def health(): 

383 """Comprehensive system health check""" 

384 

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 )) 

391 

392 with Progress( 

393 SpinnerColumn(), 

394 TextColumn("[progress.description]{task.description}"), 

395 console=console, 

396 transient=True 

397 ) as progress: 

398 

399 # Check configuration 

400 task1 = progress.add_task("📋 Checking configuration...", total=None) 

401 time.sleep(0.5) 

402 

403 # Check sessions 

404 task2 = progress.add_task("💾 Checking sessions...", total=None) 

405 time.sleep(0.5) 

406 

407 # Check providers 

408 task3 = progress.add_task("🔗 Checking providers...", total=None) 

409 time.sleep(0.5) 

410 

411 # Check models 

412 task4 = progress.add_task("🤖 Checking models...", total=None) 

413 time.sleep(0.5) 

414 

415 # Health results 

416 health_items = [] 

417 

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") 

424 

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") 

431 

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)") 

437 

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)") 

443 

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 )) 

450 

451 # Recommendations 

452 recommendations = [] 

453 

454 if settings.provider == "ollama": 

455 recommendations.append("🚀 Configure an AI provider for better models") 

456 

457 if settings.default_model == "gpt-3.5-turbo": 

458 recommendations.append("🎨 Try advanced models like GPT-4, Claude, or Gemini") 

459 

460 if len(session.list_sessions()) == 0: 

461 recommendations.append("💬 Start your first conversation") 

462 

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 )) 

469 

470@enhanced_app.command() 

471def optimize(): 

472 """Optimize Osiris performance and settings""" 

473 

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 )) 

480 

481 optimizations = [] 

482 

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)") 

490 

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}") 

496 

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") 

504 

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}") 

512 

513 console.print(Panel( 

514 "\n".join(optimizations), 

515 title="⚡ Optimization Results", 

516 border_style="green" 

517 )) 

518 

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 ))