Skip to content

ccproxy.cli.commands

ccproxy.cli.commands

Command modules for CCProxy API CLI.

api

api(
    config=None,
    port=None,
    host=None,
    reload=None,
    log_level=None,
    log_file=None,
    auth_token=None,
    enable_plugin=None,
    disable_plugin=None,
)

Start the CCProxy API server.

Source code in ccproxy/cli/commands/serve.py
def api(
    config: Annotated[
        Path | None,
        typer.Option(
            "--config",
            "-c",
            help="Path to configuration file (TOML, JSON, or YAML)",
            exists=True,
            file_okay=True,
            dir_okay=False,
            readable=True,
            rich_help_panel="Configuration",
        ),
    ] = None,
    port: Annotated[
        int | None,
        typer.Option(
            "--port",
            "-p",
            help="Port to run the server on",
            callback=validate_port,
            rich_help_panel="Server Settings",
        ),
    ] = None,
    host: Annotated[
        str | None,
        typer.Option(
            "--host",
            "-h",
            help="Host to bind the server to",
            rich_help_panel="Server Settings",
        ),
    ] = None,
    reload: Annotated[
        bool | None,
        typer.Option(
            "--reload/--no-reload",
            help="Enable auto-reload for development",
            rich_help_panel="Server Settings",
        ),
    ] = None,
    log_level: Annotated[
        str | None,
        typer.Option(
            "--log-level",
            help="Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL). Use WARNING for minimal output.",
            callback=validate_log_level,
            rich_help_panel="Server Settings",
        ),
    ] = None,
    log_file: Annotated[
        str | None,
        typer.Option(
            "--log-file",
            help="Path to JSON log file. If specified, logs will be written to this file in JSON format",
            rich_help_panel="Server Settings",
        ),
    ] = None,
    auth_token: Annotated[
        str | None,
        typer.Option(
            "--auth-token",
            help="Bearer token for API authentication",
            callback=validate_auth_token,
            rich_help_panel="Security Settings",
        ),
    ] = None,
    enable_plugin: Annotated[
        list[str] | None,
        typer.Option(
            "--enable-plugin",
            help="Enable a plugin by name (repeatable)",
            rich_help_panel="Plugin Settings",
        ),
    ] = None,
    disable_plugin: Annotated[
        list[str] | None,
        typer.Option(
            "--disable-plugin",
            help="Disable a plugin by name (repeatable)",
            rich_help_panel="Plugin Settings",
        ),
    ] = None,
    # Removed unused flags: plugin_setting, no_network_calls,
    # disable_version_check, disable_pricing_updates
) -> None:
    """Start the CCProxy API server."""
    try:
        if config is None:
            config = get_config_path_from_context()

        # Base CLI context; plugin-injected args merged below
        cli_context = {
            "port": port,
            "host": host,
            "reload": reload,
            "log_level": log_level,
            "log_file": log_file,
            "auth_token": auth_token,
            "enabled_plugins": enable_plugin,
            "disabled_plugins": disable_plugin,
        }

        # Merge plugin-provided CLI args via helper
        try:
            from ccproxy.cli.helpers import get_plugin_cli_args

            plugin_args = get_plugin_cli_args()
            if plugin_args:
                cli_context.update(plugin_args)
        except Exception:
            pass

        # Pass CLI context to settings creation
        settings = Settings.from_config(config_path=config, cli_context=cli_context)

        setup_logging(
            json_logs=settings.logging.format == "json",
            log_level_name=settings.logging.level,
            log_file=settings.logging.file,
        )

        logger = get_logger(__name__)

        logger.debug(
            "configuration_loaded",
            host=settings.server.host,
            port=settings.server.port,
            log_level=settings.logging.level,
            log_file=settings.logging.file,
            auth_enabled=bool(settings.security.auth_token),
            duckdb_enabled=bool(
                (settings.plugins.get("duckdb_storage") or {}).get("enabled", False)
            ),
        )

        _run_local_server(settings)

    except ConfigurationError as e:
        toolkit = get_rich_toolkit()
        toolkit.print(f"Configuration error: {e}", tag="error")
        raise typer.Exit(1) from e
    except OSError as e:
        toolkit = get_rich_toolkit()
        toolkit.print(
            f"Server startup failed (port/permission issue): {e}", tag="error"
        )
        raise typer.Exit(1) from e
    except ImportError as e:
        toolkit = get_rich_toolkit()
        toolkit.print(f"Import error during server startup: {e}", tag="error")
        raise typer.Exit(1) from e
    except Exception as e:
        toolkit = get_rich_toolkit()
        toolkit.print(f"Error starting server: {e}", tag="error")
        raise typer.Exit(1) from e