- Mount FastMCP at /mcp with tools for notebook CRUD, simulation,
and cell execution. Includes status resource and circuit_assistant
prompt.
- Add SSE streaming chat endpoint at /api/chat/stream backed by
GPU LLM gateway (qwen3). Chat widget sends notebook context
(SPICE cells, markdown notes) so the assistant can reference the
user's circuit.
- React floating chat panel with zustand-persisted conversation
history, streaming token display, reasoning collapse, and
keyboard shortcuts.
- Refactor main.py from deprecated on_event("startup") to lifespan
context manager with combine_lifespans for MCP integration.
- Add notebook_id path traversal validation, decouple get_engine()
from HTTPException for MCP compatibility, fix HTTP client init
race condition with asyncio.Lock.
- Update Caddy labels for /mcp/* routing and SSE streaming on
backend reverse proxy.
Without flush_interval: -1, Caddy buffers SSR responses and can
truncate large pages (380KB homepage was cut to 70KB, dropping the
ResistorColorGuide section entirely).
The base docker-compose.yml already mounts ./notebooks:/app/notebooks.
The named Docker volume was shadowing it in prod, preventing example
notebooks from being visible. Bind mount ensures examples ship with
the repo and user notebooks persist on the host filesystem.
Bind mounts inherit host UID which conflicts with the container's
non-root user. Named volumes are initialized from the image layer,
preserving the chown from the Dockerfile.
Update frontend Dockerfile prod stage from Caddy static to Node.js
running Astro SSR server. Configure caddy-docker-proxy labels to
route /api/* to backend and everything else to frontend on the same
domain. Support empty PUBLIC_API_URL for same-origin API calls.