Fix agent servers loading environment from home dir instead of project dir (#52763)

Derek Parker created

All local agent server types were calling `local_directory_environment`
with `paths::home_dir()`, causing direnv and shell environment to be
loaded from `~` rather than the project's worktree directory. This meant
project-specific `.envrc` variables (e.g. Google Vertex credentials)
were never picked up by external agents like Claude.

Added `default_environment()` on `ProjectEnvironment` that resolves the
default visible worktree path and uses it for environment loading,
falling back to home_dir() only when no worktree is available.

Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Closes #ISSUE

Release Notes:

- Fixed default environment variable context for external agents

Change summary

crates/project/src/agent_server_store.rs | 25 ++++---------------------
crates/project/src/environment.rs        | 21 +++++++++++++++++++++
2 files changed, 25 insertions(+), 21 deletions(-)

Detailed changes

crates/project/src/agent_server_store.rs 🔗

@@ -22,7 +22,6 @@ use schemars::JsonSchema;
 use serde::{Deserialize, Serialize};
 use settings::{RegisterSetting, SettingsStore};
 use sha2::{Digest, Sha256};
-use task::Shell;
 use url::Url;
 use util::{ResultExt as _, debug_panic};
 
@@ -1183,11 +1182,7 @@ impl ExternalAgentServer for LocalExtensionArchiveAgent {
             // Get project environment
             let mut env = project_environment
                 .update(cx, |project_environment, cx| {
-                    project_environment.local_directory_environment(
-                        &Shell::System,
-                        paths::home_dir().as_path().into(),
-                        cx,
-                    )
+                    project_environment.default_environment(cx)
                 })?
                 .await
                 .unwrap_or_default();
@@ -1377,11 +1372,7 @@ impl ExternalAgentServer for LocalRegistryArchiveAgent {
         cx.spawn(async move |cx| {
             let mut env = project_environment
                 .update(cx, |project_environment, cx| {
-                    project_environment.local_directory_environment(
-                        &Shell::System,
-                        paths::home_dir().as_path().into(),
-                        cx,
-                    )
+                    project_environment.default_environment(cx)
                 })?
                 .await
                 .unwrap_or_default();
@@ -1555,11 +1546,7 @@ impl ExternalAgentServer for LocalRegistryNpxAgent {
         cx.spawn(async move |cx| {
             let mut env = project_environment
                 .update(cx, |project_environment, cx| {
-                    project_environment.local_directory_environment(
-                        &Shell::System,
-                        paths::home_dir().as_path().into(),
-                        cx,
-                    )
+                    project_environment.default_environment(cx)
                 })?
                 .await
                 .unwrap_or_default();
@@ -1615,11 +1602,7 @@ impl ExternalAgentServer for LocalCustomAgent {
         cx.spawn(async move |cx| {
             let mut env = project_environment
                 .update(cx, |project_environment, cx| {
-                    project_environment.local_directory_environment(
-                        &Shell::System,
-                        paths::home_dir().as_path().into(),
-                        cx,
-                    )
+                    project_environment.default_environment(cx)
                 })?
                 .await
                 .unwrap_or_default();

crates/project/src/environment.rs 🔗

@@ -194,6 +194,27 @@ impl ProjectEnvironment {
         .unwrap_or_else(|| Task::ready(None).shared())
     }
 
+    /// Returns the project environment using the default worktree path.
+    /// This ensures that project-specific environment variables (e.g. from `.envrc`)
+    /// are loaded from the project directory rather than the home directory.
+    pub fn default_environment(
+        &mut self,
+        cx: &mut App,
+    ) -> Shared<Task<Option<HashMap<String, String>>>> {
+        let abs_path = self
+            .worktree_store
+            .read_with(cx, |worktree_store, cx| {
+                crate::Project::default_visible_worktree_paths(worktree_store, cx)
+                    .into_iter()
+                    .next()
+            })
+            .ok()
+            .flatten()
+            .map(|path| Arc::<Path>::from(path))
+            .unwrap_or_else(|| paths::home_dir().as_path().into());
+        self.local_directory_environment(&Shell::System, abs_path, cx)
+    }
+
     /// Returns the project environment, if possible.
     /// If the project was opened from the CLI, then the inherited CLI environment is returned.
     /// If it wasn't opened from the CLI, and an absolute path is given, then a shell is spawned in