diff --git a/crates/goose-cli/src/commands/configure.rs b/crates/goose-cli/src/commands/configure.rs index a4fb278aee93..9e4ed02a6a32 100644 --- a/crates/goose-cli/src/commands/configure.rs +++ b/crates/goose-cli/src/commands/configure.rs @@ -504,15 +504,31 @@ pub fn configure_extensions_dialog() -> Result<(), Box> { .placeholder(&goose::config::DEFAULT_EXTENSION_TIMEOUT.to_string()) .validate(|input: &String| match input.parse::() { Ok(_) => Ok(()), - Err(_) => Err("Please enter a valide timeout"), + Err(_) => Err("Please enter a valid timeout"), }) .interact()?; // Split the command string into command and args + // TODO: find a way to expose this to the frontend so we dont need to re-write code let mut parts = command_str.split_whitespace(); let cmd = parts.next().unwrap_or("").to_string(); let args: Vec = parts.map(String::from).collect(); + let add_desc = cliclack::confirm("Would you like to add a description?").interact()?; + + let description = if add_desc { + let desc = cliclack::input("Enter a description for this extension:") + .placeholder("Description") + .validate(|input: &String| match input.parse::() { + Ok(_) => Ok(()), + Err(_) => Err("Please enter a valid description"), + }) + .interact()?; + Some(desc) + } else { + None + }; + let add_env = cliclack::confirm("Would you like to add environment variables?").interact()?; @@ -542,6 +558,7 @@ pub fn configure_extensions_dialog() -> Result<(), Box> { cmd, args, envs: Envs::new(envs), + description, timeout: Some(timeout), }, })?; @@ -580,10 +597,25 @@ pub fn configure_extensions_dialog() -> Result<(), Box> { .placeholder(&goose::config::DEFAULT_EXTENSION_TIMEOUT.to_string()) .validate(|input: &String| match input.parse::() { Ok(_) => Ok(()), - Err(_) => Err("Please enter a valide timeout"), + Err(_) => Err("Please enter a valid timeout"), }) .interact()?; + let add_desc = cliclack::confirm("Would you like to add a description?").interact()?; + + let description = if add_desc { + let desc = cliclack::input("Enter a description for this extension:") + .placeholder("Description") + .validate(|input: &String| match input.parse::() { + Ok(_) => Ok(()), + Err(_) => Err("Please enter a valid description"), + }) + .interact()?; + Some(desc) + } else { + None + }; + let add_env = cliclack::confirm("Would you like to add environment variables?").interact()?; @@ -612,6 +644,7 @@ pub fn configure_extensions_dialog() -> Result<(), Box> { name: name.clone(), uri, envs: Envs::new(envs), + description, timeout: Some(timeout), }, })?; diff --git a/crates/goose-cli/src/session/mod.rs b/crates/goose-cli/src/session/mod.rs index ce7c44bc6845..196dd6cbfd3e 100644 --- a/crates/goose-cli/src/session/mod.rs +++ b/crates/goose-cli/src/session/mod.rs @@ -109,6 +109,7 @@ impl Session { cmd, args: parts.iter().map(|s| s.to_string()).collect(), envs: Envs::new(envs), + description: Some(goose::config::DEFAULT_EXTENSION_DESCRIPTION.to_string()), // TODO: should set timeout timeout: Some(goose::config::DEFAULT_EXTENSION_TIMEOUT), }; diff --git a/crates/goose-server/src/routes/extension.rs b/crates/goose-server/src/routes/extension.rs index 60a5b996fe21..5be0fb02cd55 100644 --- a/crates/goose-server/src/routes/extension.rs +++ b/crates/goose-server/src/routes/extension.rs @@ -115,6 +115,7 @@ async fn add_extension( name, uri, envs: Envs::new(env_map), + description: None, timeout, } } @@ -151,6 +152,7 @@ async fn add_extension( name, cmd, args, + description: None, envs: Envs::new(env_map), timeout, } diff --git a/crates/goose/examples/agent.rs b/crates/goose/examples/agent.rs index f9bed55dfcd7..84b178f12bab 100644 --- a/crates/goose/examples/agent.rs +++ b/crates/goose/examples/agent.rs @@ -1,7 +1,7 @@ use dotenv::dotenv; use futures::StreamExt; use goose::agents::{AgentFactory, ExtensionConfig}; -use goose::config::DEFAULT_EXTENSION_TIMEOUT; +use goose::config::{DEFAULT_EXTENSION_DESCRIPTION, DEFAULT_EXTENSION_TIMEOUT}; use goose::message::Message; use goose::providers::databricks::DatabricksProvider; @@ -18,6 +18,7 @@ async fn main() { let config = ExtensionConfig::stdio( "developer", "./target/debug/developer", + DEFAULT_EXTENSION_DESCRIPTION, DEFAULT_EXTENSION_TIMEOUT, ); agent.add_extension(config).await.unwrap(); diff --git a/crates/goose/src/agents/extension.rs b/crates/goose/src/agents/extension.rs index 27650fa183e0..2887d1321c12 100644 --- a/crates/goose/src/agents/extension.rs +++ b/crates/goose/src/agents/extension.rs @@ -56,6 +56,7 @@ pub enum ExtensionConfig { uri: String, #[serde(default)] envs: Envs, + description: Option, // NOTE: set timeout to be optional for compatibility. // However, new configurations should include this field. timeout: Option, @@ -70,6 +71,7 @@ pub enum ExtensionConfig { #[serde(default)] envs: Envs, timeout: Option, + description: Option, }, /// Built-in extension that is part of the goose binary #[serde(rename = "builtin")] @@ -90,21 +92,28 @@ impl Default for ExtensionConfig { } impl ExtensionConfig { - pub fn sse, T: Into>(name: S, uri: S, timeout: T) -> Self { + pub fn sse, T: Into>(name: S, uri: S, description: S, timeout: T) -> Self { Self::Sse { name: name.into(), uri: uri.into(), envs: Envs::default(), + description: Some(description.into()), timeout: Some(timeout.into()), } } - pub fn stdio, T: Into>(name: S, cmd: S, timeout: T) -> Self { + pub fn stdio, T: Into>( + name: S, + cmd: S, + description: S, + timeout: T, + ) -> Self { Self::Stdio { name: name.into(), cmd: cmd.into(), args: vec![], envs: Envs::default(), + description: Some(description.into()), timeout: Some(timeout.into()), } } @@ -120,12 +129,14 @@ impl ExtensionConfig { cmd, envs, timeout, + description, .. } => Self::Stdio { name, cmd, envs, args: args.into_iter().map(Into::into).collect(), + description, timeout, }, other => other, diff --git a/crates/goose/src/config/extensions.rs b/crates/goose/src/config/extensions.rs index d34f10c9c762..5b6db2b69cdf 100644 --- a/crates/goose/src/config/extensions.rs +++ b/crates/goose/src/config/extensions.rs @@ -7,6 +7,7 @@ use utoipa::ToSchema; pub const DEFAULT_EXTENSION: &str = "developer"; pub const DEFAULT_EXTENSION_TIMEOUT: u64 = 300; +pub const DEFAULT_EXTENSION_DESCRIPTION: &str = ""; #[derive(Debug, Deserialize, Serialize, Clone, ToSchema)] pub struct ExtensionEntry { diff --git a/crates/goose/src/config/mod.rs b/crates/goose/src/config/mod.rs index dee27c216df7..54e4b7a66024 100644 --- a/crates/goose/src/config/mod.rs +++ b/crates/goose/src/config/mod.rs @@ -8,4 +8,5 @@ pub use experiments::ExperimentManager; pub use extensions::{ExtensionEntry, ExtensionManager}; pub use extensions::DEFAULT_EXTENSION; +pub use extensions::DEFAULT_EXTENSION_DESCRIPTION; pub use extensions::DEFAULT_EXTENSION_TIMEOUT;