From 310498b366e59e244c555c80586d6cc6561ae5f3 Mon Sep 17 00:00:00 2001 From: Val Alexander <68980965+BunsDev@users.noreply.github.com> Date: Tue, 13 Oct 2026 08:15:58 -0500 Subject: [PATCH] fix(models): align Claude catalog and adaptive effort controls Coven-Harness: Codex / GPT-6 --- .../crates/api/assets/models-snapshot.json | 2 +- src-rust/crates/api/src/model_registry.rs | 67 ++++++++++ .../crates/api/src/providers/anthropic.rs | 119 +++++++++++++++++- src-rust/crates/core/src/effort.rs | 24 +++- src-rust/crates/tui/src/model_picker.rs | 92 +++++++++++++- 5 files changed, 290 insertions(+), 14 deletions(-) diff --git a/src-rust/crates/api/assets/models-snapshot.json b/src-rust/crates/api/assets/models-snapshot.json index 1bcefffe..fe0fff29 100644 --- a/src-rust/crates/api/assets/models-snapshot.json +++ b/src-rust/crates/api/assets/models-snapshot.json @@ -1 +1 @@ -{"anthropic":{"id":"anthropic","env":["ANTHROPIC_API_KEY"],"npm":"@ai-sdk/anthropic","name":"Anthropic","doc":"https://docs.anthropic.com/en/docs/about-claude/models","models":{"claude-3-sonnet-20240229":{"id":"claude-3-sonnet-20240229","name":"Claude Sonnet 3","family":"claude-sonnet","attachment":true,"reasoning":false,"tool_call":true,"temperature":true,"knowledge":"2023-08-31","release_date":"2024-03-04","last_updated":"2024-03-04","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":3,"output":15,"cache_read":0.3,"cache_write":0.3},"limit":{"context":200000,"output":4096}},"claude-haiku-4-5":{"id":"claude-haiku-4-5","name":"Claude Haiku 4.5 (latest)","family":"claude-haiku","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-02-28","release_date":"2025-10-15","last_updated":"2025-10-15","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":1,"output":5,"cache_read":0.1,"cache_write":1.25},"limit":{"context":200000,"output":64000}},"claude-opus-4-5-20251101":{"id":"claude-opus-4-5-20251101","name":"Claude Opus 4.5","family":"claude-opus","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-03-31","release_date":"2025-11-01","last_updated":"2025-11-01","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":5,"output":25,"cache_read":0.5,"cache_write":6.25},"limit":{"context":200000,"output":64000}},"claude-3-opus-20240229":{"id":"claude-3-opus-20240229","name":"Claude Opus 3","family":"claude-opus","attachment":true,"reasoning":false,"tool_call":true,"temperature":true,"knowledge":"2023-08-31","release_date":"2024-02-29","last_updated":"2024-02-29","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":15,"output":75,"cache_read":1.5,"cache_write":18.75},"limit":{"context":200000,"output":4096}},"claude-3-5-haiku-20241022":{"id":"claude-3-5-haiku-20241022","name":"Claude Haiku 3.5","family":"claude-haiku","attachment":true,"reasoning":false,"tool_call":true,"temperature":true,"knowledge":"2024-07-31","release_date":"2024-10-22","last_updated":"2024-10-22","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":0.8,"output":4,"cache_read":0.08,"cache_write":1},"limit":{"context":200000,"output":8192}},"claude-3-5-sonnet-20241022":{"id":"claude-3-5-sonnet-20241022","name":"Claude Sonnet 3.5 v2","family":"claude-sonnet","attachment":true,"reasoning":false,"tool_call":true,"temperature":true,"knowledge":"2024-04-30","release_date":"2024-10-22","last_updated":"2024-10-22","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":3,"output":15,"cache_read":0.3,"cache_write":3.75},"limit":{"context":200000,"output":8192}},"claude-sonnet-4-6":{"id":"claude-sonnet-4-6","name":"Claude Sonnet 4.6","family":"claude-sonnet","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-08-31","release_date":"2026-02-17","last_updated":"2026-03-13","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":3,"output":15,"cache_read":0.3,"cache_write":3.75},"limit":{"context":1000000,"output":64000}},"claude-opus-4-0":{"id":"claude-opus-4-0","name":"Claude Opus 4 (latest)","family":"claude-opus","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-03-31","release_date":"2025-05-22","last_updated":"2025-05-22","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":15,"output":75,"cache_read":1.5,"cache_write":18.75},"limit":{"context":200000,"output":32000}},"claude-opus-4-7":{"id":"claude-opus-4-7","name":"Claude Opus 4.7","family":"claude-opus","attachment":true,"reasoning":true,"tool_call":true,"temperature":false,"knowledge":"2026-01-31","release_date":"2026-04-16","last_updated":"2026-04-16","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":5,"output":25,"cache_read":0.5,"cache_write":6.25},"limit":{"context":1000000,"output":128000}},"claude-3-haiku-20240307":{"id":"claude-3-haiku-20240307","name":"Claude Haiku 3","family":"claude-haiku","attachment":true,"reasoning":false,"tool_call":true,"temperature":true,"knowledge":"2023-08-31","release_date":"2024-03-13","last_updated":"2024-03-13","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":0.25,"output":1.25,"cache_read":0.03,"cache_write":0.3},"limit":{"context":200000,"output":4096}},"claude-sonnet-4-5-20250929":{"id":"claude-sonnet-4-5-20250929","name":"Claude Sonnet 4.5","family":"claude-sonnet","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-07-31","release_date":"2025-09-29","last_updated":"2025-09-29","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":3,"output":15,"cache_read":0.3,"cache_write":3.75},"limit":{"context":200000,"output":64000}},"claude-3-5-haiku-latest":{"id":"claude-3-5-haiku-latest","name":"Claude Haiku 3.5 (latest)","family":"claude-haiku","attachment":true,"reasoning":false,"tool_call":true,"temperature":true,"knowledge":"2024-07-31","release_date":"2024-10-22","last_updated":"2024-10-22","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":0.8,"output":4,"cache_read":0.08,"cache_write":1},"limit":{"context":200000,"output":8192}},"claude-opus-4-1":{"id":"claude-opus-4-1","name":"Claude Opus 4.1 (latest)","family":"claude-opus","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-03-31","release_date":"2025-08-05","last_updated":"2025-08-05","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":15,"output":75,"cache_read":1.5,"cache_write":18.75},"limit":{"context":200000,"output":32000}},"claude-sonnet-4-0":{"id":"claude-sonnet-4-0","name":"Claude Sonnet 4 (latest)","family":"claude-sonnet","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-03-31","release_date":"2025-05-22","last_updated":"2025-05-22","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":3,"output":15,"cache_read":0.3,"cache_write":3.75},"limit":{"context":200000,"output":64000}},"claude-3-5-sonnet-20240620":{"id":"claude-3-5-sonnet-20240620","name":"Claude Sonnet 3.5","family":"claude-sonnet","attachment":true,"reasoning":false,"tool_call":true,"temperature":true,"knowledge":"2024-04-30","release_date":"2024-06-20","last_updated":"2024-06-20","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":3,"output":15,"cache_read":0.3,"cache_write":3.75},"limit":{"context":200000,"output":8192}},"claude-opus-4-5":{"id":"claude-opus-4-5","name":"Claude Opus 4.5 (latest)","family":"claude-opus","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-03-31","release_date":"2025-11-24","last_updated":"2025-11-24","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":5,"output":25,"cache_read":0.5,"cache_write":6.25},"limit":{"context":200000,"output":64000}},"claude-opus-4-1-20250805":{"id":"claude-opus-4-1-20250805","name":"Claude Opus 4.1","family":"claude-opus","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-03-31","release_date":"2025-08-05","last_updated":"2025-08-05","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":15,"output":75,"cache_read":1.5,"cache_write":18.75},"limit":{"context":200000,"output":32000}},"claude-haiku-4-5-20251001":{"id":"claude-haiku-4-5-20251001","name":"Claude Haiku 4.5","family":"claude-haiku","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-02-28","release_date":"2025-10-15","last_updated":"2025-10-15","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":1,"output":5,"cache_read":0.1,"cache_write":1.25},"limit":{"context":200000,"output":64000}},"claude-sonnet-4-20250514":{"id":"claude-sonnet-4-20250514","name":"Claude Sonnet 4","family":"claude-sonnet","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-03-31","release_date":"2025-05-22","last_updated":"2025-05-22","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":3,"output":15,"cache_read":0.3,"cache_write":3.75},"limit":{"context":200000,"output":64000}},"claude-opus-4-6":{"id":"claude-opus-4-6","name":"Claude Opus 4.6","family":"claude-opus","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-05-31","release_date":"2026-02-05","last_updated":"2026-03-13","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":5,"output":25,"cache_read":0.5,"cache_write":6.25},"limit":{"context":1000000,"output":128000},"experimental":{"modes":{"fast":{"cost":{"input":30,"output":150,"cache_read":3,"cache_write":37.5},"provider":{"body":{"speed":"fast"},"headers":{"anthropic-beta":"fast-mode-2026-02-01"}}}}}},"claude-3-7-sonnet-20250219":{"id":"claude-3-7-sonnet-20250219","name":"Claude Sonnet 3.7","family":"claude-sonnet","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2024-10-31","release_date":"2025-02-19","last_updated":"2025-02-19","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":3,"output":15,"cache_read":0.3,"cache_write":3.75},"limit":{"context":200000,"output":64000}},"claude-sonnet-4-5":{"id":"claude-sonnet-4-5","name":"Claude Sonnet 4.5 (latest)","family":"claude-sonnet","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-07-31","release_date":"2025-09-29","last_updated":"2025-09-29","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":3,"output":15,"cache_read":0.3,"cache_write":3.75},"limit":{"context":200000,"output":64000}},"claude-opus-4-20250514":{"id":"claude-opus-4-20250514","name":"Claude Opus 4","family":"claude-opus","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-03-31","release_date":"2025-05-22","last_updated":"2025-05-22","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":15,"output":75,"cache_read":1.5,"cache_write":18.75},"limit":{"context":200000,"output":32000}}}}} \ No newline at end of file +{"anthropic":{"id":"anthropic","env":["ANTHROPIC_API_KEY"],"npm":"@ai-sdk/anthropic","name":"Anthropic","doc":"https://docs.anthropic.com/en/docs/about-claude/models","models":{"claude-3-sonnet-20240229":{"id":"claude-3-sonnet-20240229","name":"Claude Sonnet 3","family":"claude-sonnet","attachment":true,"reasoning":false,"tool_call":true,"temperature":true,"knowledge":"2023-08-31","release_date":"2024-03-04","last_updated":"2024-03-04","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":3,"output":15,"cache_read":0.3,"cache_write":0.3},"limit":{"context":200000,"output":4096}},"claude-haiku-4-5":{"id":"claude-haiku-4-5","name":"Claude Haiku 4.5 (latest)","family":"claude-haiku","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-02-28","release_date":"2025-10-15","last_updated":"2025-10-15","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":1,"output":5,"cache_read":0.1,"cache_write":1.25},"limit":{"context":200000,"output":64000}},"claude-opus-4-5-20251101":{"id":"claude-opus-4-5-20251101","name":"Claude Opus 4.5","family":"claude-opus","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-03-31","release_date":"2025-11-01","last_updated":"2025-11-01","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":5,"output":25,"cache_read":0.5,"cache_write":6.25},"limit":{"context":200000,"output":64000}},"claude-3-opus-20240229":{"id":"claude-3-opus-20240229","name":"Claude Opus 3","family":"claude-opus","attachment":true,"reasoning":false,"tool_call":true,"temperature":true,"knowledge":"2023-08-31","release_date":"2024-02-29","last_updated":"2024-02-29","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":15,"output":75,"cache_read":1.5,"cache_write":18.75},"limit":{"context":200000,"output":4096}},"claude-3-5-haiku-20241022":{"id":"claude-3-5-haiku-20241022","name":"Claude Haiku 3.5","family":"claude-haiku","attachment":true,"reasoning":false,"tool_call":true,"temperature":true,"knowledge":"2024-07-31","release_date":"2024-10-22","last_updated":"2024-10-22","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":0.8,"output":4,"cache_read":0.08,"cache_write":1},"limit":{"context":200000,"output":8192}},"claude-3-5-sonnet-20241022":{"id":"claude-3-5-sonnet-20241022","name":"Claude Sonnet 3.5 v2","family":"claude-sonnet","attachment":true,"reasoning":false,"tool_call":true,"temperature":true,"knowledge":"2024-04-30","release_date":"2024-10-22","last_updated":"2024-10-22","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":3,"output":15,"cache_read":0.3,"cache_write":3.75},"limit":{"context":200000,"output":8192}},"claude-sonnet-4-6":{"id":"claude-sonnet-4-6","name":"Claude Sonnet 4.6","family":"claude-sonnet","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-08-31","release_date":"2026-02-17","last_updated":"2026-03-13","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":3,"output":15,"cache_read":0.3,"cache_write":3.75},"limit":{"context":1000000,"output":128000}},"claude-opus-4-0":{"id":"claude-opus-4-0","name":"Claude Opus 4 (latest)","family":"claude-opus","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-03-31","release_date":"2025-05-22","last_updated":"2025-05-22","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":15,"output":75,"cache_read":1.5,"cache_write":18.75},"limit":{"context":200000,"output":32000}},"claude-opus-4-7":{"id":"claude-opus-4-7","name":"Claude Opus 4.7","family":"claude-opus","attachment":true,"reasoning":true,"tool_call":true,"temperature":false,"knowledge":"2026-01-31","release_date":"2026-04-16","last_updated":"2026-04-16","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":5,"output":25,"cache_read":0.5,"cache_write":6.25},"limit":{"context":1000000,"output":128000}},"claude-3-haiku-20240307":{"id":"claude-3-haiku-20240307","name":"Claude Haiku 3","family":"claude-haiku","attachment":true,"reasoning":false,"tool_call":true,"temperature":true,"knowledge":"2023-08-31","release_date":"2024-03-13","last_updated":"2024-03-13","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":0.25,"output":1.25,"cache_read":0.03,"cache_write":0.3},"limit":{"context":200000,"output":4096}},"claude-sonnet-4-5-20250929":{"id":"claude-sonnet-4-5-20250929","name":"Claude Sonnet 4.5","family":"claude-sonnet","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-07-31","release_date":"2025-09-29","last_updated":"2025-09-29","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":3,"output":15,"cache_read":0.3,"cache_write":3.75},"limit":{"context":200000,"output":64000}},"claude-3-5-haiku-latest":{"id":"claude-3-5-haiku-latest","name":"Claude Haiku 3.5 (latest)","family":"claude-haiku","attachment":true,"reasoning":false,"tool_call":true,"temperature":true,"knowledge":"2024-07-31","release_date":"2024-10-22","last_updated":"2024-10-22","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":0.8,"output":4,"cache_read":0.08,"cache_write":1},"limit":{"context":200000,"output":8192}},"claude-opus-4-1":{"id":"claude-opus-4-1","name":"Claude Opus 4.1 (latest)","family":"claude-opus","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-03-31","release_date":"2025-08-05","last_updated":"2025-08-05","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":15,"output":75,"cache_read":1.5,"cache_write":18.75},"limit":{"context":200000,"output":32000}},"claude-sonnet-4-0":{"id":"claude-sonnet-4-0","name":"Claude Sonnet 4 (latest)","family":"claude-sonnet","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-03-31","release_date":"2025-05-22","last_updated":"2025-05-22","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":3,"output":15,"cache_read":0.3,"cache_write":3.75},"limit":{"context":200000,"output":64000}},"claude-3-5-sonnet-20240620":{"id":"claude-3-5-sonnet-20240620","name":"Claude Sonnet 3.5","family":"claude-sonnet","attachment":true,"reasoning":false,"tool_call":true,"temperature":true,"knowledge":"2024-04-30","release_date":"2024-06-20","last_updated":"2024-06-20","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":3,"output":15,"cache_read":0.3,"cache_write":3.75},"limit":{"context":200000,"output":8192}},"claude-opus-4-5":{"id":"claude-opus-4-5","name":"Claude Opus 4.5 (latest)","family":"claude-opus","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-03-31","release_date":"2025-11-24","last_updated":"2025-11-24","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":5,"output":25,"cache_read":0.5,"cache_write":6.25},"limit":{"context":200000,"output":64000}},"claude-opus-4-1-20250805":{"id":"claude-opus-4-1-20250805","name":"Claude Opus 4.1","family":"claude-opus","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-03-31","release_date":"2025-08-05","last_updated":"2025-08-05","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":15,"output":75,"cache_read":1.5,"cache_write":18.75},"limit":{"context":200000,"output":32000}},"claude-haiku-4-5-20251001":{"id":"claude-haiku-4-5-20251001","name":"Claude Haiku 4.5","family":"claude-haiku","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-02-28","release_date":"2025-10-15","last_updated":"2025-10-15","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":1,"output":5,"cache_read":0.1,"cache_write":1.25},"limit":{"context":200000,"output":64000}},"claude-sonnet-4-20250514":{"id":"claude-sonnet-4-20250514","name":"Claude Sonnet 4","family":"claude-sonnet","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-03-31","release_date":"2025-05-22","last_updated":"2025-05-22","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":3,"output":15,"cache_read":0.3,"cache_write":3.75},"limit":{"context":200000,"output":64000}},"claude-opus-4-6":{"id":"claude-opus-4-6","name":"Claude Opus 4.6","family":"claude-opus","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-05-31","release_date":"2026-02-05","last_updated":"2026-03-13","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":5,"output":25,"cache_read":0.5,"cache_write":6.25},"limit":{"context":1000000,"output":128000},"experimental":{"modes":{"fast":{"cost":{"input":30,"output":150,"cache_read":3,"cache_write":37.5},"provider":{"body":{"speed":"fast"},"headers":{"anthropic-beta":"fast-mode-2026-02-01"}}}}}},"claude-3-7-sonnet-20250219":{"id":"claude-3-7-sonnet-20250219","name":"Claude Sonnet 3.7","family":"claude-sonnet","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2024-10-31","release_date":"2025-02-19","last_updated":"2025-02-19","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":3,"output":15,"cache_read":0.3,"cache_write":3.75},"limit":{"context":200000,"output":64000}},"claude-sonnet-4-5":{"id":"claude-sonnet-4-5","name":"Claude Sonnet 4.5 (latest)","family":"claude-sonnet","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-07-31","release_date":"2025-09-29","last_updated":"2025-09-29","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":3,"output":15,"cache_read":0.3,"cache_write":3.75},"limit":{"context":200000,"output":64000}},"claude-opus-4-20250514":{"id":"claude-opus-4-20250514","name":"Claude Opus 4","family":"claude-opus","attachment":true,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-03-31","release_date":"2025-05-22","last_updated":"2025-05-22","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"cost":{"input":15,"output":75,"cache_read":1.5,"cache_write":18.75},"limit":{"context":200000,"output":32000}},"claude-fable-5":{"id":"claude-fable-5","name":"Claude Fable 5","description":"Claude model for creative writing, analysis, and controlled agent workflows","family":"claude-fable","attachment":true,"reasoning":true,"reasoning_options":[{"type":"effort","values":["low","medium","high","xhigh","max"]}],"tool_call":true,"structured_output":true,"temperature":false,"release_date":"2026-06-07","last_updated":"2026-06-09","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"limit":{"context":1000000,"output":128000},"cost":{"input":10,"output":50,"cache_read":1,"cache_write":12.5}},"claude-fable-5-1":{"id":"claude-fable-5-1","name":"Claude Fable 5.1","description":"Claude model for demanding reasoning and long-horizon agentic work","family":"claude-fable","attachment":true,"reasoning":true,"reasoning_options":[{"type":"effort","values":["low","medium","high","xhigh","max"]}],"tool_call":true,"structured_output":true,"temperature":false,"knowledge":"2026-06","release_date":"2026-09-01","last_updated":"2026-09-01","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"limit":{"context":1000000,"output":128000},"cost":{"input":10,"output":50,"cache_read":0.25,"cache_write":12.5},"canonical_model_id":"anthropic/claude-fable-5-1"},"claude-opus-4-8":{"id":"claude-opus-4-8","name":"Claude Opus 4.8","description":"Top Claude Opus tier for the hardest reasoning, coding, and long-horizon agents","family":"claude-opus","attachment":true,"reasoning":true,"reasoning_options":[{"type":"effort","values":["low","medium","high","xhigh","max"]}],"tool_call":true,"structured_output":true,"temperature":false,"knowledge":"2026-01","release_date":"2026-05-28","last_updated":"2026-05-28","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"limit":{"context":1000000,"output":128000},"experimental":{"modes":{"fast":{"cost":{"input":10,"output":50,"cache_read":1,"cache_write":12.5},"provider":{"body":{"speed":"fast"},"headers":{"anthropic-beta":"fast-mode-2026-02-01"}}}}},"cost":{"input":5,"output":25,"cache_read":0.5,"cache_write":6.25}},"claude-opus-5":{"id":"claude-opus-5","name":"Claude Opus 5","description":"Strongest Claude Opus model for coding, agents, and professional work","family":"claude-opus","attachment":true,"reasoning":true,"reasoning_options":[{"type":"effort","values":["low","medium","high","xhigh","max"]}],"tool_call":true,"structured_output":true,"temperature":false,"knowledge":"2026-05","release_date":"2026-07-24","last_updated":"2026-07-24","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"limit":{"context":1000000,"output":128000},"experimental":{"modes":{"fast":{"cost":{"input":10,"output":50,"cache_read":1,"cache_write":12.5},"provider":{"body":{"speed":"fast"},"headers":{"anthropic-beta":"fast-mode-2026-02-01"}}}}},"cost":{"input":5,"output":25,"cache_read":0.5,"cache_write":6.25},"canonical_model_id":"anthropic/claude-opus-5"},"claude-opus-5-5":{"id":"claude-opus-5-5","name":"Claude Opus 5.5","description":"Claude model for long-running agentic coding and knowledge work","family":"claude-opus","attachment":true,"reasoning":true,"reasoning_options":[{"type":"effort","values":["low","medium","high","xhigh","max"]}],"tool_call":true,"structured_output":true,"temperature":false,"knowledge":"2026-06","release_date":"2026-09-22","last_updated":"2026-09-22","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"limit":{"context":1000000,"output":128000},"experimental":{"modes":{"fast":{"cost":{"input":8,"output":40,"cache_read":0.4,"cache_write":10},"provider":{"body":{"speed":"fast"},"headers":{"anthropic-beta":"fast-mode-2026-02-01"}}}}},"cost":{"input":4,"output":20,"cache_read":0.2,"cache_write":5},"canonical_model_id":"anthropic/claude-opus-5-5"},"claude-sonnet-5":{"id":"claude-sonnet-5","name":"Claude Sonnet 5","description":"Everyday Claude agent model for coding, planning, browsing, and general work","family":"claude-sonnet","attachment":true,"reasoning":true,"reasoning_options":[{"type":"toggle"},{"type":"effort","values":["low","medium","high","xhigh","max"]}],"tool_call":true,"structured_output":true,"temperature":false,"knowledge":"2026-01-31","release_date":"2026-06-29","last_updated":"2026-06-30","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"limit":{"context":1000000,"output":128000},"cost":{"input":2,"output":10,"cache_read":0.2,"cache_write":2.5}},"claude-sonnet-5-5":{"id":"claude-sonnet-5-5","name":"Claude Sonnet 5.5","description":"Fast Claude model for everyday coding, agents, and knowledge work","family":"claude-sonnet","attachment":true,"reasoning":true,"reasoning_options":[{"type":"effort","values":["low","medium","high","xhigh","max"]}],"tool_call":true,"structured_output":true,"temperature":false,"knowledge":"2026-06","release_date":"2026-09-28","last_updated":"2026-09-28","modalities":{"input":["text","image","pdf"],"output":["text"]},"open_weights":false,"limit":{"context":1000000,"output":128000},"cost":{"input":2,"output":10,"cache_read":0.1,"cache_write":2.5},"canonical_model_id":"anthropic/claude-sonnet-5-5"}}}} diff --git a/src-rust/crates/api/src/model_registry.rs b/src-rust/crates/api/src/model_registry.rs index 460c6b2c..9e205408 100644 --- a/src-rust/crates/api/src/model_registry.rs +++ b/src-rust/crates/api/src/model_registry.rs @@ -964,7 +964,9 @@ impl Default for ModelRegistry { fn flagship_patterns_for(provider_id: &str) -> &'static [&'static str] { match provider_id { "anthropic" | "amazon-bedrock" | "azure" | "google-vertex" => &[ + "claude-opus-5", "claude-opus-4", + "claude-sonnet-5", "claude-sonnet-4", "claude-3-5-sonnet", "claude-sonnet-3", @@ -1105,6 +1107,71 @@ pub fn effective_model_for_config( mod tests { use super::*; + #[test] + fn current_claude_snapshot_contains_models_and_pricing() { + let registry = ModelRegistry::new(); + for id in [ + "claude-fable-5", + "claude-fable-5-1", + "claude-opus-4-8", + "claude-opus-5", + "claude-opus-5-5", + "claude-sonnet-5", + "claude-sonnet-5-5", + ] { + let entry = registry + .get("anthropic", id) + .unwrap_or_else(|| panic!("missing {id}")); + assert_eq!(entry.info.context_window, 1_000_000, "{id}"); + assert_eq!(entry.info.max_output_tokens, 128_000, "{id}"); + assert!(entry.reasoning, "{id}"); + assert!(!entry.temperature, "{id}"); + } + let sonnet = registry.get("anthropic", "claude-sonnet-5-5").unwrap(); + assert_eq!(sonnet.cost_cache_read, Some(0.1)); + assert_eq!(sonnet.cost.cache_read, Some(0.1)); + assert_eq!( + registry + .get("anthropic", "claude-sonnet-4-6") + .unwrap() + .info + .max_output_tokens, + 128_000 + ); + } + + #[test] + fn current_claude_default_prefers_new_opus_generation() { + let registry = ModelRegistry::new(); + assert_eq!( + registry.best_model_for_provider("anthropic").as_deref(), + Some("claude-opus-5-5") + ); + } + + #[test] + fn current_claude_snapshot_retains_existing_model_ids() { + let registry = ModelRegistry::new(); + for id in [ + "claude-3-5-haiku-20241022", + "claude-3-5-haiku-latest", + "claude-3-5-sonnet-20240620", + "claude-3-5-sonnet-20241022", + "claude-3-7-sonnet-20250219", + "claude-3-haiku-20240307", + "claude-3-opus-20240229", + "claude-3-sonnet-20240229", + "claude-opus-4-0", + "claude-opus-4-1", + "claude-opus-4-1-20250805", + "claude-opus-4-20250514", + "claude-sonnet-4-0", + "claude-sonnet-4-20250514", + ] { + assert!(registry.get("anthropic", id).is_some(), "missing {id}"); + } + } + #[test] fn bundled_snapshot_loads() { let reg = ModelRegistry::new(); diff --git a/src-rust/crates/api/src/providers/anthropic.rs b/src-rust/crates/api/src/providers/anthropic.rs index 075653d9..402ddd22 100644 --- a/src-rust/crates/api/src/providers/anthropic.rs +++ b/src-rust/crates/api/src/providers/anthropic.rs @@ -31,6 +31,13 @@ use super::message_normalization::normalize_anthropic_messages; pub(crate) fn claude_model_catalog() -> Vec { let anthropic_id = ProviderId::new(ProviderId::ANTHROPIC); vec![ + ModelInfo { + id: ModelId::new("claude-fable-5-1"), + provider_id: anthropic_id.clone(), + name: "Claude Fable 5.1".to_string(), + context_window: 1_000_000, + max_output_tokens: 128_000, + }, ModelInfo { id: ModelId::new("claude-fable-5"), provider_id: anthropic_id.clone(), @@ -38,6 +45,20 @@ pub(crate) fn claude_model_catalog() -> Vec { context_window: 1_000_000, max_output_tokens: 128_000, }, + ModelInfo { + id: ModelId::new("claude-opus-5-5"), + provider_id: anthropic_id.clone(), + name: "Claude Opus 5.5".to_string(), + context_window: 1_000_000, + max_output_tokens: 128_000, + }, + ModelInfo { + id: ModelId::new("claude-opus-5"), + provider_id: anthropic_id.clone(), + name: "Claude Opus 5".to_string(), + context_window: 1_000_000, + max_output_tokens: 128_000, + }, ModelInfo { id: ModelId::new("claude-opus-4-8"), provider_id: anthropic_id.clone(), @@ -45,26 +66,47 @@ pub(crate) fn claude_model_catalog() -> Vec { context_window: 1_000_000, max_output_tokens: 128_000, }, + ModelInfo { + id: ModelId::new("claude-opus-4-7"), + provider_id: anthropic_id.clone(), + name: "Claude Opus 4.7".to_string(), + context_window: 1_000_000, + max_output_tokens: 128_000, + }, ModelInfo { id: ModelId::new("claude-opus-4-6"), provider_id: anthropic_id.clone(), name: "Claude Opus 4.6".to_string(), - context_window: 200_000, - max_output_tokens: 32_000, + context_window: 1_000_000, + max_output_tokens: 128_000, + }, + ModelInfo { + id: ModelId::new("claude-sonnet-5-5"), + provider_id: anthropic_id.clone(), + name: "Claude Sonnet 5.5".to_string(), + context_window: 1_000_000, + max_output_tokens: 128_000, + }, + ModelInfo { + id: ModelId::new("claude-sonnet-5"), + provider_id: anthropic_id.clone(), + name: "Claude Sonnet 5".to_string(), + context_window: 1_000_000, + max_output_tokens: 128_000, }, ModelInfo { id: ModelId::new("claude-sonnet-4-6"), provider_id: anthropic_id.clone(), name: "Claude Sonnet 4.6".to_string(), - context_window: 200_000, - max_output_tokens: 16_000, + context_window: 1_000_000, + max_output_tokens: 128_000, }, ModelInfo { id: ModelId::new("claude-haiku-4-5-20251001"), provider_id: anthropic_id, name: "Claude Haiku 4.5".to_string(), context_window: 200_000, - max_output_tokens: 8_096, + max_output_tokens: 64_000, }, ] } @@ -133,7 +175,7 @@ impl AnthropicProvider { builder = builder.stop_sequences(request.stop_sequences.clone()); } - // Opus 4.7+, Opus 4.8, and Fable 5 reject sampling params and manual + // Adaptive Claude models reject sampling params and manual // `budget_tokens` with a 400. Send adaptive thinking instead and drop // temperature / top_p / top_k. if claurst_core::effort::model_uses_adaptive_thinking(&request.model) { @@ -361,6 +403,71 @@ mod tests { use super::*; + #[test] + fn current_claude_requests_use_adaptive_thinking_without_sampling() { + for model in [ + "claude-fable-5-1", + "claude-opus-5", + "claude-opus-5-5", + "claude-sonnet-5", + "claude-sonnet-5-5", + ] { + for thinking in [None, Some(ThinkingConfig::enabled(10_000))] { + let has_thinking = thinking.is_some(); + let request = ProviderRequest { + model: model.to_string(), + messages: Vec::new(), + system_prompt: None, + tools: Vec::new(), + max_tokens: 16_000, + temperature: Some(0.5), + top_p: Some(0.9), + top_k: Some(20), + stop_sequences: Vec::new(), + thinking, + provider_options: serde_json::json!({}), + }; + let wire = serde_json::to_value(AnthropicProvider::build_request(&request)) + .expect("request serializes"); + for field in ["temperature", "top_p", "top_k"] { + assert!(wire.get(field).is_none(), "{model} must omit {field}"); + } + if has_thinking { + assert_eq!( + wire["thinking"], + serde_json::json!({"type": "adaptive"}), + "{model}" + ); + } else { + assert!(wire.get("thinking").is_none(), "{model}"); + } + } + } + } + + #[test] + fn current_claude_catalog_has_correct_token_limits() { + let catalog = claude_model_catalog(); + for (id, context, output) in [ + ("claude-fable-5-1", 1_000_000, 128_000), + ("claude-opus-5-5", 1_000_000, 128_000), + ("claude-opus-5", 1_000_000, 128_000), + ("claude-opus-4-7", 1_000_000, 128_000), + ("claude-opus-4-6", 1_000_000, 128_000), + ("claude-sonnet-5-5", 1_000_000, 128_000), + ("claude-sonnet-5", 1_000_000, 128_000), + ("claude-sonnet-4-6", 1_000_000, 128_000), + ("claude-haiku-4-5-20251001", 200_000, 64_000), + ] { + let entry = catalog + .iter() + .find(|entry| &*entry.id == id) + .unwrap_or_else(|| panic!("missing {id}")); + assert_eq!(entry.context_window, context, "{id}"); + assert_eq!(entry.max_output_tokens, output, "{id}"); + } + } + fn response_stream( events: Vec, ) -> Pin> + Send>> { diff --git a/src-rust/crates/core/src/effort.rs b/src-rust/crates/core/src/effort.rs index 03e186b5..975aee1e 100644 --- a/src-rust/crates/core/src/effort.rs +++ b/src-rust/crates/core/src/effort.rs @@ -15,7 +15,8 @@ /// and have removed the manual `budget_tokens` and sampling parameters /// (`temperature` / `top_p` / `top_k`). /// -/// On these models (Claude Opus 4.7, Opus 4.8, and Fable 5) sending +/// On these models (Claude Opus 4.7, Opus 4.8, the Opus 5 and Sonnet 5 +/// families, and the Fable models) sending /// `thinking: {type: "enabled", budget_tokens: N}` or a `temperature` returns /// a 400 error. Callers must instead send `thinking: {type: "adaptive"}` and /// control reasoning depth with the `effort` parameter. See the Anthropic @@ -27,6 +28,8 @@ pub fn model_uses_adaptive_thinking(model: &str) -> bool { || m.contains("opus-4-7") || m.contains("claude-opus-4-8") || m.contains("opus-4-8") + || m.contains("opus-5") + || m.contains("sonnet-5") } // --------------------------------------------------------------------------- @@ -45,7 +48,7 @@ pub enum EffortLevel { Medium, /// Comprehensive implementation with extensive testing and documentation. High, - /// Maximum capability with deepest reasoning (Opus-tier and Fable models). + /// Maximum capability with deepest reasoning on supported models. Max, } @@ -130,7 +133,7 @@ impl EffortLevel { Self::Low => "Quick, straightforward implementation with minimal overhead", Self::Medium => "Balanced approach with standard implementation and testing", Self::High => "Comprehensive implementation with extensive testing and documentation", - Self::Max => "Maximum capability with deepest reasoning (Opus-tier and Fable models)", + Self::Max => "Maximum capability with deepest reasoning on supported models", } } } @@ -221,6 +224,21 @@ mod tests { assert!(!model_uses_adaptive_thinking("claude-haiku-4-5")); } + #[test] + fn current_claude_models_use_adaptive_thinking() { + for model in [ + "claude-fable-5-1", + "claude-opus-5", + "claude-opus-5-5", + "claude-sonnet-5", + "claude-sonnet-5-5", + "anthropic/claude-sonnet-5-5", + "CLAUDE-OPUS-5-5", + ] { + assert!(model_uses_adaptive_thinking(model), "{model}"); + } + } + #[test] fn display_matches_as_str() { for level in [ diff --git a/src-rust/crates/tui/src/model_picker.rs b/src-rust/crates/tui/src/model_picker.rs index 70e37a2a..0997e4f0 100644 --- a/src-rust/crates/tui/src/model_picker.rs +++ b/src-rust/crates/tui/src/model_picker.rs @@ -118,13 +118,18 @@ impl EffortLevel { pub fn model_supports_effort(id: &str) -> bool { id.starts_with("claude-3-7") || id.starts_with("claude-opus-4") + || id.starts_with("claude-opus-5") || id.starts_with("claude-sonnet-4") + || id.starts_with("claude-sonnet-5") || id.starts_with("claude-fable") } /// Returns `true` for models that support the maximum effort tier. pub fn model_supports_max_effort(id: &str) -> bool { - id.starts_with("claude-opus-4") || id.starts_with("claude-fable") + id.starts_with("claude-opus-4") + || id.starts_with("claude-opus-5") + || id.starts_with("claude-sonnet-5") + || id.starts_with("claude-fable") } /// Returns a short description string based on the model family inferred from @@ -651,17 +656,41 @@ impl ModelPickerState { /// automatically. pub fn default_models() -> Vec { vec![ + ModelEntry { + id: "claude-fable-5-1".to_string(), + display_name: "Claude Fable 5.1".to_string(), + description: "Most powerful model — deepest reasoning, 1M context".to_string(), + is_current: false, + }, ModelEntry { id: "claude-fable-5".to_string(), display_name: "Claude Fable 5".to_string(), - description: "Most powerful model — deepest reasoning, 1M context".to_string(), + description: "Previous Fable generation — deepest reasoning, 1M context" + .to_string(), + is_current: false, + }, + ModelEntry { + id: "claude-opus-5-5".to_string(), + display_name: "Claude Opus 5.5".to_string(), + description: "Current Opus — top-tier agentic work at lower cost".to_string(), + is_current: false, + }, + ModelEntry { + id: "claude-opus-5".to_string(), + display_name: "Claude Opus 5".to_string(), + description: "Previous Opus generation — long-horizon agentic work".to_string(), is_current: false, }, ModelEntry { id: "claude-opus-4-8".to_string(), display_name: "Claude Opus 4.8".to_string(), - description: "Most capable Opus — long-horizon agentic work and analysis" - .to_string(), + description: "Opus 4.8 — long-horizon agentic work and analysis".to_string(), + is_current: false, + }, + ModelEntry { + id: "claude-opus-4-7".to_string(), + display_name: "Claude Opus 4.7".to_string(), + description: "Opus 4.7 — strong complex reasoning".to_string(), is_current: false, }, ModelEntry { @@ -670,6 +699,20 @@ impl ModelPickerState { description: "Previous Opus generation — strong complex reasoning".to_string(), is_current: false, }, + ModelEntry { + id: "claude-sonnet-5-5".to_string(), + display_name: "Claude Sonnet 5.5".to_string(), + description: "Current Sonnet — speed and capability for everyday coding" + .to_string(), + is_current: false, + }, + ModelEntry { + id: "claude-sonnet-5".to_string(), + display_name: "Claude Sonnet 5".to_string(), + description: "Previous Sonnet generation — balanced performance and speed" + .to_string(), + is_current: false, + }, ModelEntry { id: "claude-sonnet-4-6".to_string(), display_name: "Claude Sonnet 4.6".to_string(), @@ -1013,6 +1056,47 @@ mod tests { } // 1. Default model list is non-empty and contains expected IDs. + #[test] + fn current_claude_picker_preserves_effort_through_confirmation() { + for id in [ + "claude-fable-5-1", + "claude-opus-5", + "claude-opus-5-5", + "claude-sonnet-5", + "claude-sonnet-5-5", + ] { + let mut picker = ModelPickerState::new(); + picker.set_models(vec![model_entry(id, id, "")]); + picker.open_with_state(id, EffortLevel::Normal, false); + assert_eq!(picker.effective_effort(), Some(EffortLevel::Normal), "{id}"); + picker.effort_next(); + assert_eq!(picker.effective_effort(), Some(EffortLevel::High), "{id}"); + picker.effort_next(); + assert_eq!(picker.effective_effort(), Some(EffortLevel::Max), "{id}"); + assert_eq!( + picker.confirm(), + Some((id.to_string(), Some(EffortLevel::Max))), + "{id}" + ); + assert!(!picker.visible); + } + } + + #[test] + fn current_claude_models_available_in_fallback_picker() { + let models = ModelPickerState::default_models(); + for id in [ + "claude-fable-5-1", + "claude-opus-5-5", + "claude-opus-5", + "claude-opus-4-7", + "claude-sonnet-5-5", + "claude-sonnet-5", + ] { + assert!(models.iter().any(|model| model.id == id), "{id}"); + } + } + #[test] fn default_models_are_populated() { let models = ModelPickerState::default_models();