fix(onboard,anthropic): stabilize oauth setup-token flow and model defaults
- fix onboard command ownership handling before spawn_blocking - restore memory helper imports in wizard to resolve build regression - centralize Anthropic OAuth beta header in apply_auth for all request paths - correct OpenRouter Anthropic Sonnet 4.5 model ID format - add regression tests for auth headers and curated model IDs
This commit is contained in:
parent
bb6034e765
commit
e197cc5b04
3 changed files with 72 additions and 4 deletions
|
|
@ -367,8 +367,14 @@ async fn main() -> Result<()> {
|
||||||
api_key,
|
api_key,
|
||||||
provider,
|
provider,
|
||||||
memory,
|
memory,
|
||||||
} = cli.command
|
} = &cli.command
|
||||||
{
|
{
|
||||||
|
let interactive = *interactive;
|
||||||
|
let channels_only = *channels_only;
|
||||||
|
let api_key = api_key.clone();
|
||||||
|
let provider = provider.clone();
|
||||||
|
let memory = memory.clone();
|
||||||
|
|
||||||
if interactive && channels_only {
|
if interactive && channels_only {
|
||||||
bail!("Use either --interactive or --channels-only, not both");
|
bail!("Use either --interactive or --channels-only, not both");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -467,7 +467,7 @@ fn default_model_for_provider(provider: &str) -> String {
|
||||||
"groq" => "llama-3.3-70b-versatile".into(),
|
"groq" => "llama-3.3-70b-versatile".into(),
|
||||||
"deepseek" => "deepseek-chat".into(),
|
"deepseek" => "deepseek-chat".into(),
|
||||||
"gemini" => "gemini-2.5-pro".into(),
|
"gemini" => "gemini-2.5-pro".into(),
|
||||||
_ => "anthropic/claude-sonnet-4-5".into(),
|
_ => "anthropic/claude-sonnet-4.5".into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -475,7 +475,7 @@ fn curated_models_for_provider(provider_name: &str) -> Vec<(String, String)> {
|
||||||
match canonical_provider_name(provider_name) {
|
match canonical_provider_name(provider_name) {
|
||||||
"openrouter" => vec![
|
"openrouter" => vec![
|
||||||
(
|
(
|
||||||
"anthropic/claude-sonnet-4-5".to_string(),
|
"anthropic/claude-sonnet-4.5".to_string(),
|
||||||
"Claude Sonnet 4.5 (balanced, recommended)".to_string(),
|
"Claude Sonnet 4.5 (balanced, recommended)".to_string(),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
|
@ -4345,6 +4345,16 @@ mod tests {
|
||||||
assert!(ids.contains(&"gpt-5-mini".to_string()));
|
assert!(ids.contains(&"gpt-5-mini".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn curated_models_for_openrouter_use_valid_anthropic_id() {
|
||||||
|
let ids: Vec<String> = curated_models_for_provider("openrouter")
|
||||||
|
.into_iter()
|
||||||
|
.map(|(id, _)| id)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
assert!(ids.contains(&"anthropic/claude-sonnet-4.5".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn supports_live_model_fetch_for_supported_and_unsupported_providers() {
|
fn supports_live_model_fetch_for_supported_and_unsupported_providers() {
|
||||||
assert!(supports_live_model_fetch("openai"));
|
assert!(supports_live_model_fetch("openai"));
|
||||||
|
|
|
||||||
|
|
@ -139,7 +139,9 @@ impl AnthropicProvider {
|
||||||
credential: &str,
|
credential: &str,
|
||||||
) -> reqwest::RequestBuilder {
|
) -> reqwest::RequestBuilder {
|
||||||
if Self::is_setup_token(credential) {
|
if Self::is_setup_token(credential) {
|
||||||
request.header("Authorization", format!("Bearer {credential}"))
|
request
|
||||||
|
.header("Authorization", format!("Bearer {credential}"))
|
||||||
|
.header("anthropic-beta", "oauth-2025-04-20")
|
||||||
} else {
|
} else {
|
||||||
request.header("x-api-key", credential)
|
request.header("x-api-key", credential)
|
||||||
}
|
}
|
||||||
|
|
@ -474,6 +476,56 @@ mod tests {
|
||||||
assert!(!AnthropicProvider::is_setup_token("sk-ant-api-key"));
|
assert!(!AnthropicProvider::is_setup_token("sk-ant-api-key"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn apply_auth_uses_bearer_and_beta_for_setup_tokens() {
|
||||||
|
let provider = AnthropicProvider::new(None);
|
||||||
|
let request = provider
|
||||||
|
.apply_auth(
|
||||||
|
provider.client.get("https://api.anthropic.com/v1/models"),
|
||||||
|
"sk-ant-oat01-test-token",
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
.expect("request should build");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
request
|
||||||
|
.headers()
|
||||||
|
.get("authorization")
|
||||||
|
.and_then(|v| v.to_str().ok()),
|
||||||
|
Some("Bearer sk-ant-oat01-test-token")
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
request
|
||||||
|
.headers()
|
||||||
|
.get("anthropic-beta")
|
||||||
|
.and_then(|v| v.to_str().ok()),
|
||||||
|
Some("oauth-2025-04-20")
|
||||||
|
);
|
||||||
|
assert!(request.headers().get("x-api-key").is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn apply_auth_uses_x_api_key_for_regular_tokens() {
|
||||||
|
let provider = AnthropicProvider::new(None);
|
||||||
|
let request = provider
|
||||||
|
.apply_auth(
|
||||||
|
provider.client.get("https://api.anthropic.com/v1/models"),
|
||||||
|
"sk-ant-api-key",
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
.expect("request should build");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
request
|
||||||
|
.headers()
|
||||||
|
.get("x-api-key")
|
||||||
|
.and_then(|v| v.to_str().ok()),
|
||||||
|
Some("sk-ant-api-key")
|
||||||
|
);
|
||||||
|
assert!(request.headers().get("authorization").is_none());
|
||||||
|
assert!(request.headers().get("anthropic-beta").is_none());
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn chat_with_system_fails_without_key() {
|
async fn chat_with_system_fails_without_key() {
|
||||||
let p = AnthropicProvider::new(None);
|
let p = AnthropicProvider::new(None);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue