147 lines
5.3 KiB
Python
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)
|