Skip to content

feat: new Claude/GPT generation support and OpenCode Zen/Go presets#53

Merged
yuanhao merged 3 commits into
mainfrom
feat/opencode-and-new-models
Jul 4, 2026
Merged

feat: new Claude/GPT generation support and OpenCode Zen/Go presets#53
yuanhao merged 3 commits into
mainfrom
feat/opencode-and-new-models

Conversation

@yuanhao

@yuanhao yuanhao commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

Closes #48

What this does

Modernizes the Anthropic provider (src/provider/anthropic.rs) — previously the only provider that ignored ModelConfig:

  • Honors base_url ({base}/messages) and custom headers; Bearer auth for gateways via AnthropicCompat.bearer_auth or a user-supplied authorization header. Pre-0.9 configs with the un-versioned official host keep working.
  • Adaptive thinking by default (thinking: {type: "adaptive"} + output_config.effort). Claude Fable 5 / Opus 4.8 / Sonnet 5 reject budget-based thinking with a 400. AnthropicCompat::legacy() keeps budget_tokens for pre-4.6 models, clamped to the API's 1024 minimum (fixes a latent 400 on Minimal/Low).
  • Maps refusal → new StopReason::Refusal (with error_message set, and empty refused turns no longer poison the conversation history) and in-stream model_context_window_exceeded → the standard overflow-error shape so compaction-retry hooks keep working.
  • max_tokens falls back to ModelConfig.max_tokens before the hardcoded 8192.

New model presets with verified context windows, output caps, and real pricing: claude_fable_5(), claude_opus_4_8(), claude_sonnet_5(), claude_haiku_4_5(), gpt_5_5().

OpenCode Zen & Go presets (#48): opencode_zen(id) / opencode_go(id) select the API protocol from the model family (GPT → Responses, Claude/Qwen → Anthropic Messages + Bearer, rest → Chat Completions). New docs page at docs/providers/opencode.md; Gemini-via-Zen documented as unsupported (warns at construction). Key-gated integration test in tests/integration_opencode.rs.

Docs refresh: stale model IDs replaced across ~25 files (claude-sonnet-4-20250514claude-sonnet-5, gpt-4ogpt-5.5, etc.); thinking and pricing tables updated.

Breaking changes (batch with reqwest 0.13 → release as 0.9.0)

  • New StopReason::Refusal variant (breaks exhaustive matches downstream)
  • New ModelConfig.anthropic: Option<AnthropicCompat> field (breaks struct-literal construction; serde-compatible with old JSON)
  • ModelConfig::anthropic() base_url now includes /v1 and defaults changed (max_tokens 8192 → 16000, reasoning true)
  • Adaptive thinking is the new default for the Anthropic provider — pre-4.6 models with thinking enabled need AnthropicCompat::legacy()

Testing

  • Full CI parity locally: fmt, clippy -Dwarnings --all-features, 270+ tests across 13 suites
  • New wiremock-based stream tests cover refusal/overflow stop-reason mapping from real SSE bytes and all three auth branches (asserting wire headers, including x-api-key absence)
  • Reviewed by a 5-agent review pass (code, tests, comments, types, silent failures); all findings addressed in the third commit
  • Not yet run: live smoke tests (integration_anthropic.rs against claude-sonnet-5 with thinking on; integration_opencode.rs against a Zen key) — no API keys in the dev environment. Recommend running both before tagging 0.9.0.

🤖 Generated with Claude Code

yuanhao and others added 3 commits July 4, 2026 15:46
Anthropic provider:
- honor ModelConfig base_url ({base}/messages) and custom headers, with
  Bearer auth for gateways via AnthropicCompat.bearer_auth or a
  user-supplied authorization header
- adaptive thinking by default (thinking: {type: adaptive} +
  output_config.effort); Claude Fable 5 / Opus 4.8 / Sonnet 5 reject
  budget-based thinking. AnthropicCompat::legacy() keeps budgets for
  pre-4.6 models, clamped to the 1024-token API minimum
- map stop_reason refusal -> new StopReason::Refusal and
  model_context_window_exceeded -> Length
- max_tokens falls back to ModelConfig.max_tokens before 8192

Presets:
- claude_fable_5/claude_opus_4_8/claude_sonnet_5/claude_haiku_4_5/gpt_5_5
  with real context windows, output caps, and pricing
- opencode_zen/opencode_go select the API protocol from the model family
  (Responses / Anthropic Messages / Chat Completions)

Closes #48

Co-Authored-By: Claude Fable 5 <[email protected]>
claude-sonnet-4-20250514 -> claude-sonnet-5, gpt-4o -> gpt-5.5,
gemini-2.0-flash -> gemini-2.5-flash, grok-3 -> grok-4.1, Bedrock
Claude 3 id -> anthropic.claude-opus-4-8; update thinking and pricing
tables for the adaptive-thinking behavior.

Co-Authored-By: Claude Fable 5 <[email protected]>
Review fixes from the multi-agent PR review:

- refusal: populate error_message, keep the tool-call fallback from
  masking Refusal/Error stop reasons, skip empty assistant messages when
  serializing history (a refused turn previously poisoned the
  conversation with an empty content block the API rejects), and show
  refusals in the CLI example
- context overflow: map in-stream model_context_window_exceeded to
  StopReason::Error with an overflow-phrase error_message so
  Message::is_context_overflow() and compaction-retry hooks keep firing
- back-compat: tolerate the pre-0.9 un-versioned official base_url in
  request_url; container-level serde(default) on AnthropicCompat
- opencode: OpenCodeGateway enum replaces correlated params, warn on
  gemini-* ids, set reasoning on Anthropic-protocol configs
- pricing/docs: fill gpt_5_5 cached-input pricing, distinguish
  configured default from model max output in preset docs, restore the
  Anthropic qualifier in ThinkingLevel docs, fix stale display names
- tests: wiremock-based stream tests (refusal + overflow mapping, all
  auth branches), serde-compat tests, max_tokens precedence, empty
  assistant filter, Refusal round-trip

Co-Authored-By: Claude Fable 5 <[email protected]>
@yuanhao
yuanhao merged commit f9df440 into main Jul 4, 2026
1 check passed
@yuanhao
yuanhao deleted the feat/opencode-and-new-models branch July 4, 2026 20:28
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.

Add support for Opencode providers

1 participant