Skip to content

fix(tui): stop defaulting to the Zen provider in the model fallback - #144

Merged
quickbeard merged 2 commits into
mainfrom
fallback-model-connected
Jul 31, 2026
Merged

quickbeard merged 2 commits into
mainfrom
fallback-model-connected

Conversation

@quickbeard

Copy link
Copy Markdown
Owner

Problem

After a fresh codevhub install, the TUI footer showed Big Pickle · OpenCode Zen even though a real gateway provider (netgate) was configured — and a first message would have gone to upstream's hosted Zen gateway instead of the configured one.

Both config writers dropped the top-level model pin in the last round (#142 / codev-hub#221), so with empty recents the TUI's fallbackModel (context/local.tsx) fell through to its last resort: a blind sync.data.provider[0]. The hosted Zen provider self-registers (its free models need no auth) during Provider.list()'s custom-loader loop, ahead of config-only providers, so it always occupies slot 0. The original Zen-hiding work covered the pickers, tips, and the footer/startup gate — but never this fallback path. (The server-side Provider.defaultModel already restricts its fallback to configured providers; the TUI's local fallback didn't.)

Fix

  • component/use-connected.tsx: extract useConnected's existing predicate into an exported isConnectedProvider(provider); the hook delegates to it — gate/footer behavior unchanged. The free-Zen auto-registration fails it; a deliberately-authenticated opencode with paid models still passes.
  • context/local.tsx: fallbackModel's last resort becomes sync.data.provider.find(isConnectedProvider) ?? sync.data.provider[0]. When only the Zen registration exists, behavior is unchanged (the configure gate is up in that state anyway).

Verification

  • New test/component/use-connected.test.ts covers the predicate and the Zen-first-in-list selection; full TUI suite passes (247 tests), bun typecheck clean.
  • Launched the TUI against a real repro state (netgate configured, empty model.json recents): footer now shows zai-org/GLM-4.7-cc netGate instead of Big Pickle OpenCode Zen.

DIVERGENCES.md row added for both upstream files; CHANGELOG entry under Unreleased.

Note for a follow-up in codev-hub: within the configured provider the default still resolves via the server's provider_default sort, not the model chosen in the install wizard — if the wizard's choice should stick, the hub needs to seed codev's model.json recents like the fork's own /configure flow does since #142.

🤖 Generated with Claude Code

With no config `model` pin and no saved recents (a fresh `codevhub
install` — both writers dropped the pin in PR #142 / hub PR #221), the
TUI's fallbackModel took sync.data.provider[0]. The hosted Zen provider
self-registers (free models need no auth) ahead of config-only
providers, so a gateway-only setup started on "Big Pickle · OpenCode
Zen" and would send messages to upstream's hosted gateway.

Extract useConnected's predicate into isConnectedProvider and make the
fallback prefer the first provider that passes it — the same "a real
provider is configured" test the startup gate and footer indicator use.
When no provider qualifies the old first-provider behavior is kept.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The hub's models-map order never carried the first-launch choice; hub
PR #229 seeds the state dir's recents (when empty) instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@quickbeard
quickbeard merged commit 7a0968f into main Jul 31, 2026
0 of 5 checks passed
@quickbeard
quickbeard deleted the fallback-model-connected branch July 31, 2026 08:01
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