Merge pull request #923 from smitb/feat/add-aws-bedrock-llm-provider-support-with-token-auth

feat: Add AWS Bedrock LLM provider support with token auth
This commit is contained in:
Jaber Jaber
2026-04-10 20:00:44 +03:00
committed by GitHub
4 changed files with 1208 additions and 4 deletions
+4
View File
@@ -2429,6 +2429,7 @@ decay_rate = 0.05
("TOGETHER_API_KEY", "Together", "together"),
("MISTRAL_API_KEY", "Mistral", "mistral"),
("FIREWORKS_API_KEY", "Fireworks", "fireworks"),
("AWS_BEARER_TOKEN_BEDROCK", "AWS Bedrock", "bedrock"),
];
let mut any_key_set = false;
@@ -4633,6 +4634,9 @@ pub(crate) fn test_api_key(provider: &str, env_var: &str) -> bool {
.get("https://openrouter.ai/api/v1/models")
.bearer_auth(&key)
.send(),
// Bedrock bearer tokens are only valid against bedrock-runtime, not the
// management plane. There is no cheap region-agnostic probe, so skip.
"bedrock" => return true,
_ => return true, // unknown provider — skip test
};
@@ -196,6 +196,14 @@ const PROVIDERS: &[ProviderInfo] = &[
needs_key: true,
hint: "",
},
ProviderInfo {
name: "bedrock",
display: "AWS Bedrock",
env_var: "AWS_BEARER_TOKEN_BEDROCK",
default_model: "anthropic.claude-sonnet-4-6",
needs_key: true,
hint: "bearer token",
},
ProviderInfo {
name: "claude-code",
display: "Claude Code",
@@ -2611,6 +2619,23 @@ fn draw_complete(f: &mut Frame, area: Rect, state: &mut State) {
);
}
// ── Bedrock credentials note ──
if p.name == "bedrock" {
f.render_widget(
Paragraph::new(vec![
Line::from(vec![Span::styled(
" AWS bearer token required \u{2014} set:",
Style::default().fg(theme::YELLOW),
)]),
Line::from(vec![Span::styled(
" AWS_BEARER_TOKEN_BEDROCK",
theme::dim_style(),
)]),
]),
chunks[14],
);
}
// ── Bottom hints ──
f.render_widget(
Paragraph::new(Line::from(vec![Span::styled(
File diff suppressed because it is too large Load Diff
+43 -4
View File
@@ -5,6 +5,7 @@
//! Mistral, Fireworks, Ollama, vLLM, Chutes.ai, and any OpenAI-compatible endpoint.
pub mod anthropic;
pub mod bedrock;
pub mod claude_code;
pub mod copilot;
pub mod fallback;
@@ -411,6 +412,18 @@ pub fn create_driver(config: &DriverConfig) -> Result<Arc<dyn LlmDriver>, LlmErr
return Ok(Arc::new(vertex::VertexAIDriver::new(project_id, region)));
}
// AWS Bedrock — Converse API with Bedrock API Key (Bearer token)
if provider == "bedrock" {
let bedrock_api_key = config.api_key.clone();
let region = std::env::var("AWS_REGION")
.or_else(|_| std::env::var("AWS_DEFAULT_REGION"))
.ok();
return Ok(Arc::new(bedrock::BedrockDriver::new_with_credentials(
bedrock_api_key,
region,
)?));
}
// Kimi for Code — Anthropic-compatible endpoint
if provider == "kimi_coding" {
let api_key = config
@@ -487,10 +500,11 @@ pub fn create_driver(config: &DriverConfig) -> Result<Arc<dyn LlmDriver>, LlmErr
Err(LlmError::Api {
status: 0,
message: format!(
"Unknown provider '{}'. Supported: anthropic, gemini, openai, azure, groq, openrouter, \
deepseek, together, mistral, fireworks, ollama, vllm, lmstudio, perplexity, \
cohere, ai21, cerebras, sambanova, huggingface, xai, replicate, github-copilot, \
chutes, venice, nvidia, codex, claude-code. Or set base_url for a custom OpenAI-compatible endpoint.",
"Unknown provider '{}'. Supported: anthropic, gemini, openai, azure, bedrock, groq, \
openrouter, deepseek, together, mistral, fireworks, ollama, vllm, lmstudio, \
perplexity, cohere, ai21, cerebras, sambanova, huggingface, xai, replicate, \
github-copilot, chutes, venice, nvidia, codex, claude-code. \
Or set base_url for a custom OpenAI-compatible endpoint.",
provider
),
})
@@ -938,4 +952,29 @@ mod tests {
"azure-openai alias should create driver successfully"
);
}
#[test]
fn test_bedrock_not_in_provider_defaults() {
// Bedrock is special-cased in create_driver(), not in provider_defaults()
assert!(provider_defaults("bedrock").is_none());
}
#[test]
fn test_bedrock_driver_requires_credentials() {
// With no credentials in env, bedrock creation should fail gracefully
// (We can't easily test this without mucking with env, so just verify
// that with an explicit api_key it succeeds at construction)
let config = DriverConfig {
provider: "bedrock".to_string(),
api_key: Some("test-bedrock-api-key".to_string()),
base_url: None,
skip_permissions: true,
};
// Should succeed because api_key is provided
let driver = create_driver(&config);
assert!(
driver.is_ok(),
"Bedrock with explicit api_key should construct successfully"
);
}
}