fix: mcp bin path (#6667)

* fix: mcp bin path

* chore: clean up unused structs

* fix: bin name

* fix: tests
This commit is contained in:
Louis 2025-09-30 22:29:15 +07:00 committed by GitHub
parent 82d29e7a7d
commit 3c7eb64353
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 62 additions and 116 deletions

View File

@ -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}...`)

View File

@ -627,17 +627,28 @@ async fn schedule_mcp_start_task<R: Runtime>(
}
} 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);

View File

@ -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");
}

View File

@ -13,7 +13,6 @@
pub mod commands;
mod constants;
pub mod helpers;
pub mod models;
pub mod utils;
#[cfg(test)]

View File

@ -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<ThreadAssistantInfo>,
pub created: i64,
pub updated: i64,
pub metadata: Option<serde_json::Value>,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ThreadMessage {
pub id: String,
pub object: String,
pub thread_id: String,
pub assistant_id: Option<String>,
pub attachments: Option<Vec<Attachment>>,
pub role: String,
pub content: Vec<ThreadContent>,
pub status: String,
pub created_at: i64,
pub completed_at: i64,
pub metadata: Option<serde_json::Value>,
pub type_: Option<String>,
pub error_code: Option<String>,
pub tool_call_id: Option<String>,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Attachment {
pub file_id: Option<String>,
pub tools: Option<Vec<Tool>>,
}
#[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<ContentValue>,
pub image_url: Option<ImageContentValue>,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ContentValue {
pub value: String,
pub annotations: Vec<String>,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ImageContentValue {
pub detail: Option<String>,
pub url: Option<String>,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ThreadAssistantInfo {
pub id: String,
pub name: String,
pub model: ModelInfo,
pub instructions: Option<String>,
pub tools: Option<Vec<AssistantTool>>,
}
#[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<String>,
parameters: Option<serde_json::Value>,
},
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ThreadState {
pub has_more: bool,
pub waiting_for_response: bool,
pub error: Option<String>,
pub last_message: Option<String>,
}