refactor(agents,core,frontends): typed kinds, prompts per kind, frontend agents as parameters
This commit is contained in:
@@ -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
|
||||
):
|
||||
|
||||
@@ -19,6 +19,7 @@ if TYPE_CHECKING:
|
||||
|
||||
from beaver_gateway.backends.base import Backend
|
||||
from beaver_gateway.core.auth import TokenStore
|
||||
from beaver_gateway.core.kinds import Kind
|
||||
from beaver_gateway.core.registry import AgentRegistry, McpRegistry
|
||||
from beaver_gateway.core.turn_record import TurnRecord
|
||||
from beaver_gateway.storage import Database
|
||||
@@ -101,7 +102,7 @@ class Frontend(ABC):
|
||||
"""
|
||||
|
||||
name: str = ""
|
||||
kinds: tuple[str, ...] = ()
|
||||
kinds: tuple[Kind, ...] = ()
|
||||
|
||||
@abstractmethod
|
||||
def configure(self, runtime: GatewayRuntime) -> None: ...
|
||||
@@ -109,7 +110,7 @@ class Frontend(ABC):
|
||||
@abstractmethod
|
||||
async def serve(self) -> None: ...
|
||||
|
||||
def agent_for(self, kind: str) -> str | None: # noqa: ARG002
|
||||
def agent_for(self, kind: Kind) -> str | None: # noqa: ARG002
|
||||
return None
|
||||
|
||||
async def materialize(self, conv: Conversation) -> ConversationBinding | None: # noqa: ARG002
|
||||
|
||||
@@ -76,6 +76,7 @@ from beaver_gateway.frontends.markdown.mirror import FRONTEND, ChatMirror
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import AsyncIterator, Callable
|
||||
|
||||
from beaver_gateway.core.kinds import Kind
|
||||
from beaver_gateway.frontends.base import GatewayRuntime
|
||||
from beaver_gateway.storage.models import Conversation, ConversationBinding
|
||||
|
||||
@@ -173,7 +174,7 @@ class MarkdownFrontend(Frontend):
|
||||
raise RuntimeError(msg)
|
||||
return self._mirror
|
||||
|
||||
def agent_for(self, kind: str) -> str | None:
|
||||
def agent_for(self, kind: Kind) -> str | None:
|
||||
return self.default_agent if kind == "deep" else None
|
||||
|
||||
async def materialize(self, conv: Conversation) -> ConversationBinding | None:
|
||||
|
||||
Reference in New Issue
Block a user