mirror of
https://github.com/block/goose.git
synced 2026-07-17 12:56:20 +02:00
Use capabilities
This commit is contained in:
@@ -44,7 +44,6 @@ async fn main() -> Result<()> {
|
||||
builtins,
|
||||
data_dir: Paths::data_dir(),
|
||||
config_dir: Paths::config_dir(),
|
||||
acp_editor_tools: false,
|
||||
}));
|
||||
let router = goose_acp::transport::create_router(server);
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::custom_requests::*;
|
||||
use crate::tools::AcpTools;
|
||||
use agent_client_protocol_schema::ClientCapabilities;
|
||||
use anyhow::Result;
|
||||
use fs_err as fs;
|
||||
use goose::agents::extension::{Envs, PLATFORM_EXTENSIONS};
|
||||
@@ -60,7 +61,7 @@ pub struct GooseAcpAgent {
|
||||
goose_mode: goose::config::GooseMode,
|
||||
disable_session_naming: bool,
|
||||
builtins: Vec<String>,
|
||||
acp_editor_tools: bool,
|
||||
client_capabilities: Mutex<ClientCapabilities>,
|
||||
}
|
||||
|
||||
fn mcp_server_to_extension_config(mcp_server: McpServer) -> Result<ExtensionConfig, String> {
|
||||
@@ -306,7 +307,6 @@ impl GooseAcpAgent {
|
||||
config_dir: std::path::PathBuf,
|
||||
goose_mode: goose::config::GooseMode,
|
||||
disable_session_naming: bool,
|
||||
acp_editor_tools: bool,
|
||||
) -> Result<Self> {
|
||||
let session_manager = Arc::new(SessionManager::new(data_dir));
|
||||
let permission_manager = Arc::new(PermissionManager::new(config_dir.clone()));
|
||||
@@ -320,7 +320,7 @@ impl GooseAcpAgent {
|
||||
goose_mode,
|
||||
disable_session_naming,
|
||||
builtins,
|
||||
acp_editor_tools,
|
||||
client_capabilities: Mutex::new(ClientCapabilities::default()),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -335,12 +335,19 @@ impl GooseAcpAgent {
|
||||
));
|
||||
let agent = Arc::new(agent);
|
||||
|
||||
if !self.acp_editor_tools {
|
||||
let config_path = self.config_dir.join(CONFIG_YAML_NAME);
|
||||
if let Ok(config_file) = Config::new(&config_path, "goose") {
|
||||
let extensions = get_enabled_extensions_with_config(&config_file);
|
||||
add_extensions(&agent, extensions).await;
|
||||
let exclude_developer = {
|
||||
let capabilities = self.client_capabilities.lock().await;
|
||||
capabilities.terminal
|
||||
|| capabilities.fs.read_text_file
|
||||
|| capabilities.fs.write_text_file
|
||||
};
|
||||
let config_path = self.config_dir.join(CONFIG_YAML_NAME);
|
||||
if let Ok(config_file) = Config::new(&config_path, "goose") {
|
||||
let mut extensions = get_enabled_extensions_with_config(&config_file);
|
||||
if exclude_developer {
|
||||
extensions.retain(|ext| ext.name() != "developer");
|
||||
}
|
||||
add_extensions(&agent, extensions).await;
|
||||
}
|
||||
add_builtins(&agent, self.builtins.clone()).await;
|
||||
|
||||
@@ -676,6 +683,11 @@ impl GooseAcpAgent {
|
||||
) -> Result<InitializeResponse, sacp::Error> {
|
||||
debug!(?args, "initialize request");
|
||||
|
||||
{
|
||||
let mut client_capabilities = self.client_capabilities.lock().await;
|
||||
*client_capabilities = args.client_capabilities;
|
||||
}
|
||||
|
||||
let capabilities = AgentCapabilities::new()
|
||||
.load_session(true)
|
||||
.prompt_capabilities(
|
||||
@@ -737,11 +749,22 @@ impl GooseAcpAgent {
|
||||
}
|
||||
}
|
||||
|
||||
if self.acp_editor_tools {
|
||||
let (fs_read, fs_write, terminal) = {
|
||||
let capabilities = self.client_capabilities.lock().await;
|
||||
(
|
||||
capabilities.fs.read_text_file,
|
||||
capabilities.fs.write_text_file,
|
||||
capabilities.terminal,
|
||||
)
|
||||
};
|
||||
if fs_read || fs_write || terminal {
|
||||
let acp_tools = Arc::new(AcpTools::new(
|
||||
cx,
|
||||
SessionId::new(goose_session.id.clone()),
|
||||
args.cwd.clone(),
|
||||
fs_read,
|
||||
fs_write,
|
||||
terminal,
|
||||
));
|
||||
agent
|
||||
.extension_manager
|
||||
@@ -1365,7 +1388,7 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn run(builtins: Vec<String>, acp_editor_tools: bool) -> Result<()> {
|
||||
pub async fn run(builtins: Vec<String>) -> Result<()> {
|
||||
register_builtin_extensions(goose_mcp::BUILTIN_EXTENSIONS.clone());
|
||||
info!("listening on stdio");
|
||||
|
||||
@@ -1377,7 +1400,6 @@ pub async fn run(builtins: Vec<String>, acp_editor_tools: bool) -> Result<()> {
|
||||
builtins,
|
||||
data_dir: Paths::data_dir(),
|
||||
config_dir: Paths::config_dir(),
|
||||
acp_editor_tools,
|
||||
});
|
||||
let agent = server.create_agent().await?;
|
||||
serve(agent, incoming, outgoing).await
|
||||
|
||||
@@ -9,7 +9,6 @@ pub struct AcpServerFactoryConfig {
|
||||
pub builtins: Vec<String>,
|
||||
pub data_dir: std::path::PathBuf,
|
||||
pub config_dir: std::path::PathBuf,
|
||||
pub acp_editor_tools: bool,
|
||||
}
|
||||
|
||||
pub struct AcpServer {
|
||||
@@ -51,7 +50,6 @@ impl AcpServer {
|
||||
self.config.config_dir.clone(),
|
||||
goose_mode,
|
||||
disable_session_naming,
|
||||
self.config.acp_editor_tools,
|
||||
)
|
||||
.await?;
|
||||
info!("Created new ACP agent");
|
||||
|
||||
@@ -18,10 +18,17 @@ use schemars::{schema_for, JsonSchema};
|
||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
struct Capabilities {
|
||||
filesystem_read: bool,
|
||||
filesystem_write: bool,
|
||||
terminal: bool,
|
||||
}
|
||||
|
||||
pub struct AcpTools {
|
||||
cx: JrConnectionCx<AgentToClient>,
|
||||
session_id: sacp::schema::SessionId,
|
||||
working_dir: PathBuf,
|
||||
capabilities: Capabilities,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
|
||||
@@ -74,9 +81,11 @@ macro_rules! schema {
|
||||
};
|
||||
}
|
||||
|
||||
static TOOL_DEFS: LazyLock<Vec<Tool>> = LazyLock::new(|| {
|
||||
static FILESYSTEM_READ_TOOL_DEFS: LazyLock<Vec<Tool>> =
|
||||
LazyLock::new(|| vec![Tool::new("read", "Read files", schema!(ReadParams))]);
|
||||
|
||||
static FILESYSTEM_WRITE_TOOL_DEFS: LazyLock<Vec<Tool>> = LazyLock::new(|| {
|
||||
vec![
|
||||
Tool::new("read", "Read files", schema!(ReadParams)),
|
||||
Tool::new("write", "Write files", schema!(WriteParams)),
|
||||
Tool::new(
|
||||
"str_replace",
|
||||
@@ -84,10 +93,17 @@ static TOOL_DEFS: LazyLock<Vec<Tool>> = LazyLock::new(|| {
|
||||
schema!(StrReplaceParams),
|
||||
),
|
||||
Tool::new("insert", "Insert strings into files", schema!(InsertParams)),
|
||||
Tool::new("shell", "Execute shell commands", schema!(ShellParams)),
|
||||
]
|
||||
});
|
||||
|
||||
static TERMINAL_TOOL_DEFS: LazyLock<Vec<Tool>> = LazyLock::new(|| {
|
||||
vec![Tool::new(
|
||||
"shell",
|
||||
"Execute shell commands",
|
||||
schema!(ShellParams),
|
||||
)]
|
||||
});
|
||||
|
||||
async fn handle_tool_call<Req, Fut>(
|
||||
mut func: impl FnMut(Req) -> Fut,
|
||||
request: JsonObject,
|
||||
@@ -149,11 +165,19 @@ impl AcpTools {
|
||||
cx: JrConnectionCx<AgentToClient>,
|
||||
session_id: sacp::schema::SessionId,
|
||||
working_dir: PathBuf,
|
||||
filesystem_read: bool,
|
||||
filesystem_write: bool,
|
||||
terminal: bool,
|
||||
) -> Self {
|
||||
AcpTools {
|
||||
cx,
|
||||
session_id,
|
||||
working_dir,
|
||||
capabilities: Capabilities {
|
||||
filesystem_read,
|
||||
filesystem_write,
|
||||
terminal,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -369,7 +393,23 @@ impl McpClientTrait for AcpTools {
|
||||
_next_cursor: Option<String>,
|
||||
_cancel_token: CancellationToken,
|
||||
) -> Result<ListToolsResult, ServiceError> {
|
||||
Ok(ListToolsResult::with_all_items(TOOL_DEFS.clone()))
|
||||
let tools = [
|
||||
(
|
||||
self.capabilities.filesystem_read,
|
||||
&*FILESYSTEM_READ_TOOL_DEFS,
|
||||
),
|
||||
(
|
||||
self.capabilities.filesystem_write,
|
||||
&*FILESYSTEM_WRITE_TOOL_DEFS,
|
||||
),
|
||||
(self.capabilities.terminal, &*TERMINAL_TOOL_DEFS),
|
||||
]
|
||||
.into_iter()
|
||||
.filter(|(enabled, _)| *enabled)
|
||||
.flat_map(|(_, defs)| defs.clone())
|
||||
.collect();
|
||||
|
||||
Ok(ListToolsResult::with_all_items(tools))
|
||||
}
|
||||
|
||||
async fn call_tool(
|
||||
|
||||
@@ -73,7 +73,6 @@ pub async fn run_initialize_without_provider() {
|
||||
temp_dir.path().to_path_buf(),
|
||||
GooseMode::Auto,
|
||||
false,
|
||||
false,
|
||||
)
|
||||
.await
|
||||
.unwrap(),
|
||||
|
||||
-1
@@ -228,7 +228,6 @@ pub async fn spawn_acp_server_in_process(
|
||||
data_root.to_path_buf(),
|
||||
goose_mode,
|
||||
true,
|
||||
false,
|
||||
)
|
||||
.await
|
||||
.unwrap(),
|
||||
|
||||
@@ -691,10 +691,6 @@ enum Command {
|
||||
value_delimiter = ','
|
||||
)]
|
||||
builtins: Vec<String>,
|
||||
|
||||
/// Enable ACP editor tools
|
||||
#[arg(long)]
|
||||
acp_editor_tools: bool,
|
||||
},
|
||||
|
||||
/// Start or resume interactive chat sessions
|
||||
@@ -1667,10 +1663,7 @@ pub async fn cli() -> anyhow::Result<()> {
|
||||
Some(Command::Configure {}) => handle_configure().await,
|
||||
Some(Command::Info { verbose }) => handle_info(verbose),
|
||||
Some(Command::Mcp { server }) => handle_mcp_command(server).await,
|
||||
Some(Command::Acp {
|
||||
builtins,
|
||||
acp_editor_tools,
|
||||
}) => goose_acp::server::run(builtins, acp_editor_tools).await,
|
||||
Some(Command::Acp { builtins }) => goose_acp::server::run(builtins).await,
|
||||
Some(Command::Session {
|
||||
command: Some(cmd), ..
|
||||
}) => handle_session_subcommand(cmd).await,
|
||||
|
||||
Reference in New Issue
Block a user