feat: add OAuth provider abstraction for CLI configuration (#3157)
Signed-off-by: Adam Tarantino <tarantino.adam@gmail.com>
This commit is contained in:
@@ -246,6 +246,39 @@ pub async fn handle_configure() -> Result<(), Box<dyn Error>> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper function to handle OAuth configuration for a provider
|
||||
async fn handle_oauth_configuration(
|
||||
provider_name: &str,
|
||||
key_name: &str,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
use goose::model::ModelConfig;
|
||||
use goose::providers::create;
|
||||
|
||||
let _ = cliclack::log::info(format!(
|
||||
"Configuring {} using OAuth device code flow...",
|
||||
key_name
|
||||
));
|
||||
|
||||
// Create a temporary provider instance to handle OAuth
|
||||
let temp_model = ModelConfig::new("temp")?;
|
||||
match create(provider_name, temp_model) {
|
||||
Ok(provider) => match provider.configure_oauth().await {
|
||||
Ok(_) => {
|
||||
let _ = cliclack::log::success("OAuth authentication completed successfully!");
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => {
|
||||
let _ = cliclack::log::error(format!("Failed to authenticate: {}", e));
|
||||
Err(format!("OAuth authentication failed for {}: {}", key_name, e).into())
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
let _ = cliclack::log::error(format!("Failed to create provider for OAuth: {}", e));
|
||||
Err(format!("Failed to create provider for OAuth: {}", e).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Dialog for configuring the AI provider and model
|
||||
pub async fn configure_provider_dialog() -> Result<bool, Box<dyn Error>> {
|
||||
// Get global config instance
|
||||
@@ -313,13 +346,52 @@ pub async fn configure_provider_dialog() -> Result<bool, Box<dyn Error>> {
|
||||
Ok(_) => {
|
||||
let _ = cliclack::log::info(format!("{} is already configured", key.name));
|
||||
if cliclack::confirm("Would you like to update this value?").interact()? {
|
||||
let new_value: String = if key.secret {
|
||||
cliclack::password(format!("Enter new value for {}", key.name))
|
||||
.mask('▪')
|
||||
.interact()?
|
||||
// Check if this key uses OAuth flow
|
||||
if key.oauth_flow {
|
||||
handle_oauth_configuration(provider_name, &key.name).await?;
|
||||
} else {
|
||||
let mut input =
|
||||
cliclack::input(format!("Enter new value for {}", key.name));
|
||||
// Non-OAuth key, use manual entry
|
||||
let value: String = if key.secret {
|
||||
cliclack::password(format!("Enter new value for {}", key.name))
|
||||
.mask('▪')
|
||||
.interact()?
|
||||
} else {
|
||||
let mut input = cliclack::input(format!(
|
||||
"Enter new value for {}",
|
||||
key.name
|
||||
));
|
||||
if key.default.is_some() {
|
||||
input = input.default_input(&key.default.clone().unwrap());
|
||||
}
|
||||
input.interact()?
|
||||
};
|
||||
|
||||
if key.secret {
|
||||
config.set_secret(&key.name, Value::String(value))?;
|
||||
} else {
|
||||
config.set_param(&key.name, Value::String(value))?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
// Check if this key uses OAuth flow
|
||||
if key.oauth_flow {
|
||||
handle_oauth_configuration(provider_name, &key.name).await?;
|
||||
} else {
|
||||
// Non-OAuth key, use manual entry
|
||||
let value: String = if key.secret {
|
||||
cliclack::password(format!(
|
||||
"Provider {} requires {}, please enter a value",
|
||||
provider_meta.display_name, key.name
|
||||
))
|
||||
.mask('▪')
|
||||
.interact()?
|
||||
} else {
|
||||
let mut input = cliclack::input(format!(
|
||||
"Provider {} requires {}, please enter a value",
|
||||
provider_meta.display_name, key.name
|
||||
));
|
||||
if key.default.is_some() {
|
||||
input = input.default_input(&key.default.clone().unwrap());
|
||||
}
|
||||
@@ -327,37 +399,12 @@ pub async fn configure_provider_dialog() -> Result<bool, Box<dyn Error>> {
|
||||
};
|
||||
|
||||
if key.secret {
|
||||
config.set_secret(&key.name, Value::String(new_value))?;
|
||||
config.set_secret(&key.name, Value::String(value))?;
|
||||
} else {
|
||||
config.set_param(&key.name, Value::String(new_value))?;
|
||||
config.set_param(&key.name, Value::String(value))?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
let value: String = if key.secret {
|
||||
cliclack::password(format!(
|
||||
"Provider {} requires {}, please enter a value",
|
||||
provider_meta.display_name, key.name
|
||||
))
|
||||
.mask('▪')
|
||||
.interact()?
|
||||
} else {
|
||||
let mut input = cliclack::input(format!(
|
||||
"Provider {} requires {}, please enter a value",
|
||||
provider_meta.display_name, key.name
|
||||
));
|
||||
if key.default.is_some() {
|
||||
input = input.default_input(&key.default.clone().unwrap());
|
||||
}
|
||||
input.interact()?
|
||||
};
|
||||
|
||||
if key.secret {
|
||||
config.set_secret(&key.name, Value::String(value))?;
|
||||
} else {
|
||||
config.set_param(&key.name, Value::String(value))?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user