Skip to content

feat: add support for OpenCode Go provider#284

Closed
jheronimus wants to merge 20 commits into
huggingface:mainfrom
jheronimus:opencode-go-support
Closed

feat: add support for OpenCode Go provider#284
jheronimus wants to merge 20 commits into
huggingface:mainfrom
jheronimus:opencode-go-support

Conversation

@jheronimus

Copy link
Copy Markdown
Contributor

Upd: needed to isolate the branch with this commit, hence had to reopen. The old PR is here.

This PR adds OpenCode Go as a provider along with all 13 models it currently offers.

The settings for each models are cross-referenced with Anomalyco's own model declarations.

Caveat: OpenCode Go serves different models through different API shapes. Because of that, the PR adds support for model-scoped provider overrides, like transport kind (Anthropic/OpenAI), thinking levels, defaults, display labels, API values, and always-on reasoning. The point is to keep the UI honest: we don't show thinking levels that can't actually be selected, or do something else entirely.

For example, Qwen models send Anthropic-style budgeted thinking and can explicitly disable reasoning, MiniMax M3 uses adaptive/disabled, while DeepSeek/GLM effort models expose only the supported high/max levels.

Always-reasoning models do not show a selector, and Tau sends no fake reasoning control for them.

I tried to keep the changes provider-agnostic, so they can be reused for other mixed-behavior catalogs. For example, DeepSeek R1 on OpenRouter.

@jheronimus
jheronimus requested a review from alejandro-ao as a code owner July 7, 2026 15:06
@jheronimus jheronimus changed the title Opencode go support feat: add support for OpenCode Go provider Jul 7, 2026
@jheronimus
jheronimus force-pushed the opencode-go-support branch 6 times, most recently from 9e376a2 to b4d3c74 Compare July 9, 2026 19:00
@jheronimus

Copy link
Copy Markdown
Contributor Author

@alejandro-ao hi!

I have went on and worked on this PR again

Gone:

  • model overrides, now I just use "thinking_level_map"
  • always_thinking field - now it's just deduced if reasoning is set to "true" and no thinking modes are listed
  • default thinking modes for models. Now I just use the default mode for the provider, and if the model doesn't have that mode, it uses upstream's fallback behavior. This eliminates the need for my fix to the problem where Tau wouldn't start if a model's default mode was unavailable.

Added:

  • support for six free OpenCode Zen models that the user can fall back to with the same API key
  • sorted the models alphabetically in the catalog.toml. With the free models being put at the end, and the better models of the same family coming before the lesser models.

What's still being added apart from the config data:

  • support for providers that serve both OpenAI and Anthropic API models. Currently the API is set per-provider, so I'd have to add two providers for OpenCode Go and the user would have to supply two API keys.
  • custom thinking mode labels. Some models use "max" instead of "xhigh", "on" labels, etc - I still map these so the UI is showing the actual level that is being used. Note that for Anthropic API models these are still mapped pretty conservatively (16K tokens max), but I figured that questions is outside of the scope of this commit.
  • a warning when the user tries to change thinking mode for an always thinking model. It will properly say why it can't change things
  • adaptive thinking. Used by MiniMax M3, but IIRC it's actually supported by most modern Anthropic models. Basically instead of telling the model its token limit we're telling it to adjust based on the task complexity.

Tests: apart from normal tests passing I've been using this extension for a couple days now. I also supplied an opencode-go-support.md doc that lists the researched capabilities for all the models and all the features currently missing from Tau that this commit implements.

Let me know if anything is still needed to merge this, please.

@jheronimus
jheronimus force-pushed the opencode-go-support branch from a5af08b to 26867e6 Compare July 13, 2026 11:03
…erified model overrides against OpenCode source code, added a design doc
Drop the parallel ProviderModelOverride/ThinkingMode abstraction.
Merge kind, always_thinking, thinking_default, and thinking_level_labels
into the existing ModelCatalogMetadata / ProviderModelMetadata types,
reusing upstream's thinking_level_map for api_value lookups.

Deleted:
- ThinkingMode, ProviderModelOverride dataclasses
- catalog_model_override() lookup function
- _CatalogThinkingMode, _CatalogModelOverride Pydantic models
- All override→metadata converters and serializers
- _thinking_mode(), _thinking_api_value() helpers (use _metadata_thinking_value instead)

