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
« 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"""
7import typer
8import os
9import sys
10from pathlib import Path
11from typing import Optional
12import asyncio
14from rich.console import Console
15from rich.panel import Panel
17from .config import settings, CONFIG_FILE
18from .enhanced_commands import enhanced_app
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)
27# Add enhanced commands as subcommand
28app.add_typer(enhanced_app, name="enhanced")
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
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
54 # Ensure tools are migrated
55 try:
56 from .tool_migration import migrate_tools
57 except:
58 pass
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)
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)
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 ))
85 # Try to find available providers
86 available_providers = []
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 }
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
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]")
109 # Update settings
110 settings.provider = selected_provider
111 settings.save()
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 ))
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 ))
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 }
154 for key, (id, name) in providers.items():
155 console.print(f"[cyan]{key}.[/cyan] {name}")
157 choice = console.input("\n[bold white]Choose provider (1-6): [/bold white]").strip()
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]")
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)
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]")
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"]
188 for i, model in enumerate(models, 1):
189 console.print(f"[cyan]{i}.[/cyan] {model}")
191 model_choice = console.input(f"[bold white]Choose model (1-{len(models)}): [/bold white]").strip()
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]")
201 # Save settings
202 settings.save()
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 ))
214 else:
215 console.print("[red]❌ Invalid choice[/red]")
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]")
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]")
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"""
240 # Apply overrides
241 if yolo:
242 settings.yolo_mode = True
243 if model:
244 settings.default_model = model
246 # Only v5.2 available
247 use_v5_2 = True # v5.2 if no other version specified
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)
263# Import theme manager (placeholder for now)
264class ThemeManager:
265 def get_theme_names(self):
266 return ["default", "cyberpunk", "minimal", "ocean"]
268class ModelManager:
269 def __init__(self):
270 self.model_cache = {}
272 def clear_cache(self):
273 self.model_cache.clear()
275theme_manager = ThemeManager()
276model_manager = ModelManager()
278if __name__ == "__main__":
279 app()