Signed-off-by: Douwe Osinga <douwe@squareup.com> Co-authored-by: Douwe Osinga <douwe@squareup.com>
This commit is contained in:
@@ -69,6 +69,7 @@ rmcp = { workspace = true, features = [
|
||||
"transport-streamable-http-client-reqwest",
|
||||
] }
|
||||
oauth2 = { version = "5.0", default-features = false }
|
||||
arboard = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
|
||||
@@ -266,9 +266,13 @@ pub struct ConfigKey {
|
||||
pub secret: bool,
|
||||
/// Optional default value for the key
|
||||
pub default: Option<String>,
|
||||
/// Whether this key should be configured using OAuth device code flow
|
||||
/// Whether this key should be configured using an OAuth flow
|
||||
/// When true, the provider's configure_oauth() method will be called instead of prompting for manual input
|
||||
pub oauth_flow: bool,
|
||||
/// Whether this OAuth flow uses the device code grant (RFC 8628)
|
||||
/// When true, the user must enter a verification code in the browser
|
||||
#[serde(default)]
|
||||
pub device_code_flow: bool,
|
||||
/// Whether this key should be shown prominently during provider setup
|
||||
/// (onboarding, settings modal, CLI configure)
|
||||
#[serde(default)]
|
||||
@@ -290,6 +294,7 @@ impl ConfigKey {
|
||||
secret,
|
||||
default: default.map(|s| s.to_string()),
|
||||
oauth_flow: false,
|
||||
device_code_flow: false,
|
||||
primary,
|
||||
}
|
||||
}
|
||||
@@ -301,11 +306,12 @@ impl ConfigKey {
|
||||
secret,
|
||||
default: Some(T::DEFAULT.to_string()),
|
||||
oauth_flow: false,
|
||||
device_code_flow: false,
|
||||
primary,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new ConfigKey that uses OAuth device code flow for configuration
|
||||
/// Create a new ConfigKey that uses an OAuth flow for configuration
|
||||
///
|
||||
/// This is used for providers that support OAuth authentication instead of manual API key entry.
|
||||
/// When oauth_flow is true, the configuration system will call the provider's configure_oauth() method.
|
||||
@@ -322,6 +328,29 @@ impl ConfigKey {
|
||||
secret,
|
||||
default: default.map(|s| s.to_string()),
|
||||
oauth_flow: true,
|
||||
device_code_flow: false,
|
||||
primary,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new ConfigKey that uses OAuth device code flow (RFC 8628) for configuration
|
||||
///
|
||||
/// Similar to new_oauth, but indicates the provider uses the device code grant where the user
|
||||
/// must enter a verification code in the browser.
|
||||
pub fn new_oauth_device_code(
|
||||
name: &str,
|
||||
required: bool,
|
||||
secret: bool,
|
||||
default: Option<&str>,
|
||||
primary: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
name: name.to_string(),
|
||||
required,
|
||||
secret,
|
||||
default: default.map(|s| s.to_string()),
|
||||
oauth_flow: true,
|
||||
device_code_flow: true,
|
||||
primary,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,6 +285,16 @@ impl GithubCopilotProvider {
|
||||
async fn login(&self) -> Result<String> {
|
||||
let device_code_info = self.get_device_code().await?;
|
||||
|
||||
if let Ok(mut clipboard) = arboard::Clipboard::new() {
|
||||
if let Err(e) = clipboard.set_text(&device_code_info.user_code) {
|
||||
tracing::warn!("Failed to copy verification code to clipboard: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(e) = webbrowser::open(&device_code_info.verification_uri) {
|
||||
tracing::warn!("Failed to open browser: {}", e);
|
||||
}
|
||||
|
||||
println!(
|
||||
"Please visit {} and enter code {}",
|
||||
device_code_info.verification_uri, device_code_info.user_code
|
||||
@@ -402,7 +412,7 @@ impl ProviderDef for GithubCopilotProvider {
|
||||
GITHUB_COPILOT_DEFAULT_MODEL,
|
||||
GITHUB_COPILOT_KNOWN_MODELS.to_vec(),
|
||||
GITHUB_COPILOT_DOC_URL,
|
||||
vec![ConfigKey::new_oauth(
|
||||
vec![ConfigKey::new_oauth_device_code(
|
||||
"GITHUB_COPILOT_TOKEN",
|
||||
true,
|
||||
true,
|
||||
|
||||
Reference in New Issue
Block a user