[Extensibility 2/4] feat: keyless demo mode - a real first-run answer instead of a 401 (stacked on #259)
From the PR description
Stacked on #259 - merge that first; until it merges, this diff shows its commit too. This PR's own change is the single
keyless demo modecommit.
Summary
A brand-new instance answers its first question with a canned, clearly-labelled, context-aware reply - plus a nudge toward Settings → API Keys - instead of a raw provider 401. First-run users and zero-setup demos work with no API keys at all, entirely offline.
Changes
Backend: providers/demo.ts (new, registered via the registry), DEMO_MODEL = "mike-demo", and resolveDemoFallback() in routes/chat.ts - a request for a keyless provider runs on the demo model instead of failing.
Frontend: "Demo (no key needed)" entry in the model picker; ChatInput falls back to demo instead of the blocking key popup; dismissible ApiKeyBanner shown while no provider key is configured.
Why
Today a fresh install hits a hard error on the very first message. This is the single highest-friction moment for new users and demos; after this PR the first message always answers, labelled as demo output, and documents never leave the workspace until a real key is added.
Testing
On this branch: backend npm test 279 passed; frontend npm test 38 passed, eslint 0 errors, next build clean.
Provenance
Mechanical port of the demo mode running in amal66/mike (main), including its keyless-fallback fixes. Full provenance in amal66#28.
🤖 Generated with Claude Code
Our analysis
Add keyless demo mode for first-run chat — read the full analysis →
Think the analysis missed something the PR description covers?
Capture this PR into my fork
Download a Markdown prompt that tells Claude how to port every
commit in this PR into your working tree. Run it via
claude -p < capture-pull-260.md from
inside the repo you want the changes in.