Skip to content

v0.9.0

Choose a tag to compare

@yuanhao yuanhao released this 05 Jul 12:51
· 316 commits to main since this release
6e2aa52

A breaking release batching the changes anticipated in #33: the reqwest 0.13/rustls upgrade, support for the current model generation, two new provider gateways, queue inspection, and a crate-wide exhaustiveness policy.

⚠️ Breaking changes

Dependencies / MSRV

  • reqwest 0.12 → 0.13 with rustls as the TLS backend — OpenSSL is no longer a build dependency (faster builds on Android/Windows). reqwest-eventsource replaced by the maintained kameleoon-reqwest-eventsource fork (aliased; reqwest_eventsource:: paths unchanged). Rust 1.85+ required (was 1.75). Public API surfaces reqwest 0.13 / fork types (classify_eventsource_error, OpenApiError::HttpError). (#52)

Anthropic provider

  • Adaptive thinking is the default (thinking: {"type": "adaptive"} + output_config.effort) — required by Claude Fable 5 / Opus 4.7+/4.8 / Sonnet 5. Pre-4.6 models with thinking enabled need AnthropicCompat::legacy() (budget-based, now clamped to the API's 1024-token minimum). (#53)
  • ModelConfig.base_url is now honored ({base}/messages); the anthropic() preset default includes /v1 (old persisted configs with the un-versioned host keep working). Custom headers apply; Bearer auth available via AnthropicCompat.bearer_auth.
  • New StopReason::Refusal variant (safety-system declines, e.g. Claude Fable 5); model_context_window_exceeded maps to the standard overflow-error shape so compaction-retry hooks fire.
  • anthropic() preset defaults: max_tokens 8192 → 16000, reasoning: true.

Exhaustiveness policy (#33 item 1, #55)

  • #[non_exhaustive] on Content (matches need a wildcard arm), on the ToolCall/Thinking variants and Message::Assistant (construct via Content::tool_call() / tool_call_with_metadata() / thinking() / thinking_signed() and Message::assistant(); patterns need ..), and on ModelConfig (construct via presets or the new ModelConfig::custom(); field mutation still works, literals/FRU do not). Future field additions become non-breaking.
  • StopReason stays deliberately exhaustive: a new variant should be a compile error downstream, not a silent wildcard fall-through.
  • ModelConfig gains the anthropic: Option<AnthropicCompat> field (serde-compatible with older persisted configs).

Features

  • New model presets with real pricing: claude_fable_5(), claude_opus_4_8(), claude_sonnet_5(), claude_haiku_4_5(), gpt_5_5() — correct context windows, output caps, and CostConfig values. (#53)
  • OpenCode Zen & Go gateways (#48): ModelConfig::opencode_zen(id) / opencode_go(id) select the API protocol from the model family (Responses / Anthropic Messages with Bearer auth / Chat Completions). See docs/providers/opencode.md.
  • Queue inspection API (#50): steering_queue_snapshot() / follow_up_queue_snapshot(), _len(), atomic take_*_queue(), and batch steer_all() / follow_up_all() — enables pi-style pending-message UIs. Edit-window semantics documented in docs/concepts/agent-loop.md.
  • ModelConfig::custom(api, provider, base_url, id, name) for protocols without a preset (Bedrock, Vertex, Azure).

Fixes

  • Google/Gemini: mid-stream {"error": ...} payloads and transport failures now surface as errors (previously a silently truncated "successful" turn); SAFETY-family finish reasons map to StopReason::Refusal; SSE splitting takes the earliest separator (mixed CRLF/LF buffers no longer merge events); an empty text part no longer swallows a functionCall in the same part. (#55)
  • Anthropic: a refused turn no longer poisons the conversation (empty assistant messages are skipped when serializing history) and carries an explanatory error_message; legacy thinking budgets below the API minimum no longer 400.
  • CI now builds with --all-features, so the openapi feature is compiled and linted on every PR.

Testing

New wiremock-based provider stream tests (Anthropic + Google) cover refusal/overflow stop-reason mapping, all auth branches, thought-signature round-trips, and SSE edge cases — scenarios previously reachable only with live API keys.

Full changelog: v0.8.4...v0.9.0