context_server: Change command string field to PathBuf (#34873)

Ben Brandt created

Release Notes:

- N/A

Change summary

crates/agent_ui/src/agent_configuration/configure_context_server_modal.rs |  8 
crates/context_server/src/context_server.rs                               |  4 
crates/extension/src/types.rs                                             |  4 
crates/extension_host/src/wasm_host/wit/since_v0_6_0.rs                   |  4 
crates/project/src/context_server_store.rs                                | 18 
crates/project/src/context_server_store/extension.rs                      |  5 
crates/project/src/project_settings.rs                                    |  2 
7 files changed, 22 insertions(+), 23 deletions(-)

Detailed changes

crates/agent_ui/src/agent_configuration/configure_context_server_modal.rs 🔗

@@ -1,4 +1,5 @@
 use std::{
+    path::PathBuf,
     sync::{Arc, Mutex},
     time::Duration,
 };
@@ -188,7 +189,7 @@ fn context_server_input(existing: Option<(ContextServerId, ContextServerCommand)
         }
         None => (
             "some-mcp-server".to_string(),
-            "".to_string(),
+            PathBuf::new(),
             "[]".to_string(),
             "{}".to_string(),
         ),
@@ -199,13 +200,14 @@ fn context_server_input(existing: Option<(ContextServerId, ContextServerCommand)
   /// The name of your MCP server
   "{name}": {{
     /// The command which runs the MCP server
-    "command": "{command}",
+    "command": "{}",
     /// The arguments to pass to the MCP server
     "args": {args},
     /// The environment variables to set
     "env": {env}
   }}
-}}"#
+}}"#,
+        command.display()
     )
 }
 

crates/context_server/src/context_server.rs 🔗

@@ -6,9 +6,9 @@ pub mod test;
 pub mod transport;
 pub mod types;
 
-use std::fmt::Display;
 use std::path::Path;
 use std::sync::Arc;
+use std::{fmt::Display, path::PathBuf};
 
 use anyhow::Result;
 use client::Client;
@@ -31,7 +31,7 @@ impl Display for ContextServerId {
 #[derive(Deserialize, Serialize, Clone, PartialEq, Eq, JsonSchema)]
 pub struct ContextServerCommand {
     #[serde(rename = "command")]
-    pub path: String,
+    pub path: PathBuf,
     pub args: Vec<String>,
     pub env: Option<HashMap<String, String>>,
 }

crates/extension/src/types.rs 🔗

@@ -3,7 +3,7 @@ mod dap;
 mod lsp;
 mod slash_command;
 
-use std::ops::Range;
+use std::{ops::Range, path::PathBuf};
 
 use util::redact::should_redact;
 
@@ -18,7 +18,7 @@ pub type EnvVars = Vec<(String, String)>;
 /// A command.
 pub struct Command {
     /// The command to execute.
-    pub command: String,
+    pub command: PathBuf,
     /// The arguments to pass to the command.
     pub args: Vec<String>,
     /// The environment variables to set for the command.

crates/extension_host/src/wasm_host/wit/since_v0_6_0.rs 🔗

@@ -75,7 +75,7 @@ impl From<Range> for std::ops::Range<usize> {
 impl From<Command> for extension::Command {
     fn from(value: Command) -> Self {
         Self {
-            command: value.command,
+            command: value.command.into(),
             args: value.args,
             env: value.env,
         }
@@ -958,7 +958,7 @@ impl ExtensionImports for WasmState {
                                 command,
                             } => Ok(serde_json::to_string(&settings::ContextServerSettings {
                                 command: Some(settings::CommandSettings {
-                                    path: Some(command.path),
+                                    path: command.path.to_str().map(|path| path.to_string()),
                                     arguments: Some(command.args),
                                     env: command.env.map(|env| env.into_iter().collect()),
                                 }),

crates/project/src/context_server_store.rs 🔗

@@ -610,7 +610,7 @@ mod tests {
     use context_server::test::create_fake_transport;
     use gpui::{AppContext, TestAppContext, UpdateGlobal as _};
     use serde_json::json;
-    use std::{cell::RefCell, rc::Rc};
+    use std::{cell::RefCell, path::PathBuf, rc::Rc};
     use util::path;
 
     #[gpui::test]
@@ -931,7 +931,7 @@ mod tests {
                         ContextServerSettings::Custom {
                             enabled: true,
                             command: ContextServerCommand {
-                                path: "somebinary".to_string(),
+                                path: "somebinary".into(),
                                 args: vec!["arg".to_string()],
                                 env: None,
                             },
@@ -971,7 +971,7 @@ mod tests {
                         ContextServerSettings::Custom {
                             enabled: true,
                             command: ContextServerCommand {
-                                path: "somebinary".to_string(),
+                                path: "somebinary".into(),
                                 args: vec!["anotherArg".to_string()],
                                 env: None,
                             },
@@ -1053,7 +1053,7 @@ mod tests {
                 ContextServerSettings::Custom {
                     enabled: true,
                     command: ContextServerCommand {
-                        path: "somebinary".to_string(),
+                        path: "somebinary".into(),
                         args: vec!["arg".to_string()],
                         env: None,
                     },
@@ -1104,7 +1104,7 @@ mod tests {
                     ContextServerSettings::Custom {
                         enabled: false,
                         command: ContextServerCommand {
-                            path: "somebinary".to_string(),
+                            path: "somebinary".into(),
                             args: vec!["arg".to_string()],
                             env: None,
                         },
@@ -1132,7 +1132,7 @@ mod tests {
                     ContextServerSettings::Custom {
                         enabled: true,
                         command: ContextServerCommand {
-                            path: "somebinary".to_string(),
+                            path: "somebinary".into(),
                             args: vec!["arg".to_string()],
                             env: None,
                         },
@@ -1184,7 +1184,7 @@ mod tests {
         ContextServerSettings::Custom {
             enabled: true,
             command: ContextServerCommand {
-                path: "somebinary".to_string(),
+                path: "somebinary".into(),
                 args: vec!["arg".to_string()],
                 env: None,
             },
@@ -1256,11 +1256,11 @@ mod tests {
     }
 
     struct FakeContextServerDescriptor {
-        path: String,
+        path: PathBuf,
     }
 
     impl FakeContextServerDescriptor {
-        fn new(path: impl Into<String>) -> Self {
+        fn new(path: impl Into<PathBuf>) -> Self {
             Self { path: path.into() }
         }
     }

crates/project/src/context_server_store/extension.rs 🔗

@@ -61,10 +61,7 @@ impl registry::ContextServerDescriptor for ContextServerDescriptor {
             let mut command = extension
                 .context_server_command(id.clone(), extension_project.clone())
                 .await?;
-            command.command = extension
-                .path_from_extension(command.command.as_ref())
-                .to_string_lossy()
-                .to_string();
+            command.command = extension.path_from_extension(&command.command);
 
             log::info!("loaded command for context server {id}: {command:?}");
 

crates/project/src/project_settings.rs 🔗

@@ -581,7 +581,7 @@ impl Settings for ProjectSettings {
 
         #[derive(Deserialize)]
         struct VsCodeContextServerCommand {
-            command: String,
+            command: PathBuf,
             args: Option<Vec<String>>,
             env: Option<HashMap<String, String>>,
             // note: we don't support envFile and type