fix: per session working dir isolation (#6920)

This commit is contained in:
Zane
2026-02-03 10:20:02 -08:00
committed by GitHub
parent 8631caa890
commit aa356bd460
16 changed files with 143 additions and 68 deletions
+47 -18
View File
@@ -599,16 +599,6 @@ impl ExtensionManager {
.await?;
Box::new(client)
} else {
// Set GOOSE_WORKING_DIR in the current process for builtin extensions
// since they run in-process and read from std::env::var
if effective_working_dir.exists() && effective_working_dir.is_dir() {
std::env::set_var("GOOSE_WORKING_DIR", &effective_working_dir);
tracing::info!(
"Set GOOSE_WORKING_DIR for builtin extension: {:?}",
effective_working_dir
);
}
let (server_read, client_write) = tokio::io::duplex(65536);
let (client_read, server_write) = tokio::io::duplex(65536);
extension_fn(server_read, server_write);
@@ -1189,6 +1179,7 @@ impl ExtensionManager {
&self,
session_id: &str,
tool_call: CallToolRequestParams,
working_dir: Option<&std::path::Path>,
cancellation_token: CancellationToken,
) -> Result<ToolCallResult> {
// Some models strip the tool prefix, so auto-add it for known code_execution tools
@@ -1248,16 +1239,24 @@ impl ExtensionManager {
let client = client.clone();
let notifications_receiver = client.lock().await.subscribe().await;
let session_id = session_id.to_string();
let working_dir_str = working_dir.map(|p| p.to_string_lossy().to_string());
let fut = async move {
tracing::debug!(
"dispatch_tool_call fut: calling client.call_tool tool={} session_id={}",
"dispatch_tool_call fut: calling client.call_tool tool={} session_id={} working_dir={:?}",
tool_name,
session_id
session_id,
working_dir_str
);
let client_guard = client.lock().await;
client_guard
.call_tool(&session_id, &tool_name, arguments, cancellation_token)
.call_tool(
&session_id,
&tool_name,
arguments,
working_dir_str.as_deref(),
cancellation_token,
)
.await
.map_err(|e| match e {
ServiceError::McpError(error_data) => error_data,
@@ -1591,6 +1590,7 @@ mod tests {
_session_id: &str,
name: &str,
_arguments: Option<JsonObject>,
_working_dir: Option<&str>,
_cancellation_token: CancellationToken,
) -> Result<CallToolResult, Error> {
match name {
@@ -1727,7 +1727,12 @@ mod tests {
};
let result = extension_manager
.dispatch_tool_call("test-session-id", tool_call, CancellationToken::default())
.dispatch_tool_call(
"test-session-id",
tool_call,
None,
CancellationToken::default(),
)
.await;
assert!(result.is_ok());
@@ -1739,7 +1744,12 @@ mod tests {
};
let result = extension_manager
.dispatch_tool_call("test-session-id", tool_call, CancellationToken::default())
.dispatch_tool_call(
"test-session-id",
tool_call,
None,
CancellationToken::default(),
)
.await;
assert!(result.is_ok());
@@ -1752,7 +1762,12 @@ mod tests {
};
let result = extension_manager
.dispatch_tool_call("test-session-id", tool_call, CancellationToken::default())
.dispatch_tool_call(
"test-session-id",
tool_call,
None,
CancellationToken::default(),
)
.await;
assert!(result.is_ok());
@@ -1765,7 +1780,12 @@ mod tests {
};
let result = extension_manager
.dispatch_tool_call("test-session-id", tool_call, CancellationToken::default())
.dispatch_tool_call(
"test-session-id",
tool_call,
None,
CancellationToken::default(),
)
.await;
assert!(result.is_ok());
@@ -1777,7 +1797,12 @@ mod tests {
};
let result = extension_manager
.dispatch_tool_call("test-session-id", tool_call, CancellationToken::default())
.dispatch_tool_call(
"test-session-id",
tool_call,
None,
CancellationToken::default(),
)
.await;
assert!(result.is_ok());
@@ -1793,6 +1818,7 @@ mod tests {
.dispatch_tool_call(
"test-session-id",
invalid_tool_call,
None,
CancellationToken::default(),
)
.await
@@ -1820,6 +1846,7 @@ mod tests {
.dispatch_tool_call(
"test-session-id",
invalid_tool_call,
None,
CancellationToken::default(),
)
.await;
@@ -1922,6 +1949,7 @@ mod tests {
.dispatch_tool_call(
"test-session-id",
unavailable_tool_call,
None,
CancellationToken::default(),
)
.await;
@@ -1947,6 +1975,7 @@ mod tests {
.dispatch_tool_call(
"test-session-id",
available_tool_call,
None,
CancellationToken::default(),
)
.await;