Coverage for src / osiris_cli / main.py: 0%

135 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2025-12-31 05:01 +0200

1#!/usr/bin/env python3 

2""" 

3Osiris CLI - Main Entry Point 

4Unified CLI interface with TUI launcher 

5""" 

6 

7import typer 

8import os 

9import sys 

10from pathlib import Path 

11from typing import Optional 

12import asyncio 

13 

14from rich.console import Console 

15from rich.panel import Panel 

16 

17from .config import settings, CONFIG_FILE 

18from .enhanced_commands import enhanced_app 

19 

20console = Console(color_system="auto", legacy_windows=False) 

21app = typer.Typer( 

22 name="osiris", 

23 help="Osiris CLI - Sovereign AGI Terminal Interface", 

24 add_completion=False 

25) 

26 

27# Add enhanced commands as subcommand 

28app.add_typer(enhanced_app, name="enhanced") 

29 

30def _ensure_config(): 

31 """Ensure configuration is loaded""" 

32 try: 

33 if not CONFIG_FILE.exists(): 

34 console.print(Panel( 

35 "[bold yellow]⚠️ First Time Setup Required[/bold yellow]\n\n" 

36 "Osiris needs to be configured before first use.\n\n" 

37 "[cyan]Run: osiris enhanced quick-start[/cyan]", 

38 title="Welcome to Osiris", 

39 border_style="yellow" 

40 )) 

41 return False 

42 return True 

43 except Exception as e: 

44 console.print(f"[red]❌ Configuration error: {e}[/red]") 

45 return False 

46 

47def _run_interactive_mode(use_v5: bool = False, use_v5_1: bool = False, use_v5_2: bool = True, agent_name: str = "main", no_select: bool = False, show_select: bool = False, print_mode: bool = False): 

48 """Launch the CLI (v4.0, v5.0, v5.1, or v5.2)""" 

49 try: 

50 # Launch v5.2 - Clean Neural Stream 

51 from .cli_v5_2 import main as cli_v5_2_main 

52 from .agent_selector import agent_selector 

53 

54 # Ensure tools are migrated 

55 try: 

56 from .tool_migration import migrate_tools 

57 except: 

58 pass 

59 

60 # Agent selection (only if explicitly requested with --select) 

61 if show_select and not no_select: 

62 selected_agent = agent_selector.select_agent() 

63 if selected_agent: 

64 agent_name = selected_agent 

65 agent_selector.update_last_used(agent_name) 

66 

67 asyncio.run(cli_v5_2_main(agent_name=agent_name, print_mode=True)) 

68 except KeyboardInterrupt: 

69 console.print("\n[yellow]Goodbye![/yellow]") # Removed emoji to prevent surrogate pair encoding errors 

70 except Exception as e: 

71 console.print(f"[red]\u274c Error launching interface: {e}[/red]") 

72 import traceback 

73 traceback.print_exc() 

74 sys.exit(1) 

75 

76def _one_click_setup(): 

77 """One-click automatic setup""" 

78 console.print(Panel( 

79 "[bold cyan]🚀 One-Click Setup[/bold cyan]\n\n" 

80 "[bold white]Detecting available providers...[/bold white]", 

81 title="Auto Setup", 

82 border_style="blue" 

83 )) 

84 

85 # Try to find available providers 

86 available_providers = [] 

87 

88 # Check for API keys in environment 

89 env_keys = { 

90 "openai": ["OPENAI_API_KEY"], 

91 "anthropic": ["ANTHROPIC_API_KEY"], 

92 "google": ["GOOGLE_API_KEY"], 

93 "groq": ["GROQ_API_KEY"], 

94 "deepseek": ["DEEPSEEK_API_KEY"], 

95 "perplexity": ["PERPLEXITY_API_KEY"] 

96 } 

97 

98 for provider, keys in env_keys.items(): 

99 for key in keys: 

100 if os.getenv(key): 

101 available_providers.append(provider) 

102 break 

103 

104 if available_providers: 

105 # Use first available provider 

106 selected_provider = available_providers[0] 

107 console.print(f"[green]✅ Found {selected_provider.upper()} API key[/green]") 

108 

109 # Update settings 

110 settings.provider = selected_provider 

111 settings.save() 

112 

113 console.print(Panel( 

114 f"[bold green]🎉 Setup Complete![/bold green]\n\n" 

115 f"Provider: {selected_provider.upper()}\n" 

116 "You can now run [cyan]osiris[/cyan] to start chatting!", 

117 title="Success", 

118 border_style="green" 

119 )) 

120 else: 

121 console.print(Panel( 

122 "[bold yellow]⚠️ No API keys found[/bold yellow]\n\n" 

123 "Please set up an API key for one of these providers:\n\n" 

124 "[cyan]• OpenAI: export OPENAI_API_KEY=your_key[/cyan]\n" 

125 "[cyan]• Anthropic: export ANTHROPIC_API_KEY=your_key[/cyan]\n" 

126 "[cyan]• Google: export GOOGLE_API_KEY=your_key[/cyan]\n" 

127 "[cyan]• Groq: export GROQ_API_KEY=your_key[/cyan]\n\n" 

128 "Or run [cyan]osiris enhanced quick-start[/cyan] for guided setup.", 

129 title="Manual Setup Required", 

130 border_style="yellow" 

131 )) 

132 

133def _quick_setup_wizard(): 

134 """Interactive setup wizard""" 

135 console.print(Panel( 

136 "[bold cyan]🧙 Setup Wizard[/bold cyan]\n\n" 

137 "[bold white]Let's configure Osiris step by step...[/bold white]", 

138 title="Interactive Setup", 

139 border_style="blue" 

140 )) 

