refactor(agents,core,frontends): typed kinds, prompts per kind, frontend agents as parameters

This commit is contained in:
hh
2026-08-28 16:36:44 +02:00
parent 827fa0977b
commit 70349e5ff4
11 changed files with 129 additions and 50 deletions
+24 -11
View File
@@ -22,7 +22,8 @@ from sqlalchemy import select as sa_select
from sqlmodel import col
from beaver_gateway.core import audit
from beaver_gateway.core.conversations import KINDS, SEEDS
from beaver_gateway.core.conversations import SEEDS
from beaver_gateway.core.kinds import Kind, as_kind
from beaver_gateway.frontends._auth import require_token
from beaver_gateway.frontends._sse import (
KEEPALIVE,
@@ -34,7 +35,7 @@ from beaver_gateway.frontends.base import Frontend
from beaver_gateway.storage.models import Usage
if TYPE_CHECKING:
from collections.abc import AsyncIterator, Mapping
from collections.abc import AsyncIterator
from beaver_gateway.core.conversations import Conversations
from beaver_gateway.frontends.base import GatewayRuntime
@@ -57,16 +58,27 @@ class ApiFrontend(Frontend):
host: str = "0.0.0.0", # noqa: S104
port: int = 8004,
public_base_url: str | None = None,
default_agents: Mapping[str, str] | None = None,
master_agent: str | None = None,
branch_agent: str | None = None,
deep_agent: str | None = None,
job_agent: str | None = None,
) -> None:
self.host = host
self.port = port
self.public_base_url = public_base_url.rstrip("/") if public_base_url else None
self.default_agents = dict(default_agents or {})
self.master_agent = master_agent
self.branch_agent = branch_agent
self.deep_agent = deep_agent
self.job_agent = job_agent
self._app: FastAPI | None = None
def agent_for(self, kind: str) -> str | None:
return self.default_agents.get(kind)
def agent_for(self, kind: Kind) -> str | None:
return {
"master": self.master_agent,
"branch": self.branch_agent,
"deep": self.deep_agent,
"job": self.job_agent,
}.get(kind)
def configure(self, runtime: GatewayRuntime) -> None:
if runtime.conversations is None or runtime.bus is None:
@@ -175,12 +187,13 @@ def _build_app(runtime: GatewayRuntime) -> FastAPI: # noqa: PLR0915
async def create_conversation(request: Request) -> dict[str, Any]:
token = await require_token(request, runtime, scope=SCOPE)
data = await body_of(request)
kind = str(data.get("kind") or "deep")
agent = data.get("agent")
if kind not in KINDS or kind == "fork":
raise HTTPException(
status.HTTP_400_BAD_REQUEST, f"kind must be one of {KINDS[:-1]}"
)
try:
kind = as_kind(str(data.get("kind") or "deep"))
except ValueError as exc:
raise HTTPException(status.HTTP_400_BAD_REQUEST, str(exc)) from exc
if kind == "fork":
raise HTTPException(status.HTTP_400_BAD_REQUEST, "fork is internal")
if agent is not None and (
not isinstance(agent, str) or agent not in runtime.agents
):