feat(goose-acp): enable parallel sessions with isolated agent state (#6392)

Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
Adrian Cole
2026-01-15 06:19:17 +08:00
committed by GitHub
parent fb0eca2c36
commit 7d4a6bd8ff
86 changed files with 2594 additions and 1938 deletions
+69 -29
View File
@@ -15,11 +15,15 @@ mod tests {
use async_trait::async_trait;
use chrono::{DateTime, Utc};
use goose::agents::platform_tools::PLATFORM_MANAGE_SCHEDULE_TOOL_NAME;
use goose::agents::AgentConfig;
use goose::config::permission::PermissionManager;
use goose::config::GooseMode;
use goose::scheduler::{ScheduledJob, SchedulerError};
use goose::scheduler_trait::SchedulerTrait;
use goose::session::Session;
use goose::session::{Session, SessionManager};
use std::path::PathBuf;
use std::sync::Arc;
use tempfile::TempDir;
struct MockScheduler {
jobs: tokio::sync::Mutex<Vec<ScheduledJob>>,
@@ -114,12 +118,20 @@ mod tests {
#[tokio::test]
async fn test_schedule_management_tool_list() {
let agent = Agent::new();
let temp_dir = TempDir::new().unwrap();
let data_dir = temp_dir.path().to_path_buf();
let session_manager = Arc::new(SessionManager::new(data_dir.clone()));
let permission_manager = Arc::new(PermissionManager::new(data_dir));
let mock_scheduler = Arc::new(MockScheduler::new());
agent.set_scheduler(mock_scheduler.clone()).await;
let config = AgentConfig::new(
session_manager,
permission_manager,
Some(mock_scheduler),
GooseMode::Auto,
);
let agent = Agent::with_config(config);
// Test that the schedule management tool is available in the tools list
let tools = agent.list_tools(None).await;
let tools = agent.list_tools("test-session-id", None).await;
let schedule_tool = tools
.iter()
.find(|tool| tool.name == PLATFORM_MANAGE_SCHEDULE_TOOL_NAME);
@@ -137,7 +149,7 @@ mod tests {
async fn test_no_schedule_management_tool_without_scheduler() {
let agent = Agent::new();
let tools = agent.list_tools(None).await;
let tools = agent.list_tools("test-session-id", None).await;
let schedule_tool = tools
.iter()
.find(|tool| tool.name == PLATFORM_MANAGE_SCHEDULE_TOOL_NAME);
@@ -146,11 +158,22 @@ mod tests {
#[tokio::test]
async fn test_schedule_management_tool_in_platform_tools() {
let agent = Agent::new();
let temp_dir = TempDir::new().unwrap();
let data_dir = temp_dir.path().to_path_buf();
let session_manager = Arc::new(SessionManager::new(data_dir.clone()));
let permission_manager = Arc::new(PermissionManager::new(data_dir));
let mock_scheduler = Arc::new(MockScheduler::new());
agent.set_scheduler(mock_scheduler.clone()).await;
let config = AgentConfig::new(
session_manager,
permission_manager,
Some(mock_scheduler),
GooseMode::Auto,
);
let agent = Agent::with_config(config);
let tools = agent.list_tools(Some("platform".to_string())).await;
let tools = agent
.list_tools("test-session-id", Some("platform".to_string()))
.await;
// Check that the schedule management tool is included in platform tools
let schedule_tool = tools
@@ -188,11 +211,20 @@ mod tests {
#[tokio::test]
async fn test_schedule_management_tool_schema_validation() {
let agent = Agent::new();
let temp_dir = TempDir::new().unwrap();
let data_dir = temp_dir.path().to_path_buf();
let session_manager = Arc::new(SessionManager::new(data_dir.clone()));
let permission_manager = Arc::new(PermissionManager::new(data_dir));
let mock_scheduler = Arc::new(MockScheduler::new());
agent.set_scheduler(mock_scheduler.clone()).await;
let config = AgentConfig::new(
session_manager,
permission_manager,
Some(mock_scheduler),
GooseMode::Auto,
);
let agent = Agent::with_config(config);
let tools = agent.list_tools(None).await;
let tools = agent.list_tools("test-session-id", None).await;
let schedule_tool = tools
.iter()
.find(|tool| tool.name == PLATFORM_MANAGE_SCHEDULE_TOOL_NAME);
@@ -307,7 +339,6 @@ mod tests {
use goose::providers::base::{Provider, ProviderMetadata, ProviderUsage, Usage};
use goose::providers::errors::ProviderError;
use goose::session::session_manager::SessionType;
use goose::session::SessionManager;
use rmcp::model::{CallToolRequestParam, Tool};
use rmcp::object;
use std::path::PathBuf;
@@ -379,12 +410,15 @@ mod tests {
let provider = Arc::new(MockToolProvider::new());
let user_message = Message::user().with_text("Hello");
let session = SessionManager::create_session(
PathBuf::default(),
"max-turn-test".to_string(),
SessionType::Hidden,
)
.await?;
let session = agent
.config
.session_manager
.create_session(
PathBuf::default(),
"max-turn-test".to_string(),
SessionType::Hidden,
)
.await?;
agent.update_provider(provider, &session.id).await?;
@@ -451,10 +485,14 @@ mod tests {
#[cfg(test)]
mod extension_manager_tests {
use super::*;
use goose::agents::extension::{ExtensionConfig, PlatformExtensionContext};
use goose::agents::extension::ExtensionConfig;
use goose::agents::extension_manager_extension::{
MANAGE_EXTENSIONS_TOOL_NAME, SEARCH_AVAILABLE_EXTENSIONS_TOOL_NAME,
};
use goose::agents::AgentConfig;
use goose::config::permission::PermissionManager;
use goose::config::GooseMode;
use goose::session::SessionManager;
async fn setup_agent_with_extension_manager() -> Agent {
// Add the TODO extension to the config so it can be discovered by search_available_extensions
@@ -472,15 +510,17 @@ mod tests {
};
set_extension(todo_extension_entry);
let agent = Agent::new();
// Create agent with session_id from the start
let temp_dir = tempfile::tempdir().unwrap();
let session_manager = Arc::new(SessionManager::new(temp_dir.path().to_path_buf()));
let config = AgentConfig::new(
session_manager,
PermissionManager::instance(),
None,
GooseMode::Auto,
);
agent
.extension_manager
.set_context(PlatformExtensionContext {
session_id: Some("test_session".to_string()),
extension_manager: Some(Arc::downgrade(&agent.extension_manager)),
})
.await;
let agent = Agent::with_config(config);
// Now add the extension manager platform extension
let ext_config = ExtensionConfig::Platform {
@@ -500,7 +540,7 @@ mod tests {
#[tokio::test]
async fn test_extension_manager_tools_available() {
let agent = setup_agent_with_extension_manager().await;
let tools = agent.list_tools(None).await;
let tools = agent.list_tools("test-session-id", None).await;
// Note: Tool names are prefixed with the normalized extension name "extensionmanager"
// not the display name "Extension Manager"