Net -100 Python lines compared to previous approach.
The fallback in _thinking_level_map_supports returned
for levels not in the map, causing xhigh to be silently excluded from
any model that had a non-empty thinking_level_map (e.g. )
even when the model didn't declare unsupported_thinking_levels.

Separated the two call sites:
- _metadata_supports_thinking_level (used to filter provider-level
  thinking_levels through model metadata) now returns True for levels
  not in the map, since unsupported levels are explicitly marked via
   entries (from unsupported_thinking_levels).
- _thinking_level_map_supports (used when deriving levels purely from
  a map, no provider-level thinking_levels) retains the old stricter
  behaviour.

Fixes the startup error:
Corrections verified against https://github.com/anomalyco/models.dev:

- Fix north-mini-code-free context window (256000 → 200000)
- Add missing 'minimal' to unsupported_thinking_levels for deepseek models
- Add thinking_level_map entries: north-mini-code-free (off→none, high→high)
- Simplify minimax-m3: toggle-only model with off→disabled, no adaptive mapping
- Remove obsolete minimax-m3 thinking_level_labels (high→on) and unsupported levels
- Update test expectations to match corrected TOML
Toggle-only models (minimax-m3, qwen3.7-*) with thinking_level_map
entries leaked non-xhigh levels via _thinking_level_map_supports
fallback (level != "xhigh"). Fixed by adding explicit
unsupported_thinking_levels for all on-levels except 'high'
(the canonical on-level).

Also changed qwen thinking_default from medium to high for
consistency with the new restricted level set.
…x-m3 high as 'on'

Upstream models.dev data confirms:
- minimax-m3: reasoning_options = [{ type: 'toggle' }] → toggle-only,
  needs 'on' label for the 'high' level
- qwen3.6-plus/qwen3.7-plus/qwen3.7-max: reasoning_options = [{ type: 'toggle' },
  { type: 'budget_tokens', max = 262_144 }] → toggle + budget, all levels work

Remove unsupported_thinking_levels from Qwen models so users can select
different thinking budgets. Add thinking_level_labels for minimax-m3
so UI shows 'on' instead of 'high'.

Fixes the startup error where saved xhigh default was rejected for qwen3.6-plus:
now xhigh is actually available for Qwen models.
Minimax-m3 is a toggle-only model — the upstream models.dev data shows
reasoning_options = [{ type: 'toggle' }] with no budget_tokens support.

Previously, the 'on' state was sending {type: enabled, budget_tokens: 8192}
which caps the model's thinking to 8K tokens in a 1M context window.

Now uses adaptive thinking ({type: adaptive, display: summarized}) which
lets the model decide its own thinking depth with no budget limit.

Also fixes _build_messages_payload to include the required 'display' field
when thinking_type is 'adaptive' — the old code was sending incomplete
adaptive payloads missing the mandatory 'display' property.
The runtime swap in `_anthropic_provider_config_for_model` rebuilt an
`AnthropicProviderConfig` for models served via the Messages API (e.g.
minimax-m3, qwen3.7-max) but did not copy `provider.model_metadata` into
the new config. As a result, per-model `thinking_level_map` values such as
`{high = "adaptive"}` for minimax-m3 never reached the Anthropic adapter
and the wire payload fell back to budget-mode thinking
(`{type: enabled, budget_tokens: 8192}`) instead of `{type: adaptive}`.

This was the missing piece of the chain: the prior commit
`fix(anthropic): use adaptive thinking for toggle-only minimax-m3`
set the catalog map correctly, but the runtime swap then dropped it.

Add `model_metadata=provider.model_metadata` to the swapped config and
a unit test that pins the behavior for the opencode-go + minimax-m3 case.
`session-temp.jsonl` is a runtime scratch file written by the agent
harness; it should not be tracked. Ignore it and remove the stale
copy that was previously committed.
…-to-worst tiers

Reorder the opencode-go provider's models list into two sections:
opencode-go models first, free opencode-zen models second. Within each
section families are alphabetical and ties within a family (e.g.
Kimi 2.7 vs 2.6, Deepseek V4 Pro vs Flash, Qwen Max vs Plus) are
ordered best to worst. Apply the same ordering to thinking_models.
@jheronimus
jheronimus force-pushed the opencode-go-support branch from 26867e6 to c8f9da7 Compare July 13, 2026 13:15
@jheronimus jheronimus closed this Jul 16, 2026
@jheronimus
jheronimus deleted the opencode-go-support branch July 16, 2026 22:10
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