diff --git a/Cargo.lock b/Cargo.lock index b4ff0ba..3f71739 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3521,7 +3521,7 @@ dependencies = [ [[package]] name = "routecode-cli" -version = "0.1.11" +version = "0.1.12" dependencies = [ "anyhow", "async-trait", @@ -3543,7 +3543,7 @@ dependencies = [ [[package]] name = "routecode-sdk" -version = "0.1.11" +version = "0.1.12" dependencies = [ "anyhow", "async-stream", diff --git a/apps/cli/src/main.rs b/apps/cli/src/main.rs index 417a4ef..e9a394e 100644 --- a/apps/cli/src/main.rs +++ b/apps/cli/src/main.rs @@ -258,6 +258,13 @@ async fn main() -> anyhow::Result<()> { let provider_name = config.provider.clone(); let api_key = std::env::var(format!("{}_API_KEY", provider_name.to_uppercase())) .ok() + .or_else(|| { + if provider_name == "vertex" { + std::env::var("GOOGLE_API_KEY").ok() + } else { + None + } + }) .or_else(|| config.api_keys.get(&provider_name).cloned()); let api_key = match api_key { @@ -447,13 +454,15 @@ async fn main() -> anyhow::Result<()> { #[cfg(target_os = "windows")] { match std::process::Command::new("powershell") - .args(["-NoProfile", "-Command", "irm https://raw.githubusercontent.com/anasx07/routecode/main/install.ps1 | iex"]) - .status() + .args([ + "-NoProfile", + "-Command", + "Start-Sleep -m 500; irm https://raw.githubusercontent.com/anasx07/routecode/main/install.ps1 | iex", + ]) + .spawn() { - Ok(status) => { - if !status.success() { - eprintln!("Update command failed with exit code: {:?}", status.code()); - } + Ok(_) => { + std::process::exit(0); } Err(e) => eprintln!("Failed to run update command: {}", e), } diff --git a/apps/cli/src/ui/events.rs b/apps/cli/src/ui/events.rs index b558dd5..30404f4 100644 --- a/apps/cli/src/ui/events.rs +++ b/apps/cli/src/ui/events.rs @@ -322,6 +322,13 @@ pub(crate) async fn handle_key_event( format!("{}_API_KEY", provider_id.to_uppercase().replace("-", "_")); let api_key = std::env::var(env_key) .ok() + .or_else(|| { + if provider_id == "vertex" { + std::env::var("GOOGLE_API_KEY").ok() + } else { + None + } + }) .or_else(|| config.api_keys.get(provider_id).cloned()); if let Some(key) = api_key { config.model = model_name.clone(); @@ -375,10 +382,11 @@ pub(crate) async fn handle_key_event( ApiKeyInputStage::ApiKey => { if let Some(provider_id) = app.pending_provider_id.clone() { if provider_id == "vertex" { - app.api_key_input_stage = ApiKeyInputStage::VertexLocation; + app.pending_account_id = Some(input_value); + app.api_key_input_stage = ApiKeyInputStage::VertexProject; app.api_key_input = TextArea::default(); app.api_key_input - .set_placeholder_text(" Location (e.g. us-central1)..."); + .set_placeholder_text(" Google Cloud Project ID..."); } else { app.pending_provider_id.take(); let mut config = app.orchestrator.config.lock().await; @@ -397,13 +405,20 @@ pub(crate) async fn handle_key_event( app.api_key_input_stage = ApiKeyInputStage::None; } } + ApiKeyInputStage::VertexProject => { + app.pending_gateway_id = Some(input_value); + app.api_key_input_stage = ApiKeyInputStage::VertexLocation; + app.api_key_input = TextArea::default(); + app.api_key_input + .set_placeholder_text(" Location (e.g. us-central1)..."); + } ApiKeyInputStage::VertexLocation => { if let Some(provider_id) = app.pending_provider_id.take() { let location = input_value; - let api_key = - app.api_key_input.lines().join("\n").trim().to_string(); + let api_key = app.pending_account_id.take().unwrap_or_default(); + let project = app.pending_gateway_id.take().unwrap_or_default(); let mut config = app.orchestrator.config.lock().await; - config.vertex_project = "".to_string(); + config.vertex_project = project; config.vertex_location = location; config.api_keys.insert(provider_id, api_key); if let Err(e) = routecode_sdk::utils::storage::save_config(&config) @@ -480,6 +495,9 @@ pub(crate) async fn handle_key_event( if api_key.is_none() && provider_id.starts_with("cloudflare") { api_key = std::env::var("CLOUDFLARE_API_KEY").ok(); } + if api_key.is_none() && provider_id == "vertex" { + api_key = std::env::var("GOOGLE_API_KEY").ok(); + } if api_key.is_none() { let config = app.orchestrator.config.lock().await; api_key = config.api_keys.get(provider_id).cloned(); diff --git a/apps/cli/src/ui/menus.rs b/apps/cli/src/ui/menus.rs index 895d1dc..54a1184 100644 --- a/apps/cli/src/ui/menus.rs +++ b/apps/cli/src/ui/menus.rs @@ -105,6 +105,10 @@ pub fn render_api_key_dialog(f: &mut Frame, app: &mut App) { ApiKeyInputStage::CloudflareApiKey => { ("Enter Cloudflare API Token:".to_string(), " API Token...") } + ApiKeyInputStage::VertexProject => ( + "Enter GCP Project ID (e.g. my-gcp-project):".to_string(), + " Project ID...", + ), ApiKeyInputStage::VertexLocation => ( "Enter GCP location (us-central1, europe-west4, us):".to_string(), " us-central1...", diff --git a/apps/cli/src/ui/types.rs b/apps/cli/src/ui/types.rs index fec2262..3315712 100644 --- a/apps/cli/src/ui/types.rs +++ b/apps/cli/src/ui/types.rs @@ -177,6 +177,7 @@ pub enum Screen { pub enum ApiKeyInputStage { None, ApiKey, + VertexProject, VertexLocation, CloudflareAccountId, CloudflareGatewayId, diff --git a/libs/sdk/src/agents/mod.rs b/libs/sdk/src/agents/mod.rs index b309996..b1606fd 100644 --- a/libs/sdk/src/agents/mod.rs +++ b/libs/sdk/src/agents/mod.rs @@ -99,21 +99,25 @@ pub fn resolve_provider_with_config( .or_else(|_| std::env::var("GCLOUD_PROJECT")) .unwrap_or_default(); - let final_project = if vertex_project.is_empty() { - &env_project + let final_project = if !env_project.is_empty() { + env_project + } else if !vertex_project.is_empty() { + vertex_project.to_string() } else { - vertex_project + "".to_string() }; - let env_location = std::env::var("GOOGLE_VERTEX_LOCATION") - .or_else(|_| std::env::var("GOOGLE_CLOUD_LOCATION")) + let env_location = std::env::var("GOOGLE_CLOUD_LOCATION") + .or_else(|_| std::env::var("GOOGLE_VERTEX_LOCATION")) .or_else(|_| std::env::var("VERTEX_LOCATION")) .unwrap_or_else(|_| "us-central1".to_string()); - let final_location = if vertex_location.is_empty() { - &env_location + let final_location = if !env_location.is_empty() { + env_location + } else if !vertex_location.is_empty() { + vertex_location.to_string() } else { - vertex_location + "us-central1".to_string() }; if final_project.is_empty() { @@ -122,8 +126,8 @@ pub fn resolve_provider_with_config( } else { std::sync::Arc::new(VertexAIProvider::new( api_key, - final_project.to_string(), - final_location.to_string(), + final_project, + final_location, )) } }