v3.1.1 — /model picker fixes
Two bugs reported by user Cheetah, both fixed. Pure bugfix release — no functional changes to the agent, plugin SDK, tools, or payment flow.
Fixed
1. /model picker only showed 16 of 55+ models
src/ui/app.tsx had its own hardcoded 16-entry PICKER_MODELS array, completely disconnected from the canonical list in src/pricing.ts. Users couldn't reach GLM, Grok, Kimi, Minimax, Gemini 3.1 Pro, O1, O3, GPT-5.3 Codex, or most of the NVIDIA free tier from the in-session picker at all.
Fix: single source of truth. PICKER_CATEGORIES, PICKER_MODELS_FLAT, and the ModelEntry type are now exported from src/ui/model-picker.ts and consumed by both the Ink UI picker and the readline pickModel() fallback. The new list has 32 models across 6 categories:
- 🔥 Promo (2) — GLM-5.1, GLM-5.1 Turbo (flat $0.001/call)
- 🧠 Smart routing (3) —
blockrun/auto,blockrun/eco,blockrun/premium - ✨ Premium frontier (8) — Claude Sonnet/Opus 4.6, GPT-5.4, GPT-5.4 Pro, Gemini 2.5 Pro, Gemini 3.1 Pro, Grok 3, Grok 4
- 🔬 Reasoning (6) — O3, O4 Mini, O1, GPT-5.3 Codex, DeepSeek R1, Grok 4.1 Fast Reasoning
- 💰 Budget (7) — Haiku 4.5, GPT-5 Mini/Nano, Gemini 2.5 Flash, DeepSeek V3, Kimi K2.5, Minimax M2.7
- 🆓 Free (6) — Nemotron Ultra, Qwen3 Coder, Devstral, Llama 4 Maverick, DeepSeek V3.2, GPT OSS 120B
Every ID is verified against pricing.ts; every shortcut is in MODEL_SHORTCUTS.
2. Switching models wiped the scrollback
When a user typed /model mid-session, the Ink UI had if (mode === 'model-picker') return <Box>...picker only...</Box>. That early-return unmounted the two <Static> components holding the conversation scrollback (completedTools and committedResponses). When the picker closed and mode flipped back, they re-mounted fresh — and Ink's <Static> doesn't re-commit already-written items. So the screen came back visually empty.
The agent's message history array was actually intact on the backend, so the next prompt still had full context. But from the user's seat, the scrollback was gone right when it was most needed — mid-debug on a large codebase, when referencing prior prompts is the whole point of switching models.
Fix: the picker now renders inline below the scrollback as an overlay. The render function always returns the same tree shape regardless of mode; only the picker vs. InputBox toggles at the bottom. The two <Static> components stay mounted across mode transitions — scrollback survives.
Also added a one-line reassurance inside the picker UI:
Your conversation stays above — picking a model keeps all history intact.
Internal
- Removed duplicated
PICKER_MODELSarrays. One inmodel-picker.ts, one inapp.tsx— both 16 entries, both drifted from reality. Now a singlePICKER_CATEGORIESexport. src/ui/app.tsxrender function is safer for future UI modes (settings, wallet details, onboarding) — they can all reuse the same always-mounted Static tree instead of unmounting scrollback.
Verification
- ✅ 7/7 local tests pass
- ✅ 13/13 E2E tests pass (GLM-5.1)
- ✅
franklin --version→3.1.1 - ✅
PICKER_CATEGORIES.length === 6,PICKER_MODELS_FLAT.length === 32 - ✅
TypeScript strictclean
Not changed
- Agent loop, plugin SDK, tools, wallet, session storage, payment flow — all identical to v3.1.0.
- The
runcodealias still works through the 60-day window from v3.0.0.
npm: @blockrun/franklin@3.1.1 · Full changelog: v3.1.0...v3.1.1
Thanks to Cheetah for the detailed bug report.