feat(core,frontends,agents): agent kinds, frontend routing, anthropic on conversations, vault mirror

This commit is contained in:
hh
2026-08-28 03:50:33 +02:00
parent e3074c266a
commit 827fa0977b
17 changed files with 1009 additions and 292 deletions
+16 -21
View File
@@ -12,7 +12,7 @@ from beaver_gateway.agents.base import ExposedMcp
from beaver_gateway.agents.claude import ClaudeAgent
from beaver_gateway.agents.raycast import RaycastAgent, RemoteTool, UserPreferences
from beaver_gateway.core.registry import Gateway
from beaver_gateway.core.turn_record import TurnRecord, slugify
from beaver_gateway.core.turn_record import slugify
from beaver_gateway.frontends.admin import AdminFrontend
from beaver_gateway.frontends.anthropic import AnthropicMessagesFrontend
from beaver_gateway.frontends.markdown import MarkdownFrontend
@@ -20,20 +20,19 @@ from beaver_gateway.frontends.mcp_server import McpServerFrontend
from beaver_gateway.mcp.types import McpServer
def chat_log_path(record: TurnRecord, vault: Path) -> Path:
"""Decide where a logged chat from another frontend lands in the vault.
def chat_path(title: str, agent: str, vault: Path) -> Path: # noqa: ARG001
"""Where a new chat file lands in the vault.
Called by ``MarkdownFrontend`` (with ``log_all_chats=True``) the first
time a conversation needs a file — continuation turns are matched by
fingerprint and stick to the file picked here. Return value can be
Called by ``MarkdownFrontend`` for every conversation that needs a
file: a ``deep`` chat spawned by the dispatcher, a ``/v1/messages``
chat (``title`` = first user message), or with ``log_all_chats=True``
the archive of a stateless agent's turns. Return value can be
absolute or relative; relative paths are anchored under ``vault``.
Layout below: ``<vault>/<YYYY-MM>/<YYYY-MM-DD>_<topic>.md`` where
``topic`` is a slug of the very first user message in the chat.
Layout below: ``<vault>/<YYYY-MM>/<YYYY-MM-DD>_<topic>.md``.
"""
today = date.today()
topic = slugify(record.first_user_text, maxlen=40)
return vault / f"{today:%Y-%m}" / f"{today:%Y-%m-%d}_{topic}.md"
return vault / f"{today:%Y-%m}" / f"{today:%Y-%m-%d}_{slugify(title, maxlen=40)}.md"
def current_time() -> str:
@@ -208,17 +207,13 @@ gateway = Gateway(
vault_path=Path(tempfile.mkdtemp(prefix="beaver-vault-")).resolve(),
default_agent="research",
log_all_chats=True,
# ``log_path`` (optional) overrides the default
# ``{vault}/_logs/<agent>/<date>_<hex>.md`` layout for chats
# logged from OTHER frontends (Anthropic Messages, admin
# in-browser chat). Defined as a top-of-file function so the
# types are explicit and the IDE can hover them; a lambda
# works too, but a real ``def`` keeps the signature visible
# and lets you docstring it. Heads up: any custom path
# forces ``warm_index`` to scan the entire vault on startup
# so the fingerprint→file map survives a restart no matter
# where you put files.
log_path=chat_log_path,
# ``chat_path`` (optional) overrides the default
# ``{vault}/_logs/<agent>/<date>_<slug>.md`` layout. Heads up:
# any custom path forces ``warm_index`` to scan the entire
# vault on startup so the fingerprint→file map of archived
# stateless chats survives a restart no matter where you put
# files.
chat_path=chat_path,
),
],
)