mirror of
https://github.com/aaif-goose/goose.git
synced 2026-07-03 14:10:03 +02:00
fix: actually set the working dir for extensions from session (#6612)
This commit is contained in:
@@ -634,6 +634,7 @@ impl Agent {
|
||||
|
||||
/// Load extensions from session into the agent
|
||||
/// Skips extensions that are already loaded
|
||||
/// Uses the session's working_dir for extension initialization
|
||||
pub async fn load_extensions_from_session(
|
||||
self: &Arc<Self>,
|
||||
session: &Session,
|
||||
@@ -651,11 +652,15 @@ impl Agent {
|
||||
}
|
||||
};
|
||||
|
||||
// Capture the session's working_dir to pass to extensions
|
||||
let working_dir = session.working_dir.clone();
|
||||
|
||||
let extension_futures = enabled_configs
|
||||
.into_iter()
|
||||
.map(|config| {
|
||||
let config_clone = config.clone();
|
||||
let agent_ref = self.clone();
|
||||
let working_dir_clone = working_dir.clone();
|
||||
|
||||
async move {
|
||||
let name = config_clone.name().to_string();
|
||||
@@ -674,7 +679,10 @@ impl Agent {
|
||||
};
|
||||
}
|
||||
|
||||
match agent_ref.add_extension(config_clone).await {
|
||||
match agent_ref
|
||||
.add_extension_with_working_dir(config_clone, Some(working_dir_clone))
|
||||
.await
|
||||
{
|
||||
Ok(_) => ExtensionLoadResult {
|
||||
name,
|
||||
success: true,
|
||||
@@ -698,6 +706,14 @@ impl Agent {
|
||||
}
|
||||
|
||||
pub async fn add_extension(&self, extension: ExtensionConfig) -> ExtensionResult<()> {
|
||||
self.add_extension_with_working_dir(extension, None).await
|
||||
}
|
||||
|
||||
pub async fn add_extension_with_working_dir(
|
||||
&self,
|
||||
extension: ExtensionConfig,
|
||||
working_dir: Option<std::path::PathBuf>,
|
||||
) -> ExtensionResult<()> {
|
||||
match &extension {
|
||||
ExtensionConfig::Frontend {
|
||||
tools,
|
||||
@@ -726,7 +742,7 @@ impl Agent {
|
||||
}
|
||||
_ => {
|
||||
self.extension_manager
|
||||
.add_extension(extension.clone())
|
||||
.add_extension_with_working_dir(extension.clone(), working_dir)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -466,13 +466,6 @@ impl ExtensionManager {
|
||||
&self.context
|
||||
}
|
||||
|
||||
/// Resolve the working directory for an extension.
|
||||
/// Falls back to current_dir when working_dir is not available.
|
||||
async fn resolve_working_dir(&self) -> PathBuf {
|
||||
// Fall back to current_dir - working_dir is passed through the call chain from session
|
||||
std::env::current_dir().unwrap_or_default()
|
||||
}
|
||||
|
||||
pub async fn supports_resources(&self) -> bool {
|
||||
self.extensions
|
||||
.lock()
|
||||
@@ -481,7 +474,14 @@ impl ExtensionManager {
|
||||
.any(|ext| ext.supports_resources())
|
||||
}
|
||||
|
||||
pub async fn add_extension(self: &Arc<Self>, config: ExtensionConfig) -> ExtensionResult<()> {
|
||||
/// Add an extension with an optional working directory.
|
||||
/// If working_dir is None, falls back to current_dir.
|
||||
#[allow(clippy::too_many_lines)]
|
||||
pub async fn add_extension_with_working_dir(
|
||||
self: &Arc<Self>,
|
||||
config: ExtensionConfig,
|
||||
working_dir: Option<PathBuf>,
|
||||
) -> ExtensionResult<()> {
|
||||
let config_name = config.key().to_string();
|
||||
let sanitized_name = normalize(&config_name);
|
||||
|
||||
@@ -489,8 +489,9 @@ impl ExtensionManager {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Resolve working_dir: session > current_dir
|
||||
let effective_working_dir = self.resolve_working_dir().await;
|
||||
// Resolve working_dir: explicit > current_dir
|
||||
let effective_working_dir =
|
||||
working_dir.unwrap_or_else(|| std::env::current_dir().unwrap_or_default());
|
||||
|
||||
let mut temp_dir = None;
|
||||
|
||||
@@ -555,6 +556,17 @@ impl ExtensionManager {
|
||||
.ok_or_else(|| {
|
||||
ExtensionError::ConfigError(format!("Unknown builtin extension: {}", name))
|
||||
})?;
|
||||
|
||||
// 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);
|
||||
(def.spawn_server)(server_read, server_write);
|
||||
|
||||
@@ -211,7 +211,7 @@ impl ExtensionManagerClient {
|
||||
};
|
||||
|
||||
extension_manager
|
||||
.add_extension(config)
|
||||
.add_extension_with_working_dir(config, None)
|
||||
.await
|
||||
.map(|_| {
|
||||
vec![Content::text(format!(
|
||||
|
||||
@@ -264,7 +264,9 @@ async fn test_replayed_session(
|
||||
|
||||
#[allow(clippy::redundant_closure_call)]
|
||||
let result = (async || -> Result<(), Box<dyn std::error::Error>> {
|
||||
extension_manager.add_extension(extension_config).await?;
|
||||
extension_manager
|
||||
.add_extension_with_working_dir(extension_config, None)
|
||||
.await?;
|
||||
let mut results = Vec::new();
|
||||
for tool_call in tool_calls {
|
||||
let tool_call = CallToolRequestParam {
|
||||
|
||||
Reference in New Issue
Block a user