@@ -27,6 +27,8 @@ const DEFAULT_OPENAI_MODEL: &str = "deepseek-v4-pro";
2727const DEFAULT_DEEPSEEK_BASE_URL : & str = "https://api.deepseek.com/beta" ;
2828const DEFAULT_NVIDIA_NIM_BASE_URL : & str = "https://integrate.api.nvidia.com/v1" ;
2929const DEFAULT_OPENAI_CODEX_MODEL : & str = "gpt-5.5" ;
30+ const DEFAULT_ANTHROPIC_MODEL : & str = "claude-sonnet-4-6" ;
31+ const DEFAULT_ANTHROPIC_BASE_URL : & str = "https://api.anthropic.com" ;
3032const DEFAULT_OPENAI_CODEX_BASE_URL : & str = "https://chatgpt.com/backend-api" ;
3133const DEFAULT_OPENAI_BASE_URL : & str = "https://api.openai.com/v1" ;
3234const DEFAULT_ATLASCLOUD_MODEL : & str = "deepseek-ai/deepseek-v4-flash" ;
@@ -152,10 +154,12 @@ pub enum ProviderKind {
152154 alias = "chatgpt_codex"
153155 ) ]
154156 OpenaiCodex ,
157+ #[ serde( alias = "claude" ) ]
158+ Anthropic ,
155159}
156160
157161impl ProviderKind {
158- pub const ALL : [ Self ; 20 ] = [
162+ pub const ALL : [ Self ; 21 ] = [
159163 Self :: Deepseek ,
160164 Self :: NvidiaNim ,
161165 Self :: Openai ,
@@ -176,6 +180,7 @@ impl ProviderKind {
176180 Self :: Huggingface ,
177181 Self :: Together ,
178182 Self :: OpenaiCodex ,
183+ Self :: Anthropic ,
179184 ] ;
180185
181186 #[ must_use]
@@ -201,6 +206,7 @@ impl ProviderKind {
201206 Self :: Huggingface => "huggingface" ,
202207 Self :: Together => "together" ,
203208 Self :: OpenaiCodex => "openai-codex" ,
209+ Self :: Anthropic => "anthropic" ,
204210 }
205211 }
206212
@@ -231,6 +237,7 @@ impl ProviderKind {
231237 "ollama" | "ollama-local" => Some ( Self :: Ollama ) ,
232238 "huggingface" | "hugging-face" | "hugging_face" | "hf" => Some ( Self :: Huggingface ) ,
233239 "together" | "together-ai" | "together_ai" => Some ( Self :: Together ) ,
240+ "anthropic" | "claude" => Some ( Self :: Anthropic ) ,
234241 "openai-codex" | "openai_codex" | "openaicodex" | "codex" | "chatgpt"
235242 | "chatgpt-codex" | "chatgpt_codex" | "chatgptcodex" => Some ( Self :: OpenaiCodex ) ,
236243 _ => None ,
@@ -312,6 +319,8 @@ pub struct ProvidersToml {
312319 alias = "chatgpt-codex"
313320 ) ]
314321 pub openai_codex : ProviderConfigToml ,
322+ #[ serde( default ) ]
323+ pub anthropic : ProviderConfigToml ,
315324}
316325
317326/// Sibling `permissions.toml` schema.
@@ -361,6 +370,7 @@ impl ProvidersToml {
361370 ProviderKind :: Huggingface => & self . huggingface ,
362371 ProviderKind :: Together => & self . together ,
363372 ProviderKind :: OpenaiCodex => & self . openai_codex ,
373+ ProviderKind :: Anthropic => & self . anthropic ,
364374 }
365375 }
366376
@@ -385,6 +395,7 @@ impl ProvidersToml {
385395 ProviderKind :: Huggingface => & mut self . huggingface ,
386396 ProviderKind :: Together => & mut self . together ,
387397 ProviderKind :: OpenaiCodex => & mut self . openai_codex ,
398+ ProviderKind :: Anthropic => & mut self . anthropic ,
388399 }
389400 }
390401}
@@ -2022,6 +2033,7 @@ impl ConfigToml {
20222033 ProviderKind :: Huggingface => DEFAULT_HUGGINGFACE_BASE_URL . to_string ( ) ,
20232034 ProviderKind :: Together => DEFAULT_TOGETHER_BASE_URL . to_string ( ) ,
20242035 ProviderKind :: OpenaiCodex => DEFAULT_OPENAI_CODEX_BASE_URL . to_string ( ) ,
2036+ ProviderKind :: Anthropic => DEFAULT_ANTHROPIC_BASE_URL . to_string ( ) ,
20252037 } )
20262038 } ;
20272039 // CLI flag wins outright. Otherwise: config-file → injected secrets/env.
@@ -2454,6 +2466,7 @@ fn default_model_for_provider(provider: ProviderKind) -> &'static str {
24542466 ProviderKind :: Huggingface => DEFAULT_HUGGINGFACE_MODEL ,
24552467 ProviderKind :: Together => DEFAULT_TOGETHER_MODEL ,
24562468 ProviderKind :: OpenaiCodex => DEFAULT_OPENAI_CODEX_MODEL ,
2469+ ProviderKind :: Anthropic => DEFAULT_ANTHROPIC_MODEL ,
24572470 }
24582471}
24592472
@@ -2479,6 +2492,7 @@ fn default_base_url_for_provider(provider: ProviderKind) -> &'static str {
24792492 ProviderKind :: Huggingface => DEFAULT_HUGGINGFACE_BASE_URL ,
24802493 ProviderKind :: Together => DEFAULT_TOGETHER_BASE_URL ,
24812494 ProviderKind :: OpenaiCodex => DEFAULT_OPENAI_CODEX_BASE_URL ,
2495+ ProviderKind :: Anthropic => DEFAULT_ANTHROPIC_BASE_URL ,
24822496 }
24832497}
24842498
@@ -3231,6 +3245,8 @@ struct EnvRuntimeOverrides {
32313245 together_model : Option < String > ,
32323246 openai_codex_base_url : Option < String > ,
32333247 openai_codex_model : Option < String > ,
3248+ anthropic_base_url : Option < String > ,
3249+ anthropic_model : Option < String > ,
32343250}
32353251
32363252impl EnvRuntimeOverrides {
@@ -3394,6 +3410,12 @@ impl EnvRuntimeOverrides {
33943410 . or_else ( |_| std:: env:: var ( "CODEX_MODEL" ) )
33953411 . ok ( )
33963412 . filter ( |v| !v. trim ( ) . is_empty ( ) ) ,
3413+ anthropic_base_url : std:: env:: var ( "ANTHROPIC_BASE_URL" )
3414+ . ok ( )
3415+ . filter ( |v| !v. trim ( ) . is_empty ( ) ) ,
3416+ anthropic_model : std:: env:: var ( "ANTHROPIC_MODEL" )
3417+ . ok ( )
3418+ . filter ( |v| !v. trim ( ) . is_empty ( ) ) ,
33973419 }
33983420 }
33993421
@@ -3422,6 +3444,7 @@ impl EnvRuntimeOverrides {
34223444 ProviderKind :: Huggingface => self . huggingface_base_url . clone ( ) ,
34233445 ProviderKind :: Together => self . together_base_url . clone ( ) ,
34243446 ProviderKind :: OpenaiCodex => self . openai_codex_base_url . clone ( ) ,
3447+ ProviderKind :: Anthropic => self . anthropic_base_url . clone ( ) ,
34253448 }
34263449 }
34273450
@@ -3441,6 +3464,7 @@ impl EnvRuntimeOverrides {
34413464 ProviderKind :: Huggingface => self . huggingface_model . clone ( ) ,
34423465 ProviderKind :: Together => self . together_model . clone ( ) ,
34433466 ProviderKind :: OpenaiCodex => self . openai_codex_model . clone ( ) ,
3467+ ProviderKind :: Anthropic => self . anthropic_model . clone ( ) ,
34443468 _ => None ,
34453469 } ?;
34463470
@@ -5132,10 +5156,12 @@ unix_socket_path = "/tmp/cw-hooks.sock"
51325156 ) ;
51335157 assert ! ( !provider. display_name( ) . trim( ) . is_empty( ) ) ;
51345158 assert ! ( !provider. env_vars( ) . is_empty( ) ) ;
5135- // OpenAI Codex (ChatGPT) speaks the Responses API; every other
5136- // built-in provider is OpenAI-compatible Chat Completions.
5159+ // OpenAI Codex (ChatGPT) speaks the Responses API and Anthropic
5160+ // speaks the native Messages API; every other built-in provider
5161+ // is OpenAI-compatible Chat Completions.
51375162 let expected_wire = match kind {
51385163 ProviderKind :: OpenaiCodex => provider:: WireFormat :: Responses ,
5164+ ProviderKind :: Anthropic => provider:: WireFormat :: AnthropicMessages ,
51395165 _ => provider:: WireFormat :: ChatCompletions ,
51405166 } ;
51415167 assert_eq ! ( provider. wire( ) , expected_wire) ;
0 commit comments