fix(acp): pass session_id when loading extensions so skills are discovered (#7868)

Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
Adrian Cole
2026-03-16 13:05:33 +08:00
committed by GitHub
parent 0cf4a619aa
commit 5265c52b74
7 changed files with 68 additions and 5 deletions
+2 -1
View File
@@ -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"),
@@ -689,6 +689,43 @@ pub async fn run_prompt_mcp<C: Connection>() {
expected_session_id.assert_matches(&session.session_id().0);
}
pub async fn run_prompt_skill<C: Connection>() {
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<C: Connection>(
mode_id: &str,
session_id_override: Option<&str>,
+2
View File
@@ -276,6 +276,7 @@ pub struct TestConnectionConfig {
pub mcp_servers: Vec<McpServer>,
pub builtins: Vec<String>,
pub goose_mode: GooseMode,
pub cwd: Option<tempfile::TempDir>,
pub data_root: PathBuf,
pub provider_factory: Option<ProviderConstructor>,
pub read_text_file: Option<ReadTextFileHandler>,
@@ -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,
+9 -1
View File
@@ -27,6 +27,7 @@ pub struct ClientToProviderConnection {
session_counter: usize,
_openai: OpenAiFixture,
_temp_dir: Option<tempfile::TempDir>,
_cwd: Option<tempfile::TempDir>,
}
#[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,
}
}
+6 -1
View File
@@ -20,6 +20,7 @@ pub struct ClientToAgentConnection {
cx: JrConnectionCx<ClientToAgent>,
// MCP servers from config, consumed by the first new_session call.
pending_mcp_servers: Vec<McpServer>,
cwd: Option<tempfile::TempDir>,
updates: Arc<Mutex<Vec<SessionNotification>>>,
permission: Arc<Mutex<PermissionDecision>>,
notify: Arc<Notify>,
@@ -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<ClientToAgentSession> {
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
+6 -1
View File
@@ -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::<ClientToProviderConnection>().await });
}
#[test]
fn test_prompt_skill() {
run_test(async { run_prompt_skill::<ClientToProviderConnection>().await });
}
+6 -1
View File
@@ -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::<ClientToAgentConnection>().await });
}
#[test]
fn test_prompt_skill() {
run_test(async { run_prompt_skill::<ClientToAgentConnection>().await });
}