Added
- Playground chat on every surface. A first-class way to talk to the FCM router
without configuring a coding tool. Press;in the TUI, click the "Playground"
nav button in the web dashboard, or runfree-coding-models --playground/
free-coding-models playgroundto open the in-TUI chat. Streams responses
token-by-token, shows the routed-via provider/model + latency + tokens on each
assistant message, and surfaces a friendly error if the router is offline. - Router pre-prompt (
router.prePrompt). A new configurable first-class
system message injected by the daemon on every/v1/chat/completionsrequest
it proxies. Default text introduces the assistant as "free-coding-models, the
free coding-model routing agent" so every tool and every Playground reply is
framed as the FCM router. Always prepended (usersystemmessages can still
override specific instructions). Disabled by settingenabled: false. GET /api/router/prepromptandPUT /api/router/preprompton both the
router daemon and the web server. Same-origin only for PUT, same CORS policy
as the rest of the API. Persists to~/.free-coding-models.json; the daemon
picks up the new value on its 10s config-reload tick./api/playground/chatproxy on the web server. Browser Playground never
talks to the daemon directly (no CORS, no exposed provider keys). Streams SSE
when the client asks forstream: true; returns the upstream JSON otherwise.fcmvirtual model support clarified.GET /v1/modelsadvertisesfcm
(the auto-router) andfcm:<set-name>per set, so the Playground model
selector shows both options.--playgroundflag andplaygroundsubcommand for the TUI:
free-coding-models --playgroundboots the TUI directly into the chat
overlay.--helplists it under "Config Flags".- Default pre-prompt covers persona + dashboard pointer. When a user asks
the model "which model served you?", the default persona tells them they
were routed through the local FCM router and points them at the dashboard. - 9 unit tests for pre-prompt injection (idempotence, no-mutation, disabled,
empty, already-set, body-merge, garbage input, length cap, default text). - 4 unit tests for playground error extraction so the OpenAI wire-format
{ error: { message, type, code } }is unwrapped into a string before
React renders it (the bug a beta tester hit when the router was down). - Robust M4 server smoke test. The pre-existing test asserted the router
was offline, which fails on developer machines with a real daemon running.
Now it asserts the response shape and adds pre-prompt + playground-proxy
round-trips to the smoke checks.
Changed
- M4 server smoke test no longer fails on local dev machines. The test
previously required the router to be offline; that is no longer a precondition. - M4 settings view is untouched but the pre-prompt edit panel will land in
a follow-up. (The pre-prompt is already exposed through the daemon API and
the Web Settings round-trip; only the textarea is missing from the UI.)
Notes
- The default pre-prompt is ~120 words in English, code-first, and
references the local dashboard. Users can fully replace it from any
surface; the text is stored verbatim in~/.free-coding-models.json. - Pre-prompt is never sent to telemetry and is not logged by the daemon.
- The Playground honors the configured pre-prompt and lets the user toggle it
off per-session. When off, the request is sent as-is and the assistant
reply will not be framed as the FCM router.