Skip to content

feat(app): add model-switching to btw_app()#196

Draft
gadenbuie wants to merge 12 commits into
mainfrom
feat/bslib-toolbar
Draft

feat(app): add model-switching to btw_app()#196
gadenbuie wants to merge 12 commits into
mainfrom
feat/bslib-toolbar

Conversation

@gadenbuie
Copy link
Copy Markdown
Collaborator

Summary

Adds a model_choices parameter to btw_app() that lets users switch between AI providers and models from within the app's status bar.

The new parameter accepts four values:

  • "auto" (default) — uses models from btw.md if the app was launched with one, otherwise falls back to the provider's model list
  • "btw_md" — shows the named client entries from the btw.md config as model choices, enabling switching between providers mid-conversation
  • "provider" — fetches available models from the active provider's API (previous behavior)
  • "none" — no model selector shown

When switching between providers ("btw_md" mode), the server creates a new client from the target config, transfers the system prompt, tools, and conversation history, and replaces any <thinking> content blocks that are incompatible across providers. A toast notification confirms the switch.

Provider model choices are populated asynchronously after session start to avoid a startup race condition. The status bar's token and cost counters reset when the chat is cleared, and the provider badge appearance was polished.

Verification

# With a btw.md that has named client entries, e.g.:
# client:
#   claude: anthropic/claude-opus-4-5
#   gemini: google-gemini/gemini-2.5-pro
btw::btw_app()
# A model selector appears in the status bar with "claude" and "gemini" as options.
# Switching mid-conversation carries the history and system prompt to the new provider.

# Or, to browse all models from your provider:
btw::btw_app(model_choices = "provider")

# To disable the selector:
btw::btw_app(model_choices = "none")

gadenbuie added 12 commits May 18, 2026 08:13
Previously, btw_status_bar_ui() made a live API call to fetch available
models during UI construction, blocking rendering on slow or unavailable
networks. Now the select input is seeded with just the current model,
and an observe() in the server populates the full list after the session
starts.
Replaces individual per-counter reset messages with a single
btw_reset_status message. The JS handler resets all status-countup
elements matching the module namespace to zero and clears all state
classes (btw-status-unknown, btw-status-recalculating), fixing a bug
where clearing chat would display $0.00 for providers with unknown
pricing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant