diff --git a/scripts/download-bin.mjs b/scripts/download-bin.mjs index 39eb9ae87..68f09bf5f 100644 --- a/scripts/download-bin.mjs +++ b/scripts/download-bin.mjs @@ -106,13 +106,11 @@ async function main() { } // Adjust these URLs based on latest releases - const bunVersion = '1.2.10' // Example Bun version - const bunUrl = `https://github.com/oven-sh/bun/releases/download/bun-v${bunVersion}/bun-${bunPlatform}.zip` + const bunUrl = `https://github.com/oven-sh/bun/releases/latest/download/bun-${bunPlatform}.zip` - const uvVersion = '0.6.17' // Example UV version - let uvUrl = `https://github.com/astral-sh/uv/releases/download/${uvVersion}/uv-${uvPlatform}.tar.gz` + let uvUrl = `https://github.com/astral-sh/uv/releases/latest/download/uv-${uvPlatform}.tar.gz` if (platform === 'win32') { - uvUrl = `https://github.com/astral-sh/uv/releases/download/${uvVersion}/uv-${uvPlatform}.zip` + uvUrl = `https://github.com/astral-sh/uv/releases/latest/download/uv-${uvPlatform}.zip` } console.log(`Downloading Bun for ${bunPlatform}...`) diff --git a/src-tauri/src/core/mcp/helpers.rs b/src-tauri/src/core/mcp/helpers.rs index 7f8565e39..8f55d7479 100644 --- a/src-tauri/src/core/mcp/helpers.rs +++ b/src-tauri/src/core/mcp/helpers.rs @@ -627,17 +627,28 @@ async fn schedule_mcp_start_task( } } else { let mut cmd = Command::new(config_params.command.clone()); - let bun_x_path = format!("{}/bun", bin_path.display()); - if config_params.command.clone() == "npx" && can_override_npx(bun_x_path.clone()) { + let bun_x_path = if cfg!(windows) { + bin_path.join("bun.exe") + } else { + bin_path.join("bun") + }; + if config_params.command.clone() == "npx" + && can_override_npx(bun_x_path.display().to_string()) + { let mut cache_dir = app_path.clone(); cache_dir.push(".npx"); - cmd = Command::new(bun_x_path); + cmd = Command::new(bun_x_path.display().to_string()); cmd.arg("x"); cmd.env("BUN_INSTALL", cache_dir.to_str().unwrap().to_string()); } - let uv_path = format!("{}/uv", bin_path.display()); - if config_params.command.clone() == "uvx" && can_override_uvx(uv_path.clone()) { + let uv_path = if cfg!(windows) { + bin_path.join("uv.exe") + } else { + bin_path.join("uv") + }; + if config_params.command.clone() == "uvx" && can_override_uvx(uv_path.display().to_string()) + { let mut cache_dir = app_path.clone(); cache_dir.push(".uvx"); cmd = Command::new(uv_path); diff --git a/src-tauri/src/core/mcp/tests.rs b/src-tauri/src/core/mcp/tests.rs index 081a188e8..42289226a 100644 --- a/src-tauri/src/core/mcp/tests.rs +++ b/src-tauri/src/core/mcp/tests.rs @@ -4,6 +4,7 @@ use crate::core::state::SharedMcpServers; use std::collections::HashMap; use std::fs::File; use std::io::Write; +use std::path::PathBuf; use std::sync::Arc; use tauri::test::mock_app; use tokio::sync::Mutex; @@ -27,8 +28,7 @@ async fn test_run_mcp_commands() { .expect("Failed to write to config file"); // Call the run_mcp_commands function - let servers_state: SharedMcpServers = - Arc::new(Mutex::new(HashMap::new())); + let servers_state: SharedMcpServers = Arc::new(Mutex::new(HashMap::new())); let result = run_mcp_commands(app.handle(), servers_state).await; // Assert that the function returns Ok(()) @@ -37,3 +37,44 @@ async fn test_run_mcp_commands() { // Clean up the mock config file std::fs::remove_file(&config_path).expect("Failed to remove config file"); } + +#[cfg(not(target_os = "windows"))] +#[test] +fn test_bin_path_construction_with_join() { + // Test that PathBuf::join properly constructs paths + let bin_path = PathBuf::from("/usr/local/bin"); + let bun_path = bin_path.join("bun"); + + assert_eq!(bun_path.to_string_lossy(), "/usr/local/bin/bun"); + + // Test conversion to String via display() + let bun_path_str = bun_path.display().to_string(); + assert_eq!(bun_path_str, "/usr/local/bin/bun"); +} + +#[cfg(not(target_os = "windows"))] +#[test] +fn test_uv_path_construction_with_join() { + // Test that PathBuf::join properly constructs paths for uv + let bin_path = PathBuf::from("/usr/local/bin"); + let uv_path = bin_path.join("uv"); + + assert_eq!(uv_path.to_string_lossy(), "/usr/local/bin/uv"); + + // Test conversion to String via display() + let uv_path_str = uv_path.display().to_string(); + assert_eq!(uv_path_str, "/usr/local/bin/uv"); +} + +#[cfg(target_os = "windows")] +#[test] +fn test_bin_path_construction_windows() { + // Test Windows-style paths + let bin_path = PathBuf::from(r"C:\Program Files\bin"); + let bun_path = bin_path.join("bun.exe"); + + assert_eq!(bun_path.to_string_lossy(), r"C:\Program Files\bin\bun.exe"); + + let bun_path_str = bun_path.display().to_string(); + assert_eq!(bun_path_str, r"C:\Program Files\bin\bun.exe"); +} diff --git a/src-tauri/src/core/threads/mod.rs b/src-tauri/src/core/threads/mod.rs index fb76bee8c..25225d538 100644 --- a/src-tauri/src/core/threads/mod.rs +++ b/src-tauri/src/core/threads/mod.rs @@ -13,7 +13,6 @@ pub mod commands; mod constants; pub mod helpers; -pub mod models; pub mod utils; #[cfg(test)] diff --git a/src-tauri/src/core/threads/models.rs b/src-tauri/src/core/threads/models.rs deleted file mode 100644 index 5038c6def..000000000 --- a/src-tauri/src/core/threads/models.rs +++ /dev/null @@ -1,103 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Serialize, Deserialize, Clone)] -pub struct Thread { - pub id: String, - pub object: String, - pub title: String, - pub assistants: Vec, - pub created: i64, - pub updated: i64, - pub metadata: Option, -} - -#[derive(Debug, Serialize, Deserialize, Clone)] -pub struct ThreadMessage { - pub id: String, - pub object: String, - pub thread_id: String, - pub assistant_id: Option, - pub attachments: Option>, - pub role: String, - pub content: Vec, - pub status: String, - pub created_at: i64, - pub completed_at: i64, - pub metadata: Option, - pub type_: Option, - pub error_code: Option, - pub tool_call_id: Option, -} - -#[derive(Debug, Serialize, Deserialize, Clone)] -pub struct Attachment { - pub file_id: Option, - pub tools: Option>, -} - -#[derive(Debug, Serialize, Deserialize, Clone)] -#[serde(tag = "type")] -pub enum Tool { - #[serde(rename = "file_search")] - FileSearch, - #[serde(rename = "code_interpreter")] - CodeInterpreter, -} - -#[derive(Debug, Serialize, Deserialize, Clone)] -pub struct ThreadContent { - pub type_: String, - pub text: Option, - pub image_url: Option, -} - -#[derive(Debug, Serialize, Deserialize, Clone)] -pub struct ContentValue { - pub value: String, - pub annotations: Vec, -} - -#[derive(Debug, Serialize, Deserialize, Clone)] -pub struct ImageContentValue { - pub detail: Option, - pub url: Option, -} - -#[derive(Debug, Serialize, Deserialize, Clone)] -pub struct ThreadAssistantInfo { - pub id: String, - pub name: String, - pub model: ModelInfo, - pub instructions: Option, - pub tools: Option>, -} - -#[derive(Debug, Serialize, Deserialize, Clone)] -pub struct ModelInfo { - pub id: String, - pub name: String, - pub settings: serde_json::Value, -} - -#[derive(Debug, Serialize, Deserialize, Clone)] -#[serde(tag = "type")] -pub enum AssistantTool { - #[serde(rename = "code_interpreter")] - CodeInterpreter, - #[serde(rename = "retrieval")] - Retrieval, - #[serde(rename = "function")] - Function { - name: String, - description: Option, - parameters: Option, - }, -} - -#[derive(Debug, Serialize, Deserialize, Clone)] -pub struct ThreadState { - pub has_more: bool, - pub waiting_for_response: bool, - pub error: Option, - pub last_message: Option, -}