refactor: add markdown frontend
This commit is contained in:
@@ -12,12 +12,30 @@ 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.frontends.admin import AdminFrontend
|
||||
from beaver_gateway.frontends.anthropic import AnthropicMessagesFrontend
|
||||
from beaver_gateway.frontends.markdown import MarkdownFrontend
|
||||
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.
|
||||
|
||||
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
|
||||
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.
|
||||
"""
|
||||
today = date.today()
|
||||
topic = slugify(record.first_user_text, maxlen=40)
|
||||
return vault / f"{today:%Y-%m}" / f"{today:%Y-%m-%d}_{topic}.md"
|
||||
|
||||
|
||||
def current_time() -> str:
|
||||
"""Return the current local time as an ISO-8601 string.
|
||||
|
||||
@@ -162,5 +180,45 @@ gateway = Gateway(
|
||||
# `messages` only work on `/v1/messages`; `mcp` only on
|
||||
# `/mcp/<name>`; `*` works everywhere.
|
||||
AdminFrontend(host="0.0.0.0", port=8002),
|
||||
# Obsidian-vault chat frontend. Each `.md` is one conversation
|
||||
# (User/Assistant turn pairs). The Obsidian companion plugin
|
||||
# POSTs `{filename, content?}` to `/chat` — the frontend reads
|
||||
# the file, runs the agent if the last turn is `user`, and
|
||||
# appends the assistant reply back. With `log_all_chats=True`
|
||||
# *every* turn (from Anthropic Messages too) is mirrored into
|
||||
# `{vault}/_logs/<agent>/` so the vault is the central archive.
|
||||
#
|
||||
# `vault_path` here points at a per-restart tempdir so the
|
||||
# example boots cleanly; in real deployments mount the
|
||||
# Obsidian-sync container's vault volume to a stable path and
|
||||
# pass that instead.
|
||||
MarkdownFrontend(
|
||||
host="0.0.0.0",
|
||||
port=8003,
|
||||
# Point at the dedicated chats subdir of your real Obsidian
|
||||
# vault — the gateway has no idea (and no need) about other
|
||||
# notes outside it. Path resolution / vault-escape checks
|
||||
# are anchored here, so absolute-path attempts (and ``..``
|
||||
# tricks) can't reach notes alongside it.
|
||||
#
|
||||
# vault_path=Path("/Users/me/Obsidian/Personal/chats"),
|
||||
#
|
||||
# Per-restart tempdir kept here so the example boots even
|
||||
# without a real vault on the host.
|
||||
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,
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user