141 

142 try: 

143 # Provider selection 

144 console.print("\n[bold cyan]Step 1: Choose Provider[/bold cyan]") 

145 providers = { 

146 "1": ("openai", "OpenAI (GPT-4, GPT-3.5)"), 

147 "2": ("anthropic", "Anthropic (Claude)"), 

148 "3": ("google", "Google (Gemini)"), 

149 "4": ("groq", "Groq (Fast inference)"), 

150 "5": ("deepseek", "DeepSeek (Cost-effective)"), 

151 "6": ("ollama", "Ollama (Local models)") 

152 } 

153 

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

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

156 

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

158 

159 if choice in providers: 

160 provider_id, provider_name = providers[choice] 

161 settings.provider = provider_id 

162 console.print(f"[green]✅ Selected: {provider_name}[/green]") 

163 

164 # API key input (skip for ollama) 

165 if provider_id != "ollama": 

166 console.print(f"\n[bold cyan]Step 2: API Key for {provider_name}[/bold cyan]") 

167 api_key = console.input("[bold white]Enter API key: [/bold white]", password=True) 

168 

169 if api_key: 

170 # Save to environment variable name 

171 key_name = f"{provider_id.upper()}_API_KEY" 

172 os.environ[key_name] = api_key 

173 console.print(f"[green]✅ API key configured[/green]") 

174 else: 

175 console.print("[yellow]⚠️ No API key entered - you'll need to set it manually[/yellow]") 

176 

177 # Model selection 

178 console.print(f"\n[bold cyan]Step 3: Default Model[/bold cyan]") 

179 if provider_id == "openai": 

180 models = ["gpt-4", "gpt-3.5-turbo"] 

181 elif provider_id == "anthropic": 

182 models = ["claude-3-5-sonnet-20241022", "claude-3-haiku-20240307"] 

183 elif provider_id == "google": 

184 models = ["gemini-pro", "gemini-1.5-flash"] 

185 else: 

186 models = ["auto"] 

187 

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

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

190 

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

192 

193 try: 

194 model_index = int(model_choice) - 1 

195 if 0 <= model_index < len(models): 

196 settings.default_model = models[model_index] 

197 console.print(f"[green]✅ Model set to: {models[model_index]}[/green]") 

198 except: 

199 console.print("[yellow]⚠️ Using default model selection[/yellow]") 

200 

201 # Save settings 

202 settings.save() 

203 

204 console.print(Panel( 

205 f"[bold green]🎉 Setup Complete![/bold green]\n\n" 

206 f"Provider: {provider_name}\n" 

207 f"Model: {settings.default_model}\n\n" 

208 "You can now run [cyan]osiris[/cyan] to start chatting!\n\n" 

209 "[dim]Pro tip: Run 'osiris enhanced status' to see your current configuration[/dim]", 

210 title="Success", 

211 border_style="green" 

212 )) 

213 

214 else: 

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

216 

217 except KeyboardInterrupt: 

218 console.print("\n[yellow]👋 Setup cancelled[/yellow]") 

219 except Exception as e: 

220 console.print(f"[red]❌ Setup error: {e}[/red]") 

221 

222# CLI Commands 

223@app.command() 

224def config(): 

225 """Configure Osiris settings""" 

226 console.print("[cyan]⚙️ Configuration not yet implemented. Use 'osiris enhanced quick-start' for setup.[/cyan]") 

227 

228@app.callback(invoke_without_command=True) 

229def main( 

230 ctx: typer.Context, 

231 prompt: Optional[str] = typer.Option(None, "--prompt", "-p", help="Send a prompt and exit"), 

232 yolo: bool = typer.Option(False, "--yolo", help="Enable autonomous mode"), 

233 model: Optional[str] = typer.Option(None, "--model", "-m", help="Override default model"), 

234 agent: Optional[str] = typer.Option("main", "--agent", "-a", help="Agent name for memory persistence"), 

235 context_file: Optional[str] = typer.Option(None, "--context-file", help="Load parent context from JSON file"), 

236 select: bool = typer.Option(False, "--select", help="Show agent selector on startup"), 

237): 

238 """Osiris CLI - Sovereign AGI Terminal Interface""" 

239 

240 # Apply overrides 

241 if yolo: 

242 settings.yolo_mode = True 

243 if model: 

244 settings.default_model = model 

245 

246 # Only v5.2 available 

247 use_v5_2 = True # v5.2 if no other version specified 

248 

249 # If no command specified, launch interactive mode 

250 if ctx.invoked_subcommand is None: 

251 if prompt: 

252 # Handle one-shot prompt mode (non-interactive) 

253 from .cli_v5_2 import main as cli_v5_2_main 

254 try: 

255 from .tool_migration import migrate_tools 

256 except: 

257 pass 

258 asyncio.run(cli_v5_2_main(agent_name=agent, prompt=prompt, print_mode=True, context_file=context_file)) 

259 else: 

260 # Launch interactive CLI 

261 _run_interactive_mode(use_v5=False, use_v5_1=False, use_v5_2=True, agent_name=agent, show_select=select, print_mode=True) 

262 

263# Import theme manager (placeholder for now) 

264class ThemeManager: 

265 def get_theme_names(self): 

266 return ["default", "cyberpunk", "minimal", "ocean"] 

267 

268class ModelManager: 

269 def __init__(self): 

270 self.model_cache = {} 

271 

272 def clear_cache(self): 

273 self.model_cache.clear() 

274 

275theme_manager = ThemeManager() 

276model_manager = ModelManager() 

277 

278if __name__ == "__main__": 

279 app()