feat(provider): enhance Claude provider configuration to support environment variable fallback

This commit is contained in:
asepharyana
2026-07-15 01:06:36 +07:00
parent 181b5128ac
commit 4b16bc3112
+31 -8
View File
@@ -143,15 +143,19 @@ struct ClaudeSettings {
env: Option<ClaudeEnv>,
}
/// Read `~/.claude/settings.json` and return a `ProviderConfig` if the file
/// contains `ANTHROPIC_BASE_URL` and `ANTHROPIC_API_KEY` in its `env` block.
/// Return a `ProviderConfig` for the Claude provider, checking both
/// `~/.claude/settings.json` and the process environment.
///
/// Flow: try the file (`env.ANTHROPIC_BASE_URL` + `env.ANTHROPIC_API_KEY`)
/// first → fall back to the `ANTHROPIC_BASE_URL` / `ANTHROPIC_API_KEY` env
/// vars → if neither source has both values, return `None`.
///
/// Why: Claude Code may inject credentials via env vars (OAuth session) rather
/// than through its settings file, so reading only the file misses them.
fn detect_claude_settings_provider() -> Option<ProviderConfig> {
let path = dirs::home_dir()?.join(".claude").join("settings.json");
let content = std::fs::read_to_string(&path).ok()?;
let settings: ClaudeSettings = serde_json::from_str(&content).ok()?;
let env = settings.env?;
let base_url = env.anthropic_base_url?;
let _ = env.anthropic_api_key?; // presence check — stored as env var, not in config.
// Prefer the file, then fall back to env vars.
let (base_url, _key) = claude_credentials_from_file()
.or_else(claude_credentials_from_env)?;
Some(ProviderConfig {
api_base: base_url,
api_key_env: Some("ANTHROPIC_API_KEY".to_string()),
@@ -159,3 +163,22 @@ fn detect_claude_settings_provider() -> Option<ProviderConfig> {
default_api_key: None,
})
}
/// Try to read Claude credentials from `~/.claude/settings.json`'s `env` block.
fn claude_credentials_from_file() -> Option<(String, String)> {
let path = dirs::home_dir()?.join(".claude").join("settings.json");
let content = std::fs::read_to_string(&path).ok()?;
let settings: ClaudeSettings = serde_json::from_str(&content).ok()?;
let env = settings.env?;
let base_url = env.anthropic_base_url?;
let key = env.anthropic_api_key?;
Some((base_url, key))
}
/// Try to read Claude credentials from `ANTHROPIC_BASE_URL` /
/// `ANTHROPIC_API_KEY` environment variables.
fn claude_credentials_from_env() -> Option<(String, String)> {
let base_url = std::env::var("ANTHROPIC_BASE_URL").ok()?;
let key = std::env::var("ANTHROPIC_API_KEY").ok()?;
Some((base_url, key))
}