fix(auth): rebase PR #200 onto main and restore auth CLI flow
This commit is contained in:
parent
96109d46d1
commit
d42cb1e906
11 changed files with 594 additions and 44 deletions
|
|
@ -6,7 +6,6 @@ use crate::tools::ToolSpec;
|
|||
use async_trait::async_trait;
|
||||
use reqwest::Client;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub struct AnthropicProvider {
|
||||
credential: Option<String>,
|
||||
|
|
@ -408,6 +407,7 @@ impl Provider for AnthropicProvider {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::auth::anthropic_token::{detect_auth_kind, AnthropicAuthKind};
|
||||
|
||||
#[test]
|
||||
fn creates_with_key() {
|
||||
|
|
|
|||
|
|
@ -374,7 +374,21 @@ fn parse_custom_provider_url(
|
|||
|
||||
/// Factory: create the right provider from config (without custom URL)
|
||||
pub fn create_provider(name: &str, api_key: Option<&str>) -> anyhow::Result<Box<dyn Provider>> {
|
||||
create_provider_with_url(name, api_key, None)
|
||||
create_provider_with_options(name, api_key, &ProviderRuntimeOptions::default())
|
||||
}
|
||||
|
||||
/// Factory: create provider with runtime options (auth profile override, state dir).
|
||||
pub fn create_provider_with_options(
|
||||
name: &str,
|
||||
api_key: Option<&str>,
|
||||
options: &ProviderRuntimeOptions,
|
||||
) -> anyhow::Result<Box<dyn Provider>> {
|
||||
match name {
|
||||
"openai-codex" | "openai_codex" | "codex" => {
|
||||
Ok(Box::new(openai_codex::OpenAiCodexProvider::new(options)))
|
||||
}
|
||||
_ => create_provider_with_url(name, api_key, None),
|
||||
}
|
||||
}
|
||||
|
||||
/// Factory: create the right provider from config with optional custom base URL
|
||||
|
|
@ -561,6 +575,7 @@ pub fn create_resilient_provider(
|
|||
create_resilient_provider_with_options(
|
||||
primary_name,
|
||||
api_key,
|
||||
api_url,
|
||||
reliability,
|
||||
&ProviderRuntimeOptions::default(),
|
||||
)
|
||||
|
|
@ -570,23 +585,27 @@ pub fn create_resilient_provider(
|
|||
pub fn create_resilient_provider_with_options(
|
||||
primary_name: &str,
|
||||
api_key: Option<&str>,
|
||||
api_url: Option<&str>,
|
||||
reliability: &crate::config::ReliabilityConfig,
|
||||
options: &ProviderRuntimeOptions,
|
||||
) -> anyhow::Result<Box<dyn Provider>> {
|
||||
let mut providers: Vec<(String, Box<dyn Provider>)> = Vec::new();
|
||||
|
||||
providers.push((
|
||||
primary_name.to_string(),
|
||||
create_provider_with_url(primary_name, api_key, api_url)?,
|
||||
));
|
||||
let primary_provider = match primary_name {
|
||||
"openai-codex" | "openai_codex" | "codex" => {
|
||||
create_provider_with_options(primary_name, api_key, options)?
|
||||
}
|
||||
_ => create_provider_with_url(primary_name, api_key, api_url)?,
|
||||
};
|
||||
providers.push((primary_name.to_string(), primary_provider));
|
||||
|
||||
for fallback in &reliability.fallback_providers {
|
||||
if fallback == primary_name || providers.iter().any(|(name, _)| name == fallback) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Fallback providers don't use the custom api_url (it's specific to primary)
|
||||
match create_provider(fallback, api_key) {
|
||||
// Fallback providers don't use the custom api_url (it's specific to primary).
|
||||
match create_provider_with_options(fallback, api_key, options) {
|
||||
Ok(provider) => providers.push((fallback.clone(), provider)),
|
||||
Err(_error) => {
|
||||
tracing::warn!(
|
||||
|
|
@ -718,6 +737,12 @@ pub fn list_providers() -> Vec<ProviderInfo> {
|
|||
aliases: &[],
|
||||
local: false,
|
||||
},
|
||||
ProviderInfo {
|
||||
name: "openai-codex",
|
||||
display_name: "OpenAI Codex (OAuth)",
|
||||
aliases: &["openai_codex", "codex"],
|
||||
local: false,
|
||||
},
|
||||
ProviderInfo {
|
||||
name: "ollama",
|
||||
display_name: "Ollama",
|
||||
|
|
|
|||
|
|
@ -195,7 +195,7 @@ fn extract_stream_event_text(event: &Value, saw_delta: bool) -> Option<String> {
|
|||
Some("response.output_text.done") if !saw_delta => {
|
||||
nonempty_preserve(event.get("text").and_then(Value::as_str))
|
||||
}
|
||||
Some("response.completed") | Some("response.done") => event
|
||||
Some("response.completed" | "response.done") => event
|
||||
.get("response")
|
||||
.and_then(|value| serde_json::from_value::<ResponsesResponse>(value.clone()).ok())
|
||||
.and_then(|response| extract_responses_text(&response)),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue