Skip to main content
Glama
commands.py12 kB
"""REPL command parsing and handling functionality.""" import logging from argparse import Namespace from typing import Callable, Optional from prompt_toolkit.formatted_text import HTML from promptheus.config import Config from promptheus.constants import VERSION, GITHUB_REPO, GITHUB_ISSUES from promptheus.providers import LLMProvider, get_provider from promptheus.utils import sanitize_error_message logger = logging.getLogger(__name__) MessageSink = Callable[[str], None] def create_command_registry(): """Create a registry of command handlers for extensibility.""" from .history_view import display_history from promptheus.utils import copy_to_clipboard from promptheus.history import get_history def handle_about(args_list, app_config, args, console, notify): show_about(console, app_config) return "handled" def handle_bug(args_list, app_config, args, console, notify): show_bug_report(console) return "handled" def handle_clear_history(args_list, app_config, args, console, notify): import questionary try: confirm = questionary.confirm( "Are you sure you want to clear all history?", default=False, ).ask() if confirm: get_history().clear() console.print("[green]✓[/green] History cleared") except KeyboardInterrupt: console.print("[yellow]Cancelled[/yellow]") return "handled" def handle_copy(args_list, app_config, args, console, notify, last_result=None): if last_result: copy_to_clipboard(last_result, console, notify) else: console.print("[yellow]No result to copy yet. Process a prompt first.[/yellow]") return "handled" def handle_help(args_list, app_config, args, console, notify): show_help(console) return "handled" def handle_history(args_list, app_config, args, console, notify): display_history(console, notify) return "handled" def handle_load(args_list, app_config, args, console, notify): if len(args_list) > 0: try: index = int(args_list[0]) entry = get_history().get_by_index(index) if entry: console.print(f"[green]✓[/green] Loaded prompt #{index} from history:\n") console.print(f"[cyan]{entry.original_prompt}[/cyan]\n") return ("load_prompt", entry.original_prompt) else: console.print(f"[yellow]No history entry found at index {index}[/yellow]") return "handled" except ValueError: console.print("[yellow]Invalid history index. Use '/load <number>'[/yellow]") return "handled" else: console.print("[yellow]Specify which prompt to load. Showing history:[/yellow]\n") display_history(console, notify) return "handled" return { 'about': handle_about, 'bug': handle_bug, 'clear-history': handle_clear_history, 'copy': handle_copy, 'help': handle_help, 'history': handle_history, 'load': handle_load, } def show_help(console) -> None: """Display help information about available commands.""" console.print() console.print("[bold cyan]Session Commands:[/bold cyan]") console.print() console.print(" [bold]/set model <name>[/bold] Change model (e.g., /set model gpt-4)") console.print(" [bold]/set provider <name>[/bold] Change AI provider (e.g., /set provider claude)") console.print(" [bold]/status[/bold] Show current session settings") console.print(" [bold]/toggle skip-questions[/bold] Toggle skip-questions mode on/off") console.print(" [bold]/toggle refine[/bold] Toggle refine mode on/off") console.print() console.print("[bold cyan]Other Commands:[/bold cyan]") console.print() console.print(" [bold]/about[/bold] Show version info") console.print(" [bold]/bug[/bold] Submit a bug report") console.print(" [bold]/clear-history[/bold] Clear all history") console.print(" [bold]/copy[/bold] Copy the last result to clipboard") console.print(" [bold]/exit[/bold] or [bold]/quit[/bold] Exit Promptheus") console.print(" [bold]/help[/bold] Show this help message") console.print(" [bold]/history[/bold] View recent prompts") console.print(" [bold]/load <number>[/bold] Load a prompt from history") console.print() console.print("[bold cyan]Key Bindings:[/bold cyan]") console.print() console.print(" [bold]Enter[/bold] Submit your prompt") console.print(" [bold]Shift+Enter[/bold] Add a new line (multiline input)") console.print(" [bold]Option/Alt+Enter[/bold] Alternate shortcut for new line") console.print(" [bold]Ctrl+C[/bold] Cancel input (press twice to exit)") console.print(" [bold]Ctrl+D[/bold] Exit Promptheus") console.print() console.print("[dim]Tip: Type / then Tab to see all available commands[/dim]") console.print() def show_about(console, app_config: Config) -> None: """Display version and system information.""" import platform import sys console.print() console.print("[bold cyan]Promptheus - AI-powered Prompt Engineering[/bold cyan]") console.print() console.print(f" [bold]Version:[/bold] {VERSION}") console.print(f" [bold]GitHub:[/bold] {GITHUB_REPO}") console.print() console.print("[bold cyan]System Information:[/bold cyan]") console.print() console.print(f" [bold]Python:[/bold] {sys.version.split()[0]}") console.print(f" [bold]Platform:[/bold] {platform.system()} {platform.release()}") console.print() console.print("[bold cyan]Current Configuration:[/bold cyan]") console.print() console.print(f" [bold]Provider:[/bold] {app_config.provider or 'auto-detect'}") console.print(f" [bold]Model:[/bold] {app_config.get_model() or 'default'}") configured = app_config.get_configured_providers() if configured: console.print(f" [bold]Available:[/bold] {', '.join(configured)}") console.print() def show_bug_report(console) -> None: """Display bug report information and optionally open GitHub issues.""" import webbrowser import questionary console.print() console.print("[bold cyan]Bug Report[/bold cyan]") console.print() console.print("Found a bug? We'd love to hear about it!") console.print() console.print(f" [bold]Report issues at:[/bold] {GITHUB_ISSUES}") console.print() try: open_browser = questionary.confirm( "Open GitHub issues in your browser?", default=True, ).ask() if open_browser: webbrowser.open(GITHUB_ISSUES) console.print("[green]✓[/green] Opened in browser") else: console.print("[yellow]Cancelled[/yellow]") except KeyboardInterrupt: console.print("[yellow]Cancelled[/yellow]") console.print() def show_status(console, app_config: Config, args: Namespace) -> None: """Display current session settings.""" console.print() console.print("[bold cyan]Current Session Settings:[/bold cyan]") console.print() console.print(f" [bold]Provider:[/bold] {app_config.provider or 'auto-detect'}") console.print(f" [bold]Model:[/bold] {app_config.get_model() or 'default'}") console.print() console.print("[bold cyan]Active Modes:[/bold cyan]") console.print() console.print(f" [bold]Skip questions:[/bold] {'ON' if getattr(args, 'skip_questions', False) else 'OFF'}") console.print(f" [bold]Refine mode:[/bold] {'ON' if args.refine else 'OFF'}") console.print() configured = app_config.get_configured_providers() if configured: console.print(f" [bold]Available providers:[/bold] {', '.join(configured)}") console.print() def handle_session_command( command_str: str, app_config: Config, args: Namespace, console, notify: MessageSink, ) -> Optional[str]: """ Handle in-session commands like /set, /toggle, /status. Returns: 'reload_provider' if the provider needs to be reloaded, 'handled' if the command was handled but doesn't need reload, None if this is not a session command """ parts = command_str.strip().split() if not parts: return None command = parts[0][1:].lower() # Remove the '/' and normalize if command == "set": if len(parts) < 3: notify("[yellow]Usage: /set provider <name> or /set model <name>[/yellow]") return "handled" setting = parts[1].lower() value = parts[2] if setting == "provider": configured = app_config.get_configured_providers() if value not in configured: notify(f"[red]✗[/red] Provider '{value}' is not configured or available") notify(f"[dim]Available providers: {', '.join(configured)}[/dim]") return "handled" app_config.set_provider(value) notify(f"[green]✓[/green] Provider set to '{value}'") return "reload_provider" elif setting == "model": app_config.set_model(value) notify(f"[green]✓[/green] Model set to '{value}'") return "reload_provider" else: notify(f"[yellow]Unknown setting: {setting}. Use 'provider' or 'model'.[/yellow]") return "handled" elif command == "toggle": if len(parts) < 2: notify("[yellow]Usage: /toggle refine or /toggle skip-questions[/yellow]") return "handled" mode = parts[1].lower() if mode == "refine": args.refine = not args.refine if args.refine: args.skip_questions = False # Mutually exclusive status = "ON" if args.refine else "OFF" notify(f"[green]✓[/green] Refine mode is now {status}") return "handled" elif mode == "skip-questions": args.skip_questions = not args.skip_questions if args.skip_questions: args.refine = False # Mutually exclusive status = "ON" if args.skip_questions else "OFF" notify(f"[green]✓[/green] Skip-questions mode is now {status}") return "handled" else: notify(f"[yellow]Unknown mode: {mode}. Use 'refine' or 'skip-questions'.[/yellow]") return "handled" elif command == "status": show_status(console, app_config, args) return "handled" else: # Not a session command, return None to let the existing handler deal with it return None def reload_provider_instance( app_config: Config, console, notify: MessageSink, ) -> Optional[LLMProvider]: """ Reload the provider instance based on current config. Returns: New provider instance, or None if initialization failed """ provider_name = app_config.provider or "google" model_name = app_config.get_model() try: with console.status(f"[bold blue]🚀 Initializing {provider_name}...", spinner="aesthetic"): new_provider = get_provider(provider_name, app_config, model_name) notify(f"[green]✓[/green] Successfully initialized {provider_name} with model {model_name}") return new_provider except Exception as exc: sanitized = sanitize_error_message(str(exc)) notify(f"[red]✗[/red] Failed to initialize provider: {sanitized}") logger.exception("Provider reload failed") return None

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/abhichandra21/Promptheus'

If you have feedback or need assistance with the MCP directory API, please join our Discord server