Skip to content

fix(tui): stop pinning a default model during gateway setup - #142

Merged
quickbeard merged 2 commits into
mainfrom
unpin-default-model
Jul 30, 2026
Merged

quickbeard merged 2 commits into
mainfrom
unpin-default-model

Conversation

@quickbeard

@quickbeard quickbeard commented Jul 30, 2026 •

Copy link
Copy Markdown
Owner

Problem

The gateway configure flow's "Choose default model" answer was written into the global config as a top-level model (buildGatewayConfig). That field outranks every other source when resolving the model to use:

  • server: Provider.defaultModel checks cfg.model before the state dir's model.json recents (packages/opencode/src/provider/provider.ts:1942)
  • TUI: fallbackModel order is --model → config.model → recents → first provider (packages/tui/src/context/local.tsx:197)

A /models switch only sets the in-memory per-agent selection (save() persists recent/favorite/variant, not model), so every switch silently reverted to the wizard's one-time pick on the next launch, and the only fix was hand-editing codev.jsonc.

Change

  • buildGatewayConfig no longer emits model. The provider block, per-model limit/modalities, and compaction are unchanged, so hub attribution still works — the hub probes provider.<id>, never model.
  • The configure flow seeds the chosen model into the persisted recents (local.model.set(..., { recent: true })) instead. It still becomes the startup default, and any later switch displaces it because recents are what the switch writes.
  • The flow now awaits instance.dispose() before sync.bootstrap(), matching the custom-provider flow: global.config.update only forks the instance reload, so a bootstrap can otherwise race it and come back without the new provider. The seed is skipped if the provider still isn't there, rather than letting model.set warn mid-onboarding.

Existing configs keep their pin; the changelog entry tells users to delete the "model" line to pick up the new behavior.

Testing

  • bun test in packages/codev-gateway (37 pass) — added a case asserting no top-level model, updated the shape assertion.
  • bun test in packages/tui (244 pass, 1 skip) and bun typecheck in both packages.
  • The SSO path itself was not exercised live (needs a fresh gateway login), so the seed + dispose ordering is verified by reading the flow, not by running it.

Divergences

Both touched source files are fork-only (packages/codev-gateway/*, packages/tui/src/component/dialog-configure.tsx), so no DIVERGENCES.md row applies. CHANGELOG.md has an Unreleased entry.

Note: the codev hub drops the same pin in quickbeard/codev-hub#221 (src/lib/configure.ts configureOpenCodeKind), for the configs it manages for both CoDev Code and opencode. The two writers stay in sync — the hub fragment this block mirrors no longer carries a top-level model either. Configs written by a hub older than that release still carry one, so an upgrade doesn't remove an existing pin; deleting the "model" line does.

🤖 Generated with Claude Code

The configure flow wrote the chosen model as a top-level `model` in the
global config. That pin outranks every other source on startup — Provider
defaultModel checks config before the state dir's model.json recents — so
each `/models` switch reverted on the next launch and only hand-editing
codev.jsonc undid it.

buildGatewayConfig no longer emits `model`; the flow seeds the choice into
the persisted recents instead, so it still starts as the default and a
later switch replaces it. The flow now awaits instance disposal before
bootstrapping (config.update only forks the reload) so the reloaded
provider list contains netgate before the seed. Hub attribution is
unaffected: it probes `provider.<id>`, never `model`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The block comment claimed this fragment deliberately differs from the hub's.
codev-hub#221 removes the same pin from configureOpenCodeKind, so the two
writers match again — say that instead, and keep the caveat that a config
written by an older hub still carries a pin.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@quickbeard
quickbeard merged commit 300fa27 into main Jul 30, 2026
0 of 5 checks passed
@quickbeard
quickbeard deleted the unpin-default-model branch July 30, 2026 13:33
quickbeard added a commit that referenced this pull request Jul 31, 2026
…144)

* fix(tui): stop defaulting to the Zen provider in the model fallback

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>

* docs(gateway): correct the hub's model-default mechanism in the comment

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>

---------

Co-authored-by: Quickbeard <quickbeard@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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