feat: one gateway port with path-mounted frontends, markdown chat, collapsible sidebars

This commit is contained in:
hh
2026-08-29 00:49:06 +02:00
parent 540327efa1
commit 16b6bbddda
32 changed files with 691 additions and 441 deletions
+15 -30
View File
@@ -144,41 +144,27 @@ gateway = Gateway(
# Anthropic-compatible Messages endpoint. Auth comes from
# `BOOTSTRAP_TOKENS` in the env (`name1:value1,name2:value2`).
#
# Behind a reverse proxy (Caddy / nginx / Cloudflare) pass
# `public_base_url=` so the admin dashboard advertises the
# outside URL instead of `host:port`. Caddy strips its own
# prefix and the frontend's internal paths (`/v1/messages`,
# `/v1/models`) get appended:
# Caddy: handle_path /ai/* { reverse_proxy localhost:8000 }
# Config: AnthropicMessagesFrontend(
# port=8000,
# public_base_url="https://domain.com/ai")
# Result: https://domain.com/ai/v1/messages
AnthropicMessagesFrontend(host="0.0.0.0", port=8000),
# Every HTTP frontend is mounted under its own path on the one
# gateway port (`Gateway.port`, 8000 here): `/anthropic/v1/messages`.
# Behind a reverse proxy set `Gateway(public_url="https://domain.com")`
# so advertised endpoints use the outside origin; the proxy just
# forwards everything to the gateway, no prefix stripping.
AnthropicMessagesFrontend(),
# Phase 3 — re-exposes every declared `McpServer` outside the
# gateway with bearer auth + audit log. Each namespace lives
# at `/<name>/` on this port (the port itself disambiguates
# MCP traffic — no extra `/mcp` segment in the route); a flat
# bundle is published at `/all/`. Discovery page (HTML,
# auth-gated) at `/` with copy-pastable Cursor / Claude
# Desktop snippets. Auth re-uses `BOOTSTRAP_TOKENS`.
#
# Same `public_base_url=` knob as above. Caddy strips its
# prefix; the frontend's `/<name>/` segment gets appended:
# Caddy: handle_path /mcp/* { reverse_proxy localhost:8001 }
# Config: McpServerFrontend(
# port=8001,
# public_base_url="https://domain.com/mcp")
# Result: https://domain.com/mcp/<name>/ (and /mcp/all/)
McpServerFrontend(host="0.0.0.0", port=8001),
# gateway with bearer auth + audit log. Each namespace lives at
# `/mcp/<name>/`; a flat bundle is published at `/mcp/all/`.
# Discovery page (HTML, auth-gated) at `/mcp/` with copy-pastable
# Cursor / Claude Desktop snippets. Auth re-uses `BOOTSTRAP_TOKENS`.
McpServerFrontend(),
# Phase 4.3 — browser admin UI. Creds come from
# `ADMIN_USER`/`ADMIN_PASS`; the session cookie is signed with
# `SESSION_SECRET`. Use it to mint tokens (Argon2-hashed in
# the DB), revoke them, and watch the audit log. Scope is
# enforced on the bearer frontends: tokens minted with scope
# `messages` only work on `/v1/messages`; `mcp` only on
# `/mcp/<name>`; `*` works everywhere.
AdminFrontend(host="0.0.0.0", port=8002),
# `/mcp/<name>`; `*` works everywhere. Served at `/admin/`; `/`
# redirects there.
AdminFrontend(),
# 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
@@ -191,9 +177,8 @@ gateway = Gateway(
# example boots cleanly; in real deployments mount the
# Obsidian-sync container's vault volume to a stable path and
# pass that instead.
# Mounted at `/md` (`/md/chat`, `/md/chat/stream`).
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