feat: one gateway port with path-mounted frontends, markdown chat, collapsible sidebars
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
"""Frontend ABC + the runtime context handed to ``configure``.
|
||||
|
||||
A frontend is anything that listens on a port and routes inbound traffic
|
||||
into the gateway. ``GatewayRuntime`` carries everything a frontend may
|
||||
need that isn't user-config: built registries, per-agent backends, and
|
||||
the in-memory token store. The user's ``/config/config.py`` defines a
|
||||
``Gateway`` (lists); ``cli.main`` turns that into a ``GatewayRuntime``
|
||||
and hands it to each frontend's ``configure``.
|
||||
A frontend is anything that routes inbound traffic into the gateway: an
|
||||
HTTP surface mounted under its ``path`` on the single gateway port
|
||||
(``frontends/root.py``), a poller (Telegram), or both. ``GatewayRuntime``
|
||||
carries everything a frontend may need that isn't user-config: built
|
||||
registries, per-agent backends, and the in-memory token store. The
|
||||
user's ``/config/config.py`` defines a ``Gateway`` (lists); ``cli.main``
|
||||
turns that into a ``GatewayRuntime`` and hands it to each frontend's
|
||||
``configure``.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -17,6 +19,8 @@ from typing import TYPE_CHECKING, Any
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Awaitable, Callable, Mapping, Sequence
|
||||
|
||||
from starlette.types import ASGIApp
|
||||
|
||||
from beaver_gateway.backends.base import Backend
|
||||
from beaver_gateway.core.auth import TokenStore
|
||||
from beaver_gateway.core.kinds import Kind
|
||||
@@ -85,10 +89,20 @@ class GatewayRuntime:
|
||||
conversations: Any = None
|
||||
bus: Any = None
|
||||
pool: Any = None
|
||||
# External origin the reverse proxy puts in front of the gateway
|
||||
# (``Gateway.public_url``); ``None`` means "derive from the request".
|
||||
public_url: str | None = None
|
||||
|
||||
|
||||
class Frontend(ABC):
|
||||
"""Listens on a port, dispatches into the gateway.
|
||||
"""Routes inbound traffic into the gateway.
|
||||
|
||||
HTTP frontends set ``path`` and return their ASGI app from ``app()``;
|
||||
``cli`` mounts every such app under that path on the one gateway
|
||||
port, so ``/anthropic/v1/messages`` reaches the Anthropic frontend's
|
||||
``/v1/messages``. ``serve()`` is for work outside HTTP - polling,
|
||||
vault mirrors - and defaults to nothing. ``landing`` marks the app
|
||||
that ``/`` redirects to (the admin console).
|
||||
|
||||
A frontend that shows conversations declares ``name`` (the binding
|
||||
key) and ``kinds`` (which conversation kinds it shows);
|
||||
@@ -103,12 +117,17 @@ class Frontend(ABC):
|
||||
|
||||
name: str = ""
|
||||
kinds: tuple[Kind, ...] = ()
|
||||
path: str | None = None
|
||||
landing: bool = False
|
||||
|
||||
@abstractmethod
|
||||
def configure(self, runtime: GatewayRuntime) -> None: ...
|
||||
|
||||
@abstractmethod
|
||||
async def serve(self) -> None: ...
|
||||
def app(self) -> ASGIApp | None:
|
||||
return None
|
||||
|
||||
async def serve(self) -> None:
|
||||
return
|
||||
|
||||
def agent_for(self, kind: Kind) -> str | None: # noqa: ARG002
|
||||
return None
|
||||
|
||||
Reference in New Issue
Block a user