fischer-agentkit/src/agentkit/cli/main.py

147 lines
5.3 KiB
Python

"""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)