import argparse import asyncio import logging import os import sys from typing import Optional logger = logging.getLogger(__name__) try: from core import R2RApp, R2RBuilder, R2RConfig from core.utils.logging_config import configure_logging except ImportError as e: logger.error( f"Failed to start server: core dependencies not installed: {e}" ) logger.error("To run the server, install the required dependencies:") logger.error("pip install 'r2r[core]'") sys.exit(1) async def create_app( config_name: Optional[str] = None, config_path: Optional[str] = None, full: bool = False, ) -> "R2RApp": """ Creates and returns an R2R application instance based on the provided or environment-sourced configuration. """ # If arguments not passed, fall back to environment variables config_name = config_name or os.getenv("R2R_CONFIG_NAME") config_path = config_path or os.getenv("R2R_CONFIG_PATH") if config_path and config_name: raise ValueError( f"Cannot specify both config_path and config_name, got {config_path} and {config_name}" ) if not config_path and not config_name: # If neither is specified nor set in environment, # default to 'full' if --full is True, else 'default' config_name = "full" if full else "default" try: r2r_instance = await R2RBuilder( config=R2RConfig.load(config_name, config_path) ).build() # Start orchestration worker await r2r_instance.orchestration_provider.start_worker() return r2r_instance except ImportError as e: logger.error(f"Failed to initialize R2R: {e}") logger.error( "Please check your configuration and installed dependencies" ) sys.exit(1) def run_server( host: Optional[str] = None, port: Optional[int] = None, config_name: Optional[str] = None, config_path: Optional[str] = None, full: bool = False, ): """ Runs the R2R server with the provided or environment-based settings. """ # Overwrite environment variables if arguments are explicitly passed if host is not None: os.environ["R2R_HOST"] = host if port is not None: os.environ["R2R_PORT"] = str(port) if config_path is not None: os.environ["R2R_CONFIG_PATH"] = config_path if config_name is not None: os.environ["R2R_CONFIG_NAME"] = config_name # Fallback to environment or defaults if necessary final_host = os.getenv("R2R_HOST", "0.0.0.0") final_port = int(os.getenv("R2R_PORT", "7272")) try: configure_logging() except Exception as e: logger.error(f"Failed to configure logging: {e}") try: async def start(): app = await create_app(config_name, config_path, full) await app.serve(final_host, final_port) asyncio.run(start()) except Exception as e: logger.error(f"Failed to start R2R server: {e}") sys.exit(1) def main(): """ Parse command-line arguments and then run the server. """ parser = argparse.ArgumentParser(description="Run the R2R server.") parser.add_argument( "--host", default=None, help="Host to bind to. Overrides R2R_HOST env if provided.", ) parser.add_argument( "--port", default=None, type=int, help="Port to bind to. Overrides R2R_PORT env if provided.", ) parser.add_argument( "--config-path", default=None, help="Path to the configuration file. Overrides R2R_CONFIG_PATH env if provided.", ) parser.add_argument( "--config-name", default=None, help="Name of the configuration. Overrides R2R_CONFIG_NAME env if provided.", ) parser.add_argument( "--full", action="store_true", help="Use the 'full' config if neither config-path nor config-name is specified.", ) args = parser.parse_args() run_server( host=args.host, port=args.port, config_name=args.config_name, config_path=args.config_path, full=args.full, ) if __name__ == "__main__": main()