Detailed changes
@@ -111,9 +111,11 @@ impl AgentServerDelegate {
continue;
};
- if let Some(version) = file_name
- .to_str()
- .and_then(|name| semver::Version::from_str(&name).ok())
+ if let Some(name) = file_name.to_str()
+ && let Some(version) = semver::Version::from_str(name).ok()
+ && fs
+ .is_file(&dir.join(file_name).join(&entrypoint_path))
+ .await
{
versions.push((version, file_name.to_owned()));
} else {
@@ -156,6 +158,7 @@ impl AgentServerDelegate {
cx.background_spawn({
let file_name = file_name.clone();
let dir = dir.clone();
+ let fs = fs.clone();
async move {
let latest_version =
node_runtime.npm_package_latest_version(&package_name).await;
@@ -184,7 +187,7 @@ impl AgentServerDelegate {
}
let dir = dir.clone();
cx.background_spawn(Self::download_latest_version(
- fs,
+ fs.clone(),
dir.clone(),
node_runtime,
package_name,
@@ -192,14 +195,18 @@ impl AgentServerDelegate {
.await?
.into()
};
+
+ let agent_server_path = dir.join(version).join(entrypoint_path);
+ let agent_server_path_exists = fs.is_file(&agent_server_path).await;
+ anyhow::ensure!(
+ agent_server_path_exists,
+ "Missing entrypoint path {} after installation",
+ agent_server_path.to_string_lossy()
+ );
+
anyhow::Ok(AgentServerCommand {
path: node_path,
- args: vec![
- dir.join(version)
- .join(entrypoint_path)
- .to_string_lossy()
- .to_string(),
- ],
+ args: vec![agent_server_path.to_string_lossy().to_string()],
env: Default::default(),
})
})
@@ -76,6 +76,7 @@ impl AgentServer for ClaudeCode {
cx: &mut App,
) -> Task<Result<Rc<dyn AgentConnection>>> {
let root_dir = root_dir.to_path_buf();
+ let fs = delegate.project().read(cx).fs().clone();
let server_name = self.name();
let settings = cx.read_global(|settings: &SettingsStore, _| {
settings.get::<AllAgentServersSettings>(None).claude.clone()
@@ -109,6 +110,13 @@ impl AgentServer for ClaudeCode {
.insert("ANTHROPIC_API_KEY".to_owned(), api_key.key);
}
+ let root_dir_exists = fs.is_dir(&root_dir).await;
+ anyhow::ensure!(
+ root_dir_exists,
+ "Session root {} does not exist or is not a directory",
+ root_dir.to_string_lossy()
+ );
+
crate::acp::connect(server_name, command.clone(), &root_dir, cx).await
})
}
@@ -36,6 +36,7 @@ impl AgentServer for Gemini {
cx: &mut App,
) -> Task<Result<Rc<dyn AgentConnection>>> {
let root_dir = root_dir.to_path_buf();
+ let fs = delegate.project().read(cx).fs().clone();
let server_name = self.name();
let settings = cx.read_global(|settings: &SettingsStore, _| {
settings.get::<AllAgentServersSettings>(None).gemini.clone()
@@ -74,6 +75,13 @@ impl AgentServer for Gemini {
.insert("GEMINI_API_KEY".to_owned(), api_key.key);
}
+ let root_dir_exists = fs.is_dir(&root_dir).await;
+ anyhow::ensure!(
+ root_dir_exists,
+ "Session root {} does not exist or is not a directory",
+ root_dir.to_string_lossy()
+ );
+
let result = crate::acp::connect(server_name, command.clone(), &root_dir, cx).await;
match &result {
Ok(connection) => {
@@ -92,7 +100,7 @@ impl AgentServer for Gemini {
log::error!("connected to gemini, but missing prompt_capabilities.image (version is {current_version})");
return Err(LoadError::Unsupported {
current_version: current_version.into(),
- command: command.path.to_string_lossy().to_string().into(),
+ command: (command.path.to_string_lossy().to_string() + " " + &command.args.join(" ")).into(),
minimum_version: Self::MINIMUM_VERSION.into(),
}
.into());
@@ -129,7 +137,7 @@ impl AgentServer for Gemini {
if !supported {
return Err(LoadError::Unsupported {
current_version: current_version.into(),
- command: command.path.to_string_lossy().to_string().into(),
+ command: (command.path.to_string_lossy().to_string() + " " + &command.args.join(" ")).into(),
minimum_version: Self::MINIMUM_VERSION.into(),
}
.into());