import argparse import sys from pathlib import Path from typing import List, Optional from .configs import OllamaConfig, ReviewConfig, create_config_from_vars from .logger import log_paths, log_review_start def normalize_server_url(url: str) -> str: """Normalize Ollama server URL to ensure proper format.""" if not url.startswith(("http://", "https://")): return f"http://{url}" return url.rstrip("/") def create_argument_parser() -> argparse.ArgumentParser: """Create and configure the argument parser.""" parser = argparse.ArgumentParser( prog="reviewllama", description="AI-powered code review assistant", formatter_class=argparse.RawDescriptionHelpFormatter, epilog=""" Examples: reviewllama . --model gemma3:27b --server localhost:11434 reviewllama src/ tests/ --model llama3.2:7b --timeout 60 """, ) parser.add_argument( "paths", nargs="+", metavar="PATH", help="One or more file paths or git directories to review", ) parser.add_argument( "--model", default="llama3.2:3b", help="Ollama model to use for code review (default: %(default)s)", ) parser.add_argument( "--server", dest="server_url", default="localhost:11434", help="Ollama server URL (default: %(default)s)", ) parser.add_argument( "--timeout", type=int, default=30, help="Request timeout in seconds (default: %(default)s)", ) parser.add_argument( "--max-retries", dest="max_retries", type=int, default=3, help="Maximum number of retry attempts (default: %(default)s)", ) return parser def parse_raw_arguments(args: Optional[List[str]] = None) -> argparse.Namespace: """Parse command line arguments into raw namespace.""" parser = create_argument_parser() return parser.parse_args(args) def transform_namespace_to_config(namespace: argparse.Namespace) -> ReviewConfig: """Transform argparse namespace into ReviewConfig.""" paths = [Path(path_str) for path_str in namespace.paths] return create_config_from_vars( paths=paths, model=namespace.model, server_url=normalize_server_url(namespace.server_url), timeout=namespace.timeout, max_retries=namespace.max_retries, ) def parse_arguments(args: Optional[List[str]] = None) -> ReviewConfig: """Parse command line arguments and return validated configuration.""" raw_namespace = parse_raw_arguments(args) return transform_namespace_to_config(raw_namespace) def cli() -> None: """Main entry point for the CLI.""" try: config = parse_arguments() # TODO: Pass config to review engine log_review_start(config) log_paths(config.paths) except SystemExit: # argparse calls sys.exit on error, let it propagate raise except Exception as e: print(f"Error: {e}", file=sys.stderr) sys.exit(1)