Skip to content

fix(opencode-go): refresh model catalog on startup without re-login - #21

Merged
elkaix merged 1 commit into
mainfrom
fix/opencode-go-refresh-on-update
May 29, 2026
Merged

fix(opencode-go): refresh model catalog on startup without re-login#21
elkaix merged 1 commit into
mainfrom
fix/opencode-go-refresh-on-update

Conversation

@elkaix

@elkaix elkaix commented May 29, 2026

Copy link
Copy Markdown
Member

Problem

The OpenCode Go model→provider map is materialized into config.toml at login and read from there at runtime. So when the bundled/served catalog changes — a new model like qwen3.7-max, or a corrected Qwen API-shape — it never reaches an existing install until the user manually runs pythinker login --opencode-go. Updating the binary alone (even to the version that ships qwen3.7-max) does not refresh it.

Why the existing refresh didn't cover it

auth.platforms.refresh_managed_models already runs as a background task on every startup and keeps other managed providers current via list_models. But it silently skipped OpenCode Go:

  • Its provider keys (managed:opencode-go-openai / -anthropic) parse to non-existent platform ids → get_platform_by_id returns None → "platform not found" → continue (logged a spurious warning every startup).
  • Even if registered, the generic _apply_models assigns all discovered ids to a single provider key — which can't express OpenCode Go's two-shape split (qwen → Anthropic-compatible, others → OpenAI-compatible).

Fix

Wire OpenCode Go into the existing every-startup refresh with its own discovery and a dedicated apply:

  • opencode_go.py: refresh_opencode_go_models() (re-discover using the saved key) and apply_opencode_go_models() (upsert + prune across both shape providers, preserving the user's default_model and default_thinking — the login path resets them; a refresh must not).
  • platforms.py: skip OpenCode Go keys in the generic loop (also removes the per-startup spurious warning), then refresh it via its own path. Discovery failures are isolated so they can't abort other providers' saves.

No new config field/version-marker — the background task already fires after any update, so refreshed models land on the next launch.

Scope / caveat

This updates config.models only, not config.providers. Model-list staleness now self-heals; a stale provider base_url (e.g. the old anthropic-base-without-/v1) would still require a re-login.

Tests

  • test_opencode_go_auth.py: upsert + shape-correction preserving user prefs; prune + default reassignment only when the default was removed; no-op returns False; discovery reuses the saved key.
  • test_platforms.py: OpenCode Go refreshed without re-login (qwen3.7-max appears on the Anthropic provider, prefs preserved, persisted); discovery-failure isolation (a generic provider still saves).
  • 216 auth tests pass; pyright 0 errors; ruff clean.

Summary by CodeRabbit

  • New Features
    • Added automatic OpenCode Go model discovery and synchronization to keep available models current
    • Default model preferences are intelligently preserved during updates or reassigned if the current default becomes unavailable
    • Stale models are automatically removed while protecting models from other providers

Review Change Stack

The OpenCode Go model->provider map is materialized into config.toml at
login and read from there at runtime, so bundled/served catalog changes
(new models like qwen3.7-max, corrected Qwen shape) never reached an
existing install until a manual `pythinker login --opencode-go`.

The every-startup background `refresh_managed_models` task already keeps
other managed providers current, but it silently skipped OpenCode Go: its
provider keys parse to non-existent platform ids, and the generic
`_apply_models` assigns all discovered ids to a single provider key, which
can't express OpenCode Go's two-shape (OpenAI/Anthropic) split.

Wire OpenCode Go into that refresh with its own discovery and a dedicated
apply that upserts/prunes across both shape providers while preserving the
user's default_model and default_thinking (the login path resets them).
Discovery failures are isolated so they can't abort other providers' saves.

This only updates config.models, not config.providers, so provider
base_url repairs still require a re-login.
@coderabbitai

coderabbitai Bot commented May 29, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 21448043-aa25-4ef8-befc-9ce23fe20185

📥 Commits

Reviewing files that changed from the base of the PR and between d55218f and ee5bba6.

📒 Files selected for processing (4)
  • src/pythinker_code/auth/opencode_go.py
  • src/pythinker_code/auth/platforms.py
  • tests/auth/test_opencode_go_auth.py
  • tests/auth/test_platforms.py

📝 Walkthrough

Walkthrough

This PR adds model refresh and discovery plumbing for OpenCode Go providers. It introduces APIs to fetch saved API keys, discover live models, and apply discoveries to the config while pruning stale entries and preserving user defaults. The refresh flow is then integrated into the existing managed provider sync pipeline with error isolation.

Changes

OpenCode Go Model Refresh Integration

Layer / File(s) Summary
OpenCode Go model refresh core APIs
src/pythinker_code/auth/opencode_go.py
Defines OPENCODE_GO_PROVIDER_KEYS constant and adds _opencode_go_api_key() to retrieve saved credentials, apply_opencode_go_models() to upsert/prune models while preserving valid user defaults, and refresh_opencode_go_models() to perform live discovery returning model tuples or None.
Managed model refresh pipeline integration
src/pythinker_code/auth/platforms.py
Modifies refresh_managed_models() to import OpenCode Go helpers, skip OpenCode Go keys in the generic provider loop, then call refresh_opencode_go_models() and apply_opencode_go_models() after generic providers with error handling and change tracking.
Unit tests for OpenCode Go refresh functions
tests/auth/test_opencode_go_auth.py
Adds test helper _stale_opencode_go_config() and five test cases verifying apply_opencode_go_models adds/corrects models while preserving defaults, prunes stale entries, detects no-change states, and refresh_opencode_go_models returns None when unconfigured and discovers using saved keys.
Integration tests for managed refresh with OpenCode Go
tests/auth/test_platforms.py
Adds helper _make_opencode_go_config() and two integration tests verifying refresh_managed_models() discovers and applies OpenCode Go models without re-login while preserving defaults, and correctly isolates discovery failures.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

bug

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 70.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed Title follows conventional commits format with type 'fix' and scope 'opencode-go', directly describing the main change: enabling model catalog refresh without re-login.
Description check ✅ Passed Description provides thorough problem statement, detailed fix explanation, scope/caveats, and test coverage. Includes related context but misses explicit issue link in the template format.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/opencode-go-refresh-on-update

Comment @coderabbitai help to get the list of available commands and usage tips.

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