"""AgentKit CLI main entry point""" from typing import Optional import typer from rich import print as rprint app = typer.Typer( name="agentkit", help="AgentKit - Unified Agent Framework CLI", no_args_is_help=True, ) from agentkit.cli.task import task_app # noqa: E402 app.add_typer(task_app, name="task") from agentkit.cli.skill import skill_app # noqa: E402 app.add_typer(skill_app, name="skill") from agentkit.cli.init import init # noqa: E402 app.command(name="init")(init) from agentkit.cli.usage import usage # noqa: E402 app.command(name="usage")(usage) from agentkit.cli.pair import pair # noqa: E402 app.command(name="pair")(pair) @app.command() def serve( host: str = typer.Option("0.0.0.0", "--host", help="Server host"), port: int = typer.Option(8001, "--port", help="Server port"), workers: int = typer.Option(1, "--workers", help="Number of workers"), reload: bool = typer.Option(False, "--reload", help="Enable auto-reload"), config: Optional[str] = typer.Option(None, "--config", help="Path to agentkit.yaml"), task_store_backend: Optional[str] = typer.Option(None, "--task-store-backend", help="Task store backend: memory or redis"), task_store_redis_url: Optional[str] = typer.Option(None, "--task-store-redis-url", help="Redis URL for task store (only used when backend=redis)"), ): """Start the AgentKit server""" import uvicorn from agentkit.server.config import ServerConfig, find_config_path # Load .env file if present config_path = find_config_path(config) if config_path: rprint(f"[green]Loading config from {config_path}[/green]") server_config = ServerConfig.from_yaml(config_path) # Load .env file for env var resolution from pathlib import Path dotenv = Path(config_path).parent / ".env" server_config.load_dotenv(str(dotenv)) # Re-load config after .env is loaded (env vars now available) server_config = ServerConfig.from_yaml(config_path) # CLI args override config file for task_store if task_store_backend is not None: server_config.task_store["backend"] = task_store_backend if task_store_redis_url is not None: server_config.task_store["redis_url"] = task_store_redis_url # CLI args override config file effective_host = host if host != "0.0.0.0" else server_config.host effective_port = port if port != 8001 else server_config.port effective_workers = workers if workers != 1 else server_config.workers # Store config for app factory import os import json as _json os.environ["AGENTKIT_CONFIG_PATH"] = config_path # Pass task_store overrides via env var so create_app can read them if server_config.task_store: os.environ["AGENTKIT_TASK_STORE"] = _json.dumps(server_config.task_store) rprint(f"[green]LLM providers: {list(server_config.llm_config.providers.keys())}[/green]") rprint(f"[green]Skill paths: {server_config.skill_paths}[/green]") ts_backend = server_config.task_store.get("backend", "memory") rprint(f"[green]Task store backend: {ts_backend}[/green]") else: rprint("[yellow]No agentkit.yaml found, using defaults[/yellow]") effective_host = host effective_port = port effective_workers = workers # Apply CLI task_store overrides even without config file import os import json as _json ts_override: dict = {} if task_store_backend is not None: ts_override["backend"] = task_store_backend if task_store_redis_url is not None: ts_override["redis_url"] = task_store_redis_url if ts_override: os.environ["AGENTKIT_TASK_STORE"] = _json.dumps(ts_override) rprint(f"[green]Starting AgentKit Server on {effective_host}:{effective_port}[/green]") uvicorn.run( "agentkit.server.app:create_app", host=effective_host, port=effective_port, workers=effective_workers, reload=reload, factory=True, ) @app.command() def version(): """Show AgentKit version""" try: from importlib.metadata import version as get_version v = get_version("fischer-agentkit") except Exception: v = "0.1.0 (dev)" rprint(f"AgentKit v{v}") @app.command() def doctor( host: str = typer.Option("localhost", "--host", help="Server host"), port: int = typer.Option(8001, "--port", help="Server port"), ): """Diagnose AgentKit server health and configuration""" import httpx url = f"http://{host}:{port}/api/v1/health" try: with httpx.Client(timeout=5.0) as client: response = client.get(url) if response.status_code == 200: data = response.json() rprint(f"[green]Server is healthy[/green]: {data}") else: rprint(f"[red]Server returned status {response.status_code}[/red]") raise typer.Exit(code=1) except httpx.ConnectError: rprint(f"[red]Cannot connect to AgentKit server at {url}[/red]") rprint("[dim]Is the server running? Start it with: agentkit serve[/dim]") raise typer.Exit(code=1) except Exception as e: rprint(f"[red]Health check failed: {e}[/red]") raise typer.Exit(code=1)