diff --git a/crates/goose-acp/src/server.rs b/crates/goose-acp/src/server.rs index ca5f475ebe..cb6d4be246 100644 --- a/crates/goose-acp/src/server.rs +++ b/crates/goose-acp/src/server.rs @@ -435,6 +435,7 @@ impl GooseAcpAgent { _ => None, }; let skip_developer = acp_developer.is_some(); + let sid_str = session_id.map(|s| s.0.to_string()); for ext in extensions { if skip_developer && ext.name() == "developer" { @@ -443,7 +444,7 @@ impl GooseAcpAgent { let name = ext.name().to_string(); match agent .extension_manager - .add_extension(ext, None, None, None) + .add_extension(ext, None, None, sid_str.as_deref()) .await { Ok(_) => info!(extension = %name, "extension loaded"), diff --git a/crates/goose-acp/tests/common_tests/mod.rs b/crates/goose-acp/tests/common_tests/mod.rs index 2e52e1a2de..a58855c664 100644 --- a/crates/goose-acp/tests/common_tests/mod.rs +++ b/crates/goose-acp/tests/common_tests/mod.rs @@ -689,6 +689,43 @@ pub async fn run_prompt_mcp() { expected_session_id.assert_matches(&session.session_id().0); } +pub async fn run_prompt_skill() { + let cwd = tempfile::tempdir().unwrap(); + let skill_dir = cwd.path().join(".agents/skills/test-skill"); + fs::create_dir_all(&skill_dir).unwrap(); + fs::write( + skill_dir.join("SKILL.md"), + "---\nname: test-skill\ndescription: skill-loaded-in-acp-session\n---\nTest instructions\n", + ) + .unwrap(); + + let expected_session_id = C::expected_session_id(); + let openai = OpenAiFixture::new( + vec![( + "skill-loaded-in-acp-session".to_string(), + include_str!("../test_data/openai_basic.txt"), + )], + expected_session_id.clone(), + ) + .await; + + let config = TestConnectionConfig { + builtins: vec!["summon".to_string()], + cwd: Some(cwd), + ..Default::default() + }; + + let mut conn = C::new(config, openai).await; + let SessionResult { mut session, .. } = conn.new_session().await; + expected_session_id.set(&session.session_id().0); + + let output = session + .prompt("what is 1+1", PermissionDecision::Cancel) + .await; + assert_eq!(output.text, "2"); + expected_session_id.assert_matches(&session.session_id().0); +} + pub async fn run_mode_set_error( mode_id: &str, session_id_override: Option<&str>, diff --git a/crates/goose-acp/tests/fixtures/mod.rs b/crates/goose-acp/tests/fixtures/mod.rs index fef698b6ae..1fe2f74257 100644 --- a/crates/goose-acp/tests/fixtures/mod.rs +++ b/crates/goose-acp/tests/fixtures/mod.rs @@ -276,6 +276,7 @@ pub struct TestConnectionConfig { pub mcp_servers: Vec, pub builtins: Vec, pub goose_mode: GooseMode, + pub cwd: Option, pub data_root: PathBuf, pub provider_factory: Option, pub read_text_file: Option, @@ -288,6 +289,7 @@ impl Default for TestConnectionConfig { mcp_servers: Vec::new(), builtins: Vec::new(), goose_mode: GooseMode::default(), + cwd: None, data_root: PathBuf::new(), provider_factory: None, read_text_file: None, diff --git a/crates/goose-acp/tests/fixtures/provider.rs b/crates/goose-acp/tests/fixtures/provider.rs index 608b2d910b..a255597c73 100644 --- a/crates/goose-acp/tests/fixtures/provider.rs +++ b/crates/goose-acp/tests/fixtures/provider.rs @@ -27,6 +27,7 @@ pub struct ClientToProviderConnection { session_counter: usize, _openai: OpenAiFixture, _temp_dir: Option, + _cwd: Option, } #[allow(dead_code)] @@ -128,12 +129,18 @@ impl Connection for ClientToProviderConnection { ) .await; + let cwd_path = config + .cwd + .as_ref() + .map(|td| td.path().to_path_buf()) + .unwrap_or(data_root); + let provider_config = AcpProviderConfig { command: "unused".into(), args: vec![], env: vec![], env_remove: vec![], - work_dir: data_root, + work_dir: cwd_path, mcp_servers, session_mode_id: None, permission_mapping: PermissionMapping::default(), @@ -159,6 +166,7 @@ impl Connection for ClientToProviderConnection { session_counter: 0, _openai: openai, _temp_dir: temp_dir, + _cwd: config.cwd, } } diff --git a/crates/goose-acp/tests/fixtures/server.rs b/crates/goose-acp/tests/fixtures/server.rs index 0c4180c0b2..edd72d2ded 100644 --- a/crates/goose-acp/tests/fixtures/server.rs +++ b/crates/goose-acp/tests/fixtures/server.rs @@ -20,6 +20,7 @@ pub struct ClientToAgentConnection { cx: JrConnectionCx, // MCP servers from config, consumed by the first new_session call. pending_mcp_servers: Vec, + cwd: Option, updates: Arc>>, permission: Arc>, notify: Arc, @@ -222,6 +223,7 @@ impl Connection for ClientToAgentConnection { Self { cx, pending_mcp_servers: config.mcp_servers, + cwd: config.cwd, updates, permission, notify, @@ -233,7 +235,10 @@ impl Connection for ClientToAgentConnection { } async fn new_session(&mut self) -> SessionResult { - let work_dir = tempfile::tempdir().unwrap(); + let work_dir = self + .cwd + .take() + .unwrap_or_else(|| tempfile::tempdir().unwrap()); let mcp_servers = std::mem::take(&mut self.pending_mcp_servers); let response = self .cx diff --git a/crates/goose-acp/tests/provider_test.rs b/crates/goose-acp/tests/provider_test.rs index 34f0435a66..fea565886d 100644 --- a/crates/goose-acp/tests/provider_test.rs +++ b/crates/goose-acp/tests/provider_test.rs @@ -8,7 +8,7 @@ use common_tests::{ run_fs_write_text_file_true, run_initialize_doesnt_hit_provider, run_load_mode, run_load_model, run_load_session_mcp, run_mode_set, run_model_list, run_model_set, run_permission_persistence, run_prompt_basic, run_prompt_codemode, run_prompt_image, run_prompt_image_attachment, - run_prompt_mcp, + run_prompt_mcp, run_prompt_skill, }; tests_mode_set_error!(ClientToProviderConnection); @@ -103,3 +103,8 @@ fn test_prompt_image_attachment() { fn test_prompt_mcp() { run_test(async { run_prompt_mcp::().await }); } + +#[test] +fn test_prompt_skill() { + run_test(async { run_prompt_skill::().await }); +} diff --git a/crates/goose-acp/tests/server_test.rs b/crates/goose-acp/tests/server_test.rs index c3a5ac7248..1a232d75a3 100644 --- a/crates/goose-acp/tests/server_test.rs +++ b/crates/goose-acp/tests/server_test.rs @@ -6,7 +6,7 @@ use common_tests::{ run_fs_write_text_file_true, run_initialize_doesnt_hit_provider, run_load_mode, run_load_model, run_load_session_mcp, run_mode_set, run_model_list, run_model_set, run_permission_persistence, run_prompt_basic, run_prompt_codemode, run_prompt_image, run_prompt_image_attachment, - run_prompt_mcp, + run_prompt_mcp, run_prompt_skill, }; tests_mode_set_error!(ClientToAgentConnection); @@ -97,3 +97,8 @@ fn test_prompt_image_attachment() { fn test_prompt_mcp() { run_test(async { run_prompt_mcp::().await }); } + +#[test] +fn test_prompt_skill() { + run_test(async { run_prompt_skill::().await }); +}